From 77b4183e76019a526b52e35119ab64ff87c3614a Mon Sep 17 00:00:00 2001 From: Boldizsar Mezei Date: Tue, 26 Mar 2024 16:35:59 +0100 Subject: [PATCH] Postgres Postgres Postgres Postgres Postgres Postgres Fixes Fixes Fixes Fixes Fixes Fixes Fixes Fixes Fixes Fixes Fixes Fixes Fixes Fixes Fixes Fixes Fixes Fixes Fixes Fixes Fixes Fixes Fixes Fixes Fixes Fixes Fixes Fixes Fixes Fixes Remove partials Fixes Fixe Fixes Fixes Fixes Fixes Fixes Fixes Fixes Fixes --- .../workflows/functions_emulated-tests.yml | 314 +- .../functions_online-emulated-tests.yml | 312 -- ...ions_tangle-online-unit-tests_emulator.yml | 3026 ---------------- .../workflows/functions_tangle-unit-tests.yml | 3213 +++++++++-------- .prettierignore | 1 + .prettierrc | 3 +- data.proto | 161 - firestore.rules | 6 - package-lock.json | 1993 ++++++---- package.json | 7 +- packages/database/.env | 6 + packages/database/.gitignore | 2 +- packages/database/generators/generator.ts | 7 + .../generators/pg.interface.generator.ts | 277 ++ packages/database/knexfile.ts | 15 + .../migrations/20240129091246_common.ts | 126 + .../migrations/20240129135000_auction.ts | 35 + .../migrations/20240129135000_award.ts | 72 + .../migrations/20240129135000_change.ts | 10 + .../migrations/20240129135000_collection.ts | 125 + .../migrations/20240129135000_member.ts | 31 + .../migrations/20240129135000_milestone.ts | 35 + .../migrations/20240129135000_mnemonic.ts | 17 + .../database/migrations/20240129135000_nft.ts | 69 + .../migrations/20240129135000_nft_stake.ts | 23 + .../migrations/20240129135000_notification.ts | 19 + .../migrations/20240129135000_project.ts | 39 + .../migrations/20240129135000_proposal.ts | 68 + .../migrations/20240129135000_soon_snap.ts | 16 + .../migrations/20240129135000_space.ts | 60 + .../migrations/20240129135000_stake.ts | 25 + .../migrations/20240129135000_stake_reward.ts | 23 + .../migrations/20240129135000_stamp.ts | 34 + .../migrations/20240129135000_swap.ts | 26 + .../migrations/20240129135000_system.ts | 13 + .../migrations/20240129135000_ticker.ts | 12 + .../migrations/20240129135000_token.ts | 190 + .../migrations/20240129135000_token_market.ts | 43 + .../20240129135000_token_purchase.ts | 33 + .../migrations/20240129135000_transaction.ts | 259 ++ packages/database/package.json | 12 +- packages/database/src/app/app.ts | 11 - packages/database/src/app/build5App.ts | 6 - packages/database/src/app/index.ts | 3 - packages/database/src/app/interface.ts | 5 - packages/database/src/firestore/build5Db.ts | 22 - packages/database/src/firestore/common.ts | 11 - packages/database/src/firestore/firestore.ts | 294 -- packages/database/src/firestore/index.ts | 4 - packages/database/src/firestore/interfaces.ts | 103 - packages/database/src/index.ts | 3 +- packages/database/src/pg/impl/common.ts | 40 + packages/database/src/pg/impl/instance.ts | 4 + packages/database/src/pg/impl/knex.ts | 45 + packages/database/src/pg/impl/postgres.ts | 650 ++++ packages/database/src/pg/impl/pubsub.ts | 20 + .../database/src/pg/impl/tables/airdrop.ts | 62 + .../database/src/pg/impl/tables/auction.ts | 64 + packages/database/src/pg/impl/tables/award.ts | 108 + .../src/pg/impl/tables/award_owner.ts | 23 + .../src/pg/impl/tables/award_participant.ts | 31 + .../database/src/pg/impl/tables/collection.ts | 206 ++ .../src/pg/impl/tables/collection_rank.ts | 22 + .../src/pg/impl/tables/collection_stats.ts | 36 + .../src/pg/impl/tables/collection_vote.ts | 22 + .../database/src/pg/impl/tables/member.ts | 67 + .../database/src/pg/impl/tables/milestone.ts | 36 + .../pg/impl/tables/milestone_transactions.ts | 53 + .../database/src/pg/impl/tables/mnemonic.ts | 39 + packages/database/src/pg/impl/tables/nft.ts | 223 ++ .../database/src/pg/impl/tables/nft_stake.ts | 41 + .../src/pg/impl/tables/notification.ts | 43 + .../database/src/pg/impl/tables/project.ts | 43 + .../src/pg/impl/tables/project_admin.ts | 23 + .../src/pg/impl/tables/project_api_key.ts | 25 + .../database/src/pg/impl/tables/proposal.ts | 80 + .../src/pg/impl/tables/proposal_member.ts | 49 + .../src/pg/impl/tables/proposal_owner.ts | 23 + .../src/pg/impl/tables/soon_snapshot.ts | 36 + packages/database/src/pg/impl/tables/space.ts | 93 + .../src/pg/impl/tables/space_guardians.ts | 23 + .../src/pg/impl/tables/space_member.ts | 23 + packages/database/src/pg/impl/tables/stake.ts | 68 + .../src/pg/impl/tables/stake_reward.ts | 42 + packages/database/src/pg/impl/tables/stamp.ts | 63 + packages/database/src/pg/impl/tables/swap.ts | 47 + .../database/src/pg/impl/tables/system.ts | 19 + .../database/src/pg/impl/tables/ticker.ts | 18 + packages/database/src/pg/impl/tables/token.ts | 152 + .../src/pg/impl/tables/token_distribution.ts | 108 + .../src/pg/impl/tables/token_market.ts | 74 + .../src/pg/impl/tables/token_purchase.ts | 68 + .../database/src/pg/impl/tables/token_rank.ts | 22 + .../src/pg/impl/tables/token_stats.ts | 74 + .../database/src/pg/impl/tables/token_vote.ts | 22 + .../src/pg/impl/tables/transaction.ts | 325 ++ packages/database/src/pg/index.ts | 8 + packages/database/src/pg/interfaces.ts | 486 +++ packages/database/src/pg/models/airdrop.ts | 21 + .../database/src/pg/models/airdrop_update.ts | 22 + packages/database/src/pg/models/auction.ts | 28 + .../database/src/pg/models/auction_update.ts | 29 + packages/database/src/pg/models/award.ts | 57 + .../database/src/pg/models/award_update.ts | 58 + packages/database/src/pg/models/changes.ts | 9 + .../database/src/pg/models/changes_update.ts | 9 + packages/database/src/pg/models/collection.ts | 88 + .../src/pg/models/collection_update.ts | 89 + packages/database/src/pg/models/common.ts | 14 + .../database/src/pg/models/common_update.ts | 14 + packages/database/src/pg/models/enums.ts | 274 ++ packages/database/src/pg/models/index.ts | 42 + packages/database/src/pg/models/member.ts | 25 + .../database/src/pg/models/member_update.ts | 26 + packages/database/src/pg/models/milestone.ts | 65 + .../src/pg/models/milestone_update.ts | 66 + packages/database/src/pg/models/mnemonic.ts | 15 + .../database/src/pg/models/mnemonic_update.ts | 16 + packages/database/src/pg/models/nft.ts | 99 + packages/database/src/pg/models/nft_update.ts | 100 + .../database/src/pg/models/notification.ts | 13 + .../src/pg/models/notification_update.ts | 13 + packages/database/src/pg/models/project.ts | 24 + .../database/src/pg/models/project_update.ts | 24 + packages/database/src/pg/models/proposal.ts | 43 + .../database/src/pg/models/proposal_update.ts | 44 + packages/database/src/pg/models/soon.ts | 13 + .../database/src/pg/models/soon_update.ts | 14 + packages/database/src/pg/models/space.ts | 48 + .../database/src/pg/models/space_update.ts | 49 + packages/database/src/pg/models/stake.ts | 32 + .../database/src/pg/models/stake_update.ts | 33 + packages/database/src/pg/models/stamp.ts | 27 + .../database/src/pg/models/stamp_update.ts | 28 + packages/database/src/pg/models/swap.ts | 19 + .../database/src/pg/models/swap_update.ts | 20 + packages/database/src/pg/models/system.ts | 10 + .../database/src/pg/models/system_update.ts | 11 + packages/database/src/pg/models/ticker.ts | 9 + .../database/src/pg/models/ticker_update.ts | 10 + packages/database/src/pg/models/token.ts | 172 + .../database/src/pg/models/token_update.ts | 173 + .../database/src/pg/models/transaction.ts | 130 + .../src/pg/models/transaction_update.ts | 135 + .../database/src/storage/build5Storage.ts | 3 +- packages/database/src/storage/storage.ts | 14 +- packages/functions/.env | 28 +- packages/functions/.env.dev | 11 - packages/functions/.env.local | 12 - packages/functions/.eslintrc.js | 10 +- packages/functions/.runtimeconfig.json | 33 - packages/functions/jest-setup.ts | 100 + packages/functions/jest.config.js | 3 +- packages/functions/migration/index.ts | 8 + packages/functions/migration/pg.migration.ts | 80 + .../functions/migration/pubsub.migration.ts | 20 + packages/functions/package.json | 27 +- packages/functions/scripts/db.upgrade.ts | 2 +- .../scripts/dbUpgrades/2.1/soon.snapshot.ts | 235 -- packages/functions/scripts/dummyTransfer.ts | 4 +- .../functions/scripts/duplicatePurchases.ts | 2 +- packages/functions/scripts/manualRefund.ts | 2 +- packages/functions/scripts/nullPayments.ts | 4 +- packages/functions/scripts/retryPayment.ts | 4 +- ...ount-key.json => service-account-key.json} | 0 .../src/controls/address/address.control.ts | 8 +- .../src/controls/auction/auction.control.ts | 6 +- .../auction/auction.create.control.ts | 8 +- .../award/award.approve.participant.ts | 4 +- .../src/controls/award/award.cancel.ts | 6 +- .../src/controls/award/award.create.ts | 8 +- .../src/controls/award/award.fund.ts | 2 +- .../src/controls/award/award.owner.ts | 21 +- .../src/controls/award/award.participate.ts | 11 +- .../src/controls/award/award.reject.ts | 4 +- .../collection/collection-mint.control.ts | 34 +- .../collection/collection.create.control.ts | 37 +- .../collection/collection.reject.control.ts | 4 +- .../collection/collection.update.control.ts | 58 +- .../src/controls/credit/credit.controller.ts | 8 +- .../src/controls/member/member.create.ts | 13 +- .../src/controls/member/member.update.ts | 26 +- .../controls/nft/NftMetadataRequestSchema.ts | 2 +- .../src/controls/nft/nft.bid.control.ts | 8 +- .../functions/src/controls/nft/nft.create.ts | 42 +- .../functions/src/controls/nft/nft.deposit.ts | 2 +- .../src/controls/nft/nft.metadata.control.ts | 16 +- .../controls/nft/nft.puchase.bulk.control.ts | 4 +- .../src/controls/nft/nft.puchase.control.ts | 5 +- .../src/controls/nft/nft.set.for.sale.ts | 12 +- .../functions/src/controls/nft/nft.stake.ts | 4 +- .../src/controls/nft/nft.transfer.ts | 22 +- .../src/controls/nft/nft.update.unsold.ts | 8 +- .../src/controls/nft/nft.withdraw.ts | 32 +- .../project/ProjectCreateRequestSchema.ts | 12 +- .../project/project.create.control.ts | 19 +- .../project/project.deactivate.control.ts | 4 +- .../proposal/approve.reject.proposal.ts | 6 +- .../src/controls/proposal/create.proposal.ts | 13 +- .../src/controls/proposal/vote.on.proposal.ts | 30 +- .../src/controls/rank/rank.control.ts | 69 +- .../controls/space/member.accept.control.ts | 20 +- .../controls/space/member.block.control.ts | 23 +- .../controls/space/member.decline.control.ts | 12 +- .../controls/space/member.leave.control.ts | 14 +- .../controls/space/member.unblock.control.ts | 8 +- .../src/controls/space/space.claim.control.ts | 12 +- .../controls/space/space.create.control.ts | 14 +- .../space/space.guardian.edit.control.ts | 21 +- .../src/controls/space/space.join.control.ts | 24 +- .../controls/space/space.update.control.ts | 24 +- .../src/controls/stake/stake.deposit.ts | 2 +- .../src/controls/stake/stake.reward.revoke.ts | 37 +- .../src/controls/stake/stake.reward.ts | 11 +- .../src/controls/stamp/stamp.create.ts | 19 +- .../src/controls/swaps/swap.create.control.ts | 6 +- .../src/controls/swaps/swap.funded.control.ts | 16 +- .../src/controls/swaps/swap.reject.control.ts | 14 +- .../token-minting/airdrop-minted-token.ts | 16 +- .../claim-minted-token.control.ts | 2 +- .../token-minting/import-minted-token.ts | 8 +- .../token-minting/token-mint.control.ts | 28 +- .../token-trading/TokenTradeRequestSchema.ts | 2 +- .../token-trade-cancel.controller.ts | 5 +- .../token-trading/token-trade.controller.ts | 22 +- .../controls/token/TokenOrderRequestSchema.ts | 2 +- .../src/controls/token/token.airdrop.claim.ts | 9 +- .../src/controls/token/token.airdrop.ts | 31 +- .../controls/token/token.cancel.pub.sale.ts | 20 +- .../src/controls/token/token.create.ts | 25 +- .../src/controls/token/token.credit.ts | 37 +- .../controls/token/token.enable.trading.ts | 10 +- .../src/controls/token/token.order.ts | 20 +- .../src/controls/token/token.set.for.sale.ts | 15 +- .../src/controls/token/token.update.ts | 12 +- .../src/controls/vote/vote.control.ts | 56 +- packages/functions/src/cron/auction.cron.ts | 18 +- packages/functions/src/cron/award.cron.ts | 6 +- packages/functions/src/cron/bitfinex.cron.ts | 11 +- .../src/cron/collection.floor.price.cron.ts | 40 +- packages/functions/src/cron/media.cron.ts | 92 +- packages/functions/src/cron/nft.cron.ts | 4 +- packages/functions/src/cron/nftStake.cron.ts | 37 +- packages/functions/src/cron/orders.cron.ts | 20 +- packages/functions/src/cron/proposal.cron.ts | 12 +- packages/functions/src/cron/stake.cron.ts | 68 +- .../functions/src/cron/stakeReward.cron.ts | 85 +- packages/functions/src/cron/stamp.cron.ts | 8 +- packages/functions/src/cron/token.cron.ts | 39 +- .../functions/src/cron/token.purchase.cron.ts | 14 +- packages/functions/src/cron/wallet.cron.ts | 37 +- packages/functions/src/index.express.ts | 101 - packages/functions/src/index.ts | 183 +- packages/functions/src/runtime/common.ts | 2 +- .../src/runtime/firebase/address/index.ts | 4 - .../src/runtime/firebase/auction/index.ts | 6 - .../src/runtime/firebase/auth/index.ts | 4 - .../src/runtime/firebase/award/index.ts | 10 - .../src/runtime/firebase/collection/index.ts | 7 - .../src/runtime/firebase/credit/index.ts | 4 - .../src/runtime/firebase/member/index.ts | 5 - .../src/runtime/firebase/nft/index.ts | 25 - .../src/runtime/firebase/project/index.ts | 5 - .../src/runtime/firebase/proposal/index.ts | 7 - .../src/runtime/firebase/rank/index.ts | 4 - .../src/runtime/firebase/space/index.ts | 22 - .../src/runtime/firebase/stake/index.ts | 6 - .../src/runtime/firebase/stamp/index.ts | 4 - .../runtime/firebase/storage/file.upload.ts | 4 - .../src/runtime/firebase/swap/index.ts | 8 - .../src/runtime/firebase/token/base/index.ts | 20 - .../runtime/firebase/token/minting/index.ts | 10 - .../runtime/firebase/token/trading/index.ts | 5 - .../src/runtime/firebase/vote/index.ts | 4 - packages/functions/src/runtime/https/https.ts | 12 +- .../src/runtime/proto/protoToJson.ts | 48 - .../functions/src/runtime/trigger/index.ts | 26 +- .../functions/src/runtime/trigger/trigger.ts | 38 +- packages/functions/src/services/joi/common.ts | 9 +- .../payment/address/address-member.service.ts | 44 +- .../payment/address/address.space.service.ts | 62 +- .../src/services/payment/address/common.ts | 26 +- .../payment/auction/auction-bid.service.ts | 76 +- .../auction/auction.finalize.service.ts | 41 +- .../services/payment/award/award-service.ts | 25 +- .../src/services/payment/credit-service.ts | 17 +- .../services/payment/metadataNft-service.ts | 61 +- .../payment/nft/collection-minting.service.ts | 57 +- .../src/services/payment/nft/common.ts | 44 +- .../payment/nft/nft-deposit.service.ts | 120 +- .../payment/nft/nft-purchase.bulk.service.ts | 42 +- .../payment/nft/nft-purchase.service.ts | 66 +- .../services/payment/nft/nft-stake.service.ts | 23 +- .../payment/nft/nft-transfer.service.ts | 20 +- .../services/payment/payment-processing.ts | 22 +- .../services/payment/space/space-service.ts | 41 +- .../src/services/payment/stake-service.ts | 24 +- .../src/services/payment/stamp.service.ts | 45 +- .../src/services/payment/swap/swap-service.ts | 39 +- .../tangle-service/TangleRequestService.ts | 16 +- .../address/address-validation.service.ts | 10 +- .../auction/auction.bid.order.ts | 27 +- .../auction/auction.bid.service.ts | 17 +- .../auction/auction.create.service.ts | 7 +- .../award.approve.participant.service.ts | 74 +- .../award/award.create.service.ts | 17 +- .../award/award.fund.service.ts | 9 +- .../build5/verify.eth.for.b5.service.ts | 18 +- .../metadataNft/mint-metadata-nft.service.ts | 30 +- .../tangle-service/nft/nft-deposit.service.ts | 5 +- .../nft/nft-purchase.bulk.service.ts | 16 +- .../nft/nft-purchase.service.ts | 78 +- .../nft/nft-set-for-sale.service.ts | 37 +- .../nft/nft-transfer.service.ts | 19 +- .../proposal/ProposalApporvalService.ts | 11 +- .../proposal/ProposalCreateService.ts | 33 +- .../proposal/voting/ProposalVoteService.ts | 51 +- .../proposal/voting/simple.voting.ts | 7 +- .../proposal/voting/staked.token.voting.ts | 120 +- .../space/SpaceAcceptMemberService.ts | 44 +- .../space/SpaceBlockMemberService.ts | 41 +- .../space/SpaceCreateService.ts | 47 +- .../space/SpaceDeclineMemberService.ts | 16 +- .../space/SpaceGuardianService.ts | 51 +- .../tangle-service/space/SpaceJoinService.ts | 48 +- .../tangle-service/space/SpaceLeaveService.ts | 41 +- .../stamp/StampTangleService.ts | 36 +- .../swap/SwapCreateTangleService.ts | 9 +- .../swap/SwapRejectTangleService.ts | 17 +- .../swap/SwapSetFundedTangleService.ts | 22 +- .../tangle-service/token/stake.service.ts | 5 +- .../token/token-claim.service.ts | 13 +- .../token/token-trade.service.ts | 27 +- .../token/import-minted-token.service.ts | 10 +- .../payment/token/token-mint.service.ts | 30 +- .../token/token-minted-airdrop.service.ts | 73 +- .../payment/token/token-purchase.service.ts | 33 +- .../services/payment/token/token-service.ts | 133 +- .../payment/token/token-trade.service.ts | 32 +- .../services/payment/transaction-service.ts | 140 +- .../src/services/payment/voting-service.ts | 52 +- .../functions/src/services/stake.service.ts | 69 +- .../src/services/validators/access.ts | 14 +- .../src/services/wallet/NativeTokenWallet.ts | 18 +- .../src/services/wallet/NftWallet.ts | 59 +- .../functions/src/services/wallet/mnemonic.ts | 16 +- .../src/services/wallet/wallet.service.ts | 9 +- .../src/triggers/algolia/algolia.trigger.ts | 34 +- .../triggers/algolia/firestore.to.algolia.ts | 27 - .../functions/src/triggers/award.trigger.ts | 65 +- .../src/triggers/collection.stats.trigger.ts | 29 +- .../src/triggers/collection.trigger.ts | 249 +- packages/functions/src/triggers/common.ts | 10 +- .../MilestoneTransactionAdapter.ts | 18 +- .../milestone-transactions-triggers/common.ts | 26 +- .../consumed.vote.outputs.ts | 71 +- .../milestone-transaction.trigger.ts | 35 +- .../token.foundry.ts | 12 +- .../src/triggers/mnemonic.trigger.ts | 37 +- .../functions/src/triggers/nft.trigger.ts | 34 +- .../src/triggers/proposal.trigger.ts | 168 +- .../token-trading/match-base-token.ts | 31 +- .../token-trading/match-minted-token.ts | 28 +- .../token-trading/match-simple-token.ts | 31 +- .../src/triggers/token-trading/match-token.ts | 119 +- .../token-trading/token-purchase.trigger.ts | 26 +- .../token-trade-order.trigger.ts | 31 +- .../functions/src/triggers/token.trigger.ts | 173 +- .../transaction-trigger/airdrop.claim.ts | 196 +- .../award.transaction.update.ts | 67 +- .../transaction-trigger/collection-minting.ts | 153 +- .../transaction-trigger/matadatNft-minting.ts | 180 +- .../transaction-trigger/nft-staked.ts | 23 +- .../transaction-trigger/proposal.vote.ts | 35 +- .../triggers/transaction-trigger/staking.ts | 54 +- .../transaction-trigger/stamp-minting.ts | 74 +- .../transaction-trigger/token-minting.ts | 86 +- .../transaction.trigger.ts | 185 +- .../transaction-trigger/wallet-params.ts | 3 +- packages/functions/src/utils/car.utils.ts | 9 +- .../nft.prop.utils.ts | 3 +- .../collection-minting-utils/nft.utils.ts | 9 +- packages/functions/src/utils/common.utils.ts | 9 +- .../functions/src/utils/dateTime.utils.ts | 3 +- packages/functions/src/utils/error.utils.ts | 20 +- packages/functions/src/utils/media.utils.ts | 30 +- packages/functions/src/utils/milestone.ts | 6 + packages/functions/src/utils/royalty.utils.ts | 6 +- packages/functions/src/utils/schema.utils.ts | 7 +- packages/functions/src/utils/space.utils.ts | 15 +- .../utils/token-minting-utils/member.utils.ts | 24 +- .../functions/src/utils/token-trade.utils.ts | 74 +- packages/functions/src/utils/token.utils.ts | 60 +- packages/functions/src/utils/wallet.utils.ts | 27 +- .../functions/test-tangle/address.spec.ts | 85 +- .../auction-tangle/auction.bit.tangle.spec.ts | 30 +- .../award-tangle/award-tangle_1.spec.ts | 22 +- .../award-tangle/award-tangle_2.spec.ts | 31 +- .../award-tangle/award-tangle_3.spec.ts | 28 +- .../award-tangle/award-tangle_4.spec.ts | 28 +- .../award-tangle/award-tangle_5.spec.ts | 27 +- .../award-tangle/award-tangle_6.spec.ts | 28 +- .../award-tangle/award-tangle_7.spec.ts | 24 +- .../test-tangle/award-tangle/common.ts | 30 +- .../test-tangle/award/award_1.spec.ts | 82 +- .../test-tangle/award/award_10.spec.ts | 53 +- .../test-tangle/award/award_11.spec.ts | 74 +- .../test-tangle/award/award_12.spec.ts | 76 +- .../test-tangle/award/award_1_b.spec.ts | 29 +- .../test-tangle/award/award_2.spec.ts | 96 +- .../test-tangle/award/award_3.spec.ts | 36 +- .../test-tangle/award/award_4.spec.ts | 71 +- .../test-tangle/award/award_5.spec.ts | 93 +- .../test-tangle/award/award_6.spec.ts | 57 +- .../test-tangle/award/award_7.spec.ts | 55 +- .../test-tangle/award/award_8.spec.ts | 90 +- .../test-tangle/award/award_9.spec.ts | 62 +- .../functions/test-tangle/award/common.ts | 30 +- .../test-tangle/base-token-trading/Helper.ts | 58 +- .../base-token-trading_1.spec.ts | 54 +- .../base-token-trading_10.spec.ts | 29 +- .../base-token-trading_11_a.spec.ts | 25 +- .../base-token-trading_11_b.spec.ts | 74 +- .../base-token-trading_11_c.spec.ts | 25 +- .../base-token-trading_11_d.spec.ts | 25 +- .../base-token-trading_12.spec.ts | 2 +- .../base-token-trading_13.spec.ts | 27 +- .../base-token-trading_14.spec.ts | 25 +- .../base-token-trading_15.spec.ts | 25 +- .../base-token-trading_16.spec.ts | 21 +- .../base-token-trading_17.spec.ts | 21 +- .../base-token-trading_18.spec.ts | 10 +- .../base-token-trading_19.spec.ts | 10 +- .../base-token-trading_2.spec.ts | 27 +- .../base-token-trading_3.spec.ts | 29 +- .../base-token-trading_4.spec.ts | 29 +- .../base-token-trading_5.spec.ts | 26 +- .../base-token-trading_6.spec.ts | 26 +- .../base-token-trading_7.spec.ts | 17 +- .../base-token-trading_8.spec.ts | 16 +- .../base-token-trading_9.spec.ts | 16 +- .../test-tangle/collection-minting/Helper.ts | 98 +- .../collection-minting_1.spec.ts | 21 +- .../collection-minting_10.spec.ts | 6 +- .../collection-minting_11.spec.ts | 8 +- .../collection-minting_12.spec.ts | 8 +- .../collection-minting_13.spec.ts | 19 +- .../collection-minting_2.spec.ts | 48 +- .../collection-minting_3.only.spec.ts | 36 +- .../collection-minting_4_a.spec.ts | 35 +- .../collection-minting_4_b.spec.ts | 31 +- .../collection-minting_4_c.spec.ts | 8 +- .../collection-minting_5.spec.ts | 29 +- .../collection-minting_6.spec.ts | 8 +- .../collection-minting_7.spec.ts | 40 +- .../collection-minting_8.spec.ts | 33 +- .../collection-minting_9.spec.ts | 31 +- packages/functions/test-tangle/common.ts | 10 +- packages/functions/test-tangle/faucet.ts | 6 +- .../test-tangle/metadata-nft/Helper.ts | 20 +- .../metadata-nft/mint-metadata-nft_1.spec.ts | 32 +- .../metadata-nft/mint-metadata-nft_10.spec.ts | 43 +- .../mint-metadata-nft_1_b.spec.ts | 32 +- .../metadata-nft/mint-metadata-nft_2.spec.ts | 31 +- .../metadata-nft/mint-metadata-nft_3.spec.ts | 34 +- .../mint-metadata-nft_3_b.spec.ts | 34 +- .../metadata-nft/mint-metadata-nft_4.spec.ts | 35 +- .../metadata-nft/mint-metadata-nft_5.spec.ts | 29 +- .../mint-metadata-nft_5_b.spec.ts | 29 +- .../metadata-nft/mint-metadata-nft_6.spec.ts | 28 +- .../metadata-nft/mint-metadata-nft_7.spec.ts | 26 +- .../metadata-nft/mint-metadata-nft_8.spec.ts | 29 +- .../metadata-nft/mint-metadata-nft_9.spec.ts | 52 +- .../test-tangle/minted-nft-trading/Helper.ts | 80 +- .../minted-nft-trading_1.spec.ts | 48 +- .../minted-nft-trading_10.spec.ts | 9 +- .../minted-nft-trading_11.only.spec.ts | 23 +- .../minted-nft-trading_1_b.spec.ts | 49 +- .../minted-nft-trading_2.spec.ts | 36 +- .../minted-nft-trading_3.spec.ts | 15 +- .../minted-nft-trading_4.spec.ts | 31 +- .../minted-nft-trading_5.spec.ts | 13 +- .../minted-nft-trading_6.spec.ts | 8 +- .../minted-nft-trading_7.spec.ts | 31 +- .../minted-nft-trading_8.spec.ts | 5 +- .../minted-token-airdrop/Helper.ts | 31 +- .../minted-token-airdrop_1_a.spec.ts | 80 +- .../minted-token-airdrop_1_b.spec.ts | 57 +- .../minted-token-airdrop_1_c.spec.ts | 30 +- .../minted-token-airdrop_2.spec.ts | 75 +- .../minted-token-airdrop_4.spec.ts | 35 +- .../minted-token-airdrop_5.spec.ts | 37 +- .../test-tangle/minted-token-claim/Helper.ts | 26 +- .../token.claim.minted_1.spec.ts | 21 +- .../token.claim.minted_2.spec.ts | 28 +- .../token.claim.minted_3.spec.ts | 20 +- .../token.claim.minted_4.spec.ts | 23 +- .../token.claim.minted_5.spec.ts | 28 +- .../token.claim.minted_6.spec.ts | 35 +- .../token.claim.minted_7.spec.ts | 35 +- .../test-tangle/minted-token-trade/Helper.ts | 55 +- .../minted-token-trade_1.spec.ts | 13 +- .../minted-token-trade_12.spec.ts | 13 +- .../minted-token-trade_12_b.spec.ts | 13 +- .../minted-token-trade_13.spec.ts | 15 +- .../minted-token-trade_14.spec.ts | 14 +- .../minted-token-trade_15.only.spec.ts | 44 +- .../minted-token-trade_16.spec.ts | 25 +- .../minted-token-trade_17.spec.ts | 52 +- .../minted-token-trade_18.spec.ts | 11 +- .../minted-token-trade_19.spec.ts | 27 +- .../minted-token-trade_2.spec.ts | 20 +- .../minted-token-trade_20.spec.ts | 25 +- .../minted-token-trade_21.spec.ts | 14 +- .../minted-token-trade_22.spec.ts | 14 +- .../minted-token-trade_23.spec.ts | 14 +- .../minted-token-trade_24.spec.ts | 22 +- .../minted-token-trade_2_b.spec.ts | 4 +- .../minted-token-trade_3.spec.ts | 31 +- .../minted-token-trade_4.spec.ts | 14 +- .../minted-token-trade_5.spec.ts | 17 +- .../minted-token-trade_6.spec.ts | 23 +- .../minted-token-trade_7.spec.ts | 23 +- .../minted-token-trade_8.spec.ts | 52 +- .../minted-token-trade_9.spec.ts | 19 +- .../functions/test-tangle/nft-bid/Helper.ts | 66 +- .../test-tangle/nft-bid/nft-bid.otr_1.spec.ts | 19 +- .../test-tangle/nft-bid/nft-bid.otr_2.spec.ts | 11 +- .../test-tangle/nft-bid/nft-bid.otr_3.spec.ts | 11 +- .../test-tangle/nft-bid/nft-bid.otr_4.spec.ts | 14 +- .../functions/test-tangle/nft-bulk/Helper.ts | 33 +- .../test-tangle/nft-bulk/order.bulk_1.spec.ts | 19 +- .../test-tangle/nft-bulk/order.bulk_2.spec.ts | 27 +- .../test-tangle/nft-bulk/order.bulk_3.spec.ts | 8 +- .../test-tangle/nft-bulk/order.bulk_4.spec.ts | 19 +- .../test-tangle/nft-bulk/order.bulk_5.spec.ts | 26 +- .../test-tangle/nft-bulk/order.bulk_6.spec.ts | 17 +- .../test-tangle/nft-set-for-sale/Helper.ts | 44 +- .../nft-set-for-sale_1.spec.ts | 9 +- .../nft-set-for-sale_2.spec.ts | 9 +- .../nft-set-for-sale_3.spec.ts | 20 +- .../test-tangle/nft-staking/Helper.ts | 94 +- .../nft-staking/nft-staking_1.spec.ts | 18 +- .../nft-staking/nft-staking_10.spec.ts | 17 +- .../nft-staking/nft-staking_2.spec.ts | 31 +- .../nft-staking/nft-staking_2_b.spec.ts | 33 +- .../nft-staking/nft-staking_3.spec.ts | 24 +- .../nft-staking/nft-staking_4.spec.ts | 33 +- .../nft-staking/nft-staking_5.spec.ts | 41 +- .../nft-staking/nft-staking_6.spec.ts | 25 +- .../nft-staking/nft-staking_7.spec.ts | 25 +- .../nft-staking/nft-staking_8.spec.ts | 35 +- .../nft-staking/nft-staking_9.spec.ts | 33 +- .../test-tangle/nft-transfer/Helper.ts | 64 +- .../nft-transfer/nft-transfer_1.spec.ts | 20 +- .../nft-transfer/nft-transfer_2.spec.ts | 10 +- .../nft-transfer/nft-transfer_3.spec.ts | 16 +- .../nft-transfer/nft-transfer_4.spec.ts | 22 +- .../nft-transfer/nft-transfer_5.spec.ts | 26 +- .../nft-transfer/nft-transfer_6.spec.ts | 16 +- .../nft-transfer/nft-transfer_7.spec.ts | 22 +- .../nft-transfer/nft-transfer_8.spec.ts | 24 +- .../test-tangle/proposal-tangle/Helper.ts | 75 +- .../proposal-tangle/proposal.approval.spec.ts | 2 +- .../proposal.simple.vote.spec.ts | 14 +- .../proposal.stake.voting.spec.ts | 22 +- .../proposal.token.voting.spec.ts | 29 +- .../test-tangle/soon.snapshot.only.spec.ts | 585 --- .../test-tangle/space-tangle/Helper.ts | 28 +- .../space-tangle/space.accept.member.spec.ts | 6 +- .../space-tangle/space.block.member.spec.ts | 25 +- .../space-tangle/space.create.spec.ts | 4 +- .../space-tangle/space.decline.member.spec.ts | 15 +- .../space-tangle/space.edit.guardian.spec.ts | 16 +- .../space-tangle/space.join.spec.ts | 13 +- .../space-tangle/space.leave.spec.ts | 14 +- .../functions/test-tangle/staking/Helper.ts | 97 +- .../test-tangle/staking/staking_1.spec.ts | 83 +- .../test-tangle/staking/staking_2.spec.ts | 15 +- .../test-tangle/staking/staking_3.spec.ts | 9 +- .../test-tangle/staking/staking_4.spec.ts | 96 +- .../test-tangle/staking/staking_5.spec.ts | 9 +- .../test-tangle/stamp-tangle/Helper.ts | 9 +- .../stamp-tangle/stamp-tangle_1_a.spec.ts | 29 +- .../stamp-tangle/stamp-tangle_1_b.spec.ts | 28 +- .../stamp-tangle/stamp-tangle_2.spec.ts | 12 +- .../stamp-tangle/stamp-tangle_3.spec.ts | 28 +- .../stamp-tangle/stamp-tangle_4.spec.ts | 8 +- .../stamp-tangle/stamp-tangle_5.spec.ts | 12 +- .../stamp-tangle/stamp-tangle_6.spec.ts | 28 +- packages/functions/test-tangle/swap/Helper.ts | 60 +- .../functions/test-tangle/swap/swap_1.spec.ts | 41 +- .../functions/test-tangle/swap/swap_2.spec.ts | 40 +- .../test-tangle/swap/swap_3_a.spec.ts | 62 +- .../test-tangle/swap/swap_3_b.spec.ts | 62 +- .../functions/test-tangle/swap/swap_4.spec.ts | 24 +- .../functions/test-tangle/swap/swap_5.spec.ts | 32 +- .../functions/test-tangle/swap/swap_6.spec.ts | 58 +- .../functions/test-tangle/swap/swap_7.spec.ts | 50 +- .../functions/test-tangle/swap/swap_8.spec.ts | 54 +- .../tangleRequest/simple.token.trade.spec.ts | 37 +- .../tangleRequest/tangle-request.spec.ts | 57 +- .../test-tangle/token-import/Helper.ts | 51 +- .../token-import/token.import_1.spec.ts | 32 +- .../token-import/token.import_2.spec.ts | 18 +- .../test-tangle/token.based.voting/Helper.ts | 89 +- .../token.based.voting/stake.voting.spec.ts | 62 +- .../token.based.voting_1.spec.ts | 8 +- .../token.based.voting_2.spec.ts | 16 +- .../token.based.voting_3.spec.ts | 19 +- .../token.based.voting_4.spec.ts | 25 +- .../token.based.voting_5.spec.ts | 10 +- .../test-tangle/token.mint/Helper.ts | 30 +- .../token.mint/token.mint_1.spec.ts | 27 +- .../token.mint/token.mint_2.spec.ts | 78 +- .../token.mint/token.mint_3.spec.ts | 89 +- .../token.mint/token.mint_4.spec.ts | 52 +- .../trade-base-token-order.spec.ts | 69 +- .../functions/test-tangle/tran.match.spec.ts | 8 +- .../transaction-trigger_1.spec.ts | 6 +- .../transaction-trigger_10.spec.ts | 10 +- .../transaction-trigger_11.spec.ts | 6 +- .../transaction-trigger_12.spec.ts | 10 +- .../transaction-trigger_13.spec.ts | 30 +- .../transaction-trigger_14.spec.ts | 14 +- .../transaction-trigger_15.spec.ts | 4 +- .../transaction-trigger_2.spec.ts | 4 +- .../transaction-trigger_3.spec.ts | 6 +- .../transaction-trigger_4.spec.ts | 10 +- .../transaction-trigger_5.spec.ts | 16 +- .../transaction-trigger_6.spec.ts | 8 +- .../transaction-trigger_7.spec.ts | 8 +- .../transaction-trigger_8.spec.ts | 8 +- .../transaction-trigger_9.spec.ts | 26 +- .../functions/test-tangle/web3/web3_1.spec.ts | 83 +- .../functions/test-tangle/web3/web3_2.spec.ts | 27 +- .../functions/test-tangle/web3/web3_3.spec.ts | 49 +- .../withdraw-deposit-nft/Helper.ts | 184 +- .../deposit-withraw-nft_10_1.spec.ts | 17 +- .../deposit-withraw-nft_10_2.spec.ts | 17 +- .../deposit-withraw-nft_10_3.spec.ts | 17 +- .../deposit-withraw-nft_11.spec.ts | 56 +- .../deposit-withraw-nft_12_a.spec.ts | 23 +- .../deposit-withraw-nft_12_b.spec.ts | 17 +- .../deposit-withraw-nft_13.spec.ts | 17 +- .../deposit-withraw-nft_14.spec.ts | 40 +- .../deposit-withraw-nft_15.spec.ts | 17 +- .../deposit-withraw-nft_16.spec.ts | 17 +- .../deposit-withraw-nft_1_a.spec.ts | 37 +- .../deposit-withraw-nft_1_b.spec.ts | 39 +- .../deposit-withraw-nft_1_c.spec.ts | 39 +- .../deposit-withraw-nft_2.spec.ts | 21 +- .../deposit-withraw-nft_4.spec.ts | 29 +- .../deposit-withraw-nft_4_b.spec.ts | 26 +- .../deposit-withraw-nft_5.spec.ts | 35 +- .../deposit-withraw-nft_6.spec.ts | 52 +- .../deposit-withraw-nft_7.spec.ts | 31 +- .../deposit-withraw-nft_8.spec.ts | 31 +- .../deposit-withraw-nft_9.spec.ts | 33 +- .../test-tangle/workflow-online.spec.ts | 25 - packages/functions/test/auth.spec.ts | 94 +- .../functions/test/auth/legacy.auth.spec.ts | 53 +- .../functions/test/controls/address.spec.ts | 124 +- .../functions/test/controls/auction/Helper.ts | 44 +- .../test/controls/auction/auction.bid.spec.ts | 66 +- .../test/controls/collection.spec.ts | 546 ++- packages/functions/test/controls/common.ts | 318 +- .../functions/test/controls/member.spec.ts | 160 +- packages/functions/test/controls/nft.spec.ts | 124 +- .../functions/test/controls/nft/Helper.ts | 56 +- .../controls/nft/nft.bidding.extends.spec.ts | 54 +- .../controls/nft/nft.bidding.finalize.spec.ts | 75 +- .../test/controls/nft/nft.bidding.spec.ts | 107 +- .../controls/nft/nft.set.for.sale.spec.ts | 61 +- .../functions/test/controls/order.spec.ts | 112 +- .../controls/project/project.create.spec.ts | 137 +- .../project/project.deactivate.spec.ts | 50 +- .../functions/test/controls/proposal.spec.ts | 252 +- .../functions/test/controls/space.spec.ts | 679 ++-- .../test/controls/stake.reward.spec.ts | 62 +- .../test/controls/stamp.control.spec.ts | 29 +- .../token-distribution-auto-trigger.spec.ts | 68 +- .../test/controls/token-distribution.spec.ts | 101 +- .../test/controls/token-trade.buy.spec.ts | 79 +- .../test/controls/token-trade.sell.spec.ts | 171 +- .../test/controls/token-trade.trigger.spec.ts | 488 +-- .../controls/token.expired.sale.cron.spec.ts | 41 +- .../test/controls/token.order.spec.ts | 306 +- .../token/token.airdrop.claim.spec.ts | 148 +- .../test/controls/token/token.airdrop.spec.ts | 118 +- .../token/token.cancel.pub.sale.spec.ts | 153 +- .../test/controls/token/token.create.spec.ts | 263 +- .../token/token.order.and.claim.air.spec.ts | 93 +- .../test/controls/token/token.rank.spec.ts | 64 +- .../controls/token/token.set.to.sale.spec.ts | 114 +- .../test/controls/token/token.update.spec.ts | 120 +- .../test/controls/token/token.vote.spec.ts | 62 +- .../test/controls/workflow-online.spec.ts | 22 - .../functions/test/controls/workflow.spec.ts | 1 - .../test/cron/floor-price.cron.only.spec.ts | 19 +- .../test/cron/nft-stake.cron.spec.ts | 16 +- .../functions/test/cron/proposal.cron.spec.ts | 13 +- packages/functions/test/notifier.ts | 160 + packages/functions/test/set-up.ts | 264 +- .../test/stake/delete.stake.reward.spec.ts | 81 +- .../test/stake/stake.reward.cron.spec.ts | 9 +- .../functions/test/storage/resize.img.spec.ts | 32 +- packages/functions/test/teardown.ts | 41 +- packages/functions/workflow.build.js | 145 +- packages/interfaces/src/models/award.ts | 4 + packages/interfaces/src/models/base.ts | 1 + packages/interfaces/src/models/collection.ts | 4 + packages/interfaces/src/models/index.ts | 2 +- packages/interfaces/src/models/member.ts | 4 +- packages/interfaces/src/models/milestone.ts | 9 + packages/interfaces/src/models/mnemonic.ts | 4 +- packages/interfaces/src/models/nft.ts | 4 + packages/interfaces/src/models/project.ts | 3 +- packages/interfaces/src/models/proposal.ts | 9 +- packages/interfaces/src/models/space.ts | 12 + packages/interfaces/src/models/stamp.ts | 4 + .../interfaces/src/models/system.config.ts | 4 +- packages/interfaces/src/models/token.ts | 9 + .../src/models/transaction/payload.ts | 7 +- packages/interfaces/src/search/post/index.ts | 16 +- .../interfaces/src/search/tangle/index.ts | 3 +- packages/notifier/.gitignore | 2 + packages/notifier/.prettierignore | 2 + packages/notifier/package.json | 22 + packages/notifier/src/index.ts | 86 + packages/notifier/tsconfig.json | 16 + packages/sdk/examples/nft/otr/purchase.ts | 2 +- packages/sdk/src/https/datasets/common.ts | 4 +- packages/sdk/src/https/utils.ts | 2 +- packages/sdk/test/otr/otr.spec.ts | 2 +- packages/search/src/common.ts | 32 +- packages/search/src/getAddresses.ts | 10 +- packages/search/src/getAvgPrice.ts | 33 +- packages/search/src/getById.ts | 17 +- packages/search/src/getMany.ts | 36 +- packages/search/src/getManyAdvanced.ts | 51 +- packages/search/src/getManyById.ts | 30 +- packages/search/src/getPriceChange.ts | 61 +- packages/search/src/getTokenPrice.ts | 25 +- packages/search/src/getUpdatedAfter.ts | 32 +- 745 files changed, 21852 insertions(+), 19454 deletions(-) delete mode 100644 .github/workflows/functions_online-emulated-tests.yml delete mode 100644 .github/workflows/functions_tangle-online-unit-tests_emulator.yml delete mode 100644 data.proto delete mode 100644 firestore.rules create mode 100644 packages/database/.env create mode 100644 packages/database/generators/generator.ts create mode 100644 packages/database/generators/pg.interface.generator.ts create mode 100644 packages/database/knexfile.ts create mode 100644 packages/database/migrations/20240129091246_common.ts create mode 100644 packages/database/migrations/20240129135000_auction.ts create mode 100644 packages/database/migrations/20240129135000_award.ts create mode 100644 packages/database/migrations/20240129135000_change.ts create mode 100644 packages/database/migrations/20240129135000_collection.ts create mode 100644 packages/database/migrations/20240129135000_member.ts create mode 100644 packages/database/migrations/20240129135000_milestone.ts create mode 100644 packages/database/migrations/20240129135000_mnemonic.ts create mode 100644 packages/database/migrations/20240129135000_nft.ts create mode 100644 packages/database/migrations/20240129135000_nft_stake.ts create mode 100644 packages/database/migrations/20240129135000_notification.ts create mode 100644 packages/database/migrations/20240129135000_project.ts create mode 100644 packages/database/migrations/20240129135000_proposal.ts create mode 100644 packages/database/migrations/20240129135000_soon_snap.ts create mode 100644 packages/database/migrations/20240129135000_space.ts create mode 100644 packages/database/migrations/20240129135000_stake.ts create mode 100644 packages/database/migrations/20240129135000_stake_reward.ts create mode 100644 packages/database/migrations/20240129135000_stamp.ts create mode 100644 packages/database/migrations/20240129135000_swap.ts create mode 100644 packages/database/migrations/20240129135000_system.ts create mode 100644 packages/database/migrations/20240129135000_ticker.ts create mode 100644 packages/database/migrations/20240129135000_token.ts create mode 100644 packages/database/migrations/20240129135000_token_market.ts create mode 100644 packages/database/migrations/20240129135000_token_purchase.ts create mode 100644 packages/database/migrations/20240129135000_transaction.ts delete mode 100644 packages/database/src/app/app.ts delete mode 100644 packages/database/src/app/build5App.ts delete mode 100644 packages/database/src/app/index.ts delete mode 100644 packages/database/src/app/interface.ts delete mode 100644 packages/database/src/firestore/build5Db.ts delete mode 100644 packages/database/src/firestore/common.ts delete mode 100644 packages/database/src/firestore/firestore.ts delete mode 100644 packages/database/src/firestore/index.ts delete mode 100644 packages/database/src/firestore/interfaces.ts create mode 100644 packages/database/src/pg/impl/common.ts create mode 100644 packages/database/src/pg/impl/instance.ts create mode 100644 packages/database/src/pg/impl/knex.ts create mode 100644 packages/database/src/pg/impl/postgres.ts create mode 100644 packages/database/src/pg/impl/pubsub.ts create mode 100644 packages/database/src/pg/impl/tables/airdrop.ts create mode 100644 packages/database/src/pg/impl/tables/auction.ts create mode 100644 packages/database/src/pg/impl/tables/award.ts create mode 100644 packages/database/src/pg/impl/tables/award_owner.ts create mode 100644 packages/database/src/pg/impl/tables/award_participant.ts create mode 100644 packages/database/src/pg/impl/tables/collection.ts create mode 100644 packages/database/src/pg/impl/tables/collection_rank.ts create mode 100644 packages/database/src/pg/impl/tables/collection_stats.ts create mode 100644 packages/database/src/pg/impl/tables/collection_vote.ts create mode 100644 packages/database/src/pg/impl/tables/member.ts create mode 100644 packages/database/src/pg/impl/tables/milestone.ts create mode 100644 packages/database/src/pg/impl/tables/milestone_transactions.ts create mode 100644 packages/database/src/pg/impl/tables/mnemonic.ts create mode 100644 packages/database/src/pg/impl/tables/nft.ts create mode 100644 packages/database/src/pg/impl/tables/nft_stake.ts create mode 100644 packages/database/src/pg/impl/tables/notification.ts create mode 100644 packages/database/src/pg/impl/tables/project.ts create mode 100644 packages/database/src/pg/impl/tables/project_admin.ts create mode 100644 packages/database/src/pg/impl/tables/project_api_key.ts create mode 100644 packages/database/src/pg/impl/tables/proposal.ts create mode 100644 packages/database/src/pg/impl/tables/proposal_member.ts create mode 100644 packages/database/src/pg/impl/tables/proposal_owner.ts create mode 100644 packages/database/src/pg/impl/tables/soon_snapshot.ts create mode 100644 packages/database/src/pg/impl/tables/space.ts create mode 100644 packages/database/src/pg/impl/tables/space_guardians.ts create mode 100644 packages/database/src/pg/impl/tables/space_member.ts create mode 100644 packages/database/src/pg/impl/tables/stake.ts create mode 100644 packages/database/src/pg/impl/tables/stake_reward.ts create mode 100644 packages/database/src/pg/impl/tables/stamp.ts create mode 100644 packages/database/src/pg/impl/tables/swap.ts create mode 100644 packages/database/src/pg/impl/tables/system.ts create mode 100644 packages/database/src/pg/impl/tables/ticker.ts create mode 100644 packages/database/src/pg/impl/tables/token.ts create mode 100644 packages/database/src/pg/impl/tables/token_distribution.ts create mode 100644 packages/database/src/pg/impl/tables/token_market.ts create mode 100644 packages/database/src/pg/impl/tables/token_purchase.ts create mode 100644 packages/database/src/pg/impl/tables/token_rank.ts create mode 100644 packages/database/src/pg/impl/tables/token_stats.ts create mode 100644 packages/database/src/pg/impl/tables/token_vote.ts create mode 100644 packages/database/src/pg/impl/tables/transaction.ts create mode 100644 packages/database/src/pg/index.ts create mode 100644 packages/database/src/pg/interfaces.ts create mode 100644 packages/database/src/pg/models/airdrop.ts create mode 100644 packages/database/src/pg/models/airdrop_update.ts create mode 100644 packages/database/src/pg/models/auction.ts create mode 100644 packages/database/src/pg/models/auction_update.ts create mode 100644 packages/database/src/pg/models/award.ts create mode 100644 packages/database/src/pg/models/award_update.ts create mode 100644 packages/database/src/pg/models/changes.ts create mode 100644 packages/database/src/pg/models/changes_update.ts create mode 100644 packages/database/src/pg/models/collection.ts create mode 100644 packages/database/src/pg/models/collection_update.ts create mode 100644 packages/database/src/pg/models/common.ts create mode 100644 packages/database/src/pg/models/common_update.ts create mode 100644 packages/database/src/pg/models/enums.ts create mode 100644 packages/database/src/pg/models/index.ts create mode 100644 packages/database/src/pg/models/member.ts create mode 100644 packages/database/src/pg/models/member_update.ts create mode 100644 packages/database/src/pg/models/milestone.ts create mode 100644 packages/database/src/pg/models/milestone_update.ts create mode 100644 packages/database/src/pg/models/mnemonic.ts create mode 100644 packages/database/src/pg/models/mnemonic_update.ts create mode 100644 packages/database/src/pg/models/nft.ts create mode 100644 packages/database/src/pg/models/nft_update.ts create mode 100644 packages/database/src/pg/models/notification.ts create mode 100644 packages/database/src/pg/models/notification_update.ts create mode 100644 packages/database/src/pg/models/project.ts create mode 100644 packages/database/src/pg/models/project_update.ts create mode 100644 packages/database/src/pg/models/proposal.ts create mode 100644 packages/database/src/pg/models/proposal_update.ts create mode 100644 packages/database/src/pg/models/soon.ts create mode 100644 packages/database/src/pg/models/soon_update.ts create mode 100644 packages/database/src/pg/models/space.ts create mode 100644 packages/database/src/pg/models/space_update.ts create mode 100644 packages/database/src/pg/models/stake.ts create mode 100644 packages/database/src/pg/models/stake_update.ts create mode 100644 packages/database/src/pg/models/stamp.ts create mode 100644 packages/database/src/pg/models/stamp_update.ts create mode 100644 packages/database/src/pg/models/swap.ts create mode 100644 packages/database/src/pg/models/swap_update.ts create mode 100644 packages/database/src/pg/models/system.ts create mode 100644 packages/database/src/pg/models/system_update.ts create mode 100644 packages/database/src/pg/models/ticker.ts create mode 100644 packages/database/src/pg/models/ticker_update.ts create mode 100644 packages/database/src/pg/models/token.ts create mode 100644 packages/database/src/pg/models/token_update.ts create mode 100644 packages/database/src/pg/models/transaction.ts create mode 100644 packages/database/src/pg/models/transaction_update.ts delete mode 100644 packages/functions/.env.dev delete mode 100644 packages/functions/.env.local delete mode 100644 packages/functions/.runtimeconfig.json create mode 100644 packages/functions/jest-setup.ts create mode 100644 packages/functions/migration/index.ts create mode 100644 packages/functions/migration/pg.migration.ts create mode 100644 packages/functions/migration/pubsub.migration.ts delete mode 100644 packages/functions/scripts/dbUpgrades/2.1/soon.snapshot.ts rename packages/functions/{test-service-account-key.json => service-account-key.json} (100%) delete mode 100644 packages/functions/src/index.express.ts delete mode 100644 packages/functions/src/runtime/firebase/address/index.ts delete mode 100644 packages/functions/src/runtime/firebase/auction/index.ts delete mode 100644 packages/functions/src/runtime/firebase/auth/index.ts delete mode 100644 packages/functions/src/runtime/firebase/award/index.ts delete mode 100644 packages/functions/src/runtime/firebase/collection/index.ts delete mode 100644 packages/functions/src/runtime/firebase/credit/index.ts delete mode 100644 packages/functions/src/runtime/firebase/member/index.ts delete mode 100644 packages/functions/src/runtime/firebase/nft/index.ts delete mode 100644 packages/functions/src/runtime/firebase/project/index.ts delete mode 100644 packages/functions/src/runtime/firebase/proposal/index.ts delete mode 100644 packages/functions/src/runtime/firebase/rank/index.ts delete mode 100644 packages/functions/src/runtime/firebase/space/index.ts delete mode 100644 packages/functions/src/runtime/firebase/stake/index.ts delete mode 100644 packages/functions/src/runtime/firebase/stamp/index.ts delete mode 100644 packages/functions/src/runtime/firebase/storage/file.upload.ts delete mode 100644 packages/functions/src/runtime/firebase/swap/index.ts delete mode 100644 packages/functions/src/runtime/firebase/token/base/index.ts delete mode 100644 packages/functions/src/runtime/firebase/token/minting/index.ts delete mode 100644 packages/functions/src/runtime/firebase/token/trading/index.ts delete mode 100644 packages/functions/src/runtime/firebase/vote/index.ts delete mode 100644 packages/functions/src/runtime/proto/protoToJson.ts delete mode 100644 packages/functions/src/triggers/algolia/firestore.to.algolia.ts create mode 100644 packages/functions/src/utils/milestone.ts delete mode 100644 packages/functions/test-tangle/soon.snapshot.only.spec.ts delete mode 100644 packages/functions/test-tangle/workflow-online.spec.ts delete mode 100644 packages/functions/test/controls/workflow-online.spec.ts create mode 100644 packages/functions/test/notifier.ts create mode 100644 packages/notifier/.gitignore create mode 100644 packages/notifier/.prettierignore create mode 100644 packages/notifier/package.json create mode 100644 packages/notifier/src/index.ts create mode 100644 packages/notifier/tsconfig.json diff --git a/.github/workflows/functions_emulated-tests.yml b/.github/workflows/functions_emulated-tests.yml index 979f17873b..ab68bc31bf 100644 --- a/.github/workflows/functions_emulated-tests.yml +++ b/.github/workflows/functions_emulated-tests.yml @@ -4,6 +4,7 @@ on: pull_request: paths: - packages/functions/** + - packages/database/** jobs: npm-install: @@ -30,6 +31,21 @@ jobs: needs: npm-install runs-on: ubuntu-latest timeout-minutes: 20 + + services: + postgres: + image: postgres + env: + POSTGRES_DB: build5db + POSTGRES_PASSWORD: postgres + ports: + - 5432:5432 + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 @@ -43,34 +59,38 @@ jobs: packages/interfaces/node_modules key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - name: Init - run: | - npm run build:functions - npm install -g firebase-tools + run: npm run build:functions - name: Test working-directory: packages/functions run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test:ci -- --forceExit --findRelatedTests ./test/auth.spec.ts && - npm run test:ci -- --forceExit --findRelatedTests ./test/auth/legacy.auth.spec.ts && - npm run test:ci -- --forceExit --findRelatedTests ./test/controls/address.spec.ts && - npm run test:ci -- --forceExit --findRelatedTests ./test/controls/auction/auction.bid.spec.ts && - npm run test:ci -- --forceExit --findRelatedTests ./test/controls/collection.spec.ts && - npm run test:ci -- --forceExit --findRelatedTests ./test/controls/member.spec.ts && - npm run test:ci -- --forceExit --findRelatedTests ./test/controls/nft.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-chunk_0 - path: ./packages/functions/firestore-data/ - retention-days: 1 + npm run start & + npm run notifier & + npm run test -- --findRelatedTests --forceExit ./test/auth.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test/auth/legacy.auth.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test/controls/address.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test/controls/auction/auction.bid.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test/controls/collection.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test/controls/member.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test/controls/nft.spec.ts chunk_1: needs: npm-install runs-on: ubuntu-latest timeout-minutes: 20 + + services: + postgres: + image: postgres + env: + POSTGRES_DB: build5db + POSTGRES_PASSWORD: postgres + ports: + - 5432:5432 + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 @@ -84,34 +104,38 @@ jobs: packages/interfaces/node_modules key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - name: Init - run: | - npm run build:functions - npm install -g firebase-tools + run: npm run build:functions - name: Test working-directory: packages/functions run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test:ci -- --forceExit --findRelatedTests ./test/controls/nft/nft.bidding.extends.spec.ts && - npm run test:ci -- --forceExit --findRelatedTests ./test/controls/nft/nft.bidding.finalize.spec.ts && - npm run test:ci -- --forceExit --findRelatedTests ./test/controls/nft/nft.bidding.spec.ts && - npm run test:ci -- --forceExit --findRelatedTests ./test/controls/nft/nft.set.for.sale.spec.ts && - npm run test:ci -- --forceExit --findRelatedTests ./test/controls/order.spec.ts && - npm run test:ci -- --forceExit --findRelatedTests ./test/controls/project/project.create.spec.ts && - npm run test:ci -- --forceExit --findRelatedTests ./test/controls/project/project.deactivate.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-chunk_1 - path: ./packages/functions/firestore-data/ - retention-days: 1 + npm run start & + npm run notifier & + npm run test -- --findRelatedTests --forceExit ./test/controls/nft/nft.bidding.extends.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test/controls/nft/nft.bidding.finalize.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test/controls/nft/nft.bidding.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test/controls/nft/nft.set.for.sale.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test/controls/order.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test/controls/project/project.create.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test/controls/project/project.deactivate.spec.ts chunk_2: needs: npm-install runs-on: ubuntu-latest timeout-minutes: 20 + + services: + postgres: + image: postgres + env: + POSTGRES_DB: build5db + POSTGRES_PASSWORD: postgres + ports: + - 5432:5432 + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 @@ -125,34 +149,38 @@ jobs: packages/interfaces/node_modules key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - name: Init - run: | - npm run build:functions - npm install -g firebase-tools + run: npm run build:functions - name: Test working-directory: packages/functions run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test:ci -- --forceExit --findRelatedTests ./test/controls/proposal.spec.ts && - npm run test:ci -- --forceExit --findRelatedTests ./test/controls/space.spec.ts && - npm run test:ci -- --forceExit --findRelatedTests ./test/controls/stake.reward.spec.ts && - npm run test:ci -- --forceExit --findRelatedTests ./test/controls/stamp.control.spec.ts && - npm run test:ci -- --forceExit --findRelatedTests ./test/controls/token-distribution-auto-trigger.spec.ts && - npm run test:ci -- --forceExit --findRelatedTests ./test/controls/token-distribution.spec.ts && - npm run test:ci -- --forceExit --findRelatedTests ./test/controls/token-trade.buy.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-chunk_2 - path: ./packages/functions/firestore-data/ - retention-days: 1 + npm run start & + npm run notifier & + npm run test -- --findRelatedTests --forceExit ./test/controls/proposal.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test/controls/space.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test/controls/stake.reward.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test/controls/stamp.control.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test/controls/token-distribution-auto-trigger.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test/controls/token-distribution.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test/controls/token-trade.buy.spec.ts chunk_3: needs: npm-install runs-on: ubuntu-latest timeout-minutes: 20 + + services: + postgres: + image: postgres + env: + POSTGRES_DB: build5db + POSTGRES_PASSWORD: postgres + ports: + - 5432:5432 + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 @@ -166,34 +194,38 @@ jobs: packages/interfaces/node_modules key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - name: Init - run: | - npm run build:functions - npm install -g firebase-tools + run: npm run build:functions - name: Test working-directory: packages/functions run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test:ci -- --forceExit --findRelatedTests ./test/controls/token-trade.sell.spec.ts && - npm run test:ci -- --forceExit --findRelatedTests ./test/controls/token-trade.trigger.spec.ts && - npm run test:ci -- --forceExit --findRelatedTests ./test/controls/token.expired.sale.cron.spec.ts && - npm run test:ci -- --forceExit --findRelatedTests ./test/controls/token.order.spec.ts && - npm run test:ci -- --forceExit --findRelatedTests ./test/controls/token/token.airdrop.claim.spec.ts && - npm run test:ci -- --forceExit --findRelatedTests ./test/controls/token/token.airdrop.spec.ts && - npm run test:ci -- --forceExit --findRelatedTests ./test/controls/token/token.cancel.pub.sale.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-chunk_3 - path: ./packages/functions/firestore-data/ - retention-days: 1 + npm run start & + npm run notifier & + npm run test -- --findRelatedTests --forceExit ./test/controls/token-trade.sell.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test/controls/token-trade.trigger.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test/controls/token.expired.sale.cron.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test/controls/token.order.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test/controls/token/token.airdrop.claim.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test/controls/token/token.airdrop.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test/controls/token/token.cancel.pub.sale.spec.ts chunk_4: needs: npm-install runs-on: ubuntu-latest timeout-minutes: 20 + + services: + postgres: + image: postgres + env: + POSTGRES_DB: build5db + POSTGRES_PASSWORD: postgres + ports: + - 5432:5432 + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 @@ -207,34 +239,38 @@ jobs: packages/interfaces/node_modules key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - name: Init - run: | - npm run build:functions - npm install -g firebase-tools + run: npm run build:functions - name: Test working-directory: packages/functions run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test:ci -- --forceExit --findRelatedTests ./test/controls/token/token.create.spec.ts && - npm run test:ci -- --forceExit --findRelatedTests ./test/controls/token/token.order.and.claim.air.spec.ts && - npm run test:ci -- --forceExit --findRelatedTests ./test/controls/token/token.rank.spec.ts && - npm run test:ci -- --forceExit --findRelatedTests ./test/controls/token/token.set.to.sale.spec.ts && - npm run test:ci -- --forceExit --findRelatedTests ./test/controls/token/token.update.spec.ts && - npm run test:ci -- --forceExit --findRelatedTests ./test/controls/token/token.vote.spec.ts && - npm run test:ci -- --forceExit --findRelatedTests ./test/controls/workflow-online.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-chunk_4 - path: ./packages/functions/firestore-data/ - retention-days: 1 + npm run start & + npm run notifier & + npm run test -- --findRelatedTests --forceExit ./test/controls/token/token.create.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test/controls/token/token.order.and.claim.air.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test/controls/token/token.rank.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test/controls/token/token.set.to.sale.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test/controls/token/token.update.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test/controls/token/token.vote.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test/controls/workflow.spec.ts chunk_5: needs: npm-install runs-on: ubuntu-latest timeout-minutes: 20 + + services: + postgres: + image: postgres + env: + POSTGRES_DB: build5db + POSTGRES_PASSWORD: postgres + ports: + - 5432:5432 + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 @@ -248,34 +284,38 @@ jobs: packages/interfaces/node_modules key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - name: Init - run: | - npm run build:functions - npm install -g firebase-tools + run: npm run build:functions - name: Test working-directory: packages/functions run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test:ci -- --forceExit --findRelatedTests ./test/controls/workflow.spec.ts && - npm run test:ci -- --forceExit --findRelatedTests ./test/cron/floor-price.cron.only.spec.ts && - npm run test:ci -- --forceExit --findRelatedTests ./test/cron/nft-stake.cron.spec.ts && - npm run test:ci -- --forceExit --findRelatedTests ./test/cron/proposal.cron.spec.ts && - npm run test:ci -- --forceExit --findRelatedTests ./test/db.roll.spec.ts && - npm run test:ci -- --forceExit --findRelatedTests ./test/func.name.spec.ts && - npm run test:ci -- --forceExit --findRelatedTests ./test/naming.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-chunk_5 - path: ./packages/functions/firestore-data/ - retention-days: 1 + npm run start & + npm run notifier & + npm run test -- --findRelatedTests --forceExit ./test/cron/floor-price.cron.only.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test/cron/nft-stake.cron.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test/cron/proposal.cron.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test/db.roll.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test/func.name.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test/naming.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test/stake/delete.stake.reward.spec.ts chunk_6: needs: npm-install runs-on: ubuntu-latest timeout-minutes: 20 + + services: + postgres: + image: postgres + env: + POSTGRES_DB: build5db + POSTGRES_PASSWORD: postgres + ports: + - 5432:5432 + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 @@ -289,23 +329,11 @@ jobs: packages/interfaces/node_modules key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - name: Init - run: | - npm run build:functions - npm install -g firebase-tools + run: npm run build:functions - name: Test working-directory: packages/functions run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test:ci -- --forceExit --findRelatedTests ./test/stake/delete.stake.reward.spec.ts && - npm run test:ci -- --forceExit --findRelatedTests ./test/stake/stake.reward.cron.spec.ts && - npm run test:ci -- --forceExit --findRelatedTests ./test/storage/resize.img.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-chunk_6 - path: ./packages/functions/firestore-data/ - retention-days: 1 + npm run start & + npm run notifier & + npm run test -- --findRelatedTests --forceExit ./test/stake/stake.reward.cron.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test/storage/resize.img.spec.ts diff --git a/.github/workflows/functions_online-emulated-tests.yml b/.github/workflows/functions_online-emulated-tests.yml deleted file mode 100644 index 17f6aaa17a..0000000000 --- a/.github/workflows/functions_online-emulated-tests.yml +++ /dev/null @@ -1,312 +0,0 @@ -name: Functions | Online Emulated Unit Tests - -on: - workflow_run: - workflows: ["Firebase Deploy DEV"] - types: [completed] - branches: - - "develop" - -jobs: - npm-install: - runs-on: ubuntu-latest - timeout-minutes: 10 - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version: 20.x - - uses: actions/cache@v4 - id: cache - with: - path: | - node_modules - packages/functions/node_modules - packages/interfaces/node_modules - key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - - name: Install Dependencies - if: steps.cache.outputs.cache-hit != 'true' - run: npm run build:functions - - chunk_0: - needs: npm-install - runs-on: ubuntu-latest - timeout-minutes: 20 - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version: 20.x - - uses: actions/cache@v4 - with: - path: | - node_modules - packages/functions/node_modules - packages/interfaces/node_modules - key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - - name: Init - run: | - npm run build:functions - npm install -g firebase-tools - - name: Test - working-directory: packages/functions - run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-online:ci -- --forceExit --findRelatedTests ./test/auth.spec.ts && - npm run test-online:ci -- --forceExit --findRelatedTests ./test/auth/legacy.auth.spec.ts && - npm run test-online:ci -- --forceExit --findRelatedTests ./test/controls/address.spec.ts && - npm run test-online:ci -- --forceExit --findRelatedTests ./test/controls/auction/auction.bid.spec.ts && - npm run test-online:ci -- --forceExit --findRelatedTests ./test/controls/collection.spec.ts && - npm run test-online:ci -- --forceExit --findRelatedTests ./test/controls/member.spec.ts && - npm run test-online:ci -- --forceExit --findRelatedTests ./test/controls/nft.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-online-chunk_0 - path: ./packages/functions/firestore-data/ - retention-days: 1 - chunk_1: - needs: npm-install - runs-on: ubuntu-latest - timeout-minutes: 20 - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version: 20.x - - uses: actions/cache@v4 - with: - path: | - node_modules - packages/functions/node_modules - packages/interfaces/node_modules - key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - - name: Init - run: | - npm run build:functions - npm install -g firebase-tools - - name: Test - working-directory: packages/functions - run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-online:ci -- --forceExit --findRelatedTests ./test/controls/nft/nft.bidding.extends.spec.ts && - npm run test-online:ci -- --forceExit --findRelatedTests ./test/controls/nft/nft.bidding.finalize.spec.ts && - npm run test-online:ci -- --forceExit --findRelatedTests ./test/controls/nft/nft.bidding.spec.ts && - npm run test-online:ci -- --forceExit --findRelatedTests ./test/controls/nft/nft.set.for.sale.spec.ts && - npm run test-online:ci -- --forceExit --findRelatedTests ./test/controls/order.spec.ts && - npm run test-online:ci -- --forceExit --findRelatedTests ./test/controls/project/project.create.spec.ts && - npm run test-online:ci -- --forceExit --findRelatedTests ./test/controls/project/project.deactivate.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-online-chunk_1 - path: ./packages/functions/firestore-data/ - retention-days: 1 - chunk_2: - needs: npm-install - runs-on: ubuntu-latest - timeout-minutes: 20 - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version: 20.x - - uses: actions/cache@v4 - with: - path: | - node_modules - packages/functions/node_modules - packages/interfaces/node_modules - key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - - name: Init - run: | - npm run build:functions - npm install -g firebase-tools - - name: Test - working-directory: packages/functions - run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-online:ci -- --forceExit --findRelatedTests ./test/controls/proposal.spec.ts && - npm run test-online:ci -- --forceExit --findRelatedTests ./test/controls/space.spec.ts && - npm run test-online:ci -- --forceExit --findRelatedTests ./test/controls/stake.reward.spec.ts && - npm run test-online:ci -- --forceExit --findRelatedTests ./test/controls/stamp.control.spec.ts && - npm run test-online:ci -- --forceExit --findRelatedTests ./test/controls/token-distribution-auto-trigger.spec.ts && - npm run test-online:ci -- --forceExit --findRelatedTests ./test/controls/token-distribution.spec.ts && - npm run test-online:ci -- --forceExit --findRelatedTests ./test/controls/token-trade.buy.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-online-chunk_2 - path: ./packages/functions/firestore-data/ - retention-days: 1 - chunk_3: - needs: npm-install - runs-on: ubuntu-latest - timeout-minutes: 20 - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version: 20.x - - uses: actions/cache@v4 - with: - path: | - node_modules - packages/functions/node_modules - packages/interfaces/node_modules - key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - - name: Init - run: | - npm run build:functions - npm install -g firebase-tools - - name: Test - working-directory: packages/functions - run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-online:ci -- --forceExit --findRelatedTests ./test/controls/token-trade.sell.spec.ts && - npm run test-online:ci -- --forceExit --findRelatedTests ./test/controls/token-trade.trigger.spec.ts && - npm run test-online:ci -- --forceExit --findRelatedTests ./test/controls/token.expired.sale.cron.spec.ts && - npm run test-online:ci -- --forceExit --findRelatedTests ./test/controls/token.order.spec.ts && - npm run test-online:ci -- --forceExit --findRelatedTests ./test/controls/token/token.airdrop.claim.spec.ts && - npm run test-online:ci -- --forceExit --findRelatedTests ./test/controls/token/token.airdrop.spec.ts && - npm run test-online:ci -- --forceExit --findRelatedTests ./test/controls/token/token.cancel.pub.sale.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-online-chunk_3 - path: ./packages/functions/firestore-data/ - retention-days: 1 - chunk_4: - needs: npm-install - runs-on: ubuntu-latest - timeout-minutes: 20 - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version: 20.x - - uses: actions/cache@v4 - with: - path: | - node_modules - packages/functions/node_modules - packages/interfaces/node_modules - key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - - name: Init - run: | - npm run build:functions - npm install -g firebase-tools - - name: Test - working-directory: packages/functions - run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-online:ci -- --forceExit --findRelatedTests ./test/controls/token/token.create.spec.ts && - npm run test-online:ci -- --forceExit --findRelatedTests ./test/controls/token/token.order.and.claim.air.spec.ts && - npm run test-online:ci -- --forceExit --findRelatedTests ./test/controls/token/token.rank.spec.ts && - npm run test-online:ci -- --forceExit --findRelatedTests ./test/controls/token/token.set.to.sale.spec.ts && - npm run test-online:ci -- --forceExit --findRelatedTests ./test/controls/token/token.update.spec.ts && - npm run test-online:ci -- --forceExit --findRelatedTests ./test/controls/token/token.vote.spec.ts && - npm run test-online:ci -- --forceExit --findRelatedTests ./test/controls/workflow-online.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-online-chunk_4 - path: ./packages/functions/firestore-data/ - retention-days: 1 - chunk_5: - needs: npm-install - runs-on: ubuntu-latest - timeout-minutes: 20 - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version: 20.x - - uses: actions/cache@v4 - with: - path: | - node_modules - packages/functions/node_modules - packages/interfaces/node_modules - key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - - name: Init - run: | - npm run build:functions - npm install -g firebase-tools - - name: Test - working-directory: packages/functions - run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-online:ci -- --forceExit --findRelatedTests ./test/controls/workflow.spec.ts && - npm run test-online:ci -- --forceExit --findRelatedTests ./test/cron/nft-stake.cron.spec.ts && - npm run test-online:ci -- --forceExit --findRelatedTests ./test/cron/proposal.cron.spec.ts && - npm run test-online:ci -- --forceExit --findRelatedTests ./test/db.roll.spec.ts && - npm run test-online:ci -- --forceExit --findRelatedTests ./test/func.name.spec.ts && - npm run test-online:ci -- --forceExit --findRelatedTests ./test/naming.spec.ts && - npm run test-online:ci -- --forceExit --findRelatedTests ./test/stake/delete.stake.reward.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-online-chunk_5 - path: ./packages/functions/firestore-data/ - retention-days: 1 - chunk_6: - needs: npm-install - runs-on: ubuntu-latest - timeout-minutes: 20 - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version: 20.x - - uses: actions/cache@v4 - with: - path: | - node_modules - packages/functions/node_modules - packages/interfaces/node_modules - key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - - name: Init - run: | - npm run build:functions - npm install -g firebase-tools - - name: Test - working-directory: packages/functions - run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-online:ci -- --forceExit --findRelatedTests ./test/stake/stake.reward.cron.spec.ts && - npm run test-online:ci -- --forceExit --findRelatedTests ./test/storage/resize.img.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-online-chunk_6 - path: ./packages/functions/firestore-data/ - retention-days: 1 diff --git a/.github/workflows/functions_tangle-online-unit-tests_emulator.yml b/.github/workflows/functions_tangle-online-unit-tests_emulator.yml deleted file mode 100644 index 9d776381a2..0000000000 --- a/.github/workflows/functions_tangle-online-unit-tests_emulator.yml +++ /dev/null @@ -1,3026 +0,0 @@ -name: Functions | Tangle - Online - Emulated Unit Tests - -on: - workflow_run: - workflows: ["Firebase Deploy DEV"] - types: [completed] - branches: - - "develop" - -jobs: - npm-install: - runs-on: ubuntu-latest - timeout-minutes: 10 - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version: 20.x - - uses: actions/cache@v4 - id: cache - with: - path: | - node_modules - packages/functions/node_modules - packages/interfaces/node_modules - key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - - name: Install Dependencies - if: steps.cache.outputs.cache-hit != 'true' - run: npm run build:functions - - chunk_0: - needs: npm-install - runs-on: ubuntu-latest - timeout-minutes: 20 - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version: 20.x - - uses: actions/cache@v4 - with: - path: | - node_modules - packages/functions/node_modules - packages/interfaces/node_modules - key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - - name: Init - run: | - npm run build:functions - npm install -g firebase-tools - - name: Test - working-directory: packages/functions - run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/address.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/auction-tangle/auction.bit.tangle.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/award-tangle/award-tangle_1.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-online-chunk_0 - path: ./packages/functions/firestore-data/ - retention-days: 1 - chunk_1: - needs: npm-install - runs-on: ubuntu-latest - timeout-minutes: 20 - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version: 20.x - - uses: actions/cache@v4 - with: - path: | - node_modules - packages/functions/node_modules - packages/interfaces/node_modules - key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - - name: Init - run: | - npm run build:functions - npm install -g firebase-tools - - name: Test - working-directory: packages/functions - run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/award-tangle/award-tangle_2.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/award-tangle/award-tangle_3.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/award-tangle/award-tangle_4.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-online-chunk_1 - path: ./packages/functions/firestore-data/ - retention-days: 1 - chunk_2: - needs: npm-install - runs-on: ubuntu-latest - timeout-minutes: 20 - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version: 20.x - - uses: actions/cache@v4 - with: - path: | - node_modules - packages/functions/node_modules - packages/interfaces/node_modules - key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - - name: Init - run: | - npm run build:functions - npm install -g firebase-tools - - name: Test - working-directory: packages/functions - run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/award-tangle/award-tangle_5.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/award-tangle/award-tangle_6.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/award-tangle/award-tangle_7.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-online-chunk_2 - path: ./packages/functions/firestore-data/ - retention-days: 1 - chunk_3: - needs: npm-install - runs-on: ubuntu-latest - timeout-minutes: 20 - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version: 20.x - - uses: actions/cache@v4 - with: - path: | - node_modules - packages/functions/node_modules - packages/interfaces/node_modules - key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - - name: Init - run: | - npm run build:functions - npm install -g firebase-tools - - name: Test - working-directory: packages/functions - run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/award/award_1_b.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/award/award_1.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/award/award_10.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-online-chunk_3 - path: ./packages/functions/firestore-data/ - retention-days: 1 - chunk_4: - needs: npm-install - runs-on: ubuntu-latest - timeout-minutes: 20 - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version: 20.x - - uses: actions/cache@v4 - with: - path: | - node_modules - packages/functions/node_modules - packages/interfaces/node_modules - key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - - name: Init - run: | - npm run build:functions - npm install -g firebase-tools - - name: Test - working-directory: packages/functions - run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/award/award_11.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/award/award_12.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/award/award_2.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-online-chunk_4 - path: ./packages/functions/firestore-data/ - retention-days: 1 - chunk_5: - needs: npm-install - runs-on: ubuntu-latest - timeout-minutes: 20 - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version: 20.x - - uses: actions/cache@v4 - with: - path: | - node_modules - packages/functions/node_modules - packages/interfaces/node_modules - key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - - name: Init - run: | - npm run build:functions - npm install -g firebase-tools - - name: Test - working-directory: packages/functions - run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/award/award_3.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/award/award_4.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/award/award_5.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-online-chunk_5 - path: ./packages/functions/firestore-data/ - retention-days: 1 - chunk_6: - needs: npm-install - runs-on: ubuntu-latest - timeout-minutes: 20 - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version: 20.x - - uses: actions/cache@v4 - with: - path: | - node_modules - packages/functions/node_modules - packages/interfaces/node_modules - key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - - name: Init - run: | - npm run build:functions - npm install -g firebase-tools - - name: Test - working-directory: packages/functions - run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/award/award_6.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/award/award_7.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/award/award_8.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-online-chunk_6 - path: ./packages/functions/firestore-data/ - retention-days: 1 - chunk_7: - needs: npm-install - runs-on: ubuntu-latest - timeout-minutes: 20 - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version: 20.x - - uses: actions/cache@v4 - with: - path: | - node_modules - packages/functions/node_modules - packages/interfaces/node_modules - key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - - name: Init - run: | - npm run build:functions - npm install -g firebase-tools - - name: Test - working-directory: packages/functions - run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/award/award_9.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/base-token-trading/base-token-trading_1.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/base-token-trading/base-token-trading_10.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-online-chunk_7 - path: ./packages/functions/firestore-data/ - retention-days: 1 - chunk_8: - needs: npm-install - runs-on: ubuntu-latest - timeout-minutes: 20 - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version: 20.x - - uses: actions/cache@v4 - with: - path: | - node_modules - packages/functions/node_modules - packages/interfaces/node_modules - key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - - name: Init - run: | - npm run build:functions - npm install -g firebase-tools - - name: Test - working-directory: packages/functions - run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/base-token-trading/base-token-trading_11_a.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/base-token-trading/base-token-trading_11_b.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/base-token-trading/base-token-trading_11_c.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-online-chunk_8 - path: ./packages/functions/firestore-data/ - retention-days: 1 - chunk_9: - needs: npm-install - runs-on: ubuntu-latest - timeout-minutes: 20 - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version: 20.x - - uses: actions/cache@v4 - with: - path: | - node_modules - packages/functions/node_modules - packages/interfaces/node_modules - key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - - name: Init - run: | - npm run build:functions - npm install -g firebase-tools - - name: Test - working-directory: packages/functions - run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/base-token-trading/base-token-trading_11_d.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/base-token-trading/base-token-trading_12.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/base-token-trading/base-token-trading_13.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-online-chunk_9 - path: ./packages/functions/firestore-data/ - retention-days: 1 - chunk_10: - needs: npm-install - runs-on: ubuntu-latest - timeout-minutes: 20 - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version: 20.x - - uses: actions/cache@v4 - with: - path: | - node_modules - packages/functions/node_modules - packages/interfaces/node_modules - key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - - name: Init - run: | - npm run build:functions - npm install -g firebase-tools - - name: Test - working-directory: packages/functions - run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/base-token-trading/base-token-trading_14.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/base-token-trading/base-token-trading_15.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/base-token-trading/base-token-trading_16.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-online-chunk_10 - path: ./packages/functions/firestore-data/ - retention-days: 1 - chunk_11: - needs: npm-install - runs-on: ubuntu-latest - timeout-minutes: 20 - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version: 20.x - - uses: actions/cache@v4 - with: - path: | - node_modules - packages/functions/node_modules - packages/interfaces/node_modules - key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - - name: Init - run: | - npm run build:functions - npm install -g firebase-tools - - name: Test - working-directory: packages/functions - run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/base-token-trading/base-token-trading_17.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/base-token-trading/base-token-trading_18.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/base-token-trading/base-token-trading_19.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-online-chunk_11 - path: ./packages/functions/firestore-data/ - retention-days: 1 - chunk_12: - needs: npm-install - runs-on: ubuntu-latest - timeout-minutes: 20 - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version: 20.x - - uses: actions/cache@v4 - with: - path: | - node_modules - packages/functions/node_modules - packages/interfaces/node_modules - key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - - name: Init - run: | - npm run build:functions - npm install -g firebase-tools - - name: Test - working-directory: packages/functions - run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/base-token-trading/base-token-trading_2.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/base-token-trading/base-token-trading_3.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/base-token-trading/base-token-trading_4.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-online-chunk_12 - path: ./packages/functions/firestore-data/ - retention-days: 1 - chunk_13: - needs: npm-install - runs-on: ubuntu-latest - timeout-minutes: 20 - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version: 20.x - - uses: actions/cache@v4 - with: - path: | - node_modules - packages/functions/node_modules - packages/interfaces/node_modules - key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - - name: Init - run: | - npm run build:functions - npm install -g firebase-tools - - name: Test - working-directory: packages/functions - run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/base-token-trading/base-token-trading_5.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/base-token-trading/base-token-trading_6.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/base-token-trading/base-token-trading_7.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-online-chunk_13 - path: ./packages/functions/firestore-data/ - retention-days: 1 - chunk_14: - needs: npm-install - runs-on: ubuntu-latest - timeout-minutes: 20 - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version: 20.x - - uses: actions/cache@v4 - with: - path: | - node_modules - packages/functions/node_modules - packages/interfaces/node_modules - key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - - name: Init - run: | - npm run build:functions - npm install -g firebase-tools - - name: Test - working-directory: packages/functions - run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/base-token-trading/base-token-trading_8.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/base-token-trading/base-token-trading_9.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/collection-minting/collection-minting_1.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-online-chunk_14 - path: ./packages/functions/firestore-data/ - retention-days: 1 - chunk_15: - needs: npm-install - runs-on: ubuntu-latest - timeout-minutes: 20 - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version: 20.x - - uses: actions/cache@v4 - with: - path: | - node_modules - packages/functions/node_modules - packages/interfaces/node_modules - key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - - name: Init - run: | - npm run build:functions - npm install -g firebase-tools - - name: Test - working-directory: packages/functions - run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/collection-minting/collection-minting_10.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/collection-minting/collection-minting_11.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/collection-minting/collection-minting_12.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-online-chunk_15 - path: ./packages/functions/firestore-data/ - retention-days: 1 - chunk_16: - needs: npm-install - runs-on: ubuntu-latest - timeout-minutes: 20 - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version: 20.x - - uses: actions/cache@v4 - with: - path: | - node_modules - packages/functions/node_modules - packages/interfaces/node_modules - key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - - name: Init - run: | - npm run build:functions - npm install -g firebase-tools - - name: Test - working-directory: packages/functions - run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/collection-minting/collection-minting_13.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/collection-minting/collection-minting_2.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/collection-minting/collection-minting_4_a.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-online-chunk_16 - path: ./packages/functions/firestore-data/ - retention-days: 1 - chunk_17: - needs: npm-install - runs-on: ubuntu-latest - timeout-minutes: 20 - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version: 20.x - - uses: actions/cache@v4 - with: - path: | - node_modules - packages/functions/node_modules - packages/interfaces/node_modules - key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - - name: Init - run: | - npm run build:functions - npm install -g firebase-tools - - name: Test - working-directory: packages/functions - run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/collection-minting/collection-minting_4_b.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/collection-minting/collection-minting_4_c.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/collection-minting/collection-minting_5.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-online-chunk_17 - path: ./packages/functions/firestore-data/ - retention-days: 1 - chunk_18: - needs: npm-install - runs-on: ubuntu-latest - timeout-minutes: 20 - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version: 20.x - - uses: actions/cache@v4 - with: - path: | - node_modules - packages/functions/node_modules - packages/interfaces/node_modules - key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - - name: Init - run: | - npm run build:functions - npm install -g firebase-tools - - name: Test - working-directory: packages/functions - run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/collection-minting/collection-minting_6.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/collection-minting/collection-minting_7.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/collection-minting/collection-minting_8.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-online-chunk_18 - path: ./packages/functions/firestore-data/ - retention-days: 1 - chunk_19: - needs: npm-install - runs-on: ubuntu-latest - timeout-minutes: 20 - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version: 20.x - - uses: actions/cache@v4 - with: - path: | - node_modules - packages/functions/node_modules - packages/interfaces/node_modules - key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - - name: Init - run: | - npm run build:functions - npm install -g firebase-tools - - name: Test - working-directory: packages/functions - run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/collection-minting/collection-minting_9.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/metadata-nft/mint-metadata-nft_1_b.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/metadata-nft/mint-metadata-nft_1.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-online-chunk_19 - path: ./packages/functions/firestore-data/ - retention-days: 1 - chunk_20: - needs: npm-install - runs-on: ubuntu-latest - timeout-minutes: 20 - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version: 20.x - - uses: actions/cache@v4 - with: - path: | - node_modules - packages/functions/node_modules - packages/interfaces/node_modules - key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - - name: Init - run: | - npm run build:functions - npm install -g firebase-tools - - name: Test - working-directory: packages/functions - run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/metadata-nft/mint-metadata-nft_10.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/metadata-nft/mint-metadata-nft_2.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/metadata-nft/mint-metadata-nft_3_b.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-online-chunk_20 - path: ./packages/functions/firestore-data/ - retention-days: 1 - chunk_21: - needs: npm-install - runs-on: ubuntu-latest - timeout-minutes: 20 - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version: 20.x - - uses: actions/cache@v4 - with: - path: | - node_modules - packages/functions/node_modules - packages/interfaces/node_modules - key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - - name: Init - run: | - npm run build:functions - npm install -g firebase-tools - - name: Test - working-directory: packages/functions - run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/metadata-nft/mint-metadata-nft_3.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/metadata-nft/mint-metadata-nft_4.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/metadata-nft/mint-metadata-nft_5_b.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-online-chunk_21 - path: ./packages/functions/firestore-data/ - retention-days: 1 - chunk_22: - needs: npm-install - runs-on: ubuntu-latest - timeout-minutes: 20 - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version: 20.x - - uses: actions/cache@v4 - with: - path: | - node_modules - packages/functions/node_modules - packages/interfaces/node_modules - key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - - name: Init - run: | - npm run build:functions - npm install -g firebase-tools - - name: Test - working-directory: packages/functions - run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/metadata-nft/mint-metadata-nft_5.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/metadata-nft/mint-metadata-nft_6.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/metadata-nft/mint-metadata-nft_7.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-online-chunk_22 - path: ./packages/functions/firestore-data/ - retention-days: 1 - chunk_23: - needs: npm-install - runs-on: ubuntu-latest - timeout-minutes: 20 - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version: 20.x - - uses: actions/cache@v4 - with: - path: | - node_modules - packages/functions/node_modules - packages/interfaces/node_modules - key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - - name: Init - run: | - npm run build:functions - npm install -g firebase-tools - - name: Test - working-directory: packages/functions - run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/metadata-nft/mint-metadata-nft_8.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/metadata-nft/mint-metadata-nft_9.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/minted-nft-trading/minted-nft-trading_1_b.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-online-chunk_23 - path: ./packages/functions/firestore-data/ - retention-days: 1 - chunk_24: - needs: npm-install - runs-on: ubuntu-latest - timeout-minutes: 20 - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version: 20.x - - uses: actions/cache@v4 - with: - path: | - node_modules - packages/functions/node_modules - packages/interfaces/node_modules - key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - - name: Init - run: | - npm run build:functions - npm install -g firebase-tools - - name: Test - working-directory: packages/functions - run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/minted-nft-trading/minted-nft-trading_1.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/minted-nft-trading/minted-nft-trading_10.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/minted-nft-trading/minted-nft-trading_2.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-online-chunk_24 - path: ./packages/functions/firestore-data/ - retention-days: 1 - chunk_25: - needs: npm-install - runs-on: ubuntu-latest - timeout-minutes: 20 - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version: 20.x - - uses: actions/cache@v4 - with: - path: | - node_modules - packages/functions/node_modules - packages/interfaces/node_modules - key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - - name: Init - run: | - npm run build:functions - npm install -g firebase-tools - - name: Test - working-directory: packages/functions - run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/minted-nft-trading/minted-nft-trading_3.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/minted-nft-trading/minted-nft-trading_4.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/minted-nft-trading/minted-nft-trading_5.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-online-chunk_25 - path: ./packages/functions/firestore-data/ - retention-days: 1 - chunk_26: - needs: npm-install - runs-on: ubuntu-latest - timeout-minutes: 20 - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version: 20.x - - uses: actions/cache@v4 - with: - path: | - node_modules - packages/functions/node_modules - packages/interfaces/node_modules - key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - - name: Init - run: | - npm run build:functions - npm install -g firebase-tools - - name: Test - working-directory: packages/functions - run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/minted-nft-trading/minted-nft-trading_6.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/minted-nft-trading/minted-nft-trading_7.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/minted-nft-trading/minted-nft-trading_8.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-online-chunk_26 - path: ./packages/functions/firestore-data/ - retention-days: 1 - chunk_27: - needs: npm-install - runs-on: ubuntu-latest - timeout-minutes: 20 - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version: 20.x - - uses: actions/cache@v4 - with: - path: | - node_modules - packages/functions/node_modules - packages/interfaces/node_modules - key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - - name: Init - run: | - npm run build:functions - npm install -g firebase-tools - - name: Test - working-directory: packages/functions - run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/minted-token-airdrop/minted-token-airdrop_1_a.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/minted-token-airdrop/minted-token-airdrop_1_b.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/minted-token-airdrop/minted-token-airdrop_1_c.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-online-chunk_27 - path: ./packages/functions/firestore-data/ - retention-days: 1 - chunk_28: - needs: npm-install - runs-on: ubuntu-latest - timeout-minutes: 20 - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version: 20.x - - uses: actions/cache@v4 - with: - path: | - node_modules - packages/functions/node_modules - packages/interfaces/node_modules - key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - - name: Init - run: | - npm run build:functions - npm install -g firebase-tools - - name: Test - working-directory: packages/functions - run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/minted-token-airdrop/minted-token-airdrop_2.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/minted-token-airdrop/minted-token-airdrop_4.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/minted-token-airdrop/minted-token-airdrop_5.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-online-chunk_28 - path: ./packages/functions/firestore-data/ - retention-days: 1 - chunk_29: - needs: npm-install - runs-on: ubuntu-latest - timeout-minutes: 20 - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version: 20.x - - uses: actions/cache@v4 - with: - path: | - node_modules - packages/functions/node_modules - packages/interfaces/node_modules - key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - - name: Init - run: | - npm run build:functions - npm install -g firebase-tools - - name: Test - working-directory: packages/functions - run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/minted-token-claim/token.claim.minted_1.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/minted-token-claim/token.claim.minted_2.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/minted-token-claim/token.claim.minted_3.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-online-chunk_29 - path: ./packages/functions/firestore-data/ - retention-days: 1 - chunk_30: - needs: npm-install - runs-on: ubuntu-latest - timeout-minutes: 20 - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version: 20.x - - uses: actions/cache@v4 - with: - path: | - node_modules - packages/functions/node_modules - packages/interfaces/node_modules - key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - - name: Init - run: | - npm run build:functions - npm install -g firebase-tools - - name: Test - working-directory: packages/functions - run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/minted-token-claim/token.claim.minted_4.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/minted-token-claim/token.claim.minted_5.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/minted-token-claim/token.claim.minted_6.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-online-chunk_30 - path: ./packages/functions/firestore-data/ - retention-days: 1 - chunk_31: - needs: npm-install - runs-on: ubuntu-latest - timeout-minutes: 20 - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version: 20.x - - uses: actions/cache@v4 - with: - path: | - node_modules - packages/functions/node_modules - packages/interfaces/node_modules - key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - - name: Init - run: | - npm run build:functions - npm install -g firebase-tools - - name: Test - working-directory: packages/functions - run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/minted-token-claim/token.claim.minted_7.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/minted-token-trade/minted-token-trade_1.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/minted-token-trade/minted-token-trade_10.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-online-chunk_31 - path: ./packages/functions/firestore-data/ - retention-days: 1 - chunk_32: - needs: npm-install - runs-on: ubuntu-latest - timeout-minutes: 20 - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version: 20.x - - uses: actions/cache@v4 - with: - path: | - node_modules - packages/functions/node_modules - packages/interfaces/node_modules - key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - - name: Init - run: | - npm run build:functions - npm install -g firebase-tools - - name: Test - working-directory: packages/functions - run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/minted-token-trade/minted-token-trade_11.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/minted-token-trade/minted-token-trade_12_b.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/minted-token-trade/minted-token-trade_12.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-online-chunk_32 - path: ./packages/functions/firestore-data/ - retention-days: 1 - chunk_33: - needs: npm-install - runs-on: ubuntu-latest - timeout-minutes: 20 - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version: 20.x - - uses: actions/cache@v4 - with: - path: | - node_modules - packages/functions/node_modules - packages/interfaces/node_modules - key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - - name: Init - run: | - npm run build:functions - npm install -g firebase-tools - - name: Test - working-directory: packages/functions - run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/minted-token-trade/minted-token-trade_13.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/minted-token-trade/minted-token-trade_14_b.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/minted-token-trade/minted-token-trade_14.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-online-chunk_33 - path: ./packages/functions/firestore-data/ - retention-days: 1 - chunk_34: - needs: npm-install - runs-on: ubuntu-latest - timeout-minutes: 20 - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version: 20.x - - uses: actions/cache@v4 - with: - path: | - node_modules - packages/functions/node_modules - packages/interfaces/node_modules - key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - - name: Init - run: | - npm run build:functions - npm install -g firebase-tools - - name: Test - working-directory: packages/functions - run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/minted-token-trade/minted-token-trade_16.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/minted-token-trade/minted-token-trade_17.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/minted-token-trade/minted-token-trade_18.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-online-chunk_34 - path: ./packages/functions/firestore-data/ - retention-days: 1 - chunk_35: - needs: npm-install - runs-on: ubuntu-latest - timeout-minutes: 20 - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version: 20.x - - uses: actions/cache@v4 - with: - path: | - node_modules - packages/functions/node_modules - packages/interfaces/node_modules - key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - - name: Init - run: | - npm run build:functions - npm install -g firebase-tools - - name: Test - working-directory: packages/functions - run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/minted-token-trade/minted-token-trade_19.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/minted-token-trade/minted-token-trade_2_b.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/minted-token-trade/minted-token-trade_2.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-online-chunk_35 - path: ./packages/functions/firestore-data/ - retention-days: 1 - chunk_36: - needs: npm-install - runs-on: ubuntu-latest - timeout-minutes: 20 - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version: 20.x - - uses: actions/cache@v4 - with: - path: | - node_modules - packages/functions/node_modules - packages/interfaces/node_modules - key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - - name: Init - run: | - npm run build:functions - npm install -g firebase-tools - - name: Test - working-directory: packages/functions - run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/minted-token-trade/minted-token-trade_20.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/minted-token-trade/minted-token-trade_21.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/minted-token-trade/minted-token-trade_22.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-online-chunk_36 - path: ./packages/functions/firestore-data/ - retention-days: 1 - chunk_37: - needs: npm-install - runs-on: ubuntu-latest - timeout-minutes: 20 - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version: 20.x - - uses: actions/cache@v4 - with: - path: | - node_modules - packages/functions/node_modules - packages/interfaces/node_modules - key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - - name: Init - run: | - npm run build:functions - npm install -g firebase-tools - - name: Test - working-directory: packages/functions - run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/minted-token-trade/minted-token-trade_23.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/minted-token-trade/minted-token-trade_24.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/minted-token-trade/minted-token-trade_3.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-online-chunk_37 - path: ./packages/functions/firestore-data/ - retention-days: 1 - chunk_38: - needs: npm-install - runs-on: ubuntu-latest - timeout-minutes: 20 - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version: 20.x - - uses: actions/cache@v4 - with: - path: | - node_modules - packages/functions/node_modules - packages/interfaces/node_modules - key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - - name: Init - run: | - npm run build:functions - npm install -g firebase-tools - - name: Test - working-directory: packages/functions - run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/minted-token-trade/minted-token-trade_4.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/minted-token-trade/minted-token-trade_5.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/minted-token-trade/minted-token-trade_6.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-online-chunk_38 - path: ./packages/functions/firestore-data/ - retention-days: 1 - chunk_39: - needs: npm-install - runs-on: ubuntu-latest - timeout-minutes: 20 - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version: 20.x - - uses: actions/cache@v4 - with: - path: | - node_modules - packages/functions/node_modules - packages/interfaces/node_modules - key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - - name: Init - run: | - npm run build:functions - npm install -g firebase-tools - - name: Test - working-directory: packages/functions - run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/minted-token-trade/minted-token-trade_7.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/minted-token-trade/minted-token-trade_8.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/minted-token-trade/minted-token-trade_9.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-online-chunk_39 - path: ./packages/functions/firestore-data/ - retention-days: 1 - chunk_40: - needs: npm-install - runs-on: ubuntu-latest - timeout-minutes: 20 - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version: 20.x - - uses: actions/cache@v4 - with: - path: | - node_modules - packages/functions/node_modules - packages/interfaces/node_modules - key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - - name: Init - run: | - npm run build:functions - npm install -g firebase-tools - - name: Test - working-directory: packages/functions - run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/nft-bid/nft-bid.otr_1.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/nft-bid/nft-bid.otr_2.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/nft-bid/nft-bid.otr_3.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-online-chunk_40 - path: ./packages/functions/firestore-data/ - retention-days: 1 - chunk_41: - needs: npm-install - runs-on: ubuntu-latest - timeout-minutes: 20 - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version: 20.x - - uses: actions/cache@v4 - with: - path: | - node_modules - packages/functions/node_modules - packages/interfaces/node_modules - key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - - name: Init - run: | - npm run build:functions - npm install -g firebase-tools - - name: Test - working-directory: packages/functions - run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/nft-bid/nft-bid.otr_4.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/nft-bulk/order.bulk_1.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/nft-bulk/order.bulk_2.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-online-chunk_41 - path: ./packages/functions/firestore-data/ - retention-days: 1 - chunk_42: - needs: npm-install - runs-on: ubuntu-latest - timeout-minutes: 20 - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version: 20.x - - uses: actions/cache@v4 - with: - path: | - node_modules - packages/functions/node_modules - packages/interfaces/node_modules - key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - - name: Init - run: | - npm run build:functions - npm install -g firebase-tools - - name: Test - working-directory: packages/functions - run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/nft-bulk/order.bulk_3.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/nft-bulk/order.bulk_4.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/nft-bulk/order.bulk_5.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-online-chunk_42 - path: ./packages/functions/firestore-data/ - retention-days: 1 - chunk_43: - needs: npm-install - runs-on: ubuntu-latest - timeout-minutes: 20 - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version: 20.x - - uses: actions/cache@v4 - with: - path: | - node_modules - packages/functions/node_modules - packages/interfaces/node_modules - key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - - name: Init - run: | - npm run build:functions - npm install -g firebase-tools - - name: Test - working-directory: packages/functions - run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/nft-bulk/order.bulk_6.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/nft-set-for-sale/nft-set-for-sale_1.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/nft-set-for-sale/nft-set-for-sale_2.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-online-chunk_43 - path: ./packages/functions/firestore-data/ - retention-days: 1 - chunk_44: - needs: npm-install - runs-on: ubuntu-latest - timeout-minutes: 20 - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version: 20.x - - uses: actions/cache@v4 - with: - path: | - node_modules - packages/functions/node_modules - packages/interfaces/node_modules - key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - - name: Init - run: | - npm run build:functions - npm install -g firebase-tools - - name: Test - working-directory: packages/functions - run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/nft-set-for-sale/nft-set-for-sale_3.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/nft-staking/nft-staking_1.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/nft-staking/nft-staking_10.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-online-chunk_44 - path: ./packages/functions/firestore-data/ - retention-days: 1 - chunk_45: - needs: npm-install - runs-on: ubuntu-latest - timeout-minutes: 20 - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version: 20.x - - uses: actions/cache@v4 - with: - path: | - node_modules - packages/functions/node_modules - packages/interfaces/node_modules - key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - - name: Init - run: | - npm run build:functions - npm install -g firebase-tools - - name: Test - working-directory: packages/functions - run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/nft-staking/nft-staking_2_b.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/nft-staking/nft-staking_2.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/nft-staking/nft-staking_3.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-online-chunk_45 - path: ./packages/functions/firestore-data/ - retention-days: 1 - chunk_46: - needs: npm-install - runs-on: ubuntu-latest - timeout-minutes: 20 - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version: 20.x - - uses: actions/cache@v4 - with: - path: | - node_modules - packages/functions/node_modules - packages/interfaces/node_modules - key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - - name: Init - run: | - npm run build:functions - npm install -g firebase-tools - - name: Test - working-directory: packages/functions - run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/nft-staking/nft-staking_4.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/nft-staking/nft-staking_5.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/nft-staking/nft-staking_6.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-online-chunk_46 - path: ./packages/functions/firestore-data/ - retention-days: 1 - chunk_47: - needs: npm-install - runs-on: ubuntu-latest - timeout-minutes: 20 - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version: 20.x - - uses: actions/cache@v4 - with: - path: | - node_modules - packages/functions/node_modules - packages/interfaces/node_modules - key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - - name: Init - run: | - npm run build:functions - npm install -g firebase-tools - - name: Test - working-directory: packages/functions - run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/nft-staking/nft-staking_7.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/nft-staking/nft-staking_8.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/nft-staking/nft-staking_9.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-online-chunk_47 - path: ./packages/functions/firestore-data/ - retention-days: 1 - chunk_48: - needs: npm-install - runs-on: ubuntu-latest - timeout-minutes: 20 - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version: 20.x - - uses: actions/cache@v4 - with: - path: | - node_modules - packages/functions/node_modules - packages/interfaces/node_modules - key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - - name: Init - run: | - npm run build:functions - npm install -g firebase-tools - - name: Test - working-directory: packages/functions - run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/nft-transfer/nft-transfer_1.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/nft-transfer/nft-transfer_2.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/nft-transfer/nft-transfer_3.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-online-chunk_48 - path: ./packages/functions/firestore-data/ - retention-days: 1 - chunk_49: - needs: npm-install - runs-on: ubuntu-latest - timeout-minutes: 20 - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version: 20.x - - uses: actions/cache@v4 - with: - path: | - node_modules - packages/functions/node_modules - packages/interfaces/node_modules - key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - - name: Init - run: | - npm run build:functions - npm install -g firebase-tools - - name: Test - working-directory: packages/functions - run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/nft-transfer/nft-transfer_4.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/nft-transfer/nft-transfer_5.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/nft-transfer/nft-transfer_6.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-online-chunk_49 - path: ./packages/functions/firestore-data/ - retention-days: 1 - chunk_50: - needs: npm-install - runs-on: ubuntu-latest - timeout-minutes: 20 - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version: 20.x - - uses: actions/cache@v4 - with: - path: | - node_modules - packages/functions/node_modules - packages/interfaces/node_modules - key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - - name: Init - run: | - npm run build:functions - npm install -g firebase-tools - - name: Test - working-directory: packages/functions - run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/nft-transfer/nft-transfer_7.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/nft-transfer/nft-transfer_8.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/proposal-tangle/proposal.approval.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-online-chunk_50 - path: ./packages/functions/firestore-data/ - retention-days: 1 - chunk_51: - needs: npm-install - runs-on: ubuntu-latest - timeout-minutes: 20 - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version: 20.x - - uses: actions/cache@v4 - with: - path: | - node_modules - packages/functions/node_modules - packages/interfaces/node_modules - key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - - name: Init - run: | - npm run build:functions - npm install -g firebase-tools - - name: Test - working-directory: packages/functions - run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/proposal-tangle/proposal.create.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/proposal-tangle/proposal.simple.vote.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/proposal-tangle/proposal.stake.voting.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-online-chunk_51 - path: ./packages/functions/firestore-data/ - retention-days: 1 - chunk_52: - needs: npm-install - runs-on: ubuntu-latest - timeout-minutes: 20 - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version: 20.x - - uses: actions/cache@v4 - with: - path: | - node_modules - packages/functions/node_modules - packages/interfaces/node_modules - key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - - name: Init - run: | - npm run build:functions - npm install -g firebase-tools - - name: Test - working-directory: packages/functions - run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/proposal-tangle/proposal.token.voting.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/space-tangle/space.accept.member.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/space-tangle/space.block.member.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-online-chunk_52 - path: ./packages/functions/firestore-data/ - retention-days: 1 - chunk_53: - needs: npm-install - runs-on: ubuntu-latest - timeout-minutes: 20 - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version: 20.x - - uses: actions/cache@v4 - with: - path: | - node_modules - packages/functions/node_modules - packages/interfaces/node_modules - key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - - name: Init - run: | - npm run build:functions - npm install -g firebase-tools - - name: Test - working-directory: packages/functions - run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/space-tangle/space.create.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/space-tangle/space.decline.member.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/space-tangle/space.edit.guardian.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-online-chunk_53 - path: ./packages/functions/firestore-data/ - retention-days: 1 - chunk_54: - needs: npm-install - runs-on: ubuntu-latest - timeout-minutes: 20 - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version: 20.x - - uses: actions/cache@v4 - with: - path: | - node_modules - packages/functions/node_modules - packages/interfaces/node_modules - key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - - name: Init - run: | - npm run build:functions - npm install -g firebase-tools - - name: Test - working-directory: packages/functions - run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/space-tangle/space.join.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/space-tangle/space.leave.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/staking/staking_1.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-online-chunk_54 - path: ./packages/functions/firestore-data/ - retention-days: 1 - chunk_55: - needs: npm-install - runs-on: ubuntu-latest - timeout-minutes: 20 - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version: 20.x - - uses: actions/cache@v4 - with: - path: | - node_modules - packages/functions/node_modules - packages/interfaces/node_modules - key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - - name: Init - run: | - npm run build:functions - npm install -g firebase-tools - - name: Test - working-directory: packages/functions - run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/staking/staking_2.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/staking/staking_3.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/staking/staking_4.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-online-chunk_55 - path: ./packages/functions/firestore-data/ - retention-days: 1 - chunk_56: - needs: npm-install - runs-on: ubuntu-latest - timeout-minutes: 20 - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version: 20.x - - uses: actions/cache@v4 - with: - path: | - node_modules - packages/functions/node_modules - packages/interfaces/node_modules - key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - - name: Init - run: | - npm run build:functions - npm install -g firebase-tools - - name: Test - working-directory: packages/functions - run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/staking/staking_5.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/stamp-tangle/stamp-tangle_1_a.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/stamp-tangle/stamp-tangle_1_b.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-online-chunk_56 - path: ./packages/functions/firestore-data/ - retention-days: 1 - chunk_57: - needs: npm-install - runs-on: ubuntu-latest - timeout-minutes: 20 - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version: 20.x - - uses: actions/cache@v4 - with: - path: | - node_modules - packages/functions/node_modules - packages/interfaces/node_modules - key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - - name: Init - run: | - npm run build:functions - npm install -g firebase-tools - - name: Test - working-directory: packages/functions - run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/stamp-tangle/stamp-tangle_2.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/stamp-tangle/stamp-tangle_3.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/stamp-tangle/stamp-tangle_4.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-online-chunk_57 - path: ./packages/functions/firestore-data/ - retention-days: 1 - chunk_58: - needs: npm-install - runs-on: ubuntu-latest - timeout-minutes: 20 - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version: 20.x - - uses: actions/cache@v4 - with: - path: | - node_modules - packages/functions/node_modules - packages/interfaces/node_modules - key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - - name: Init - run: | - npm run build:functions - npm install -g firebase-tools - - name: Test - working-directory: packages/functions - run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/stamp-tangle/stamp-tangle_5.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/stamp-tangle/stamp-tangle_6.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/swap/swap_1.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-online-chunk_58 - path: ./packages/functions/firestore-data/ - retention-days: 1 - chunk_59: - needs: npm-install - runs-on: ubuntu-latest - timeout-minutes: 20 - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version: 20.x - - uses: actions/cache@v4 - with: - path: | - node_modules - packages/functions/node_modules - packages/interfaces/node_modules - key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - - name: Init - run: | - npm run build:functions - npm install -g firebase-tools - - name: Test - working-directory: packages/functions - run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/swap/swap_2.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/swap/swap_3_a.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/swap/swap_3_b.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-online-chunk_59 - path: ./packages/functions/firestore-data/ - retention-days: 1 - chunk_60: - needs: npm-install - runs-on: ubuntu-latest - timeout-minutes: 20 - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version: 20.x - - uses: actions/cache@v4 - with: - path: | - node_modules - packages/functions/node_modules - packages/interfaces/node_modules - key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - - name: Init - run: | - npm run build:functions - npm install -g firebase-tools - - name: Test - working-directory: packages/functions - run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/swap/swap_4.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/swap/swap_5.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/swap/swap_6.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-online-chunk_60 - path: ./packages/functions/firestore-data/ - retention-days: 1 - chunk_61: - needs: npm-install - runs-on: ubuntu-latest - timeout-minutes: 20 - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version: 20.x - - uses: actions/cache@v4 - with: - path: | - node_modules - packages/functions/node_modules - packages/interfaces/node_modules - key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - - name: Init - run: | - npm run build:functions - npm install -g firebase-tools - - name: Test - working-directory: packages/functions - run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/swap/swap_7.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/swap/swap_8.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/tangleRequest/simple.token.trade.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-online-chunk_61 - path: ./packages/functions/firestore-data/ - retention-days: 1 - chunk_62: - needs: npm-install - runs-on: ubuntu-latest - timeout-minutes: 20 - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version: 20.x - - uses: actions/cache@v4 - with: - path: | - node_modules - packages/functions/node_modules - packages/interfaces/node_modules - key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - - name: Init - run: | - npm run build:functions - npm install -g firebase-tools - - name: Test - working-directory: packages/functions - run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/tangleRequest/tangle-request.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/token-import/token.import_1.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/token-import/token.import_2.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-online-chunk_62 - path: ./packages/functions/firestore-data/ - retention-days: 1 - chunk_63: - needs: npm-install - runs-on: ubuntu-latest - timeout-minutes: 20 - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version: 20.x - - uses: actions/cache@v4 - with: - path: | - node_modules - packages/functions/node_modules - packages/interfaces/node_modules - key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - - name: Init - run: | - npm run build:functions - npm install -g firebase-tools - - name: Test - working-directory: packages/functions - run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/token.based.voting/stake.voting.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/token.based.voting/token.based.voting_1.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/token.based.voting/token.based.voting_2.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-online-chunk_63 - path: ./packages/functions/firestore-data/ - retention-days: 1 - chunk_64: - needs: npm-install - runs-on: ubuntu-latest - timeout-minutes: 20 - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version: 20.x - - uses: actions/cache@v4 - with: - path: | - node_modules - packages/functions/node_modules - packages/interfaces/node_modules - key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - - name: Init - run: | - npm run build:functions - npm install -g firebase-tools - - name: Test - working-directory: packages/functions - run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/token.based.voting/token.based.voting_3.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/token.based.voting/token.based.voting_4.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/token.based.voting/token.based.voting_5.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-online-chunk_64 - path: ./packages/functions/firestore-data/ - retention-days: 1 - chunk_65: - needs: npm-install - runs-on: ubuntu-latest - timeout-minutes: 20 - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version: 20.x - - uses: actions/cache@v4 - with: - path: | - node_modules - packages/functions/node_modules - packages/interfaces/node_modules - key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - - name: Init - run: | - npm run build:functions - npm install -g firebase-tools - - name: Test - working-directory: packages/functions - run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/token.mint/token.mint_1.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/token.mint/token.mint_2.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/token.mint/token.mint_3.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-online-chunk_65 - path: ./packages/functions/firestore-data/ - retention-days: 1 - chunk_66: - needs: npm-install - runs-on: ubuntu-latest - timeout-minutes: 20 - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version: 20.x - - uses: actions/cache@v4 - with: - path: | - node_modules - packages/functions/node_modules - packages/interfaces/node_modules - key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - - name: Init - run: | - npm run build:functions - npm install -g firebase-tools - - name: Test - working-directory: packages/functions - run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/token.mint/token.mint_4.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/trade-base-token-order.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/tran.match.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-online-chunk_66 - path: ./packages/functions/firestore-data/ - retention-days: 1 - chunk_67: - needs: npm-install - runs-on: ubuntu-latest - timeout-minutes: 20 - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version: 20.x - - uses: actions/cache@v4 - with: - path: | - node_modules - packages/functions/node_modules - packages/interfaces/node_modules - key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - - name: Init - run: | - npm run build:functions - npm install -g firebase-tools - - name: Test - working-directory: packages/functions - run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/transaction-trigger/transaction-trigger_1.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/transaction-trigger/transaction-trigger_10.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/transaction-trigger/transaction-trigger_11.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-online-chunk_67 - path: ./packages/functions/firestore-data/ - retention-days: 1 - chunk_68: - needs: npm-install - runs-on: ubuntu-latest - timeout-minutes: 20 - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version: 20.x - - uses: actions/cache@v4 - with: - path: | - node_modules - packages/functions/node_modules - packages/interfaces/node_modules - key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - - name: Init - run: | - npm run build:functions - npm install -g firebase-tools - - name: Test - working-directory: packages/functions - run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/transaction-trigger/transaction-trigger_12.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/transaction-trigger/transaction-trigger_13.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/transaction-trigger/transaction-trigger_14.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-online-chunk_68 - path: ./packages/functions/firestore-data/ - retention-days: 1 - chunk_69: - needs: npm-install - runs-on: ubuntu-latest - timeout-minutes: 20 - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version: 20.x - - uses: actions/cache@v4 - with: - path: | - node_modules - packages/functions/node_modules - packages/interfaces/node_modules - key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - - name: Init - run: | - npm run build:functions - npm install -g firebase-tools - - name: Test - working-directory: packages/functions - run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/transaction-trigger/transaction-trigger_15.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/transaction-trigger/transaction-trigger_2.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/transaction-trigger/transaction-trigger_3.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-online-chunk_69 - path: ./packages/functions/firestore-data/ - retention-days: 1 - chunk_70: - needs: npm-install - runs-on: ubuntu-latest - timeout-minutes: 20 - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version: 20.x - - uses: actions/cache@v4 - with: - path: | - node_modules - packages/functions/node_modules - packages/interfaces/node_modules - key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - - name: Init - run: | - npm run build:functions - npm install -g firebase-tools - - name: Test - working-directory: packages/functions - run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/transaction-trigger/transaction-trigger_4.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/transaction-trigger/transaction-trigger_5.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/transaction-trigger/transaction-trigger_6.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-online-chunk_70 - path: ./packages/functions/firestore-data/ - retention-days: 1 - chunk_71: - needs: npm-install - runs-on: ubuntu-latest - timeout-minutes: 20 - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version: 20.x - - uses: actions/cache@v4 - with: - path: | - node_modules - packages/functions/node_modules - packages/interfaces/node_modules - key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - - name: Init - run: | - npm run build:functions - npm install -g firebase-tools - - name: Test - working-directory: packages/functions - run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/transaction-trigger/transaction-trigger_7.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/transaction-trigger/transaction-trigger_8.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/transaction-trigger/transaction-trigger_9.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-online-chunk_71 - path: ./packages/functions/firestore-data/ - retention-days: 1 - chunk_72: - needs: npm-install - runs-on: ubuntu-latest - timeout-minutes: 20 - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version: 20.x - - uses: actions/cache@v4 - with: - path: | - node_modules - packages/functions/node_modules - packages/interfaces/node_modules - key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - - name: Init - run: | - npm run build:functions - npm install -g firebase-tools - - name: Test - working-directory: packages/functions - run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/web3/web3_1.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/web3/web3_2.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/web3/web3_3.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-online-chunk_72 - path: ./packages/functions/firestore-data/ - retention-days: 1 - chunk_73: - needs: npm-install - runs-on: ubuntu-latest - timeout-minutes: 20 - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version: 20.x - - uses: actions/cache@v4 - with: - path: | - node_modules - packages/functions/node_modules - packages/interfaces/node_modules - key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - - name: Init - run: | - npm run build:functions - npm install -g firebase-tools - - name: Test - working-directory: packages/functions - run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/withdraw-deposit-nft/deposit-withraw-nft_1_a.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/withdraw-deposit-nft/deposit-withraw-nft_1_b.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/withdraw-deposit-nft/deposit-withraw-nft_1_c.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-online-chunk_73 - path: ./packages/functions/firestore-data/ - retention-days: 1 - chunk_74: - needs: npm-install - runs-on: ubuntu-latest - timeout-minutes: 20 - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version: 20.x - - uses: actions/cache@v4 - with: - path: | - node_modules - packages/functions/node_modules - packages/interfaces/node_modules - key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - - name: Init - run: | - npm run build:functions - npm install -g firebase-tools - - name: Test - working-directory: packages/functions - run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/withdraw-deposit-nft/deposit-withraw-nft_10_1.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/withdraw-deposit-nft/deposit-withraw-nft_10_2.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/withdraw-deposit-nft/deposit-withraw-nft_10_3.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-online-chunk_74 - path: ./packages/functions/firestore-data/ - retention-days: 1 - chunk_75: - needs: npm-install - runs-on: ubuntu-latest - timeout-minutes: 20 - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version: 20.x - - uses: actions/cache@v4 - with: - path: | - node_modules - packages/functions/node_modules - packages/interfaces/node_modules - key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - - name: Init - run: | - npm run build:functions - npm install -g firebase-tools - - name: Test - working-directory: packages/functions - run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/withdraw-deposit-nft/deposit-withraw-nft_11.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/withdraw-deposit-nft/deposit-withraw-nft_12_a.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/withdraw-deposit-nft/deposit-withraw-nft_12_b.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-online-chunk_75 - path: ./packages/functions/firestore-data/ - retention-days: 1 - chunk_76: - needs: npm-install - runs-on: ubuntu-latest - timeout-minutes: 20 - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version: 20.x - - uses: actions/cache@v4 - with: - path: | - node_modules - packages/functions/node_modules - packages/interfaces/node_modules - key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - - name: Init - run: | - npm run build:functions - npm install -g firebase-tools - - name: Test - working-directory: packages/functions - run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/withdraw-deposit-nft/deposit-withraw-nft_13.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/withdraw-deposit-nft/deposit-withraw-nft_14.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/withdraw-deposit-nft/deposit-withraw-nft_15.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-online-chunk_76 - path: ./packages/functions/firestore-data/ - retention-days: 1 - chunk_77: - needs: npm-install - runs-on: ubuntu-latest - timeout-minutes: 20 - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version: 20.x - - uses: actions/cache@v4 - with: - path: | - node_modules - packages/functions/node_modules - packages/interfaces/node_modules - key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - - name: Init - run: | - npm run build:functions - npm install -g firebase-tools - - name: Test - working-directory: packages/functions - run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/withdraw-deposit-nft/deposit-withraw-nft_16.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/withdraw-deposit-nft/deposit-withraw-nft_2.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/withdraw-deposit-nft/deposit-withraw-nft_4_b.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-online-chunk_77 - path: ./packages/functions/firestore-data/ - retention-days: 1 - chunk_78: - needs: npm-install - runs-on: ubuntu-latest - timeout-minutes: 20 - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version: 20.x - - uses: actions/cache@v4 - with: - path: | - node_modules - packages/functions/node_modules - packages/interfaces/node_modules - key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - - name: Init - run: | - npm run build:functions - npm install -g firebase-tools - - name: Test - working-directory: packages/functions - run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/withdraw-deposit-nft/deposit-withraw-nft_4.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/withdraw-deposit-nft/deposit-withraw-nft_5.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/withdraw-deposit-nft/deposit-withraw-nft_6.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-online-chunk_78 - path: ./packages/functions/firestore-data/ - retention-days: 1 - chunk_79: - needs: npm-install - runs-on: ubuntu-latest - timeout-minutes: 20 - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version: 20.x - - uses: actions/cache@v4 - with: - path: | - node_modules - packages/functions/node_modules - packages/interfaces/node_modules - key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - - name: Init - run: | - npm run build:functions - npm install -g firebase-tools - - name: Test - working-directory: packages/functions - run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/withdraw-deposit-nft/deposit-withraw-nft_7.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/withdraw-deposit-nft/deposit-withraw-nft_8.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/withdraw-deposit-nft/deposit-withraw-nft_9.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-online-chunk_79 - path: ./packages/functions/firestore-data/ - retention-days: 1 - chunk_80: - needs: npm-install - runs-on: ubuntu-latest - timeout-minutes: 20 - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version: 20.x - - uses: actions/cache@v4 - with: - path: | - node_modules - packages/functions/node_modules - packages/interfaces/node_modules - key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - - name: Init - run: | - npm run build:functions - npm install -g firebase-tools - - name: Test - working-directory: packages/functions - run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/workflow-online.spec.ts && - npm run test-tangle-online:ci -- --forceExit --findRelatedTests ./test-tangle/workflow.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-online-chunk_80 - path: ./packages/functions/firestore-data/ - retention-days: 1 diff --git a/.github/workflows/functions_tangle-unit-tests.yml b/.github/workflows/functions_tangle-unit-tests.yml index 68d1f3f0a0..27bb332925 100644 --- a/.github/workflows/functions_tangle-unit-tests.yml +++ b/.github/workflows/functions_tangle-unit-tests.yml @@ -4,6 +4,7 @@ on: pull_request: paths: - packages/functions/** + - packages/database/** jobs: npm-install: @@ -30,6 +31,21 @@ jobs: needs: npm-install runs-on: ubuntu-latest timeout-minutes: 20 + + services: + postgres: + image: postgres + env: + POSTGRES_DB: build5db + POSTGRES_PASSWORD: postgres + ports: + - 5432:5432 + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 @@ -43,30 +59,34 @@ jobs: packages/interfaces/node_modules key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - name: Init - run: | - npm run build:functions - npm install -g firebase-tools + run: npm run build:functions - name: Test working-directory: packages/functions run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/address.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/auction-tangle/auction.bit.tangle.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/award-tangle/award-tangle_1.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-chunk_0 - path: ./packages/functions/firestore-data/ - retention-days: 1 + npm run start & + npm run notifier & + npm run test -- --findRelatedTests --forceExit ./test-tangle/address.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/auction-tangle/auction.bit.tangle.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/award-tangle/award-tangle_1.spec.ts chunk_1: needs: npm-install runs-on: ubuntu-latest timeout-minutes: 20 + + services: + postgres: + image: postgres + env: + POSTGRES_DB: build5db + POSTGRES_PASSWORD: postgres + ports: + - 5432:5432 + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 @@ -80,30 +100,34 @@ jobs: packages/interfaces/node_modules key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - name: Init - run: | - npm run build:functions - npm install -g firebase-tools + run: npm run build:functions - name: Test working-directory: packages/functions run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/award-tangle/award-tangle_2.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/award-tangle/award-tangle_3.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/award-tangle/award-tangle_4.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-chunk_1 - path: ./packages/functions/firestore-data/ - retention-days: 1 + npm run start & + npm run notifier & + npm run test -- --findRelatedTests --forceExit ./test-tangle/award-tangle/award-tangle_2.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/award-tangle/award-tangle_3.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/award-tangle/award-tangle_4.spec.ts chunk_2: needs: npm-install runs-on: ubuntu-latest timeout-minutes: 20 + + services: + postgres: + image: postgres + env: + POSTGRES_DB: build5db + POSTGRES_PASSWORD: postgres + ports: + - 5432:5432 + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 @@ -117,30 +141,34 @@ jobs: packages/interfaces/node_modules key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - name: Init - run: | - npm run build:functions - npm install -g firebase-tools + run: npm run build:functions - name: Test working-directory: packages/functions run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/award-tangle/award-tangle_5.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/award-tangle/award-tangle_6.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/award-tangle/award-tangle_7.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-chunk_2 - path: ./packages/functions/firestore-data/ - retention-days: 1 + npm run start & + npm run notifier & + npm run test -- --findRelatedTests --forceExit ./test-tangle/award-tangle/award-tangle_5.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/award-tangle/award-tangle_6.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/award-tangle/award-tangle_7.spec.ts chunk_3: needs: npm-install runs-on: ubuntu-latest timeout-minutes: 20 + + services: + postgres: + image: postgres + env: + POSTGRES_DB: build5db + POSTGRES_PASSWORD: postgres + ports: + - 5432:5432 + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 @@ -154,30 +182,34 @@ jobs: packages/interfaces/node_modules key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - name: Init - run: | - npm run build:functions - npm install -g firebase-tools + run: npm run build:functions - name: Test working-directory: packages/functions run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/award/award_1_b.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/award/award_1.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/award/award_10.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-chunk_3 - path: ./packages/functions/firestore-data/ - retention-days: 1 + npm run start & + npm run notifier & + npm run test -- --findRelatedTests --forceExit ./test-tangle/award/award_1_b.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/award/award_1.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/award/award_10.spec.ts chunk_4: needs: npm-install runs-on: ubuntu-latest timeout-minutes: 20 + + services: + postgres: + image: postgres + env: + POSTGRES_DB: build5db + POSTGRES_PASSWORD: postgres + ports: + - 5432:5432 + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 @@ -191,30 +223,34 @@ jobs: packages/interfaces/node_modules key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - name: Init - run: | - npm run build:functions - npm install -g firebase-tools + run: npm run build:functions - name: Test working-directory: packages/functions run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/award/award_11.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/award/award_12.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/award/award_2.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-chunk_4 - path: ./packages/functions/firestore-data/ - retention-days: 1 + npm run start & + npm run notifier & + npm run test -- --findRelatedTests --forceExit ./test-tangle/award/award_11.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/award/award_12.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/award/award_2.spec.ts chunk_5: needs: npm-install runs-on: ubuntu-latest timeout-minutes: 20 + + services: + postgres: + image: postgres + env: + POSTGRES_DB: build5db + POSTGRES_PASSWORD: postgres + ports: + - 5432:5432 + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 @@ -228,30 +264,34 @@ jobs: packages/interfaces/node_modules key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - name: Init - run: | - npm run build:functions - npm install -g firebase-tools + run: npm run build:functions - name: Test working-directory: packages/functions run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/award/award_3.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/award/award_4.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/award/award_5.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-chunk_5 - path: ./packages/functions/firestore-data/ - retention-days: 1 + npm run start & + npm run notifier & + npm run test -- --findRelatedTests --forceExit ./test-tangle/award/award_3.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/award/award_4.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/award/award_5.spec.ts chunk_6: needs: npm-install runs-on: ubuntu-latest timeout-minutes: 20 + + services: + postgres: + image: postgres + env: + POSTGRES_DB: build5db + POSTGRES_PASSWORD: postgres + ports: + - 5432:5432 + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 @@ -265,30 +305,34 @@ jobs: packages/interfaces/node_modules key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - name: Init - run: | - npm run build:functions - npm install -g firebase-tools + run: npm run build:functions - name: Test working-directory: packages/functions run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/award/award_6.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/award/award_7.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/award/award_8.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-chunk_6 - path: ./packages/functions/firestore-data/ - retention-days: 1 + npm run start & + npm run notifier & + npm run test -- --findRelatedTests --forceExit ./test-tangle/award/award_6.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/award/award_7.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/award/award_8.spec.ts chunk_7: needs: npm-install runs-on: ubuntu-latest timeout-minutes: 20 + + services: + postgres: + image: postgres + env: + POSTGRES_DB: build5db + POSTGRES_PASSWORD: postgres + ports: + - 5432:5432 + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 @@ -302,30 +346,34 @@ jobs: packages/interfaces/node_modules key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - name: Init - run: | - npm run build:functions - npm install -g firebase-tools + run: npm run build:functions - name: Test working-directory: packages/functions run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/award/award_9.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/base-token-trading/base-token-trading_1.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/base-token-trading/base-token-trading_10.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-chunk_7 - path: ./packages/functions/firestore-data/ - retention-days: 1 + npm run start & + npm run notifier & + npm run test -- --findRelatedTests --forceExit ./test-tangle/award/award_9.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/base-token-trading/base-token-trading_1.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/base-token-trading/base-token-trading_10.spec.ts chunk_8: needs: npm-install runs-on: ubuntu-latest timeout-minutes: 20 + + services: + postgres: + image: postgres + env: + POSTGRES_DB: build5db + POSTGRES_PASSWORD: postgres + ports: + - 5432:5432 + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 @@ -339,30 +387,34 @@ jobs: packages/interfaces/node_modules key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - name: Init - run: | - npm run build:functions - npm install -g firebase-tools + run: npm run build:functions - name: Test working-directory: packages/functions run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/base-token-trading/base-token-trading_11_a.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/base-token-trading/base-token-trading_11_b.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/base-token-trading/base-token-trading_11_c.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-chunk_8 - path: ./packages/functions/firestore-data/ - retention-days: 1 + npm run start & + npm run notifier & + npm run test -- --findRelatedTests --forceExit ./test-tangle/base-token-trading/base-token-trading_11_a.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/base-token-trading/base-token-trading_11_b.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/base-token-trading/base-token-trading_11_c.spec.ts chunk_9: needs: npm-install runs-on: ubuntu-latest timeout-minutes: 20 + + services: + postgres: + image: postgres + env: + POSTGRES_DB: build5db + POSTGRES_PASSWORD: postgres + ports: + - 5432:5432 + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 @@ -376,30 +428,34 @@ jobs: packages/interfaces/node_modules key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - name: Init - run: | - npm run build:functions - npm install -g firebase-tools + run: npm run build:functions - name: Test working-directory: packages/functions run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/base-token-trading/base-token-trading_11_d.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/base-token-trading/base-token-trading_12.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/base-token-trading/base-token-trading_13.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-chunk_9 - path: ./packages/functions/firestore-data/ - retention-days: 1 + npm run start & + npm run notifier & + npm run test -- --findRelatedTests --forceExit ./test-tangle/base-token-trading/base-token-trading_11_d.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/base-token-trading/base-token-trading_12.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/base-token-trading/base-token-trading_13.spec.ts chunk_10: needs: npm-install runs-on: ubuntu-latest timeout-minutes: 20 + + services: + postgres: + image: postgres + env: + POSTGRES_DB: build5db + POSTGRES_PASSWORD: postgres + ports: + - 5432:5432 + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 @@ -413,30 +469,34 @@ jobs: packages/interfaces/node_modules key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - name: Init - run: | - npm run build:functions - npm install -g firebase-tools + run: npm run build:functions - name: Test working-directory: packages/functions run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/base-token-trading/base-token-trading_14.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/base-token-trading/base-token-trading_15.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/base-token-trading/base-token-trading_16.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-chunk_10 - path: ./packages/functions/firestore-data/ - retention-days: 1 + npm run start & + npm run notifier & + npm run test -- --findRelatedTests --forceExit ./test-tangle/base-token-trading/base-token-trading_14.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/base-token-trading/base-token-trading_15.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/base-token-trading/base-token-trading_16.spec.ts chunk_11: needs: npm-install runs-on: ubuntu-latest timeout-minutes: 20 + + services: + postgres: + image: postgres + env: + POSTGRES_DB: build5db + POSTGRES_PASSWORD: postgres + ports: + - 5432:5432 + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 @@ -450,30 +510,34 @@ jobs: packages/interfaces/node_modules key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - name: Init - run: | - npm run build:functions - npm install -g firebase-tools + run: npm run build:functions - name: Test working-directory: packages/functions run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/base-token-trading/base-token-trading_17.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/base-token-trading/base-token-trading_18.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/base-token-trading/base-token-trading_19.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-chunk_11 - path: ./packages/functions/firestore-data/ - retention-days: 1 + npm run start & + npm run notifier & + npm run test -- --findRelatedTests --forceExit ./test-tangle/base-token-trading/base-token-trading_17.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/base-token-trading/base-token-trading_18.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/base-token-trading/base-token-trading_19.spec.ts chunk_12: needs: npm-install runs-on: ubuntu-latest timeout-minutes: 20 + + services: + postgres: + image: postgres + env: + POSTGRES_DB: build5db + POSTGRES_PASSWORD: postgres + ports: + - 5432:5432 + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 @@ -487,30 +551,34 @@ jobs: packages/interfaces/node_modules key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - name: Init - run: | - npm run build:functions - npm install -g firebase-tools + run: npm run build:functions - name: Test working-directory: packages/functions run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/base-token-trading/base-token-trading_2.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/base-token-trading/base-token-trading_3.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/base-token-trading/base-token-trading_4.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-chunk_12 - path: ./packages/functions/firestore-data/ - retention-days: 1 + npm run start & + npm run notifier & + npm run test -- --findRelatedTests --forceExit ./test-tangle/base-token-trading/base-token-trading_2.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/base-token-trading/base-token-trading_3.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/base-token-trading/base-token-trading_4.spec.ts chunk_13: needs: npm-install runs-on: ubuntu-latest timeout-minutes: 20 + + services: + postgres: + image: postgres + env: + POSTGRES_DB: build5db + POSTGRES_PASSWORD: postgres + ports: + - 5432:5432 + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 @@ -524,30 +592,34 @@ jobs: packages/interfaces/node_modules key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - name: Init - run: | - npm run build:functions - npm install -g firebase-tools + run: npm run build:functions - name: Test working-directory: packages/functions run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/base-token-trading/base-token-trading_5.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/base-token-trading/base-token-trading_6.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/base-token-trading/base-token-trading_7.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-chunk_13 - path: ./packages/functions/firestore-data/ - retention-days: 1 + npm run start & + npm run notifier & + npm run test -- --findRelatedTests --forceExit ./test-tangle/base-token-trading/base-token-trading_5.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/base-token-trading/base-token-trading_6.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/base-token-trading/base-token-trading_7.spec.ts chunk_14: needs: npm-install runs-on: ubuntu-latest timeout-minutes: 20 + + services: + postgres: + image: postgres + env: + POSTGRES_DB: build5db + POSTGRES_PASSWORD: postgres + ports: + - 5432:5432 + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 @@ -561,30 +633,34 @@ jobs: packages/interfaces/node_modules key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - name: Init - run: | - npm run build:functions - npm install -g firebase-tools + run: npm run build:functions - name: Test working-directory: packages/functions run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/base-token-trading/base-token-trading_8.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/base-token-trading/base-token-trading_9.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/collection-minting/collection-minting_1.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-chunk_14 - path: ./packages/functions/firestore-data/ - retention-days: 1 + npm run start & + npm run notifier & + npm run test -- --findRelatedTests --forceExit ./test-tangle/base-token-trading/base-token-trading_8.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/base-token-trading/base-token-trading_9.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/collection-minting/collection-minting_1.spec.ts chunk_15: needs: npm-install runs-on: ubuntu-latest timeout-minutes: 20 + + services: + postgres: + image: postgres + env: + POSTGRES_DB: build5db + POSTGRES_PASSWORD: postgres + ports: + - 5432:5432 + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 @@ -598,30 +674,34 @@ jobs: packages/interfaces/node_modules key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - name: Init - run: | - npm run build:functions - npm install -g firebase-tools + run: npm run build:functions - name: Test working-directory: packages/functions run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/collection-minting/collection-minting_10.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/collection-minting/collection-minting_11.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/collection-minting/collection-minting_12.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-chunk_15 - path: ./packages/functions/firestore-data/ - retention-days: 1 + npm run start & + npm run notifier & + npm run test -- --findRelatedTests --forceExit ./test-tangle/collection-minting/collection-minting_10.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/collection-minting/collection-minting_11.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/collection-minting/collection-minting_12.spec.ts chunk_16: needs: npm-install runs-on: ubuntu-latest timeout-minutes: 20 + + services: + postgres: + image: postgres + env: + POSTGRES_DB: build5db + POSTGRES_PASSWORD: postgres + ports: + - 5432:5432 + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 @@ -635,30 +715,34 @@ jobs: packages/interfaces/node_modules key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - name: Init - run: | - npm run build:functions - npm install -g firebase-tools + run: npm run build:functions - name: Test working-directory: packages/functions run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/collection-minting/collection-minting_13.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/collection-minting/collection-minting_2.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/collection-minting/collection-minting_4_a.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-chunk_16 - path: ./packages/functions/firestore-data/ - retention-days: 1 + npm run start & + npm run notifier & + npm run test -- --findRelatedTests --forceExit ./test-tangle/collection-minting/collection-minting_13.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/collection-minting/collection-minting_2.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/collection-minting/collection-minting_4_a.spec.ts chunk_17: needs: npm-install runs-on: ubuntu-latest timeout-minutes: 20 + + services: + postgres: + image: postgres + env: + POSTGRES_DB: build5db + POSTGRES_PASSWORD: postgres + ports: + - 5432:5432 + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 @@ -672,30 +756,34 @@ jobs: packages/interfaces/node_modules key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - name: Init - run: | - npm run build:functions - npm install -g firebase-tools + run: npm run build:functions - name: Test working-directory: packages/functions run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/collection-minting/collection-minting_4_b.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/collection-minting/collection-minting_4_c.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/collection-minting/collection-minting_5.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-chunk_17 - path: ./packages/functions/firestore-data/ - retention-days: 1 + npm run start & + npm run notifier & + npm run test -- --findRelatedTests --forceExit ./test-tangle/collection-minting/collection-minting_4_b.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/collection-minting/collection-minting_4_c.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/collection-minting/collection-minting_5.spec.ts chunk_18: needs: npm-install runs-on: ubuntu-latest timeout-minutes: 20 + + services: + postgres: + image: postgres + env: + POSTGRES_DB: build5db + POSTGRES_PASSWORD: postgres + ports: + - 5432:5432 + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 @@ -709,30 +797,34 @@ jobs: packages/interfaces/node_modules key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - name: Init - run: | - npm run build:functions - npm install -g firebase-tools + run: npm run build:functions - name: Test working-directory: packages/functions run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/collection-minting/collection-minting_6.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/collection-minting/collection-minting_7.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/collection-minting/collection-minting_8.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-chunk_18 - path: ./packages/functions/firestore-data/ - retention-days: 1 + npm run start & + npm run notifier & + npm run test -- --findRelatedTests --forceExit ./test-tangle/collection-minting/collection-minting_6.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/collection-minting/collection-minting_7.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/collection-minting/collection-minting_8.spec.ts chunk_19: needs: npm-install runs-on: ubuntu-latest timeout-minutes: 20 + + services: + postgres: + image: postgres + env: + POSTGRES_DB: build5db + POSTGRES_PASSWORD: postgres + ports: + - 5432:5432 + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 @@ -746,30 +838,34 @@ jobs: packages/interfaces/node_modules key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - name: Init - run: | - npm run build:functions - npm install -g firebase-tools + run: npm run build:functions - name: Test working-directory: packages/functions run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/collection-minting/collection-minting_9.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/metadata-nft/mint-metadata-nft_1_b.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/metadata-nft/mint-metadata-nft_1.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-chunk_19 - path: ./packages/functions/firestore-data/ - retention-days: 1 + npm run start & + npm run notifier & + npm run test -- --findRelatedTests --forceExit ./test-tangle/collection-minting/collection-minting_9.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/metadata-nft/mint-metadata-nft_1_b.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/metadata-nft/mint-metadata-nft_1.spec.ts chunk_20: needs: npm-install runs-on: ubuntu-latest timeout-minutes: 20 + + services: + postgres: + image: postgres + env: + POSTGRES_DB: build5db + POSTGRES_PASSWORD: postgres + ports: + - 5432:5432 + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 @@ -783,30 +879,34 @@ jobs: packages/interfaces/node_modules key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - name: Init - run: | - npm run build:functions - npm install -g firebase-tools + run: npm run build:functions - name: Test working-directory: packages/functions run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/metadata-nft/mint-metadata-nft_10.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/metadata-nft/mint-metadata-nft_2.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/metadata-nft/mint-metadata-nft_3_b.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-chunk_20 - path: ./packages/functions/firestore-data/ - retention-days: 1 + npm run start & + npm run notifier & + npm run test -- --findRelatedTests --forceExit ./test-tangle/metadata-nft/mint-metadata-nft_10.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/metadata-nft/mint-metadata-nft_2.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/metadata-nft/mint-metadata-nft_3_b.spec.ts chunk_21: needs: npm-install runs-on: ubuntu-latest timeout-minutes: 20 + + services: + postgres: + image: postgres + env: + POSTGRES_DB: build5db + POSTGRES_PASSWORD: postgres + ports: + - 5432:5432 + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 @@ -820,30 +920,34 @@ jobs: packages/interfaces/node_modules key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - name: Init - run: | - npm run build:functions - npm install -g firebase-tools + run: npm run build:functions - name: Test working-directory: packages/functions run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/metadata-nft/mint-metadata-nft_3.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/metadata-nft/mint-metadata-nft_4.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/metadata-nft/mint-metadata-nft_5_b.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-chunk_21 - path: ./packages/functions/firestore-data/ - retention-days: 1 + npm run start & + npm run notifier & + npm run test -- --findRelatedTests --forceExit ./test-tangle/metadata-nft/mint-metadata-nft_3.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/metadata-nft/mint-metadata-nft_4.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/metadata-nft/mint-metadata-nft_5_b.spec.ts chunk_22: needs: npm-install runs-on: ubuntu-latest timeout-minutes: 20 + + services: + postgres: + image: postgres + env: + POSTGRES_DB: build5db + POSTGRES_PASSWORD: postgres + ports: + - 5432:5432 + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 @@ -857,30 +961,34 @@ jobs: packages/interfaces/node_modules key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - name: Init - run: | - npm run build:functions - npm install -g firebase-tools + run: npm run build:functions - name: Test working-directory: packages/functions run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/metadata-nft/mint-metadata-nft_5.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/metadata-nft/mint-metadata-nft_6.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/metadata-nft/mint-metadata-nft_7.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-chunk_22 - path: ./packages/functions/firestore-data/ - retention-days: 1 + npm run start & + npm run notifier & + npm run test -- --findRelatedTests --forceExit ./test-tangle/metadata-nft/mint-metadata-nft_5.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/metadata-nft/mint-metadata-nft_6.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/metadata-nft/mint-metadata-nft_7.spec.ts chunk_23: needs: npm-install runs-on: ubuntu-latest timeout-minutes: 20 + + services: + postgres: + image: postgres + env: + POSTGRES_DB: build5db + POSTGRES_PASSWORD: postgres + ports: + - 5432:5432 + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 @@ -894,30 +1002,34 @@ jobs: packages/interfaces/node_modules key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - name: Init - run: | - npm run build:functions - npm install -g firebase-tools + run: npm run build:functions - name: Test working-directory: packages/functions run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/metadata-nft/mint-metadata-nft_8.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/metadata-nft/mint-metadata-nft_9.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/minted-nft-trading/minted-nft-trading_1_b.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-chunk_23 - path: ./packages/functions/firestore-data/ - retention-days: 1 + npm run start & + npm run notifier & + npm run test -- --findRelatedTests --forceExit ./test-tangle/metadata-nft/mint-metadata-nft_8.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/metadata-nft/mint-metadata-nft_9.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/minted-nft-trading/minted-nft-trading_1_b.spec.ts chunk_24: needs: npm-install runs-on: ubuntu-latest timeout-minutes: 20 + + services: + postgres: + image: postgres + env: + POSTGRES_DB: build5db + POSTGRES_PASSWORD: postgres + ports: + - 5432:5432 + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 @@ -931,30 +1043,34 @@ jobs: packages/interfaces/node_modules key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - name: Init - run: | - npm run build:functions - npm install -g firebase-tools + run: npm run build:functions - name: Test working-directory: packages/functions run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/minted-nft-trading/minted-nft-trading_1.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/minted-nft-trading/minted-nft-trading_10.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/minted-nft-trading/minted-nft-trading_2.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-chunk_24 - path: ./packages/functions/firestore-data/ - retention-days: 1 + npm run start & + npm run notifier & + npm run test -- --findRelatedTests --forceExit ./test-tangle/minted-nft-trading/minted-nft-trading_1.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/minted-nft-trading/minted-nft-trading_10.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/minted-nft-trading/minted-nft-trading_2.spec.ts chunk_25: needs: npm-install runs-on: ubuntu-latest timeout-minutes: 20 + + services: + postgres: + image: postgres + env: + POSTGRES_DB: build5db + POSTGRES_PASSWORD: postgres + ports: + - 5432:5432 + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 @@ -968,30 +1084,34 @@ jobs: packages/interfaces/node_modules key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - name: Init - run: | - npm run build:functions - npm install -g firebase-tools + run: npm run build:functions - name: Test working-directory: packages/functions run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/minted-nft-trading/minted-nft-trading_3.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/minted-nft-trading/minted-nft-trading_4.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/minted-nft-trading/minted-nft-trading_5.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-chunk_25 - path: ./packages/functions/firestore-data/ - retention-days: 1 + npm run start & + npm run notifier & + npm run test -- --findRelatedTests --forceExit ./test-tangle/minted-nft-trading/minted-nft-trading_3.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/minted-nft-trading/minted-nft-trading_4.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/minted-nft-trading/minted-nft-trading_5.spec.ts chunk_26: needs: npm-install runs-on: ubuntu-latest timeout-minutes: 20 + + services: + postgres: + image: postgres + env: + POSTGRES_DB: build5db + POSTGRES_PASSWORD: postgres + ports: + - 5432:5432 + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 @@ -1005,30 +1125,34 @@ jobs: packages/interfaces/node_modules key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - name: Init - run: | - npm run build:functions - npm install -g firebase-tools + run: npm run build:functions - name: Test working-directory: packages/functions run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/minted-nft-trading/minted-nft-trading_6.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/minted-nft-trading/minted-nft-trading_7.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/minted-nft-trading/minted-nft-trading_8.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-chunk_26 - path: ./packages/functions/firestore-data/ - retention-days: 1 + npm run start & + npm run notifier & + npm run test -- --findRelatedTests --forceExit ./test-tangle/minted-nft-trading/minted-nft-trading_6.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/minted-nft-trading/minted-nft-trading_7.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/minted-nft-trading/minted-nft-trading_8.spec.ts chunk_27: needs: npm-install runs-on: ubuntu-latest timeout-minutes: 20 + + services: + postgres: + image: postgres + env: + POSTGRES_DB: build5db + POSTGRES_PASSWORD: postgres + ports: + - 5432:5432 + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 @@ -1042,30 +1166,34 @@ jobs: packages/interfaces/node_modules key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - name: Init - run: | - npm run build:functions - npm install -g firebase-tools + run: npm run build:functions - name: Test working-directory: packages/functions run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/minted-token-airdrop/minted-token-airdrop_1_a.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/minted-token-airdrop/minted-token-airdrop_1_b.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/minted-token-airdrop/minted-token-airdrop_1_c.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-chunk_27 - path: ./packages/functions/firestore-data/ - retention-days: 1 + npm run start & + npm run notifier & + npm run test -- --findRelatedTests --forceExit ./test-tangle/minted-token-airdrop/minted-token-airdrop_1_a.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/minted-token-airdrop/minted-token-airdrop_1_b.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/minted-token-airdrop/minted-token-airdrop_1_c.spec.ts chunk_28: needs: npm-install runs-on: ubuntu-latest timeout-minutes: 20 + + services: + postgres: + image: postgres + env: + POSTGRES_DB: build5db + POSTGRES_PASSWORD: postgres + ports: + - 5432:5432 + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 @@ -1079,30 +1207,34 @@ jobs: packages/interfaces/node_modules key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - name: Init - run: | - npm run build:functions - npm install -g firebase-tools + run: npm run build:functions - name: Test working-directory: packages/functions run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/minted-token-airdrop/minted-token-airdrop_2.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/minted-token-airdrop/minted-token-airdrop_4.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/minted-token-airdrop/minted-token-airdrop_5.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-chunk_28 - path: ./packages/functions/firestore-data/ - retention-days: 1 + npm run start & + npm run notifier & + npm run test -- --findRelatedTests --forceExit ./test-tangle/minted-token-airdrop/minted-token-airdrop_2.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/minted-token-airdrop/minted-token-airdrop_4.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/minted-token-airdrop/minted-token-airdrop_5.spec.ts chunk_29: needs: npm-install runs-on: ubuntu-latest timeout-minutes: 20 + + services: + postgres: + image: postgres + env: + POSTGRES_DB: build5db + POSTGRES_PASSWORD: postgres + ports: + - 5432:5432 + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 @@ -1116,30 +1248,34 @@ jobs: packages/interfaces/node_modules key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - name: Init - run: | - npm run build:functions - npm install -g firebase-tools + run: npm run build:functions - name: Test working-directory: packages/functions run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/minted-token-claim/token.claim.minted_1.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/minted-token-claim/token.claim.minted_2.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/minted-token-claim/token.claim.minted_3.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-chunk_29 - path: ./packages/functions/firestore-data/ - retention-days: 1 + npm run start & + npm run notifier & + npm run test -- --findRelatedTests --forceExit ./test-tangle/minted-token-claim/token.claim.minted_1.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/minted-token-claim/token.claim.minted_2.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/minted-token-claim/token.claim.minted_3.spec.ts chunk_30: needs: npm-install runs-on: ubuntu-latest timeout-minutes: 20 + + services: + postgres: + image: postgres + env: + POSTGRES_DB: build5db + POSTGRES_PASSWORD: postgres + ports: + - 5432:5432 + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 @@ -1153,30 +1289,34 @@ jobs: packages/interfaces/node_modules key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - name: Init - run: | - npm run build:functions - npm install -g firebase-tools + run: npm run build:functions - name: Test working-directory: packages/functions run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/minted-token-claim/token.claim.minted_4.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/minted-token-claim/token.claim.minted_5.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/minted-token-claim/token.claim.minted_6.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-chunk_30 - path: ./packages/functions/firestore-data/ - retention-days: 1 + npm run start & + npm run notifier & + npm run test -- --findRelatedTests --forceExit ./test-tangle/minted-token-claim/token.claim.minted_4.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/minted-token-claim/token.claim.minted_5.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/minted-token-claim/token.claim.minted_6.spec.ts chunk_31: needs: npm-install runs-on: ubuntu-latest timeout-minutes: 20 + + services: + postgres: + image: postgres + env: + POSTGRES_DB: build5db + POSTGRES_PASSWORD: postgres + ports: + - 5432:5432 + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 @@ -1190,30 +1330,34 @@ jobs: packages/interfaces/node_modules key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - name: Init - run: | - npm run build:functions - npm install -g firebase-tools + run: npm run build:functions - name: Test working-directory: packages/functions run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/minted-token-claim/token.claim.minted_7.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/minted-token-trade/minted-token-trade_1.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/minted-token-trade/minted-token-trade_10.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-chunk_31 - path: ./packages/functions/firestore-data/ - retention-days: 1 + npm run start & + npm run notifier & + npm run test -- --findRelatedTests --forceExit ./test-tangle/minted-token-claim/token.claim.minted_7.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/minted-token-trade/minted-token-trade_1.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/minted-token-trade/minted-token-trade_10.spec.ts chunk_32: needs: npm-install runs-on: ubuntu-latest timeout-minutes: 20 + + services: + postgres: + image: postgres + env: + POSTGRES_DB: build5db + POSTGRES_PASSWORD: postgres + ports: + - 5432:5432 + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 @@ -1227,30 +1371,34 @@ jobs: packages/interfaces/node_modules key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - name: Init - run: | - npm run build:functions - npm install -g firebase-tools + run: npm run build:functions - name: Test working-directory: packages/functions run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/minted-token-trade/minted-token-trade_11.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/minted-token-trade/minted-token-trade_12_b.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/minted-token-trade/minted-token-trade_12.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-chunk_32 - path: ./packages/functions/firestore-data/ - retention-days: 1 + npm run start & + npm run notifier & + npm run test -- --findRelatedTests --forceExit ./test-tangle/minted-token-trade/minted-token-trade_11.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/minted-token-trade/minted-token-trade_12_b.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/minted-token-trade/minted-token-trade_12.spec.ts chunk_33: needs: npm-install runs-on: ubuntu-latest timeout-minutes: 20 + + services: + postgres: + image: postgres + env: + POSTGRES_DB: build5db + POSTGRES_PASSWORD: postgres + ports: + - 5432:5432 + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 @@ -1264,30 +1412,34 @@ jobs: packages/interfaces/node_modules key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - name: Init - run: | - npm run build:functions - npm install -g firebase-tools + run: npm run build:functions - name: Test working-directory: packages/functions run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/minted-token-trade/minted-token-trade_13.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/minted-token-trade/minted-token-trade_14_b.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/minted-token-trade/minted-token-trade_14.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-chunk_33 - path: ./packages/functions/firestore-data/ - retention-days: 1 + npm run start & + npm run notifier & + npm run test -- --findRelatedTests --forceExit ./test-tangle/minted-token-trade/minted-token-trade_13.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/minted-token-trade/minted-token-trade_14_b.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/minted-token-trade/minted-token-trade_14.spec.ts chunk_34: needs: npm-install runs-on: ubuntu-latest timeout-minutes: 20 + + services: + postgres: + image: postgres + env: + POSTGRES_DB: build5db + POSTGRES_PASSWORD: postgres + ports: + - 5432:5432 + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 @@ -1301,30 +1453,34 @@ jobs: packages/interfaces/node_modules key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - name: Init - run: | - npm run build:functions - npm install -g firebase-tools + run: npm run build:functions - name: Test working-directory: packages/functions run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/minted-token-trade/minted-token-trade_16.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/minted-token-trade/minted-token-trade_17.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/minted-token-trade/minted-token-trade_18.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-chunk_34 - path: ./packages/functions/firestore-data/ - retention-days: 1 + npm run start & + npm run notifier & + npm run test -- --findRelatedTests --forceExit ./test-tangle/minted-token-trade/minted-token-trade_16.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/minted-token-trade/minted-token-trade_17.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/minted-token-trade/minted-token-trade_18.spec.ts chunk_35: needs: npm-install runs-on: ubuntu-latest timeout-minutes: 20 + + services: + postgres: + image: postgres + env: + POSTGRES_DB: build5db + POSTGRES_PASSWORD: postgres + ports: + - 5432:5432 + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 @@ -1338,30 +1494,34 @@ jobs: packages/interfaces/node_modules key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - name: Init - run: | - npm run build:functions - npm install -g firebase-tools + run: npm run build:functions - name: Test working-directory: packages/functions run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/minted-token-trade/minted-token-trade_19.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/minted-token-trade/minted-token-trade_2_b.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/minted-token-trade/minted-token-trade_2.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-chunk_35 - path: ./packages/functions/firestore-data/ - retention-days: 1 + npm run start & + npm run notifier & + npm run test -- --findRelatedTests --forceExit ./test-tangle/minted-token-trade/minted-token-trade_19.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/minted-token-trade/minted-token-trade_2_b.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/minted-token-trade/minted-token-trade_2.spec.ts chunk_36: needs: npm-install runs-on: ubuntu-latest timeout-minutes: 20 + + services: + postgres: + image: postgres + env: + POSTGRES_DB: build5db + POSTGRES_PASSWORD: postgres + ports: + - 5432:5432 + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 @@ -1375,30 +1535,34 @@ jobs: packages/interfaces/node_modules key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - name: Init - run: | - npm run build:functions - npm install -g firebase-tools + run: npm run build:functions - name: Test working-directory: packages/functions run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/minted-token-trade/minted-token-trade_20.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/minted-token-trade/minted-token-trade_21.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/minted-token-trade/minted-token-trade_22.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-chunk_36 - path: ./packages/functions/firestore-data/ - retention-days: 1 + npm run start & + npm run notifier & + npm run test -- --findRelatedTests --forceExit ./test-tangle/minted-token-trade/minted-token-trade_20.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/minted-token-trade/minted-token-trade_21.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/minted-token-trade/minted-token-trade_22.spec.ts chunk_37: needs: npm-install runs-on: ubuntu-latest timeout-minutes: 20 + + services: + postgres: + image: postgres + env: + POSTGRES_DB: build5db + POSTGRES_PASSWORD: postgres + ports: + - 5432:5432 + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 @@ -1412,30 +1576,34 @@ jobs: packages/interfaces/node_modules key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - name: Init - run: | - npm run build:functions - npm install -g firebase-tools + run: npm run build:functions - name: Test working-directory: packages/functions run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/minted-token-trade/minted-token-trade_23.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/minted-token-trade/minted-token-trade_24.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/minted-token-trade/minted-token-trade_3.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-chunk_37 - path: ./packages/functions/firestore-data/ - retention-days: 1 + npm run start & + npm run notifier & + npm run test -- --findRelatedTests --forceExit ./test-tangle/minted-token-trade/minted-token-trade_23.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/minted-token-trade/minted-token-trade_24.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/minted-token-trade/minted-token-trade_3.spec.ts chunk_38: needs: npm-install runs-on: ubuntu-latest timeout-minutes: 20 + + services: + postgres: + image: postgres + env: + POSTGRES_DB: build5db + POSTGRES_PASSWORD: postgres + ports: + - 5432:5432 + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 @@ -1449,30 +1617,34 @@ jobs: packages/interfaces/node_modules key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - name: Init - run: | - npm run build:functions - npm install -g firebase-tools + run: npm run build:functions - name: Test working-directory: packages/functions run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/minted-token-trade/minted-token-trade_4.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/minted-token-trade/minted-token-trade_5.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/minted-token-trade/minted-token-trade_6.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-chunk_38 - path: ./packages/functions/firestore-data/ - retention-days: 1 + npm run start & + npm run notifier & + npm run test -- --findRelatedTests --forceExit ./test-tangle/minted-token-trade/minted-token-trade_4.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/minted-token-trade/minted-token-trade_5.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/minted-token-trade/minted-token-trade_6.spec.ts chunk_39: needs: npm-install runs-on: ubuntu-latest timeout-minutes: 20 + + services: + postgres: + image: postgres + env: + POSTGRES_DB: build5db + POSTGRES_PASSWORD: postgres + ports: + - 5432:5432 + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 @@ -1486,30 +1658,34 @@ jobs: packages/interfaces/node_modules key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - name: Init - run: | - npm run build:functions - npm install -g firebase-tools + run: npm run build:functions - name: Test working-directory: packages/functions run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/minted-token-trade/minted-token-trade_7.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/minted-token-trade/minted-token-trade_8.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/minted-token-trade/minted-token-trade_9.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-chunk_39 - path: ./packages/functions/firestore-data/ - retention-days: 1 + npm run start & + npm run notifier & + npm run test -- --findRelatedTests --forceExit ./test-tangle/minted-token-trade/minted-token-trade_7.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/minted-token-trade/minted-token-trade_8.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/minted-token-trade/minted-token-trade_9.spec.ts chunk_40: needs: npm-install runs-on: ubuntu-latest timeout-minutes: 20 + + services: + postgres: + image: postgres + env: + POSTGRES_DB: build5db + POSTGRES_PASSWORD: postgres + ports: + - 5432:5432 + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 @@ -1523,30 +1699,34 @@ jobs: packages/interfaces/node_modules key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - name: Init - run: | - npm run build:functions - npm install -g firebase-tools + run: npm run build:functions - name: Test working-directory: packages/functions run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/nft-bid/nft-bid.otr_1.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/nft-bid/nft-bid.otr_2.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/nft-bid/nft-bid.otr_3.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-chunk_40 - path: ./packages/functions/firestore-data/ - retention-days: 1 + npm run start & + npm run notifier & + npm run test -- --findRelatedTests --forceExit ./test-tangle/nft-bid/nft-bid.otr_1.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/nft-bid/nft-bid.otr_2.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/nft-bid/nft-bid.otr_3.spec.ts chunk_41: needs: npm-install runs-on: ubuntu-latest timeout-minutes: 20 + + services: + postgres: + image: postgres + env: + POSTGRES_DB: build5db + POSTGRES_PASSWORD: postgres + ports: + - 5432:5432 + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 @@ -1560,30 +1740,34 @@ jobs: packages/interfaces/node_modules key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - name: Init - run: | - npm run build:functions - npm install -g firebase-tools + run: npm run build:functions - name: Test working-directory: packages/functions run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/nft-bid/nft-bid.otr_4.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/nft-bulk/order.bulk_1.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/nft-bulk/order.bulk_2.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-chunk_41 - path: ./packages/functions/firestore-data/ - retention-days: 1 + npm run start & + npm run notifier & + npm run test -- --findRelatedTests --forceExit ./test-tangle/nft-bid/nft-bid.otr_4.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/nft-bulk/order.bulk_1.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/nft-bulk/order.bulk_2.spec.ts chunk_42: needs: npm-install runs-on: ubuntu-latest timeout-minutes: 20 + + services: + postgres: + image: postgres + env: + POSTGRES_DB: build5db + POSTGRES_PASSWORD: postgres + ports: + - 5432:5432 + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 @@ -1597,30 +1781,34 @@ jobs: packages/interfaces/node_modules key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - name: Init - run: | - npm run build:functions - npm install -g firebase-tools + run: npm run build:functions - name: Test working-directory: packages/functions run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/nft-bulk/order.bulk_3.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/nft-bulk/order.bulk_4.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/nft-bulk/order.bulk_5.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-chunk_42 - path: ./packages/functions/firestore-data/ - retention-days: 1 + npm run start & + npm run notifier & + npm run test -- --findRelatedTests --forceExit ./test-tangle/nft-bulk/order.bulk_3.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/nft-bulk/order.bulk_4.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/nft-bulk/order.bulk_5.spec.ts chunk_43: needs: npm-install runs-on: ubuntu-latest timeout-minutes: 20 + + services: + postgres: + image: postgres + env: + POSTGRES_DB: build5db + POSTGRES_PASSWORD: postgres + ports: + - 5432:5432 + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 @@ -1634,30 +1822,34 @@ jobs: packages/interfaces/node_modules key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - name: Init - run: | - npm run build:functions - npm install -g firebase-tools + run: npm run build:functions - name: Test working-directory: packages/functions run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/nft-bulk/order.bulk_6.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/nft-set-for-sale/nft-set-for-sale_1.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/nft-set-for-sale/nft-set-for-sale_2.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-chunk_43 - path: ./packages/functions/firestore-data/ - retention-days: 1 + npm run start & + npm run notifier & + npm run test -- --findRelatedTests --forceExit ./test-tangle/nft-bulk/order.bulk_6.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/nft-set-for-sale/nft-set-for-sale_1.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/nft-set-for-sale/nft-set-for-sale_2.spec.ts chunk_44: needs: npm-install runs-on: ubuntu-latest timeout-minutes: 20 + + services: + postgres: + image: postgres + env: + POSTGRES_DB: build5db + POSTGRES_PASSWORD: postgres + ports: + - 5432:5432 + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 @@ -1671,30 +1863,34 @@ jobs: packages/interfaces/node_modules key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - name: Init - run: | - npm run build:functions - npm install -g firebase-tools + run: npm run build:functions - name: Test working-directory: packages/functions run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/nft-set-for-sale/nft-set-for-sale_3.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/nft-staking/nft-staking_1.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/nft-staking/nft-staking_10.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-chunk_44 - path: ./packages/functions/firestore-data/ - retention-days: 1 + npm run start & + npm run notifier & + npm run test -- --findRelatedTests --forceExit ./test-tangle/nft-set-for-sale/nft-set-for-sale_3.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/nft-staking/nft-staking_1.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/nft-staking/nft-staking_10.spec.ts chunk_45: needs: npm-install runs-on: ubuntu-latest timeout-minutes: 20 + + services: + postgres: + image: postgres + env: + POSTGRES_DB: build5db + POSTGRES_PASSWORD: postgres + ports: + - 5432:5432 + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 @@ -1708,30 +1904,34 @@ jobs: packages/interfaces/node_modules key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - name: Init - run: | - npm run build:functions - npm install -g firebase-tools + run: npm run build:functions - name: Test working-directory: packages/functions run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/nft-staking/nft-staking_2_b.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/nft-staking/nft-staking_2.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/nft-staking/nft-staking_3.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-chunk_45 - path: ./packages/functions/firestore-data/ - retention-days: 1 + npm run start & + npm run notifier & + npm run test -- --findRelatedTests --forceExit ./test-tangle/nft-staking/nft-staking_2_b.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/nft-staking/nft-staking_2.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/nft-staking/nft-staking_3.spec.ts chunk_46: needs: npm-install runs-on: ubuntu-latest timeout-minutes: 20 + + services: + postgres: + image: postgres + env: + POSTGRES_DB: build5db + POSTGRES_PASSWORD: postgres + ports: + - 5432:5432 + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 @@ -1745,30 +1945,34 @@ jobs: packages/interfaces/node_modules key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - name: Init - run: | - npm run build:functions - npm install -g firebase-tools + run: npm run build:functions - name: Test working-directory: packages/functions run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/nft-staking/nft-staking_4.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/nft-staking/nft-staking_5.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/nft-staking/nft-staking_6.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-chunk_46 - path: ./packages/functions/firestore-data/ - retention-days: 1 + npm run start & + npm run notifier & + npm run test -- --findRelatedTests --forceExit ./test-tangle/nft-staking/nft-staking_4.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/nft-staking/nft-staking_5.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/nft-staking/nft-staking_6.spec.ts chunk_47: needs: npm-install runs-on: ubuntu-latest timeout-minutes: 20 + + services: + postgres: + image: postgres + env: + POSTGRES_DB: build5db + POSTGRES_PASSWORD: postgres + ports: + - 5432:5432 + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 @@ -1782,30 +1986,34 @@ jobs: packages/interfaces/node_modules key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - name: Init - run: | - npm run build:functions - npm install -g firebase-tools + run: npm run build:functions - name: Test working-directory: packages/functions run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/nft-staking/nft-staking_7.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/nft-staking/nft-staking_8.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/nft-staking/nft-staking_9.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-chunk_47 - path: ./packages/functions/firestore-data/ - retention-days: 1 + npm run start & + npm run notifier & + npm run test -- --findRelatedTests --forceExit ./test-tangle/nft-staking/nft-staking_7.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/nft-staking/nft-staking_8.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/nft-staking/nft-staking_9.spec.ts chunk_48: needs: npm-install runs-on: ubuntu-latest timeout-minutes: 20 + + services: + postgres: + image: postgres + env: + POSTGRES_DB: build5db + POSTGRES_PASSWORD: postgres + ports: + - 5432:5432 + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 @@ -1819,30 +2027,34 @@ jobs: packages/interfaces/node_modules key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - name: Init - run: | - npm run build:functions - npm install -g firebase-tools + run: npm run build:functions - name: Test working-directory: packages/functions run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/nft-transfer/nft-transfer_1.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/nft-transfer/nft-transfer_2.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/nft-transfer/nft-transfer_3.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-chunk_48 - path: ./packages/functions/firestore-data/ - retention-days: 1 + npm run start & + npm run notifier & + npm run test -- --findRelatedTests --forceExit ./test-tangle/nft-transfer/nft-transfer_1.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/nft-transfer/nft-transfer_2.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/nft-transfer/nft-transfer_3.spec.ts chunk_49: needs: npm-install runs-on: ubuntu-latest timeout-minutes: 20 + + services: + postgres: + image: postgres + env: + POSTGRES_DB: build5db + POSTGRES_PASSWORD: postgres + ports: + - 5432:5432 + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 @@ -1856,30 +2068,34 @@ jobs: packages/interfaces/node_modules key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - name: Init - run: | - npm run build:functions - npm install -g firebase-tools + run: npm run build:functions - name: Test working-directory: packages/functions run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/nft-transfer/nft-transfer_4.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/nft-transfer/nft-transfer_5.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/nft-transfer/nft-transfer_6.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-chunk_49 - path: ./packages/functions/firestore-data/ - retention-days: 1 + npm run start & + npm run notifier & + npm run test -- --findRelatedTests --forceExit ./test-tangle/nft-transfer/nft-transfer_4.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/nft-transfer/nft-transfer_5.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/nft-transfer/nft-transfer_6.spec.ts chunk_50: needs: npm-install runs-on: ubuntu-latest timeout-minutes: 20 + + services: + postgres: + image: postgres + env: + POSTGRES_DB: build5db + POSTGRES_PASSWORD: postgres + ports: + - 5432:5432 + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 @@ -1893,30 +2109,34 @@ jobs: packages/interfaces/node_modules key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - name: Init - run: | - npm run build:functions - npm install -g firebase-tools + run: npm run build:functions - name: Test working-directory: packages/functions run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/nft-transfer/nft-transfer_7.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/nft-transfer/nft-transfer_8.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/proposal-tangle/proposal.approval.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-chunk_50 - path: ./packages/functions/firestore-data/ - retention-days: 1 + npm run start & + npm run notifier & + npm run test -- --findRelatedTests --forceExit ./test-tangle/nft-transfer/nft-transfer_7.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/nft-transfer/nft-transfer_8.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/proposal-tangle/proposal.approval.spec.ts chunk_51: needs: npm-install runs-on: ubuntu-latest timeout-minutes: 20 + + services: + postgres: + image: postgres + env: + POSTGRES_DB: build5db + POSTGRES_PASSWORD: postgres + ports: + - 5432:5432 + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 @@ -1930,30 +2150,34 @@ jobs: packages/interfaces/node_modules key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - name: Init - run: | - npm run build:functions - npm install -g firebase-tools + run: npm run build:functions - name: Test working-directory: packages/functions run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/proposal-tangle/proposal.create.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/proposal-tangle/proposal.simple.vote.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/proposal-tangle/proposal.stake.voting.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-chunk_51 - path: ./packages/functions/firestore-data/ - retention-days: 1 + npm run start & + npm run notifier & + npm run test -- --findRelatedTests --forceExit ./test-tangle/proposal-tangle/proposal.create.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/proposal-tangle/proposal.simple.vote.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/proposal-tangle/proposal.stake.voting.spec.ts chunk_52: needs: npm-install runs-on: ubuntu-latest timeout-minutes: 20 + + services: + postgres: + image: postgres + env: + POSTGRES_DB: build5db + POSTGRES_PASSWORD: postgres + ports: + - 5432:5432 + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 @@ -1967,30 +2191,34 @@ jobs: packages/interfaces/node_modules key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - name: Init - run: | - npm run build:functions - npm install -g firebase-tools + run: npm run build:functions - name: Test working-directory: packages/functions run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/proposal-tangle/proposal.token.voting.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/space-tangle/space.accept.member.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/space-tangle/space.block.member.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-chunk_52 - path: ./packages/functions/firestore-data/ - retention-days: 1 + npm run start & + npm run notifier & + npm run test -- --findRelatedTests --forceExit ./test-tangle/proposal-tangle/proposal.token.voting.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/space-tangle/space.accept.member.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/space-tangle/space.block.member.spec.ts chunk_53: needs: npm-install runs-on: ubuntu-latest timeout-minutes: 20 + + services: + postgres: + image: postgres + env: + POSTGRES_DB: build5db + POSTGRES_PASSWORD: postgres + ports: + - 5432:5432 + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 @@ -2004,30 +2232,34 @@ jobs: packages/interfaces/node_modules key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - name: Init - run: | - npm run build:functions - npm install -g firebase-tools + run: npm run build:functions - name: Test working-directory: packages/functions run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/space-tangle/space.create.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/space-tangle/space.decline.member.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/space-tangle/space.edit.guardian.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-chunk_53 - path: ./packages/functions/firestore-data/ - retention-days: 1 + npm run start & + npm run notifier & + npm run test -- --findRelatedTests --forceExit ./test-tangle/space-tangle/space.create.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/space-tangle/space.decline.member.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/space-tangle/space.edit.guardian.spec.ts chunk_54: needs: npm-install runs-on: ubuntu-latest timeout-minutes: 20 + + services: + postgres: + image: postgres + env: + POSTGRES_DB: build5db + POSTGRES_PASSWORD: postgres + ports: + - 5432:5432 + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 @@ -2041,30 +2273,34 @@ jobs: packages/interfaces/node_modules key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - name: Init - run: | - npm run build:functions - npm install -g firebase-tools + run: npm run build:functions - name: Test working-directory: packages/functions run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/space-tangle/space.join.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/space-tangle/space.leave.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/staking/staking_1.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-chunk_54 - path: ./packages/functions/firestore-data/ - retention-days: 1 + npm run start & + npm run notifier & + npm run test -- --findRelatedTests --forceExit ./test-tangle/space-tangle/space.join.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/space-tangle/space.leave.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/staking/staking_1.spec.ts chunk_55: needs: npm-install runs-on: ubuntu-latest timeout-minutes: 20 + + services: + postgres: + image: postgres + env: + POSTGRES_DB: build5db + POSTGRES_PASSWORD: postgres + ports: + - 5432:5432 + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 @@ -2078,30 +2314,34 @@ jobs: packages/interfaces/node_modules key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - name: Init - run: | - npm run build:functions - npm install -g firebase-tools + run: npm run build:functions - name: Test working-directory: packages/functions run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/staking/staking_2.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/staking/staking_3.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/staking/staking_4.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-chunk_55 - path: ./packages/functions/firestore-data/ - retention-days: 1 + npm run start & + npm run notifier & + npm run test -- --findRelatedTests --forceExit ./test-tangle/staking/staking_2.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/staking/staking_3.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/staking/staking_4.spec.ts chunk_56: needs: npm-install runs-on: ubuntu-latest timeout-minutes: 20 + + services: + postgres: + image: postgres + env: + POSTGRES_DB: build5db + POSTGRES_PASSWORD: postgres + ports: + - 5432:5432 + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 @@ -2115,30 +2355,34 @@ jobs: packages/interfaces/node_modules key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - name: Init - run: | - npm run build:functions - npm install -g firebase-tools + run: npm run build:functions - name: Test working-directory: packages/functions run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/staking/staking_5.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/stamp-tangle/stamp-tangle_1_a.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/stamp-tangle/stamp-tangle_1_b.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-chunk_56 - path: ./packages/functions/firestore-data/ - retention-days: 1 + npm run start & + npm run notifier & + npm run test -- --findRelatedTests --forceExit ./test-tangle/staking/staking_5.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/stamp-tangle/stamp-tangle_1_a.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/stamp-tangle/stamp-tangle_1_b.spec.ts chunk_57: needs: npm-install runs-on: ubuntu-latest timeout-minutes: 20 + + services: + postgres: + image: postgres + env: + POSTGRES_DB: build5db + POSTGRES_PASSWORD: postgres + ports: + - 5432:5432 + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 @@ -2152,30 +2396,34 @@ jobs: packages/interfaces/node_modules key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - name: Init - run: | - npm run build:functions - npm install -g firebase-tools + run: npm run build:functions - name: Test working-directory: packages/functions run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/stamp-tangle/stamp-tangle_2.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/stamp-tangle/stamp-tangle_3.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/stamp-tangle/stamp-tangle_4.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-chunk_57 - path: ./packages/functions/firestore-data/ - retention-days: 1 + npm run start & + npm run notifier & + npm run test -- --findRelatedTests --forceExit ./test-tangle/stamp-tangle/stamp-tangle_2.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/stamp-tangle/stamp-tangle_3.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/stamp-tangle/stamp-tangle_4.spec.ts chunk_58: needs: npm-install runs-on: ubuntu-latest timeout-minutes: 20 + + services: + postgres: + image: postgres + env: + POSTGRES_DB: build5db + POSTGRES_PASSWORD: postgres + ports: + - 5432:5432 + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 @@ -2189,30 +2437,34 @@ jobs: packages/interfaces/node_modules key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - name: Init - run: | - npm run build:functions - npm install -g firebase-tools + run: npm run build:functions - name: Test working-directory: packages/functions run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/stamp-tangle/stamp-tangle_5.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/stamp-tangle/stamp-tangle_6.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/swap/swap_1.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-chunk_58 - path: ./packages/functions/firestore-data/ - retention-days: 1 + npm run start & + npm run notifier & + npm run test -- --findRelatedTests --forceExit ./test-tangle/stamp-tangle/stamp-tangle_5.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/stamp-tangle/stamp-tangle_6.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/swap/swap_1.spec.ts chunk_59: needs: npm-install runs-on: ubuntu-latest timeout-minutes: 20 + + services: + postgres: + image: postgres + env: + POSTGRES_DB: build5db + POSTGRES_PASSWORD: postgres + ports: + - 5432:5432 + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 @@ -2226,30 +2478,34 @@ jobs: packages/interfaces/node_modules key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - name: Init - run: | - npm run build:functions - npm install -g firebase-tools + run: npm run build:functions - name: Test working-directory: packages/functions run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/swap/swap_2.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/swap/swap_3_a.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/swap/swap_3_b.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-chunk_59 - path: ./packages/functions/firestore-data/ - retention-days: 1 + npm run start & + npm run notifier & + npm run test -- --findRelatedTests --forceExit ./test-tangle/swap/swap_2.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/swap/swap_3_a.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/swap/swap_3_b.spec.ts chunk_60: needs: npm-install runs-on: ubuntu-latest timeout-minutes: 20 + + services: + postgres: + image: postgres + env: + POSTGRES_DB: build5db + POSTGRES_PASSWORD: postgres + ports: + - 5432:5432 + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 @@ -2263,30 +2519,34 @@ jobs: packages/interfaces/node_modules key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - name: Init - run: | - npm run build:functions - npm install -g firebase-tools + run: npm run build:functions - name: Test working-directory: packages/functions run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/swap/swap_4.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/swap/swap_5.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/swap/swap_6.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-chunk_60 - path: ./packages/functions/firestore-data/ - retention-days: 1 + npm run start & + npm run notifier & + npm run test -- --findRelatedTests --forceExit ./test-tangle/swap/swap_4.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/swap/swap_5.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/swap/swap_6.spec.ts chunk_61: needs: npm-install runs-on: ubuntu-latest timeout-minutes: 20 + + services: + postgres: + image: postgres + env: + POSTGRES_DB: build5db + POSTGRES_PASSWORD: postgres + ports: + - 5432:5432 + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 @@ -2300,30 +2560,34 @@ jobs: packages/interfaces/node_modules key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - name: Init - run: | - npm run build:functions - npm install -g firebase-tools + run: npm run build:functions - name: Test working-directory: packages/functions run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/swap/swap_7.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/swap/swap_8.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/tangleRequest/simple.token.trade.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-chunk_61 - path: ./packages/functions/firestore-data/ - retention-days: 1 + npm run start & + npm run notifier & + npm run test -- --findRelatedTests --forceExit ./test-tangle/swap/swap_7.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/swap/swap_8.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/tangleRequest/simple.token.trade.spec.ts chunk_62: needs: npm-install runs-on: ubuntu-latest timeout-minutes: 20 + + services: + postgres: + image: postgres + env: + POSTGRES_DB: build5db + POSTGRES_PASSWORD: postgres + ports: + - 5432:5432 + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 @@ -2337,30 +2601,34 @@ jobs: packages/interfaces/node_modules key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - name: Init - run: | - npm run build:functions - npm install -g firebase-tools + run: npm run build:functions - name: Test working-directory: packages/functions run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/tangleRequest/tangle-request.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/token-import/token.import_1.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/token-import/token.import_2.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-chunk_62 - path: ./packages/functions/firestore-data/ - retention-days: 1 + npm run start & + npm run notifier & + npm run test -- --findRelatedTests --forceExit ./test-tangle/tangleRequest/tangle-request.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/token-import/token.import_1.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/token-import/token.import_2.spec.ts chunk_63: needs: npm-install runs-on: ubuntu-latest timeout-minutes: 20 + + services: + postgres: + image: postgres + env: + POSTGRES_DB: build5db + POSTGRES_PASSWORD: postgres + ports: + - 5432:5432 + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 @@ -2374,30 +2642,34 @@ jobs: packages/interfaces/node_modules key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - name: Init - run: | - npm run build:functions - npm install -g firebase-tools + run: npm run build:functions - name: Test working-directory: packages/functions run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/token.based.voting/stake.voting.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/token.based.voting/token.based.voting_1.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/token.based.voting/token.based.voting_2.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-chunk_63 - path: ./packages/functions/firestore-data/ - retention-days: 1 + npm run start & + npm run notifier & + npm run test -- --findRelatedTests --forceExit ./test-tangle/token.based.voting/stake.voting.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/token.based.voting/token.based.voting_1.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/token.based.voting/token.based.voting_2.spec.ts chunk_64: needs: npm-install runs-on: ubuntu-latest timeout-minutes: 20 + + services: + postgres: + image: postgres + env: + POSTGRES_DB: build5db + POSTGRES_PASSWORD: postgres + ports: + - 5432:5432 + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 @@ -2411,30 +2683,34 @@ jobs: packages/interfaces/node_modules key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - name: Init - run: | - npm run build:functions - npm install -g firebase-tools + run: npm run build:functions - name: Test working-directory: packages/functions run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/token.based.voting/token.based.voting_3.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/token.based.voting/token.based.voting_4.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/token.based.voting/token.based.voting_5.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-chunk_64 - path: ./packages/functions/firestore-data/ - retention-days: 1 + npm run start & + npm run notifier & + npm run test -- --findRelatedTests --forceExit ./test-tangle/token.based.voting/token.based.voting_3.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/token.based.voting/token.based.voting_4.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/token.based.voting/token.based.voting_5.spec.ts chunk_65: needs: npm-install runs-on: ubuntu-latest timeout-minutes: 20 + + services: + postgres: + image: postgres + env: + POSTGRES_DB: build5db + POSTGRES_PASSWORD: postgres + ports: + - 5432:5432 + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 @@ -2448,30 +2724,34 @@ jobs: packages/interfaces/node_modules key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - name: Init - run: | - npm run build:functions - npm install -g firebase-tools + run: npm run build:functions - name: Test working-directory: packages/functions run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/token.mint/token.mint_1.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/token.mint/token.mint_2.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/token.mint/token.mint_3.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-chunk_65 - path: ./packages/functions/firestore-data/ - retention-days: 1 + npm run start & + npm run notifier & + npm run test -- --findRelatedTests --forceExit ./test-tangle/token.mint/token.mint_1.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/token.mint/token.mint_2.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/token.mint/token.mint_3.spec.ts chunk_66: needs: npm-install runs-on: ubuntu-latest timeout-minutes: 20 + + services: + postgres: + image: postgres + env: + POSTGRES_DB: build5db + POSTGRES_PASSWORD: postgres + ports: + - 5432:5432 + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 @@ -2485,30 +2765,34 @@ jobs: packages/interfaces/node_modules key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - name: Init - run: | - npm run build:functions - npm install -g firebase-tools + run: npm run build:functions - name: Test working-directory: packages/functions run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/token.mint/token.mint_4.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/trade-base-token-order.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/tran.match.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-chunk_66 - path: ./packages/functions/firestore-data/ - retention-days: 1 + npm run start & + npm run notifier & + npm run test -- --findRelatedTests --forceExit ./test-tangle/token.mint/token.mint_4.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/trade-base-token-order.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/tran.match.spec.ts chunk_67: needs: npm-install runs-on: ubuntu-latest timeout-minutes: 20 + + services: + postgres: + image: postgres + env: + POSTGRES_DB: build5db + POSTGRES_PASSWORD: postgres + ports: + - 5432:5432 + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 @@ -2522,30 +2806,34 @@ jobs: packages/interfaces/node_modules key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - name: Init - run: | - npm run build:functions - npm install -g firebase-tools + run: npm run build:functions - name: Test working-directory: packages/functions run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/transaction-trigger/transaction-trigger_1.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/transaction-trigger/transaction-trigger_10.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/transaction-trigger/transaction-trigger_11.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-chunk_67 - path: ./packages/functions/firestore-data/ - retention-days: 1 + npm run start & + npm run notifier & + npm run test -- --findRelatedTests --forceExit ./test-tangle/transaction-trigger/transaction-trigger_1.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/transaction-trigger/transaction-trigger_10.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/transaction-trigger/transaction-trigger_11.spec.ts chunk_68: needs: npm-install runs-on: ubuntu-latest timeout-minutes: 20 + + services: + postgres: + image: postgres + env: + POSTGRES_DB: build5db + POSTGRES_PASSWORD: postgres + ports: + - 5432:5432 + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 @@ -2559,30 +2847,34 @@ jobs: packages/interfaces/node_modules key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - name: Init - run: | - npm run build:functions - npm install -g firebase-tools + run: npm run build:functions - name: Test working-directory: packages/functions run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/transaction-trigger/transaction-trigger_12.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/transaction-trigger/transaction-trigger_13.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/transaction-trigger/transaction-trigger_14.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-chunk_68 - path: ./packages/functions/firestore-data/ - retention-days: 1 + npm run start & + npm run notifier & + npm run test -- --findRelatedTests --forceExit ./test-tangle/transaction-trigger/transaction-trigger_12.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/transaction-trigger/transaction-trigger_13.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/transaction-trigger/transaction-trigger_14.spec.ts chunk_69: needs: npm-install runs-on: ubuntu-latest timeout-minutes: 20 + + services: + postgres: + image: postgres + env: + POSTGRES_DB: build5db + POSTGRES_PASSWORD: postgres + ports: + - 5432:5432 + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 @@ -2596,30 +2888,34 @@ jobs: packages/interfaces/node_modules key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - name: Init - run: | - npm run build:functions - npm install -g firebase-tools + run: npm run build:functions - name: Test working-directory: packages/functions run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/transaction-trigger/transaction-trigger_15.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/transaction-trigger/transaction-trigger_2.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/transaction-trigger/transaction-trigger_3.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-chunk_69 - path: ./packages/functions/firestore-data/ - retention-days: 1 + npm run start & + npm run notifier & + npm run test -- --findRelatedTests --forceExit ./test-tangle/transaction-trigger/transaction-trigger_15.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/transaction-trigger/transaction-trigger_2.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/transaction-trigger/transaction-trigger_3.spec.ts chunk_70: needs: npm-install runs-on: ubuntu-latest timeout-minutes: 20 + + services: + postgres: + image: postgres + env: + POSTGRES_DB: build5db + POSTGRES_PASSWORD: postgres + ports: + - 5432:5432 + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 @@ -2633,30 +2929,34 @@ jobs: packages/interfaces/node_modules key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - name: Init - run: | - npm run build:functions - npm install -g firebase-tools + run: npm run build:functions - name: Test working-directory: packages/functions run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/transaction-trigger/transaction-trigger_4.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/transaction-trigger/transaction-trigger_5.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/transaction-trigger/transaction-trigger_6.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-chunk_70 - path: ./packages/functions/firestore-data/ - retention-days: 1 + npm run start & + npm run notifier & + npm run test -- --findRelatedTests --forceExit ./test-tangle/transaction-trigger/transaction-trigger_4.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/transaction-trigger/transaction-trigger_5.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/transaction-trigger/transaction-trigger_6.spec.ts chunk_71: needs: npm-install runs-on: ubuntu-latest timeout-minutes: 20 + + services: + postgres: + image: postgres + env: + POSTGRES_DB: build5db + POSTGRES_PASSWORD: postgres + ports: + - 5432:5432 + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 @@ -2670,30 +2970,34 @@ jobs: packages/interfaces/node_modules key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - name: Init - run: | - npm run build:functions - npm install -g firebase-tools + run: npm run build:functions - name: Test working-directory: packages/functions run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/transaction-trigger/transaction-trigger_7.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/transaction-trigger/transaction-trigger_8.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/transaction-trigger/transaction-trigger_9.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-chunk_71 - path: ./packages/functions/firestore-data/ - retention-days: 1 + npm run start & + npm run notifier & + npm run test -- --findRelatedTests --forceExit ./test-tangle/transaction-trigger/transaction-trigger_7.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/transaction-trigger/transaction-trigger_8.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/transaction-trigger/transaction-trigger_9.spec.ts chunk_72: needs: npm-install runs-on: ubuntu-latest timeout-minutes: 20 + + services: + postgres: + image: postgres + env: + POSTGRES_DB: build5db + POSTGRES_PASSWORD: postgres + ports: + - 5432:5432 + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 @@ -2707,30 +3011,34 @@ jobs: packages/interfaces/node_modules key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - name: Init - run: | - npm run build:functions - npm install -g firebase-tools + run: npm run build:functions - name: Test working-directory: packages/functions run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/web3/web3_1.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/web3/web3_2.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/web3/web3_3.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-chunk_72 - path: ./packages/functions/firestore-data/ - retention-days: 1 + npm run start & + npm run notifier & + npm run test -- --findRelatedTests --forceExit ./test-tangle/web3/web3_1.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/web3/web3_2.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/web3/web3_3.spec.ts chunk_73: needs: npm-install runs-on: ubuntu-latest timeout-minutes: 20 + + services: + postgres: + image: postgres + env: + POSTGRES_DB: build5db + POSTGRES_PASSWORD: postgres + ports: + - 5432:5432 + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 @@ -2744,30 +3052,34 @@ jobs: packages/interfaces/node_modules key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - name: Init - run: | - npm run build:functions - npm install -g firebase-tools + run: npm run build:functions - name: Test working-directory: packages/functions run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/withdraw-deposit-nft/deposit-withraw-nft_1_a.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/withdraw-deposit-nft/deposit-withraw-nft_1_b.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/withdraw-deposit-nft/deposit-withraw-nft_1_c.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-chunk_73 - path: ./packages/functions/firestore-data/ - retention-days: 1 + npm run start & + npm run notifier & + npm run test -- --findRelatedTests --forceExit ./test-tangle/withdraw-deposit-nft/deposit-withraw-nft_1_a.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/withdraw-deposit-nft/deposit-withraw-nft_1_b.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/withdraw-deposit-nft/deposit-withraw-nft_1_c.spec.ts chunk_74: needs: npm-install runs-on: ubuntu-latest timeout-minutes: 20 + + services: + postgres: + image: postgres + env: + POSTGRES_DB: build5db + POSTGRES_PASSWORD: postgres + ports: + - 5432:5432 + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 @@ -2781,30 +3093,34 @@ jobs: packages/interfaces/node_modules key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - name: Init - run: | - npm run build:functions - npm install -g firebase-tools + run: npm run build:functions - name: Test working-directory: packages/functions run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/withdraw-deposit-nft/deposit-withraw-nft_10_1.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/withdraw-deposit-nft/deposit-withraw-nft_10_2.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/withdraw-deposit-nft/deposit-withraw-nft_10_3.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-chunk_74 - path: ./packages/functions/firestore-data/ - retention-days: 1 + npm run start & + npm run notifier & + npm run test -- --findRelatedTests --forceExit ./test-tangle/withdraw-deposit-nft/deposit-withraw-nft_10_1.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/withdraw-deposit-nft/deposit-withraw-nft_10_2.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/withdraw-deposit-nft/deposit-withraw-nft_10_3.spec.ts chunk_75: needs: npm-install runs-on: ubuntu-latest timeout-minutes: 20 + + services: + postgres: + image: postgres + env: + POSTGRES_DB: build5db + POSTGRES_PASSWORD: postgres + ports: + - 5432:5432 + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 @@ -2818,30 +3134,34 @@ jobs: packages/interfaces/node_modules key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - name: Init - run: | - npm run build:functions - npm install -g firebase-tools + run: npm run build:functions - name: Test working-directory: packages/functions run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/withdraw-deposit-nft/deposit-withraw-nft_11.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/withdraw-deposit-nft/deposit-withraw-nft_12_a.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/withdraw-deposit-nft/deposit-withraw-nft_12_b.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-chunk_75 - path: ./packages/functions/firestore-data/ - retention-days: 1 + npm run start & + npm run notifier & + npm run test -- --findRelatedTests --forceExit ./test-tangle/withdraw-deposit-nft/deposit-withraw-nft_11.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/withdraw-deposit-nft/deposit-withraw-nft_12_a.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/withdraw-deposit-nft/deposit-withraw-nft_12_b.spec.ts chunk_76: needs: npm-install runs-on: ubuntu-latest timeout-minutes: 20 + + services: + postgres: + image: postgres + env: + POSTGRES_DB: build5db + POSTGRES_PASSWORD: postgres + ports: + - 5432:5432 + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 @@ -2855,30 +3175,34 @@ jobs: packages/interfaces/node_modules key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - name: Init - run: | - npm run build:functions - npm install -g firebase-tools + run: npm run build:functions - name: Test working-directory: packages/functions run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/withdraw-deposit-nft/deposit-withraw-nft_13.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/withdraw-deposit-nft/deposit-withraw-nft_14.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/withdraw-deposit-nft/deposit-withraw-nft_15.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-chunk_76 - path: ./packages/functions/firestore-data/ - retention-days: 1 + npm run start & + npm run notifier & + npm run test -- --findRelatedTests --forceExit ./test-tangle/withdraw-deposit-nft/deposit-withraw-nft_13.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/withdraw-deposit-nft/deposit-withraw-nft_14.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/withdraw-deposit-nft/deposit-withraw-nft_15.spec.ts chunk_77: needs: npm-install runs-on: ubuntu-latest timeout-minutes: 20 + + services: + postgres: + image: postgres + env: + POSTGRES_DB: build5db + POSTGRES_PASSWORD: postgres + ports: + - 5432:5432 + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 @@ -2892,30 +3216,34 @@ jobs: packages/interfaces/node_modules key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - name: Init - run: | - npm run build:functions - npm install -g firebase-tools + run: npm run build:functions - name: Test working-directory: packages/functions run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/withdraw-deposit-nft/deposit-withraw-nft_16.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/withdraw-deposit-nft/deposit-withraw-nft_2.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/withdraw-deposit-nft/deposit-withraw-nft_4_b.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-chunk_77 - path: ./packages/functions/firestore-data/ - retention-days: 1 + npm run start & + npm run notifier & + npm run test -- --findRelatedTests --forceExit ./test-tangle/withdraw-deposit-nft/deposit-withraw-nft_16.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/withdraw-deposit-nft/deposit-withraw-nft_2.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/withdraw-deposit-nft/deposit-withraw-nft_4_b.spec.ts chunk_78: needs: npm-install runs-on: ubuntu-latest timeout-minutes: 20 + + services: + postgres: + image: postgres + env: + POSTGRES_DB: build5db + POSTGRES_PASSWORD: postgres + ports: + - 5432:5432 + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 @@ -2929,30 +3257,34 @@ jobs: packages/interfaces/node_modules key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - name: Init - run: | - npm run build:functions - npm install -g firebase-tools + run: npm run build:functions - name: Test working-directory: packages/functions run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/withdraw-deposit-nft/deposit-withraw-nft_4.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/withdraw-deposit-nft/deposit-withraw-nft_5.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/withdraw-deposit-nft/deposit-withraw-nft_6.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-chunk_78 - path: ./packages/functions/firestore-data/ - retention-days: 1 + npm run start & + npm run notifier & + npm run test -- --findRelatedTests --forceExit ./test-tangle/withdraw-deposit-nft/deposit-withraw-nft_4.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/withdraw-deposit-nft/deposit-withraw-nft_5.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/withdraw-deposit-nft/deposit-withraw-nft_6.spec.ts chunk_79: needs: npm-install runs-on: ubuntu-latest timeout-minutes: 20 + + services: + postgres: + image: postgres + env: + POSTGRES_DB: build5db + POSTGRES_PASSWORD: postgres + ports: + - 5432:5432 + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 @@ -2966,30 +3298,34 @@ jobs: packages/interfaces/node_modules key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - name: Init - run: | - npm run build:functions - npm install -g firebase-tools + run: npm run build:functions - name: Test working-directory: packages/functions run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/withdraw-deposit-nft/deposit-withraw-nft_7.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/withdraw-deposit-nft/deposit-withraw-nft_8.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/withdraw-deposit-nft/deposit-withraw-nft_9.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-chunk_79 - path: ./packages/functions/firestore-data/ - retention-days: 1 + npm run start & + npm run notifier & + npm run test -- --findRelatedTests --forceExit ./test-tangle/withdraw-deposit-nft/deposit-withraw-nft_7.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/withdraw-deposit-nft/deposit-withraw-nft_8.spec.ts && + npm run test -- --findRelatedTests --forceExit ./test-tangle/withdraw-deposit-nft/deposit-withraw-nft_9.spec.ts chunk_80: needs: npm-install runs-on: ubuntu-latest timeout-minutes: 20 + + services: + postgres: + image: postgres + env: + POSTGRES_DB: build5db + POSTGRES_PASSWORD: postgres + ports: + - 5432:5432 + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 @@ -3003,29 +3339,32 @@ jobs: packages/interfaces/node_modules key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - name: Init - run: | - npm run build:functions - npm install -g firebase-tools + run: npm run build:functions - name: Test working-directory: packages/functions run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/workflow-online.spec.ts && - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/workflow.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-chunk_80 - path: ./packages/functions/firestore-data/ - retention-days: 1 + npm run start & + npm run notifier & + npm run test -- --findRelatedTests --forceExit ./test-tangle/workflow.spec.ts chunk_81: needs: npm-install runs-on: ubuntu-latest timeout-minutes: 20 + + services: + postgres: + image: postgres + env: + POSTGRES_DB: build5db + POSTGRES_PASSWORD: postgres + ports: + - 5432:5432 + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 @@ -3039,28 +3378,32 @@ jobs: packages/interfaces/node_modules key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - name: Init - run: | - npm run build:functions - npm install -g firebase-tools + run: npm run build:functions - name: Test working-directory: packages/functions run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/collection-minting/collection-minting_3.only.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-chunk_81 - path: ./packages/functions/firestore-data/ - retention-days: 1 + npm run start & + npm run notifier & + npm run test -- --findRelatedTests --forceExit ./test-tangle/collection-minting/collection-minting_3.only.spec.ts chunk_82: needs: npm-install runs-on: ubuntu-latest timeout-minutes: 20 + + services: + postgres: + image: postgres + env: + POSTGRES_DB: build5db + POSTGRES_PASSWORD: postgres + ports: + - 5432:5432 + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 @@ -3074,28 +3417,32 @@ jobs: packages/interfaces/node_modules key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - name: Init - run: | - npm run build:functions - npm install -g firebase-tools + run: npm run build:functions - name: Test working-directory: packages/functions run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/minted-nft-trading/minted-nft-trading_11.only.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-chunk_82 - path: ./packages/functions/firestore-data/ - retention-days: 1 + npm run start & + npm run notifier & + npm run test -- --findRelatedTests --forceExit ./test-tangle/minted-nft-trading/minted-nft-trading_11.only.spec.ts chunk_83: needs: npm-install runs-on: ubuntu-latest timeout-minutes: 20 + + services: + postgres: + image: postgres + env: + POSTGRES_DB: build5db + POSTGRES_PASSWORD: postgres + ports: + - 5432:5432 + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 @@ -3109,56 +3456,10 @@ jobs: packages/interfaces/node_modules key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - name: Init - run: | - npm run build:functions - npm install -g firebase-tools - - name: Test - working-directory: packages/functions - run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/minted-token-trade/minted-token-trade_15.only.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-chunk_83 - path: ./packages/functions/firestore-data/ - retention-days: 1 - chunk_84: - needs: npm-install - runs-on: ubuntu-latest - timeout-minutes: 20 - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version: 20.x - - uses: actions/cache@v4 - with: - path: | - node_modules - packages/functions/node_modules - packages/interfaces/node_modules - key: ${{ runner.os }}-modules-${{ hashFiles('**/package.json') }} - - name: Init - run: | - npm run build:functions - npm install -g firebase-tools + run: npm run build:functions - name: Test working-directory: packages/functions run: | - export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json" - npm run milestone-sync & - firebase emulators:exec " - npm run test-tangle:ci -- --forceExit --findRelatedTests ./test-tangle/soon.snapshot.only.spec.ts - " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data - - name: Archive firestore data - uses: actions/upload-artifact@v4 - if: ${{ failure() }} - with: - name: firestore-data-test-tangle-chunk_84 - path: ./packages/functions/firestore-data/ - retention-days: 1 + npm run start & + npm run notifier & + npm run test -- --findRelatedTests --forceExit ./test-tangle/minted-token-trade/minted-token-trade_15.only.spec.ts diff --git a/.prettierignore b/.prettierignore index 362a9b7593..f8c80276c6 100644 --- a/.prettierignore +++ b/.prettierignore @@ -1,4 +1,5 @@ /dist +**/lib /coverage **/src/**/files **/node_modules diff --git a/.prettierrc b/.prettierrc index 6366838f16..426bb97b58 100644 --- a/.prettierrc +++ b/.prettierrc @@ -5,5 +5,6 @@ "printWidth": 100, "tabWidth": 2, "useTabs": false, - "endOfLine": "auto" + "endOfLine": "auto", + "plugins": ["prettier-plugin-organize-imports"] } diff --git a/data.proto b/data.proto deleted file mode 100644 index 0f241e1dfd..0000000000 --- a/data.proto +++ /dev/null @@ -1,161 +0,0 @@ -// Copyright 2023 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -syntax = "proto3"; - -package google.events.cloud.firestore.v1; - -import "google/protobuf/struct.proto"; -import "google/protobuf/timestamp.proto"; - -option csharp_namespace = "Google.Events.Protobuf.Cloud.Firestore.V1"; -option php_namespace = "Google\\Events\\Cloud\\Firestore\\V1"; -option ruby_package = "Google::Events::Cloud::Firestore::V1"; - -// The data within all Firestore document events. -message DocumentEventData { - // A Document object containing a post-operation document snapshot. - // This is not populated for delete events. - Document value = 1; - - // A Document object containing a pre-operation document snapshot. - // This is only populated for update and delete events. - Document old_value = 2; - - // A DocumentMask object that lists changed fields. - // This is only populated for update events. - DocumentMask update_mask = 3; -} - -// A set of field paths on a document. -message DocumentMask { - // The list of field paths in the mask. - // See [Document.fields][google.cloud.firestore.v1.events.Document.fields] - // for a field path syntax reference. - repeated string field_paths = 1; -} - -// A Firestore document. -message Document { - // The resource name of the document. For example: - // `projects/{project_id}/databases/{database_id}/documents/{document_path}` - string name = 1; - - // The document's fields. - // - // The map keys represent field names. - // - // A simple field name contains only characters `a` to `z`, `A` to `Z`, - // `0` to `9`, or `_`, and must not start with `0` to `9`. For example, - // `foo_bar_17`. - // - // Field names matching the regular expression `__.*__` are reserved. Reserved - // field names are forbidden except in certain documented contexts. The map - // keys, represented as UTF-8, must not exceed 1,500 bytes and cannot be - // empty. - // - // Field paths may be used in other contexts to refer to structured fields - // defined here. For `map_value`, the field path is represented by the simple - // or quoted field names of the containing fields, delimited by `.`. For - // example, the structured field - // `"foo" : { map_value: { "x&y" : { string_value: "hello" }}}` would be - // represented by the field path `foo.x&y`. - // - // Within a field path, a quoted field name starts and ends with `` ` `` and - // may contain any character. Some characters, including `` ` ``, must be - // escaped using a `\`. For example, `` `x&y` `` represents `x&y` and - // `` `bak\`tik` `` represents `` bak`tik ``. - map fields = 2; - - // The time at which the document was created. - // - // This value increases monotonically when a document is deleted then - // recreated. It can also be compared to values from other documents and - // the `read_time` of a query. - google.protobuf.Timestamp create_time = 3; - - // The time at which the document was last changed. - // - // This value is initially set to the `create_time` then increases - // monotonically with each change to the document. It can also be - // compared to values from other documents and the `read_time` of a query. - google.protobuf.Timestamp update_time = 4; -} - -// A message that can hold any of the supported value types. -message Value { - // Must have a value set. - oneof value_type { - // A null value. - google.protobuf.NullValue null_value = 11; - - // A boolean value. - bool boolean_value = 1; - - // An integer value. - int64 integer_value = 2; - - // A double value. - double double_value = 3; - - // A timestamp value. - // - // Precise only to microseconds. When stored, any additional precision is - // rounded down. - google.protobuf.Timestamp timestamp_value = 10; - - // A string value. - // - // The string, represented as UTF-8, must not exceed 1 MiB - 89 bytes. - // Only the first 1,500 bytes of the UTF-8 representation are considered by - // queries. - string string_value = 17; - - // A bytes value. - // - // Must not exceed 1 MiB - 89 bytes. - // Only the first 1,500 bytes are considered by queries. - bytes bytes_value = 18; - - // A reference to a document. For example: - // `projects/{project_id}/databases/{database_id}/documents/{document_path}`. - string reference_value = 5; - - // An array value. - // - // Cannot directly contain another array value, though can contain an - // map which contains another array. - ArrayValue array_value = 9; - - // A map value. - MapValue map_value = 6; - } -} - -// An array value. -message ArrayValue { - // Values in the array. - repeated Value values = 1; -} - -// A map value. -message MapValue { - // The map's fields. - // - // The map keys represent field names. Field names matching the regular - // expression `__.*__` are reserved. Reserved field names are forbidden except - // in certain documented contexts. The map keys, represented as UTF-8, must - // not exceed 1,500 bytes and cannot be empty. - map fields = 1; -} diff --git a/firestore.rules b/firestore.rules deleted file mode 100644 index ca9f680ece..0000000000 --- a/firestore.rules +++ /dev/null @@ -1,6 +0,0 @@ -rules_version = '2'; -service cloud.firestore { - match /{document=**} { - allow read, write: if false; - } -} \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index ab67393e06..750dfed839 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6,6 +6,7 @@ "": { "name": "root", "workspaces": [ + "packages/notifier", "packages/indexes", "packages/interfaces", "packages/sdk", @@ -147,13 +148,13 @@ } }, "node_modules/@ampproject/remapping": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz", - "integrity": "sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", + "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", "dev": true, "dependencies": { - "@jridgewell/gen-mapping": "^0.3.0", - "@jridgewell/trace-mapping": "^0.3.9" + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" }, "engines": { "node": ">=6.0.0" @@ -165,42 +166,42 @@ "integrity": "sha512-HazVq9zwTVwGmqdwYzu7WyQ6FQVZ7SwET0KKQuKm55jD0IfUpZgN0OPIiZG3zV1iSrVYcN0bdwLRXI/VNCYsUA==" }, "node_modules/@babel/code-frame": { - "version": "7.23.5", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.5.tgz", - "integrity": "sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==", + "version": "7.24.2", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.2.tgz", + "integrity": "sha512-y5+tLQyV8pg3fsiln67BVLD1P13Eg4lh5RW9mF0zUuvLrv9uIQ4MCL+CRT+FTsBlBjcIan6PGsLcBN0m3ClUyQ==", "dependencies": { - "@babel/highlight": "^7.23.4", - "chalk": "^2.4.2" + "@babel/highlight": "^7.24.2", + "picocolors": "^1.0.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/compat-data": { - "version": "7.23.5", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.23.5.tgz", - "integrity": "sha512-uU27kfDRlhfKl+w1U6vp16IuvSLtjAxdArVXPa9BvLkrr7CYIsxH5adpHObeAGY/41+syctUWOZ140a2Rvkgjw==", + "version": "7.24.4", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.24.4.tgz", + "integrity": "sha512-vg8Gih2MLK+kOkHJp4gBEIkyaIi00jgWot2D9QOmmfLC8jINSOzmCLta6Bvz/JSBCqnegV0L80jhxkol5GWNfQ==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/core": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.9.tgz", - "integrity": "sha512-5q0175NOjddqpvvzU+kDiSOAk4PfdO6FvwCWoQ6RO7rTzEe8vlo+4HVfcnAREhD4npMs0e9uZypjTwzZPCf/cw==", + "version": "7.24.4", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.4.tgz", + "integrity": "sha512-MBVlMXP+kkl5394RBLSxxk/iLTeVGuXTV3cIDXavPpMMqnSnt6apKgan/U8O3USWZCWZT/TbgfEpKa4uMgN4Dg==", "dev": true, "dependencies": { "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.23.5", - "@babel/generator": "^7.23.6", + "@babel/code-frame": "^7.24.2", + "@babel/generator": "^7.24.4", "@babel/helper-compilation-targets": "^7.23.6", "@babel/helper-module-transforms": "^7.23.3", - "@babel/helpers": "^7.23.9", - "@babel/parser": "^7.23.9", - "@babel/template": "^7.23.9", - "@babel/traverse": "^7.23.9", - "@babel/types": "^7.23.9", + "@babel/helpers": "^7.24.4", + "@babel/parser": "^7.24.4", + "@babel/template": "^7.24.0", + "@babel/traverse": "^7.24.1", + "@babel/types": "^7.24.0", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -216,13 +217,13 @@ } }, "node_modules/@babel/generator": { - "version": "7.23.6", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.6.tgz", - "integrity": "sha512-qrSfCYxYQB5owCmGLbl8XRpX1ytXlpueOb0N0UmQwA073KZxejgQTzAmJezxvpwQD9uGtK2shHdi55QT+MbjIw==", + "version": "7.24.4", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.24.4.tgz", + "integrity": "sha512-Xd6+v6SnjWVx/nus+y0l1sxMOTOMBkyL4+BIdbALyatQnAe/SRVjANeDPSCYaX+i1iJmuGSKf3Z+E+V/va1Hvw==", "dependencies": { - "@babel/types": "^7.23.6", - "@jridgewell/gen-mapping": "^0.3.2", - "@jridgewell/trace-mapping": "^0.3.17", + "@babel/types": "^7.24.0", + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25", "jsesc": "^2.5.1" }, "engines": { @@ -258,9 +259,9 @@ } }, "node_modules/@babel/helper-create-class-features-plugin": { - "version": "7.23.10", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.23.10.tgz", - "integrity": "sha512-2XpP2XhkXzgxecPNEEK8Vz8Asj9aRxt08oKOqtiZoqV2UGZ5T+EkyP9sXQ9nwMxBIG34a7jmasVqoMop7VdPUw==", + "version": "7.24.4", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.24.4.tgz", + "integrity": "sha512-lG75yeuUSVu0pIcbhiYMXBXANHrpUPaOfu7ryAzskCgKUHuAxRQI5ssrtmF0X9UXldPlvT0XM/A4F44OXRt6iQ==", "dev": true, "dependencies": { "@babel/helper-annotate-as-pure": "^7.22.5", @@ -268,7 +269,7 @@ "@babel/helper-function-name": "^7.23.0", "@babel/helper-member-expression-to-functions": "^7.23.0", "@babel/helper-optimise-call-expression": "^7.22.5", - "@babel/helper-replace-supers": "^7.22.20", + "@babel/helper-replace-supers": "^7.24.1", "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", "@babel/helper-split-export-declaration": "^7.22.6", "semver": "^6.3.1" @@ -324,12 +325,12 @@ } }, "node_modules/@babel/helper-module-imports": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz", - "integrity": "sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==", + "version": "7.24.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.24.3.tgz", + "integrity": "sha512-viKb0F9f2s0BCS22QSF308z/+1YWKV/76mwt61NBzS5izMzDPwdq1pTrzf+Li3npBWX9KdQbkeCt1jSAM7lZqg==", "dev": true, "dependencies": { - "@babel/types": "^7.22.15" + "@babel/types": "^7.24.0" }, "engines": { "node": ">=6.9.0" @@ -367,22 +368,22 @@ } }, "node_modules/@babel/helper-plugin-utils": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz", - "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==", + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.0.tgz", + "integrity": "sha512-9cUznXMG0+FxRuJfvL82QlTqIzhVW9sL0KjMPHhAOOvpQGL8QtdxnBKILjBqxlHyliz0yCa1G903ZXI/FuHy2w==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-replace-supers": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.22.20.tgz", - "integrity": "sha512-qsW0In3dbwQUbK8kejJ4R7IHVGwHJlV6lpG6UA7a9hSa2YEiAib+N1T2kr6PEeUT+Fl7najmSOS6SmAwCHK6Tw==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.24.1.tgz", + "integrity": "sha512-QCR1UqC9BzG5vZl8BMicmZ28RuUBnHhAMddD8yHFHDRH9lLTZ9uUPehX8ctVPT8l0TKblJidqcgUUKGVrePleQ==", "dev": true, "dependencies": { "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-member-expression-to-functions": "^7.22.15", + "@babel/helper-member-expression-to-functions": "^7.23.0", "@babel/helper-optimise-call-expression": "^7.22.5" }, "engines": { @@ -428,9 +429,9 @@ } }, "node_modules/@babel/helper-string-parser": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz", - "integrity": "sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.1.tgz", + "integrity": "sha512-2ofRCjnnA9y+wk8b9IAREroeUP02KHp431N2mhKniy2yKIDKpbrHv9eXwm8cBeWQYcJmzv5qKCu65P47eCF7CQ==", "engines": { "node": ">=6.9.0" } @@ -453,36 +454,37 @@ } }, "node_modules/@babel/helpers": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.23.9.tgz", - "integrity": "sha512-87ICKgU5t5SzOT7sBMfCOZQ2rHjRU+Pcb9BoILMYz600W6DkVRLFBPwQ18gwUVvggqXivaUakpnxWQGbpywbBQ==", + "version": "7.24.4", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.24.4.tgz", + "integrity": "sha512-FewdlZbSiwaVGlgT1DPANDuCHaDMiOo+D/IDYRFYjHOuv66xMSJ7fQwwODwRNAPkADIO/z1EoF/l2BCWlWABDw==", "dev": true, "dependencies": { - "@babel/template": "^7.23.9", - "@babel/traverse": "^7.23.9", - "@babel/types": "^7.23.9" + "@babel/template": "^7.24.0", + "@babel/traverse": "^7.24.1", + "@babel/types": "^7.24.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/highlight": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.23.4.tgz", - "integrity": "sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==", + "version": "7.24.2", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.2.tgz", + "integrity": "sha512-Yac1ao4flkTxTteCDZLEvdxg2fZfz1v8M4QpaGypq/WPDqg3ijHYbDfs+LG5hvzSoqaSZ9/Z9lKSP3CjZjv+pA==", "dependencies": { "@babel/helper-validator-identifier": "^7.22.20", "chalk": "^2.4.2", - "js-tokens": "^4.0.0" + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/parser": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.9.tgz", - "integrity": "sha512-9tcKgqKbs3xGJ+NtKF2ndOBBLVwPjl1SHxPQkd36r3Dlirw3xWUeGaTbqr7uGZcTaxkVNwc+03SVP7aCdWrTlA==", + "version": "7.24.4", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.4.tgz", + "integrity": "sha512-zTvEBcghmeBma9QIGunWevvBAp4/Qu9Bdq+2k0Ot4fVMD6v3dsC9WOcRSKk7tRRyBM/53yKMJko9xOatGQAwSg==", "bin": { "parser": "bin/babel-parser.js" }, @@ -551,12 +553,12 @@ } }, "node_modules/@babel/plugin-syntax-jsx": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.23.3.tgz", - "integrity": "sha512-EB2MELswq55OHUoRZLGg/zC7QWUKfNLpE57m/S2yr1uEneIgsTgrSzXP3NXEsMkVn76OlaVVnzN+ugObuYGwhg==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.24.1.tgz", + "integrity": "sha512-2eCtxZXf+kbkMIsXS4poTvT4Yu5rXiRa+9xGVT56raghjmBTKMpFNc9R4IDiB4emao9eO22Ox7CxuJG7BgExqA==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.0" }, "engines": { "node": ">=6.9.0" @@ -653,12 +655,12 @@ } }, "node_modules/@babel/plugin-syntax-typescript": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.23.3.tgz", - "integrity": "sha512-9EiNjVJOMwCO+43TqoTrgQ8jMwcAd0sWyXi9RPfIsLTj4R2MADDDQXELhffaUx/uJv2AYcxBgPwH6j4TIA4ytQ==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.24.1.tgz", + "integrity": "sha512-Yhnmvy5HZEnHUty6i++gcfH1/l68AHnItFHnaCv6hn9dNh0hQvvQJsxpi4BMBFN5DLeHBuucT/0DgzXif/OyRw==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.0" }, "engines": { "node": ">=6.9.0" @@ -668,13 +670,13 @@ } }, "node_modules/@babel/plugin-transform-modules-commonjs": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.23.3.tgz", - "integrity": "sha512-aVS0F65LKsdNOtcz6FRCpE4OgsP2OFnW46qNxNIX9h3wuzaNcSQsJysuMwqSibC98HPrf2vCgtxKNwS0DAlgcA==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.24.1.tgz", + "integrity": "sha512-szog8fFTUxBfw0b98gEWPaEqF42ZUD/T3bkynW/wtgx2p/XCP55WEsb+VosKceRSd6njipdZvNogqdtI4Q0chw==", "dev": true, "dependencies": { "@babel/helper-module-transforms": "^7.23.3", - "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-plugin-utils": "^7.24.0", "@babel/helper-simple-access": "^7.22.5" }, "engines": { @@ -685,15 +687,15 @@ } }, "node_modules/@babel/plugin-transform-typescript": { - "version": "7.23.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.23.6.tgz", - "integrity": "sha512-6cBG5mBvUu4VUD04OHKnYzbuHNP8huDsD3EDqqpIpsswTDoqHCjLoHb6+QgsV1WsT2nipRqCPgxD3LXnEO7XfA==", + "version": "7.24.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.24.4.tgz", + "integrity": "sha512-79t3CQ8+oBGk/80SQ8MN3Bs3obf83zJ0YZjDmDaEZN8MqhMI760apl5z6a20kFeMXBwJX99VpKT8CKxEBp5H1g==", "dev": true, "dependencies": { "@babel/helper-annotate-as-pure": "^7.22.5", - "@babel/helper-create-class-features-plugin": "^7.23.6", - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/plugin-syntax-typescript": "^7.23.3" + "@babel/helper-create-class-features-plugin": "^7.24.4", + "@babel/helper-plugin-utils": "^7.24.0", + "@babel/plugin-syntax-typescript": "^7.24.1" }, "engines": { "node": ">=6.9.0" @@ -722,31 +724,31 @@ } }, "node_modules/@babel/template": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.23.9.tgz", - "integrity": "sha512-+xrD2BWLpvHKNmX2QbpdpsBaWnRxahMwJjO+KZk2JOElj5nSmKezyS1B4u+QbHMTX69t4ukm6hh9lsYQ7GHCKA==", + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.24.0.tgz", + "integrity": "sha512-Bkf2q8lMB0AFpX0NFEqSbx1OkTHf0f+0j82mkw+ZpzBnkk7e9Ql0891vlfgi+kHwOk8tQjiQHpqh4LaSa0fKEA==", "dependencies": { "@babel/code-frame": "^7.23.5", - "@babel/parser": "^7.23.9", - "@babel/types": "^7.23.9" + "@babel/parser": "^7.24.0", + "@babel/types": "^7.24.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.9.tgz", - "integrity": "sha512-I/4UJ9vs90OkBtY6iiiTORVMyIhJ4kAVmsKo9KFc8UOxMeUfi2hvtIBsET5u9GizXE6/GFSuKCTNfgCswuEjRg==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.24.1.tgz", + "integrity": "sha512-xuU6o9m68KeqZbQuDt2TcKSxUw/mrsvavlEqQ1leZ/B+C9tk6E4sRWy97WaXgvq5E+nU3cXMxv3WKOCanVMCmQ==", "dependencies": { - "@babel/code-frame": "^7.23.5", - "@babel/generator": "^7.23.6", + "@babel/code-frame": "^7.24.1", + "@babel/generator": "^7.24.1", "@babel/helper-environment-visitor": "^7.22.20", "@babel/helper-function-name": "^7.23.0", "@babel/helper-hoist-variables": "^7.22.5", "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/parser": "^7.23.9", - "@babel/types": "^7.23.9", + "@babel/parser": "^7.24.1", + "@babel/types": "^7.24.0", "debug": "^4.3.1", "globals": "^11.1.0" }, @@ -755,9 +757,9 @@ } }, "node_modules/@babel/types": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.9.tgz", - "integrity": "sha512-dQjSq/7HaSjRM43FFGnv5keM2HsxpmyV1PfaSVm0nzzjwwTmjOe6J4bC8e3+pTEIgHaHj+1ZlLThRJ2auc/w1Q==", + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.0.tgz", + "integrity": "sha512-+j7a5c253RfKh8iABBhywc8NSfP5LURe7Uh4qpsh6jc+aLJguvmIUBdjSdEMQv2bENrCR5MfRdjGo7vzS/ob7w==", "dependencies": { "@babel/helper-string-parser": "^7.23.4", "@babel/helper-validator-identifier": "^7.22.20", @@ -789,6 +791,10 @@ "resolved": "packages/interfaces", "link": true }, + "node_modules/@build-5/notifier": { + "resolved": "packages/notifier", + "link": true + }, "node_modules/@build-5/sdk": { "resolved": "packages/sdk", "link": true @@ -902,22 +908,6 @@ "url": "https://opencollective.com/eslint" } }, - "node_modules/@eslint/eslintrc/node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, "node_modules/@eslint/eslintrc/node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", @@ -961,12 +951,6 @@ "js-yaml": "bin/js-yaml.js" } }, - "node_modules/@eslint/eslintrc/node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, "node_modules/@eslint/eslintrc/node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", @@ -1296,91 +1280,91 @@ ] }, "node_modules/@firebase/app-check-interop-types": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@firebase/app-check-interop-types/-/app-check-interop-types-0.3.0.tgz", - "integrity": "sha512-xAxHPZPIgFXnI+vb4sbBjZcde7ZluzPPaSK7Lx3/nmuVk4TjZvnL8ONnkd4ERQKL8WePQySU+pRcWkh8rDf5Sg==" + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@firebase/app-check-interop-types/-/app-check-interop-types-0.3.1.tgz", + "integrity": "sha512-NILZbe6RH3X1pZmJnfOfY2gLIrlKmrkUMMrrK6VSXHcSE0eQv28xFEcw16D198i9JYZpy5Kwq394My62qCMaIw==" }, "node_modules/@firebase/app-types": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/@firebase/app-types/-/app-types-0.9.0.tgz", - "integrity": "sha512-AeweANOIo0Mb8GiYm3xhTEBVCmPwTYAu9Hcd2qSkLuga/6+j9b1Jskl5bpiSQWy9eJ/j5pavxj6eYogmnuzm+Q==" + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/@firebase/app-types/-/app-types-0.9.1.tgz", + "integrity": "sha512-nFGqTYsnDFn1oXf1tCwPAc+hQPxyvBT/QB7qDjwK+IDYThOn63nGhzdUTXxVD9Ca8gUY/e5PQMngeo0ZW/E3uQ==" }, "node_modules/@firebase/auth-interop-types": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/@firebase/auth-interop-types/-/auth-interop-types-0.2.1.tgz", - "integrity": "sha512-VOaGzKp65MY6P5FI84TfYKBXEPi6LmOCSMMzys6o2BN2LOsqy7pCuZCup7NYnfbk5OkkQKzvIfHOzTm0UDpkyg==" + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/@firebase/auth-interop-types/-/auth-interop-types-0.2.2.tgz", + "integrity": "sha512-k3NA28Jfoo0+o391bFjoV9X5QLnUL1WbLhZZRbTQhZdmdGYJfX8ixtNNlHsYQ94bwG0QRbsmvkzDnzuhHrV11w==" }, "node_modules/@firebase/component": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.6.5.tgz", - "integrity": "sha512-2tVDk1ixi12sbDmmfITK8lxSjmcb73BMF6Qwc3U44hN/J1Fi1QY/Hnnb6klFlbB9/G16a3J3d4nXykye2EADTw==", + "version": "0.6.6", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.6.6.tgz", + "integrity": "sha512-pp7sWqHmAAlA3os6ERgoM3k5Cxff510M9RLXZ9Mc8KFKMBc2ct3RkZTWUF7ixJNvMiK/iNgRLPDrLR2gtRJ9iQ==", "dependencies": { - "@firebase/util": "1.9.4", + "@firebase/util": "1.9.5", "tslib": "^2.1.0" } }, "node_modules/@firebase/database": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@firebase/database/-/database-1.0.3.tgz", - "integrity": "sha512-9fjqLt9JzL46gw9+NRqsgQEMjgRwfd8XtzcKqG+UYyhVeFCdVRQ0Wp6Dw/dvYHnbH5vNEKzNv36dcB4p+PIAAA==", - "dependencies": { - "@firebase/app-check-interop-types": "0.3.0", - "@firebase/auth-interop-types": "0.2.1", - "@firebase/component": "0.6.5", - "@firebase/logger": "0.4.0", - "@firebase/util": "1.9.4", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@firebase/database/-/database-1.0.4.tgz", + "integrity": "sha512-k84cXh+dtpzvY6yOhfyr1B+I1vjvSMtmlqotE0lTNVylc8m5nmOohjzpTLEQDrBWvwACX/VP5fEyajAdmnOKqA==", + "dependencies": { + "@firebase/app-check-interop-types": "0.3.1", + "@firebase/auth-interop-types": "0.2.2", + "@firebase/component": "0.6.6", + "@firebase/logger": "0.4.1", + "@firebase/util": "1.9.5", "faye-websocket": "0.11.4", "tslib": "^2.1.0" } }, "node_modules/@firebase/database-compat": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@firebase/database-compat/-/database-compat-1.0.3.tgz", - "integrity": "sha512-7tHEOcMbK5jJzHWyphPux4osogH/adWwncxdMxdBpB9g1DNIyY4dcz1oJdlkXGM/i/AjUBesZsd5CuwTRTBNTw==", - "dependencies": { - "@firebase/component": "0.6.5", - "@firebase/database": "1.0.3", - "@firebase/database-types": "1.0.1", - "@firebase/logger": "0.4.0", - "@firebase/util": "1.9.4", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@firebase/database-compat/-/database-compat-1.0.4.tgz", + "integrity": "sha512-GEEDAvsSMAkqy0BIFSVtFzoOIIcKHFfDM4aXHtWL/JCaNn4OOjH7td73jDfN3ALvpIN4hQki0FcxQ89XjqaTjQ==", + "dependencies": { + "@firebase/component": "0.6.6", + "@firebase/database": "1.0.4", + "@firebase/database-types": "1.0.2", + "@firebase/logger": "0.4.1", + "@firebase/util": "1.9.5", "tslib": "^2.1.0" } }, "node_modules/@firebase/database-types": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@firebase/database-types/-/database-types-1.0.1.tgz", - "integrity": "sha512-Tmcmx5XgiI7UVF/4oGg2P3AOTfq3WKEPsm2yf+uXtN7uG/a4WTWhVMrXGYRY2ZUL1xPxv9V33wQRJ+CcrUhVXw==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@firebase/database-types/-/database-types-1.0.2.tgz", + "integrity": "sha512-JRigr5JNLEHqOkI99tAGHDZF47469/cJz1tRAgGs8Feh+3ZmQy/vVChSqwMp2DuVUGp9PlmGsNSlpINJ/hDuIA==", "dependencies": { - "@firebase/app-types": "0.9.0", - "@firebase/util": "1.9.4" + "@firebase/app-types": "0.9.1", + "@firebase/util": "1.9.5" } }, "node_modules/@firebase/logger": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.4.0.tgz", - "integrity": "sha512-eRKSeykumZ5+cJPdxxJRgAC3G5NknY2GwEbKfymdnXtnT0Ucm4pspfR6GT4MUQEDuJwRVbVcSx85kgJulMoFFA==", + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.4.1.tgz", + "integrity": "sha512-tTIixB5UJbG9ZHSGZSZdX7THr3KWOLrejZ9B7jYsm6fpwgRNngKznQKA2wgYVyvBc1ta7dGFh9NtJ8n7qfiYIw==", "dependencies": { "tslib": "^2.1.0" } }, "node_modules/@firebase/util": { - "version": "1.9.4", - "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.9.4.tgz", - "integrity": "sha512-WLonYmS1FGHT97TsUmRN3qnTh5TeeoJp1Gg5fithzuAgdZOUtsYECfy7/noQ3llaguios8r5BuXSEiK82+UrxQ==", + "version": "1.9.5", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.9.5.tgz", + "integrity": "sha512-PP4pAFISDxsf70l3pEy34Mf3GkkUcVQ3MdKp6aSVb7tcpfUQxnsdV7twDd8EkfB6zZylH6wpUAoangQDmCUMqw==", "dependencies": { "tslib": "^2.1.0" } }, "node_modules/@google-cloud/firestore": { - "version": "7.3.0", - "resolved": "https://registry.npmjs.org/@google-cloud/firestore/-/firestore-7.3.0.tgz", - "integrity": "sha512-2IftQLAbCuVp0nTd3neeu+d3OYIegJpV/V9R4USQj51LzJcXPe8h8jZ7j3+svSNhJVGy6JsN0T1QqlJdMDhTwg==", + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@google-cloud/firestore/-/firestore-7.6.0.tgz", + "integrity": "sha512-WUDbaLY8UnPxgwsyIaxj6uxCtSDAaUyvzWJykNH5rZ9i92/SZCsPNNMN0ajrVpAR81hPIL4amXTaMJ40y5L+Yg==", "optional": true, "dependencies": { "fast-deep-equal": "^3.1.1", "functional-red-black-tree": "^1.0.1", - "google-gax": "^4.0.4", - "protobufjs": "^7.2.5" + "google-gax": "^4.3.1", + "protobufjs": "^7.2.6" }, "engines": { "node": ">=14.0.0" @@ -1390,7 +1374,6 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/@google-cloud/paginator/-/paginator-5.0.0.tgz", "integrity": "sha512-87aeg6QQcEPxGCOthnpUjvw4xAZ57G7pL8FS0C4e/81fr3FjkpUpibf1s2v5XGyGhUVGF4Jfg7yEcxqn2iUw1w==", - "optional": true, "dependencies": { "arrify": "^2.0.0", "extend": "^3.0.2" @@ -1399,11 +1382,18 @@ "node": ">=14.0.0" } }, + "node_modules/@google-cloud/precise-date": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@google-cloud/precise-date/-/precise-date-4.0.0.tgz", + "integrity": "sha512-1TUx3KdaU3cN7nfCdNf+UVqA/PSX29Cjcox3fZZBtINlRrXVTmUkQnCKv2MbBUbCopbK4olAT1IHl76uZyCiVA==", + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/@google-cloud/projectify": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/@google-cloud/projectify/-/projectify-4.0.0.tgz", "integrity": "sha512-MmaX6HeSvyPbWGwFq7mXdo0uQZLGBYCwziiLIGq5JVX+/bdI3SAq6bP98trV5eTWfLuvsMcIC1YJOF2vfteLFA==", - "optional": true, "engines": { "node": ">=14.0.0" } @@ -1412,16 +1402,40 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/@google-cloud/promisify/-/promisify-4.0.0.tgz", "integrity": "sha512-Orxzlfb9c67A15cq2JQEyVc7wEsmFBmHjZWZYQMUyJ1qivXyMwdyNOs9odi79hze+2zqdTtu1E19IM/FtqZ10g==", - "optional": true, "engines": { "node": ">=14" } }, + "node_modules/@google-cloud/pubsub": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@google-cloud/pubsub/-/pubsub-4.3.3.tgz", + "integrity": "sha512-vJKh9L4dHf1XGSDKS1SB0IpqP/sUajQh4/QwhYasuq/NjzfHSxqSt+CuhrFGb5/gioTWE4gce0sn7h1SW7qESg==", + "dependencies": { + "@google-cloud/paginator": "^5.0.0", + "@google-cloud/precise-date": "^4.0.0", + "@google-cloud/projectify": "^4.0.0", + "@google-cloud/promisify": "^4.0.0", + "@opentelemetry/api": "^1.6.0", + "@opentelemetry/semantic-conventions": "~1.21.0", + "@types/duplexify": "^3.6.0", + "@types/long": "^4.0.0", + "arrify": "^2.0.0", + "extend": "^3.0.2", + "google-auth-library": "^9.3.0", + "google-gax": "^4.3.1", + "heap-js": "^2.2.0", + "is-stream-ended": "^0.1.4", + "lodash.snakecase": "^4.1.1", + "p-defer": "^3.0.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/@google-cloud/storage": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@google-cloud/storage/-/storage-7.7.0.tgz", - "integrity": "sha512-EMCEY+6JiIkx7Dt8NXVGGjy1vRdSGdHkoqZoqjJw7cEBkT7ZkX0c7puedfn1MamnzW5SX4xoa2jVq5u7OWBmkQ==", - "optional": true, + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@google-cloud/storage/-/storage-7.9.0.tgz", + "integrity": "sha512-PlFl7g3r91NmXtZHXsSEfTZES5ysD3SSBWmX4iBdQ2TFH7tN/Vn/IhnVELCHtgh1vc+uYPZ7XvRYaqtDCdghIA==", "dependencies": { "@google-cloud/paginator": "^5.0.0", "@google-cloud/projectify": "^4.0.0", @@ -1429,11 +1443,11 @@ "abort-controller": "^3.0.0", "async-retry": "^1.3.3", "compressible": "^2.0.12", - "duplexify": "^4.0.0", + "duplexify": "^4.1.3", "ent": "^2.2.0", "fast-xml-parser": "^4.3.0", "gaxios": "^6.0.2", - "google-auth-library": "^9.0.0", + "google-auth-library": "^9.6.3", "mime": "^3.0.0", "mime-types": "^2.0.8", "p-limit": "^3.0.1", @@ -1449,29 +1463,26 @@ "version": "8.3.2", "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "optional": true, "bin": { "uuid": "dist/bin/uuid" } }, "node_modules/@grpc/grpc-js": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.10.1.tgz", - "integrity": "sha512-55ONqFytZExfOIjF1RjXPcVmT/jJqFzbbDqxK9jmRV4nxiYWtL9hENSW1Jfx0SdZfrvoqd44YJ/GJTqfRrawSQ==", - "optional": true, + "version": "1.10.6", + "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.10.6.tgz", + "integrity": "sha512-xP58G7wDQ4TCmN/cMUHh00DS7SRDv/+lC+xFLrTkMIN8h55X5NhZMLYbvy7dSELP15qlI6hPhNCRWVMtZMwqLA==", "dependencies": { - "@grpc/proto-loader": "^0.7.8", - "@types/node": ">=12.12.47" + "@grpc/proto-loader": "^0.7.10", + "@js-sdsl/ordered-map": "^4.4.2" }, "engines": { - "node": "^8.13.0 || >=10.10.0" + "node": ">=12.10.0" } }, "node_modules/@grpc/proto-loader": { - "version": "0.7.10", - "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.7.10.tgz", - "integrity": "sha512-CAqDfoaQ8ykFd9zqBDn4k6iWT9loLAlc2ETmDFS9JCD70gDcnA4L3AFEo2iV7KyAtAAHFW9ftq1Fz+Vsgq80RQ==", - "optional": true, + "version": "0.7.12", + "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.7.12.tgz", + "integrity": "sha512-DCVwMxqYzpUCiDMl7hQ384FqP4T3DbNpXU8pt681l3UWCip1WUiD5JrkImUwCB9a7f2cq4CUTmi5r/xIMRPY1Q==", "dependencies": { "lodash.camelcase": "^4.3.0", "long": "^5.0.0", @@ -1548,9 +1559,9 @@ } }, "node_modules/@humanwhocodes/object-schema": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.2.tgz", - "integrity": "sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", + "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", "dev": true }, "node_modules/@img/sharp-darwin-arm64": { @@ -2088,9 +2099,9 @@ } }, "node_modules/@iota/sdk/node_modules/@types/node": { - "version": "18.19.17", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.17.tgz", - "integrity": "sha512-SzyGKgwPzuWp2SHhlpXKzCX0pIOfcI4V2eF37nNBJOhwlegQ83omtVQ1XxZpDE06V/d6AQvfQdPfnw0tRC//Ng==", + "version": "18.19.31", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.31.tgz", + "integrity": "sha512-ArgCD39YpyyrtFKIqMDvjz79jto5fcI/SVUs2HwB+f0dAzq68yqOdyaSivLiLugSziTpNXLQrVb7RZFmdZzbhA==", "dependencies": { "undici-types": "~5.26.4" } @@ -2926,13 +2937,13 @@ } }, "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", - "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", "dependencies": { - "@jridgewell/set-array": "^1.0.1", + "@jridgewell/set-array": "^1.2.1", "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" + "@jridgewell/trace-mapping": "^0.3.24" }, "engines": { "node": ">=6.0.0" @@ -2947,9 +2958,9 @@ } }, "node_modules/@jridgewell/set-array": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", - "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", "engines": { "node": ">=6.0.0" } @@ -2960,23 +2971,37 @@ "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==" }, "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.22", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.22.tgz", - "integrity": "sha512-Wf963MzWtA2sjrNt+g18IAln9lKnlRp+K2eH4jjIoF1wYeq3aMREpG09xhlhdzS0EjwU7qmUJYangWa+151vZw==", + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, + "node_modules/@js-sdsl/ordered-map": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/@js-sdsl/ordered-map/-/ordered-map-4.4.2.tgz", + "integrity": "sha512-iUKgm52T8HOE/makSxjqoWhe95ZJA1/G1sYsGev2JDKUSS14KAgg1LHb+Ba+IPow0xflbnSkOsZcO08C7w1gYw==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/js-sdsl" + } + }, + "node_modules/@leichtgewicht/ip-codec": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.5.tgz", + "integrity": "sha512-Vo+PSpZG2/fmgmiNzYK9qWRh8h/CHrwD0mo1h1DzL4yzHNSfWYujGTYsWGreD000gcgmZ7K4Ys6Tx9TxtsKdDw==" + }, "node_modules/@libp2p/interface": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@libp2p/interface/-/interface-1.1.3.tgz", - "integrity": "sha512-id22Ve5acg6CM0jjL8s9cyEaBYWn7z1R+1gy75RpHi0qgW15ifozwi0oFSTGLVA5XzRnNzioDLj+ZP6QwvhIVQ==", + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/@libp2p/interface/-/interface-1.1.6.tgz", + "integrity": "sha512-CLz6TAZf+Mw1PCIU8pjMIct1uh3A1fIene2/t+E57Tw4uJLCBJE9CLed/Opxliy5RH0e32Aa6bi4QSXtkJTK7A==", "dependencies": { - "@multiformats/multiaddr": "^12.1.14", + "@multiformats/multiaddr": "^12.2.1", "it-pushable": "^3.2.3", "it-stream-types": "^2.0.1", - "multiformats": "^13.0.1", + "multiformats": "^13.1.0", "progress-events": "^1.0.0", "uint8arraylist": "^2.4.8" } @@ -3010,9 +3035,9 @@ } }, "node_modules/@metamask/utils": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/@metamask/utils/-/utils-8.3.0.tgz", - "integrity": "sha512-WFVcMPEkKKRCJ8DDkZUTVbLlpwgRn98F4VM/WzN89HM8PmHMnCyk/oG0AmK/seOxtik7uC7Bbi2YBC5Z5XB2zw==", + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/@metamask/utils/-/utils-8.4.0.tgz", + "integrity": "sha512-dbIc3C7alOe0agCuBHM1h71UaEaEqOk2W8rAtEn8QGz4haH2Qq7MoK6i7v2guzvkJVVh79c+QCzIqphC3KvrJg==", "dependencies": { "@ethereumjs/tx": "^4.2.0", "@noble/hashes": "^1.3.1", @@ -3021,7 +3046,8 @@ "debug": "^4.3.4", "pony-cause": "^2.1.10", "semver": "^7.5.4", - "superstruct": "^1.0.3" + "superstruct": "^1.0.3", + "uuid": "^9.0.1" }, "engines": { "node": ">=16.0.0" @@ -3057,6 +3083,20 @@ "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" }, + "node_modules/@multiformats/dns": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@multiformats/dns/-/dns-1.0.6.tgz", + "integrity": "sha512-nt/5UqjMPtyvkG9BQYdJ4GfLK3nMqGpFZOzf4hAmIa0sJh2LlS9YKXZ4FgwBDsaHvzZqR/rUFIywIc7pkHNNuw==", + "dependencies": { + "@types/dns-packet": "^5.6.5", + "buffer": "^6.0.3", + "dns-packet": "^5.6.1", + "hashlru": "^2.3.0", + "p-queue": "^8.0.1", + "progress-events": "^1.0.0", + "uint8arrays": "^5.0.2" + } + }, "node_modules/@multiformats/mafmt": { "version": "12.1.6", "resolved": "https://registry.npmjs.org/@multiformats/mafmt/-/mafmt-12.1.6.tgz", @@ -3066,14 +3106,14 @@ } }, "node_modules/@multiformats/multiaddr": { - "version": "12.1.14", - "resolved": "https://registry.npmjs.org/@multiformats/multiaddr/-/multiaddr-12.1.14.tgz", - "integrity": "sha512-1C0Mo73chzu7pTzTquuKs5vUtw70jhqg1i6pUNznGb0WV6RFa6vyB+D697Os5+cLx+DiItrAY6VzMtlGQsMzYg==", + "version": "12.2.1", + "resolved": "https://registry.npmjs.org/@multiformats/multiaddr/-/multiaddr-12.2.1.tgz", + "integrity": "sha512-UwjoArBbv64FlaetV4DDwh+PUMfzXUBltxQwdh+uTYnGFzVa8ZfJsn1vt1RJlJ6+Xtrm3RMekF/B+K338i2L5Q==", "dependencies": { "@chainsafe/is-ip": "^2.0.1", "@chainsafe/netmask": "^2.0.0", "@libp2p/interface": "^1.0.0", - "dns-over-http-resolver": "^3.0.2", + "@multiformats/dns": "^1.0.3", "multiformats": "^13.0.0", "uint8-varint": "^2.0.1", "uint8arrays": "^5.0.0" @@ -3104,7 +3144,7 @@ "url": "https://paulmillr.com/funding/" } }, - "node_modules/@noble/hashes": { + "node_modules/@noble/curves/node_modules/@noble/hashes": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.3.tgz", "integrity": "sha512-V7/fPHgl+jsVPXqqeOzT8egNj2iBIVt+ECeMMG8TdcnTikP3oaBtUVqpT/gYCR68aEBJSF+XbYUxStjbFMqIIA==", @@ -3115,6 +3155,17 @@ "url": "https://paulmillr.com/funding/" } }, + "node_modules/@noble/hashes": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.4.0.tgz", + "integrity": "sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==", + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -3150,6 +3201,22 @@ "node": ">= 8" } }, + "node_modules/@opentelemetry/api": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.8.0.tgz", + "integrity": "sha512-I/s6F7yKUDdtMsoBWXJe8Qz40Tui5vsuKCWJEWVL+5q9sSWRzzx6v2KeNsOBEwd94j0eWkpWCH4yB6rZg9Mf0w==", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@opentelemetry/semantic-conventions": { + "version": "1.21.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.21.0.tgz", + "integrity": "sha512-lkC8kZYntxVKr7b8xmjCVUgE0a8xgDakPyDo9uSWavXPyYqLgYYGdEd2j8NxihRyb6UwpX3G/hFUF4/9q2V+/g==", + "engines": { + "node": ">=14" + } + }, "node_modules/@pkgr/core": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.1.tgz", @@ -3217,9 +3284,9 @@ "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==" }, "node_modules/@scure/base": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.1.5.tgz", - "integrity": "sha512-Brj9FiG2W1MRQSTB212YVPRrcbjkv48FoZi/u4l/zds/ieRrqsh7aUf6CLwkAq61oKXr/ZlTzlY66gLIj3TFTQ==", + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.1.6.tgz", + "integrity": "sha512-ok9AWwhcgYuGG3Zfhyqg+zwl+Wn5uE+dwC0NV/2qQkx4dABbb/bx96vWu8NSj+BNjjSjno+JRYRjle1jV08k3g==", "funding": { "url": "https://paulmillr.com/funding/" } @@ -3237,6 +3304,17 @@ "url": "https://paulmillr.com/funding/" } }, + "node_modules/@scure/bip32/node_modules/@noble/hashes": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.3.tgz", + "integrity": "sha512-V7/fPHgl+jsVPXqqeOzT8egNj2iBIVt+ECeMMG8TdcnTikP3oaBtUVqpT/gYCR68aEBJSF+XbYUxStjbFMqIIA==", + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, "node_modules/@scure/bip39": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.2.2.tgz", @@ -3249,6 +3327,17 @@ "url": "https://paulmillr.com/funding/" } }, + "node_modules/@scure/bip39/node_modules/@noble/hashes": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.3.tgz", + "integrity": "sha512-V7/fPHgl+jsVPXqqeOzT8egNj2iBIVt+ECeMMG8TdcnTikP3oaBtUVqpT/gYCR68aEBJSF+XbYUxStjbFMqIIA==", + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, "node_modules/@sideway/address": { "version": "4.1.5", "resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.5.tgz", @@ -3321,15 +3410,14 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", - "optional": true, "engines": { "node": ">= 10" } }, "node_modules/@tsconfig/node10": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", - "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==", + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz", + "integrity": "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==", "dev": true }, "node_modules/@tsconfig/node12": { @@ -3412,8 +3500,7 @@ "node_modules/@types/caseless": { "version": "0.12.5", "resolved": "https://registry.npmjs.org/@types/caseless/-/caseless-0.12.5.tgz", - "integrity": "sha512-hWtVTC2q7hc7xZ/RLbxapMvDMgUnDvKvMOpKal4DrMyfGBUfB1oKaZlIRr6mJL+If3bAP6sV/QneGzF6tJjZDg==", - "optional": true + "integrity": "sha512-hWtVTC2q7hc7xZ/RLbxapMvDMgUnDvKvMOpKal4DrMyfGBUfB1oKaZlIRr6mJL+If3bAP6sV/QneGzF6tJjZDg==" }, "node_modules/@types/chai": { "version": "4.3.11", @@ -3448,6 +3535,7 @@ "version": "2.8.17", "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.17.tgz", "integrity": "sha512-8CGDvrBj1zgo2qE+oS3pOCyYNqCPryMWY2bGfwA0dcfopWGgxs+78df0Rs3rc9THP4JkOhLsAa+15VdpAqkcUA==", + "dev": true, "dependencies": { "@types/node": "*" } @@ -3475,6 +3563,14 @@ "@types/node": "*" } }, + "node_modules/@types/dns-packet": { + "version": "5.6.5", + "resolved": "https://registry.npmjs.org/@types/dns-packet/-/dns-packet-5.6.5.tgz", + "integrity": "sha512-qXOC7XLOEe43ehtWJCMnQXvgcIpv6rPmQ1jXT98Ad8A3TB1Ue50jsCbSSSyuazScEuZ/Q026vHbrOTVkmwA+7Q==", + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/download": { "version": "8.0.5", "resolved": "https://registry.npmjs.org/@types/download/-/download-8.0.5.tgz", @@ -3486,6 +3582,14 @@ "@types/node": "*" } }, + "node_modules/@types/duplexify": { + "version": "3.6.4", + "resolved": "https://registry.npmjs.org/@types/duplexify/-/duplexify-3.6.4.tgz", + "integrity": "sha512-2eahVPsd+dy3CL6FugAzJcxoraWhUghZGEQJns1kTKfCXWKJ5iG/VkaB05wRVrDKHfOFKqb0X0kXh91eE99RZg==", + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/express": { "version": "4.17.21", "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.21.tgz", @@ -3498,9 +3602,9 @@ } }, "node_modules/@types/express-serve-static-core": { - "version": "4.17.43", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.43.tgz", - "integrity": "sha512-oaYtiBirUOPQGSWNGPWnzyAFJ0BP3cwvN4oWZQY+zUBwpVIGsKUkpBpSztp74drYcjavs7SKFZ4DX1V2QeN8rg==", + "version": "4.19.0", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.0.tgz", + "integrity": "sha512-bGyep3JqPCRry1wq+O5n7oiBgGWmeIJXPjXXCo8EK0u8duZGSYar7cGqd3ML2JUsLGeB7fmc06KYo9fLGWqPvQ==", "dependencies": { "@types/node": "*", "@types/qs": "*", @@ -3639,9 +3743,9 @@ "integrity": "sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g==" }, "node_modules/@types/node": { - "version": "20.11.19", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.19.tgz", - "integrity": "sha512-7xMnVEcZFu0DikYjWOlRq7NTPETrm7teqUT2WkQjrTIkEgUyyGdWsj/Zg8bEJt5TNklzbPD1X3fqfsHw3SpapQ==", + "version": "20.12.7", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.7.tgz", + "integrity": "sha512-wq0cICSkRLVaf3UGLMGItu/PtdY7oaXaI/RVU+xliKVOtRna3PRY57ZDfztpDL0n11vfymMUnXv8QwYCO7L1wg==", "dependencies": { "undici-types": "~5.26.4" } @@ -3652,9 +3756,9 @@ "integrity": "sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==" }, "node_modules/@types/qs": { - "version": "6.9.11", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.11.tgz", - "integrity": "sha512-oGk0gmhnEJK4Yyk+oI7EfXsLayXatCWPHary1MtcmbAifkobT9cM9yutG/hZKIseOU0MqbIwQ/u2nn/Gb+ltuQ==" + "version": "6.9.14", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.14.tgz", + "integrity": "sha512-5khscbd3SwWMhFqylJBLQ0zIu7c1K6Vz0uBIt915BI3zV0q1nfjRQD3RqSBcPaO6PHEF4ov/t9y89fSiyThlPA==" }, "node_modules/@types/range-parser": { "version": "1.2.7", @@ -3665,7 +3769,6 @@ "version": "2.48.12", "resolved": "https://registry.npmjs.org/@types/request/-/request-2.48.12.tgz", "integrity": "sha512-G3sY+NpsA9jnwm0ixhAFQSJ3Q9JkpLZpJbI3GMv0mIAT0y3mRabYeINzal5WOChIiaTEGQYlHOKgkaM9EisWHw==", - "optional": true, "dependencies": { "@types/caseless": "*", "@types/node": "*", @@ -3677,7 +3780,6 @@ "version": "2.5.1", "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.1.tgz", "integrity": "sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA==", - "optional": true, "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.6", @@ -3693,9 +3795,9 @@ "integrity": "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==" }, "node_modules/@types/semver": { - "version": "7.5.7", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.7.tgz", - "integrity": "sha512-/wdoPq1QqkSj9/QOeKkFquEuPzQbHTWAMPH/PaUMB+JuR31lXhlWXRZ52IpfDYVlDOUBvX09uBrPwxGT1hjNBg==", + "version": "7.5.8", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.8.tgz", + "integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==", "dev": true }, "node_modules/@types/send": { @@ -3708,13 +3810,13 @@ } }, "node_modules/@types/serve-static": { - "version": "1.15.5", - "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.5.tgz", - "integrity": "sha512-PDRk21MnK70hja/YF8AHfC7yIsiQHn1rcXx7ijCFBX/k+XQJhQT/gw3xekXKJvx+5SXaMMS8oqQy09Mzvz2TuQ==", + "version": "1.15.7", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.7.tgz", + "integrity": "sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==", "dependencies": { "@types/http-errors": "*", - "@types/mime": "*", - "@types/node": "*" + "@types/node": "*", + "@types/send": "*" } }, "node_modules/@types/sharp": { @@ -3761,8 +3863,7 @@ "node_modules/@types/tough-cookie": { "version": "4.0.5", "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.5.tgz", - "integrity": "sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==", - "devOptional": true + "integrity": "sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==" }, "node_modules/@types/uuid": { "version": "9.0.8", @@ -4218,10 +4319,9 @@ "integrity": "sha512-G965FqalsNyrPqgEGON7nIx1e/OVENSgiEIzyC63haUMuvNnwIgIjMs52hlTCKhkBny7A2ORNlfY9Zu+jmGk1Q==" }, "node_modules/agent-base": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.0.tgz", - "integrity": "sha512-o/zjMZRhJxny7OyEF+Op8X+efiELC7k7yOjMzgfzVqOzXqkBkWI79YoTdOtsuWd5BWhAGAuOY/Xa6xpiaWXiNg==", - "optional": true, + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", + "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", "dependencies": { "debug": "^4.3.4" }, @@ -4230,13 +4330,14 @@ } }, "node_modules/ajv": { - "version": "8.12.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", - "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, "dependencies": { "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" }, "funding": { @@ -4244,22 +4345,6 @@ "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/ajv-formats": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", - "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", - "dependencies": { - "ajv": "^8.0.0" - }, - "peerDependencies": { - "ajv": "^8.0.0" - }, - "peerDependenciesMeta": { - "ajv": { - "optional": true - } - } - }, "node_modules/algoliasearch": { "version": "4.22.1", "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-4.22.1.tgz", @@ -4300,7 +4385,6 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "devOptional": true, "engines": { "node": ">=8" } @@ -4384,15 +4468,16 @@ "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" }, "node_modules/array-includes": { - "version": "3.1.7", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.7.tgz", - "integrity": "sha512-dlcsNBIiWhPkHdOEEKnehA+RNUWDc4UqFtnIXU4uuYDPtA4LDkr7qip2p0VvFAEXNDr0yWZ9PJyIRiGjRLQzwQ==", + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.8.tgz", + "integrity": "sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "get-intrinsic": "^1.2.1", + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.4", "is-string": "^1.0.7" }, "engines": { @@ -4411,35 +4496,17 @@ "node": ">=8" } }, - "node_modules/array.prototype.filter": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/array.prototype.filter/-/array.prototype.filter-1.0.3.tgz", - "integrity": "sha512-VizNcj/RGJiUyQBgzwxzE5oHdeuXY5hSbbmKMlphj1cy1Vl7Pn2asCGbSrru6hSQjmCzqTBPVWAF/whmEOVHbw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "es-array-method-boxes-properly": "^1.0.0", - "is-string": "^1.0.7" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/array.prototype.findlastindex": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.4.tgz", - "integrity": "sha512-hzvSHUshSpCflDR1QMUBLHGHP1VIEBegT4pix9H/Z92Xw3ySoy6c2qh7lJWTJnRJ8JCZ9bJNCgTyYaJGcJu6xQ==", + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.5.tgz", + "integrity": "sha512-zfETvRFA8o7EiNn++N5f/kaCw221hrpGsDmcpndVupkPzEc1Wuf3VgC0qby1BbHs7f5DVYjgtEU2LLh5bqeGfQ==", "dev": true, "dependencies": { - "call-bind": "^1.0.5", + "call-bind": "^1.0.7", "define-properties": "^1.2.1", - "es-abstract": "^1.22.3", + "es-abstract": "^1.23.2", "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", "es-shim-unscopables": "^1.0.2" }, "engines": { @@ -4511,7 +4578,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz", "integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==", - "optional": true, "engines": { "node": ">=8" } @@ -4520,7 +4586,6 @@ "version": "1.3.3", "resolved": "https://registry.npmjs.org/async-retry/-/async-retry-1.3.3.tgz", "integrity": "sha512-wfr/jstw9xNi/0teMHrRW7dsz3Lt5ARhYNZ2ewpadnhaIp5mbALhOAP+EAdsC7t4Z6wqsDVv9+W6gm1Dk9mEyw==", - "optional": true, "dependencies": { "retry": "0.13.1" } @@ -4802,12 +4867,12 @@ "integrity": "sha512-HoMUjhH9T8DDBNT+6xzkrd9ga/XiBI4xLr58LJACwK6G3HTOPeMz4nB4KJs33L2BelrIJa7P0VuNaVF3hMYfjg==" }, "node_modules/body-parser": { - "version": "1.20.1", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", - "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", + "version": "1.20.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", + "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", "dependencies": { "bytes": "3.1.2", - "content-type": "~1.0.4", + "content-type": "~1.0.5", "debug": "2.6.9", "depd": "2.0.0", "destroy": "1.2.0", @@ -4815,7 +4880,7 @@ "iconv-lite": "0.4.24", "on-finished": "2.4.1", "qs": "6.11.0", - "raw-body": "2.5.1", + "raw-body": "2.5.2", "type-is": "~1.6.18", "unpipe": "1.0.0" }, @@ -4950,6 +5015,14 @@ "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", "dev": true }, + "node_modules/buffer-writer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/buffer-writer/-/buffer-writer-2.0.0.tgz", + "integrity": "sha512-a7ZpuTZU1TRtnwyCNW3I5dc0wWNC3VR9S++Ewyk2HHZdrO3CQJqSpd+95Us590V6AL7JqUAH2IwZ/398PmNFgw==", + "engines": { + "node": ">=4" + } + }, "node_modules/builtin-modules": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.3.0.tgz", @@ -5033,9 +5106,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001588", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001588.tgz", - "integrity": "sha512-+hVY9jE44uKLkH0SrUTqxjxqNTOWHsbnQDIKjwkZ3lNTzUUVdBLBGXtj/q5Mp5u98r3droaZAewQuEDzjQdZlQ==", + "version": "1.0.30001608", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001608.tgz", + "integrity": "sha512-cjUJTQkk9fQlJR2s4HMuPMvTiRggl0rAVMtthQuyOlDWuqHXqN8azLq+pi8B2TjwKJ32diHjUqRIKeFX4z1FoA==", "dev": true, "funding": [ { @@ -5157,7 +5230,6 @@ "version": "8.0.1", "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "devOptional": true, "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.1", @@ -5167,30 +5239,6 @@ "node": ">=12" } }, - "node_modules/cloudevents": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/cloudevents/-/cloudevents-8.0.0.tgz", - "integrity": "sha512-G1Z/r8QMFAsP+F1PuZSHzx1ocPy4vrdQMTHD3orjDaM5kccmPU6nMmpVrF07b53aaxcrLbORUmRepY/DgvdhVw==", - "dependencies": { - "ajv": "^8.11.0", - "ajv-formats": "^2.1.1", - "json-bigint": "^1.0.0", - "process": "^0.11.10", - "util": "^0.12.4", - "uuid": "^8.3.2" - }, - "engines": { - "node": ">=16 <=20" - } - }, - "node_modules/cloudevents/node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "bin": { - "uuid": "dist/bin/uuid" - } - }, "node_modules/co": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", @@ -5257,6 +5305,11 @@ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, + "node_modules/colorette": { + "version": "2.0.19", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.19.tgz", + "integrity": "sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ==" + }, "node_modules/combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", @@ -5268,6 +5321,14 @@ "node": ">= 0.8" } }, + "node_modules/commander": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", + "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", + "engines": { + "node": ">=14" + } + }, "node_modules/comment-parser": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/comment-parser/-/comment-parser-1.4.1.tgz", @@ -5290,7 +5351,6 @@ "version": "2.0.18", "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", - "optional": true, "dependencies": { "mime-db": ">= 1.43.0 < 2" }, @@ -5329,9 +5389,9 @@ "dev": true }, "node_modules/cookie": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", - "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", + "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", "engines": { "node": ">= 0.6" } @@ -5497,10 +5557,61 @@ "node": ">= 6" } }, - "node_modules/dayjs": { - "version": "1.11.10", - "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.10.tgz", - "integrity": "sha512-vjAczensTgRcqDERK0SR2XMwsF/tSvnvlv6VcF2GIhg6Sx4yOIt/irsr1RDJsKiIyBzJDpCoXiWWq28MqH2cnQ==" + "node_modules/data-view-buffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.1.tgz", + "integrity": "sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/data-view-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.1.tgz", + "integrity": "sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/data-view-byte-offset": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.0.tgz", + "integrity": "sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/dayjs": { + "version": "1.11.10", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.10.tgz", + "integrity": "sha512-vjAczensTgRcqDERK0SR2XMwsF/tSvnvlv6VcF2GIhg6Sx4yOIt/irsr1RDJsKiIyBzJDpCoXiWWq28MqH2cnQ==" }, "node_modules/debug": { "version": "4.3.4", @@ -5659,9 +5770,9 @@ } }, "node_modules/detect-libc": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.2.tgz", - "integrity": "sha512-UX6sGumvvqSaXgdKGUsgZWqcUyIXZ/vZTrlRT/iobiKhGL0zL4d3osHj3uqllWJK+i+sixDS/3COVEOFbupFyw==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz", + "integrity": "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==", "engines": { "node": ">=8" } @@ -5712,14 +5823,26 @@ "dev": true }, "node_modules/dns-over-http-resolver": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/dns-over-http-resolver/-/dns-over-http-resolver-3.0.2.tgz", - "integrity": "sha512-5batkHOjCkuAfrFa+IPmt3jyeZqLtSMfAo1HQp3hfwtzgUwHooecTFplnYC093u5oRNL4CQHCXh3OfER7+vWrA==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/dns-over-http-resolver/-/dns-over-http-resolver-1.2.3.tgz", + "integrity": "sha512-miDiVSI6KSNbi4SVifzO/reD8rMnxgrlnkrlkugOLQpWQTe2qMdHsZp5DmfKjxNE+/T3VAAYLQUZMv9SMr6+AA==", "dependencies": { - "debug": "^4.3.4", + "debug": "^4.3.1", + "native-fetch": "^3.0.0", "receptacle": "^1.3.2" } }, + "node_modules/dns-packet": { + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-5.6.1.tgz", + "integrity": "sha512-l4gcSouhcgIKRvyy99RNVOgxXiicE+2jZoNmaNmZ6JXiGajBOJAesk1OBlJuM5k2c+eudGdLxDqXuPCKIj6kpw==", + "dependencies": { + "@leichtgewicht/ip-codec": "^2.0.1" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/doctrine": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", @@ -5744,15 +5867,14 @@ } }, "node_modules/duplexify": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.2.tgz", - "integrity": "sha512-fz3OjcNCHmRP12MJoZMPglx8m4rrFP8rovnk4vT8Fs+aonZoCwGg10dSsQsfP/E62eZcPTMSMP6686fu9Qlqtw==", - "optional": true, + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.3.tgz", + "integrity": "sha512-M3BmBhwJRZsSx38lZyhE53Csddgzl5R7xGJNk7CVddZD6CcmwMCH8J+7AprIrQKH7TonKxaCjcv27Qmf+sQ+oA==", "dependencies": { "end-of-stream": "^1.4.1", "inherits": "^2.0.3", "readable-stream": "^3.1.1", - "stream-shift": "^1.0.0" + "stream-shift": "^1.0.2" } }, "node_modules/ecdsa-sig-formatter": { @@ -5780,9 +5902,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.4.677", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.677.tgz", - "integrity": "sha512-erDa3CaDzwJOpyvfKhOiJjBVNnMM0qxHq47RheVVwsSQrgBA9ZSGV9kdaOfZDPXcHzhG7lBxhj6A7KvfLJBd6Q==", + "version": "1.4.731", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.731.tgz", + "integrity": "sha512-+TqVfZjpRz2V/5SPpmJxq9qK620SC5SqCnxQIOi7i/U08ZDcTpKbT7Xjj9FU5CbXTMUb4fywbIr8C7cGv4hcjw==", "dev": true }, "node_modules/emittery": { @@ -5800,8 +5922,7 @@ "node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "devOptional": true + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" }, "node_modules/encodeurl": { "version": "1.0.2", @@ -5839,9 +5960,9 @@ } }, "node_modules/enhanced-resolve": { - "version": "5.15.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.15.0.tgz", - "integrity": "sha512-LXYT42KJ7lpIKECr2mAXIaMldcNCh/7E0KBKOu4KSfkHmP+mZmSs+8V5gBAqisWBy0OO4W5Oyys0GO1Y8KtdKg==", + "version": "5.16.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.16.0.tgz", + "integrity": "sha512-O+QWCviPNSSLAD9Ucn8Awv+poAkqn3T1XY5/N7kR7rQO9yfSGWkYZDwpJ+iKF7B8rxaQKWngSqACpgzeapSyoA==", "dev": true, "dependencies": { "graceful-fs": "^4.2.4", @@ -5854,8 +5975,7 @@ "node_modules/ent": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/ent/-/ent-2.2.0.tgz", - "integrity": "sha512-GHrMyVZQWvTIdDtpiEXdHZnFQKzeO09apj8Cbl4pKWy4i0Oprcq17usfDt5aO63swf0JOeMWjWQE/LzgSRuWpA==", - "optional": true + "integrity": "sha512-GHrMyVZQWvTIdDtpiEXdHZnFQKzeO09apj8Cbl4pKWy4i0Oprcq17usfDt5aO63swf0JOeMWjWQE/LzgSRuWpA==" }, "node_modules/err-code": { "version": "3.0.1", @@ -5871,18 +5991,22 @@ } }, "node_modules/es-abstract": { - "version": "1.22.4", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.4.tgz", - "integrity": "sha512-vZYJlk2u6qHYxBOTjAeg7qUxHdNfih64Uu2J8QqWgXZ2cri0ZpJAkzDUK/q593+mvKwlxyaxr6F1Q+3LKoQRgg==", + "version": "1.23.3", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.3.tgz", + "integrity": "sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A==", "dev": true, "dependencies": { "array-buffer-byte-length": "^1.0.1", "arraybuffer.prototype.slice": "^1.0.3", - "available-typed-arrays": "^1.0.6", + "available-typed-arrays": "^1.0.7", "call-bind": "^1.0.7", + "data-view-buffer": "^1.0.1", + "data-view-byte-length": "^1.0.1", + "data-view-byte-offset": "^1.0.0", "es-define-property": "^1.0.0", "es-errors": "^1.3.0", - "es-set-tostringtag": "^2.0.2", + "es-object-atoms": "^1.0.0", + "es-set-tostringtag": "^2.0.3", "es-to-primitive": "^1.2.1", "function.prototype.name": "^1.1.6", "get-intrinsic": "^1.2.4", @@ -5890,15 +6014,16 @@ "globalthis": "^1.0.3", "gopd": "^1.0.1", "has-property-descriptors": "^1.0.2", - "has-proto": "^1.0.1", + "has-proto": "^1.0.3", "has-symbols": "^1.0.3", - "hasown": "^2.0.1", + "hasown": "^2.0.2", "internal-slot": "^1.0.7", "is-array-buffer": "^3.0.4", "is-callable": "^1.2.7", - "is-negative-zero": "^2.0.2", + "is-data-view": "^1.0.1", + "is-negative-zero": "^2.0.3", "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.2", + "is-shared-array-buffer": "^1.0.3", "is-string": "^1.0.7", "is-typed-array": "^1.1.13", "is-weakref": "^1.0.2", @@ -5906,17 +6031,17 @@ "object-keys": "^1.1.1", "object.assign": "^4.1.5", "regexp.prototype.flags": "^1.5.2", - "safe-array-concat": "^1.1.0", + "safe-array-concat": "^1.1.2", "safe-regex-test": "^1.0.3", - "string.prototype.trim": "^1.2.8", - "string.prototype.trimend": "^1.0.7", - "string.prototype.trimstart": "^1.0.7", - "typed-array-buffer": "^1.0.1", - "typed-array-byte-length": "^1.0.0", - "typed-array-byte-offset": "^1.0.0", - "typed-array-length": "^1.0.4", + "string.prototype.trim": "^1.2.9", + "string.prototype.trimend": "^1.0.8", + "string.prototype.trimstart": "^1.0.8", + "typed-array-buffer": "^1.0.2", + "typed-array-byte-length": "^1.0.1", + "typed-array-byte-offset": "^1.0.2", + "typed-array-length": "^1.0.6", "unbox-primitive": "^1.0.2", - "which-typed-array": "^1.1.14" + "which-typed-array": "^1.1.15" }, "engines": { "node": ">= 0.4" @@ -5925,12 +6050,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/es-array-method-boxes-properly": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz", - "integrity": "sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA==", - "dev": true - }, "node_modules/es-define-property": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", @@ -5950,6 +6069,18 @@ "node": ">= 0.4" } }, + "node_modules/es-object-atoms": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz", + "integrity": "sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==", + "dev": true, + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/es-set-tostringtag": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz", @@ -5994,7 +6125,6 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", - "devOptional": true, "engines": { "node": ">=6" } @@ -6137,9 +6267,9 @@ } }, "node_modules/eslint-module-utils": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.0.tgz", - "integrity": "sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==", + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.1.tgz", + "integrity": "sha512-rXDXR3h7cs7dy9RNpUlQf80nX31XWJEyGq1tRMo+6GsO5VmTe4UTwtmonAD4ZkAsrfMVDA2wlGJ3790Ys+D49Q==", "dev": true, "dependencies": { "debug": "^3.2.7" @@ -6377,22 +6507,6 @@ "url": "https://opencollective.com/eslint" } }, - "node_modules/eslint/node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, "node_modules/eslint/node_modules/ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", @@ -6536,12 +6650,6 @@ "js-yaml": "bin/js-yaml.js" } }, - "node_modules/eslint/node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, "node_modules/eslint/node_modules/locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", @@ -6623,6 +6731,14 @@ "node": ">= 8" } }, + "node_modules/esm": { + "version": "3.2.25", + "resolved": "https://registry.npmjs.org/esm/-/esm-3.2.25.tgz", + "integrity": "sha512-U1suiZ2oDVWv4zPO56S0NcR5QriEahGtdN2OR6FiOG4WJvcjBVFB0qI4+eKoWFH483PKGuLuu6V8Z4T5g63UVA==", + "engines": { + "node": ">=6" + } + }, "node_modules/espree": { "version": "9.6.1", "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", @@ -6714,6 +6830,17 @@ "@scure/bip39": "1.2.2" } }, + "node_modules/ethereum-cryptography/node_modules/@noble/hashes": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.3.tgz", + "integrity": "sha512-V7/fPHgl+jsVPXqqeOzT8egNj2iBIVt+ECeMMG8TdcnTikP3oaBtUVqpT/gYCR68aEBJSF+XbYUxStjbFMqIIA==", + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, "node_modules/ethers": { "version": "6.11.1", "resolved": "https://registry.npmjs.org/ethers/-/ethers-6.11.1.tgz", @@ -6796,6 +6923,11 @@ "node": ">=6" } }, + "node_modules/eventemitter3": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", + "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==" + }, "node_modules/execa": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", @@ -6882,16 +7014,16 @@ } }, "node_modules/express": { - "version": "4.18.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", - "integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==", + "version": "4.19.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz", + "integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==", "dependencies": { "accepts": "~1.3.8", "array-flatten": "1.1.1", - "body-parser": "1.20.1", + "body-parser": "1.20.2", "content-disposition": "0.5.4", "content-type": "~1.0.4", - "cookie": "0.5.0", + "cookie": "0.6.0", "cookie-signature": "1.0.6", "debug": "2.6.9", "depd": "2.0.0", @@ -6938,13 +7070,13 @@ "node_modules/extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", - "optional": true + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "devOptional": true }, "node_modules/fast-diff": { "version": "1.3.0", @@ -6998,9 +7130,9 @@ "dev": true }, "node_modules/fast-xml-parser": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.3.4.tgz", - "integrity": "sha512-utnwm92SyozgA3hhH2I8qldf2lBqm6qHOICawRNRFu1qMe3+oqr+GcXjGqTmXTMGE5T4eC03kr/rlh5C1IRdZA==", + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.3.6.tgz", + "integrity": "sha512-M2SovcRxD4+vC493Uc2GZVcZaj66CCJhWurC4viynVSTvrpErCShNcDz1lAho6n9REQKvL/ll4A4/fw6Y9z8nw==", "funding": [ { "type": "github", @@ -7011,7 +7143,6 @@ "url": "https://paypal.me/naturalintelligence" } ], - "optional": true, "dependencies": { "strnum": "^1.0.5" }, @@ -7147,57 +7278,6 @@ "@google-cloud/storage": "^7.7.0" } }, - "node_modules/firebase-functions": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/firebase-functions/-/firebase-functions-4.7.0.tgz", - "integrity": "sha512-YgWqA9otWlBUouY4I2yd0vq9SyQdQ6GJxfH7wGJclzS2pzBQHcU5HhE1Vz/xTrWcKJyw8uPN98WtSE9/APUJJg==", - "dependencies": { - "@types/cors": "^2.8.5", - "@types/express": "4.17.3", - "cors": "^2.8.5", - "express": "^4.17.1", - "node-fetch": "^2.6.7", - "protobufjs": "^7.2.2" - }, - "bin": { - "firebase-functions": "lib/bin/firebase-functions.js" - }, - "engines": { - "node": ">=14.10.0" - }, - "peerDependencies": { - "firebase-admin": "^10.0.0 || ^11.0.0 || ^12.0.0" - } - }, - "node_modules/firebase-functions-test": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/firebase-functions-test/-/firebase-functions-test-3.1.1.tgz", - "integrity": "sha512-IlDzcd+8rUd87hD1ZAPXsc3cX5JGdfpKmKlUJWdZJlErdyznwXssPQzbRPX8rh929ZhwmzGpubFBt7itkXAg+A==", - "dev": true, - "dependencies": { - "@types/lodash": "^4.14.104", - "lodash": "^4.17.5", - "ts-deepmerge": "^2.0.1" - }, - "engines": { - "node": ">=14.0.0" - }, - "peerDependencies": { - "firebase-admin": "^8.0.0 || ^9.0.0 || ^10.0.0 || ^11.0.0 || ^12.0.0", - "firebase-functions": ">=4.3.0", - "jest": ">=28.0.0" - } - }, - "node_modules/firebase-functions/node_modules/@types/express": { - "version": "4.17.3", - "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.3.tgz", - "integrity": "sha512-I8cGRJj3pyOLs/HndoP+25vOqhqWkAZsWMEmq1qXy/b/M3ppufecUwaK2/TVDVxcV61/iSdhykUjQQ2DLSrTdg==", - "dependencies": { - "@types/body-parser": "*", - "@types/express-serve-static-core": "*", - "@types/serve-static": "*" - } - }, "node_modules/flat-cache": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", @@ -7341,15 +7421,15 @@ } }, "node_modules/gaxios": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-6.3.0.tgz", - "integrity": "sha512-p+ggrQw3fBwH2F5N/PAI4k/G/y1art5OxKpb2J2chwNNHM4hHuAOtivjPuirMF4KNKwTTUal/lPfL2+7h2mEcg==", - "optional": true, + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-6.4.0.tgz", + "integrity": "sha512-apAloYrY4dlBGlhauDAYSZveafb5U6+L9titing1wox6BvWM0TSXBp603zTrLpyLMGkrcFgohnUN150dFN/zOA==", "dependencies": { "extend": "^3.0.2", "https-proxy-agent": "^7.0.1", "is-stream": "^2.0.0", - "node-fetch": "^2.6.9" + "node-fetch": "^2.6.9", + "uuid": "^9.0.1" }, "engines": { "node": ">=14" @@ -7359,7 +7439,6 @@ "version": "2.7.0", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", - "optional": true, "dependencies": { "whatwg-url": "^5.0.0" }, @@ -7379,7 +7458,6 @@ "version": "6.1.0", "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-6.1.0.tgz", "integrity": "sha512-Jh/AIwwgaxan+7ZUUmRLCjtchyDiqh4KjBJ5tW3plBZb5iL/BPcso8A5DlzeD9qlw0duCamnNdpFjxwaT0KyKg==", - "optional": true, "dependencies": { "gaxios": "^6.0.0", "json-bigint": "^1.0.0" @@ -7401,7 +7479,6 @@ "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "devOptional": true, "engines": { "node": "6.* || 8.* || >= 10.*" } @@ -7433,7 +7510,6 @@ "version": "0.1.0", "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", - "dev": true, "engines": { "node": ">=8.0.0" } @@ -7468,9 +7544,9 @@ } }, "node_modules/get-tsconfig": { - "version": "4.7.2", - "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.7.2.tgz", - "integrity": "sha512-wuMsz4leaj5hbGgg4IvDU0bqJagpftG5l5cXIAvo8uZrqn0NJqwtfupTN00VnkQJPcIRrxYrm1Ue24btpCha2A==", + "version": "4.7.3", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.7.3.tgz", + "integrity": "sha512-ZvkrzoUA0PQZM6fy6+/Hce561s+faD1rsNwhnO5FelNjyy7EMGJ3Rz1AQ8GYDWjhRs/7dBLOEJvhK8MiEJOAFg==", "dev": true, "dependencies": { "resolve-pkg-maps": "^1.0.0" @@ -7479,6 +7555,11 @@ "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" } }, + "node_modules/getopts": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/getopts/-/getopts-2.3.0.tgz", + "integrity": "sha512-5eDf9fuSXwxBL6q5HX+dhDj+dslFGWzU5thZ9kNKUkcPtaPdatmUFKwHFrLb/uf/WpA4BHET+AX3Scl56cAjpA==" + }, "node_modules/github-from-package": { "version": "0.0.0", "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", @@ -7571,10 +7652,9 @@ } }, "node_modules/google-auth-library": { - "version": "9.6.3", - "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-9.6.3.tgz", - "integrity": "sha512-4CacM29MLC2eT9Cey5GDVK4Q8t+MMp8+OEdOaqD9MG6b0dOyLORaaeJMPQ7EESVgm/+z5EKYyFLxgzBJlJgyHQ==", - "optional": true, + "version": "9.7.0", + "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-9.7.0.tgz", + "integrity": "sha512-I/AvzBiUXDzLOy4iIZ2W+Zq33W4lcukQv1nl7C8WUA6SQwyQwUwu3waNmWNAvzds//FG8SZ+DnKnW/2k6mQS8A==", "dependencies": { "base64-js": "^1.3.0", "ecdsa-sig-formatter": "^1.0.11", @@ -7588,10 +7668,9 @@ } }, "node_modules/google-gax": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/google-gax/-/google-gax-4.3.1.tgz", - "integrity": "sha512-qpSfslpwqToIgQ+Tf3MjWIDjYK4UFIZ0uz6nLtttlW9N1NQA4PhGf9tlGo6KDYJ4rgL2w4CjXVd0z5yeNpN/Iw==", - "optional": true, + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/google-gax/-/google-gax-4.3.2.tgz", + "integrity": "sha512-2mw7qgei2LPdtGrmd1zvxQviOcduTnsvAWYzCxhOWXK4IQKmQztHnDQwD0ApB690fBQJemFKSU7DnceAy3RLzw==", "dependencies": { "@grpc/grpc-js": "~1.10.0", "@grpc/proto-loader": "^0.7.0", @@ -7636,7 +7715,6 @@ "version": "7.1.0", "resolved": "https://registry.npmjs.org/gtoken/-/gtoken-7.1.0.tgz", "integrity": "sha512-pCcEwRi+TKpMlxAQObHDQ56KawURgyAf6jtIY046fJ5tIv3zDe/LEIubckAO8fj6JnAxLdmWkUfNyulQ2iKdEw==", - "optional": true, "dependencies": { "gaxios": "^6.0.0", "jws": "^4.0.0" @@ -7764,10 +7842,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/hashlru": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/hashlru/-/hashlru-2.3.0.tgz", + "integrity": "sha512-0cMsjjIC8I+D3M44pOQdsy0OHXGLVz6Z0beRuufhKa0KfaD2wGwAev6jILzXsd3/vpnNQJmWyZtIILqM1N+n5A==" + }, "node_modules/hasown": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.1.tgz", - "integrity": "sha512-1/th4MHjnwncwXsIW6QMzlvYL9kG5e/CpVvLRZe4XPa8TOUNbCELqmvhDmnkNsAjwaG4+I8gJJL0JBvTTLO9qA==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", "dependencies": { "function-bind": "^1.1.2" }, @@ -7775,6 +7858,14 @@ "node": ">= 0.4" } }, + "node_modules/heap-js": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/heap-js/-/heap-js-2.5.0.tgz", + "integrity": "sha512-kUGoI3p7u6B41z/dp33G6OaL7J4DRqRYwVmeIlwLClx7yaaAy7hoDExnuejTKtuDwfcatGmddHDEOjf6EyIxtQ==", + "engines": { + "node": ">=10.0.0" + } + }, "node_modules/hosted-git-info": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", @@ -7832,7 +7923,6 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", - "optional": true, "dependencies": { "@tootallnate/once": "2", "agent-base": "6", @@ -7846,7 +7936,6 @@ "version": "6.0.2", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "optional": true, "dependencies": { "debug": "4" }, @@ -7858,7 +7947,6 @@ "version": "7.0.4", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.4.tgz", "integrity": "sha512-wlwpilI7YdjSkWaQ/7omYBMTliDcmCN8OLihO6I9B86g06lMyAoqgoDpV0XqoaPOKj+0DIdAvnsWfyAAhmimcg==", - "optional": true, "dependencies": { "agent-base": "^7.0.2", "debug": "4" @@ -8043,14 +8131,6 @@ "resolved": "https://registry.npmjs.org/interface-store/-/interface-store-2.0.2.tgz", "integrity": "sha512-rScRlhDcz6k199EkHqT8NpM87ebN89ICOzILoBHgaG36/WX50N32BnU/kpZgCGPLhARRAWUUX5/cyaIjt7Kipg==" }, - "node_modules/interfaces": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/interfaces/-/interfaces-0.0.3.tgz", - "integrity": "sha512-nfHWLvWzsZoRme8F21HgoEC69T2vpCHWaFzjptYLzkFiYy6t9GsfWL14Bc0IyvgHRKj51zJg68Rv/emBcbKXgQ==", - "dependencies": { - "underscore": "*" - } - }, "node_modules/internal-slot": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz", @@ -8065,6 +8145,14 @@ "node": ">= 0.4" } }, + "node_modules/interpret": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-2.2.0.tgz", + "integrity": "sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw==", + "engines": { + "node": ">= 0.10" + } + }, "node_modules/ip-regex": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-4.3.0.tgz", @@ -8460,6 +8548,21 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-data-view": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.1.tgz", + "integrity": "sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==", + "dev": true, + "dependencies": { + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-date-object": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", @@ -8493,7 +8596,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "devOptional": true, "engines": { "node": ">=8" } @@ -8648,7 +8750,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "devOptional": true, "engines": { "node": ">=8" }, @@ -8656,6 +8757,11 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/is-stream-ended": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-stream-ended/-/is-stream-ended-0.1.4.tgz", + "integrity": "sha512-xj0XPvmr7bQFTvirqnFr50o0hQIh6ZItDqloxt5aJrR4NQsYeSsyFQERYGCAzfindAcnKjINnwEEgLx4IqVzQw==" + }, "node_modules/is-string": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", @@ -8908,6 +9014,17 @@ "p-defer": "^4.0.0" } }, + "node_modules/it-pushable/node_modules/p-defer": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-4.0.1.tgz", + "integrity": "sha512-Mr5KC5efvAK5VUptYEIopP1bakB85k2IWXaRC0rsh1uwn1L6M0LVml8OIQ4Gudg4oyZakf7FmeRLkMMtZW1i5A==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/it-stream-types": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/it-stream-types/-/it-stream-types-2.0.1.tgz", @@ -8935,14 +9052,6 @@ "readable-stream": "^3.6.0" } }, - "node_modules/it-to-stream/node_modules/p-defer": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-3.0.0.tgz", - "integrity": "sha512-ugZxsxmtTln604yeYd29EGrNhazN2lywetzpKhfmQjW/VJmhpDmWbiX+h0zL8V91R0UXkhb3KtPmyq9PZw3aYw==", - "engines": { - "node": ">=8" - } - }, "node_modules/jest": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz", @@ -9578,30 +9687,6 @@ "fsevents": "^2.3.2" } }, - "node_modules/jest-junit": { - "version": "16.0.0", - "resolved": "https://registry.npmjs.org/jest-junit/-/jest-junit-16.0.0.tgz", - "integrity": "sha512-A94mmw6NfJab4Fg/BlvVOUXzXgF0XIH6EmTgJ5NDPp4xoKq0Kr7sErb+4Xs9nZvu58pJojz5RFGpqnZYJTrRfQ==", - "dev": true, - "dependencies": { - "mkdirp": "^1.0.4", - "strip-ansi": "^6.0.1", - "uuid": "^8.3.2", - "xml": "^1.0.1" - }, - "engines": { - "node": ">=10.12.0" - } - }, - "node_modules/jest-junit/node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "dev": true, - "bin": { - "uuid": "dist/bin/uuid" - } - }, "node_modules/jest-leak-detector": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz", @@ -10629,9 +10714,11 @@ } }, "node_modules/joi": { - "version": "17.12.1", - "resolved": "https://registry.npmjs.org/joi/-/joi-17.12.1.tgz", - "integrity": "sha512-vtxmq+Lsc5SlfqotnfVjlViWfOL9nt/avKNbKYizwf6gsCfq9NYY/ceYRMFD8XDdrjJ9abJyScWmhmIiy+XRtQ==", + "version": "17.12.3", + "resolved": "https://registry.npmjs.org/joi/-/joi-17.12.3.tgz", + "integrity": "sha512-2RRziagf555owrm9IRVtdKynOBeITiDpuZqIpgwqXShPncPKNiRQoiGsl/T8SQdq+8ugRzH2LqY67irr2y/d+g==", + "dev": true, + "peer": true, "dependencies": { "@hapi/hoek": "^9.3.0", "@hapi/topo": "^5.1.0", @@ -10726,9 +10813,10 @@ "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==" }, "node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true }, "node_modules/json-stable-stringify-without-jsonify": { "version": "1.0.1", @@ -10828,7 +10916,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.0.tgz", "integrity": "sha512-jrZ2Qx916EA+fq9cEAeCROWPTfCwi1IVHqT2tapuqLEVVDKFDENFw1oL+MwrTvH6msKxsd1YTDVw6uKEcsrLEA==", - "optional": true, "dependencies": { "buffer-equal-constant-time": "1.0.1", "ecdsa-sig-formatter": "1.0.11", @@ -10855,7 +10942,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/jws/-/jws-4.0.0.tgz", "integrity": "sha512-KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg==", - "optional": true, "dependencies": { "jwa": "^2.0.0", "safe-buffer": "^5.0.1" @@ -10887,23 +10973,73 @@ "node": ">=6" } }, - "node_modules/leven": { + "node_modules/knex": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", - "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "dev": true, + "resolved": "https://registry.npmjs.org/knex/-/knex-3.1.0.tgz", + "integrity": "sha512-GLoII6hR0c4ti243gMs5/1Rb3B+AjwMOfjYm97pu0FOQa7JH56hgBxYf5WK2525ceSbBY1cjeZ9yk99GPMB6Kw==", "dependencies": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" + "colorette": "2.0.19", + "commander": "^10.0.0", + "debug": "4.3.4", + "escalade": "^3.1.1", + "esm": "^3.2.25", + "get-package-type": "^0.1.0", + "getopts": "2.3.0", + "interpret": "^2.2.0", + "lodash": "^4.17.21", + "pg-connection-string": "2.6.2", + "rechoir": "^0.8.0", + "resolve-from": "^5.0.0", + "tarn": "^3.0.2", + "tildify": "2.0.0" + }, + "bin": { + "knex": "bin/cli.js" + }, + "engines": { + "node": ">=16" + }, + "peerDependenciesMeta": { + "better-sqlite3": { + "optional": true + }, + "mysql": { + "optional": true + }, + "mysql2": { + "optional": true + }, + "pg": { + "optional": true + }, + "pg-native": { + "optional": true + }, + "sqlite3": { + "optional": true + }, + "tedious": { + "optional": true + } + } + }, + "node_modules/leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" }, "engines": { "node": ">= 0.8.0" @@ -10938,8 +11074,7 @@ "node_modules/lodash.camelcase": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", - "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==", - "optional": true + "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==" }, "node_modules/lodash.clonedeep": { "version": "4.5.0", @@ -10999,6 +11134,11 @@ "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==" }, + "node_modules/lodash.snakecase": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.snakecase/-/lodash.snakecase-4.1.1.tgz", + "integrity": "sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw==" + }, "node_modules/loglevel": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.9.1.tgz", @@ -11293,7 +11433,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz", "integrity": "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==", - "optional": true, "bin": { "mime": "cli.js" }, @@ -11400,18 +11539,6 @@ "node": ">=0.10.0" } }, - "node_modules/mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "dev": true, - "bin": { - "mkdirp": "bin/cmd.js" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/mkdirp-classic": { "version": "0.5.3", "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", @@ -11467,16 +11594,6 @@ "multiaddr": "^10.0.0" } }, - "node_modules/multiaddr/node_modules/dns-over-http-resolver": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/dns-over-http-resolver/-/dns-over-http-resolver-1.2.3.tgz", - "integrity": "sha512-miDiVSI6KSNbi4SVifzO/reD8rMnxgrlnkrlkugOLQpWQTe2qMdHsZp5DmfKjxNE+/T3VAAYLQUZMv9SMr6+AA==", - "dependencies": { - "debug": "^4.3.1", - "native-fetch": "^3.0.0", - "receptacle": "^1.3.2" - } - }, "node_modules/multiaddr/node_modules/multiformats": { "version": "9.9.0", "resolved": "https://registry.npmjs.org/multiformats/-/multiformats-9.9.0.tgz", @@ -11627,9 +11744,9 @@ } }, "node_modules/node-abi": { - "version": "3.55.0", - "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.55.0.tgz", - "integrity": "sha512-uPEjtyh2tFEvWYt4Jw7McOD5FPcHkcxm/tHZc5PWaDB3JYq0rGFUbgaAK+CT5pYpQddBfsZVWI08OwoRfdfbcQ==", + "version": "3.57.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.57.0.tgz", + "integrity": "sha512-Dp+A9JWxRaKuHP35H77I4kCKesDy5HUDEmScia2FyncMTOXASMyg251F5PhFoDA5uqBrDDffiLpbqnrZmNXW+g==", "dependencies": { "semver": "^7.3.5" }, @@ -11811,7 +11928,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", - "optional": true, "engines": { "node": ">= 6" } @@ -11852,14 +11968,15 @@ } }, "node_modules/object.fromentries": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.7.tgz", - "integrity": "sha512-UPbPHML6sL8PI/mOqPwsH4G6iyXcCGzLin8KvEPenOZN5lpCNBZZQ+V62vdjB1mQHrmqGQt5/OJzemUA+KJmEA==", + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz", + "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0" }, "engines": { "node": ">= 0.4" @@ -11869,27 +11986,28 @@ } }, "node_modules/object.groupby": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.2.tgz", - "integrity": "sha512-bzBq58S+x+uo0VjurFT0UktpKHOZmv4/xePiOA1nbB9pMqpGK7rUPNgf+1YC+7mE+0HzhTMqNUuCqvKhj6FnBw==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.3.tgz", + "integrity": "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==", "dev": true, "dependencies": { - "array.prototype.filter": "^1.0.3", - "call-bind": "^1.0.5", + "call-bind": "^1.0.7", "define-properties": "^1.2.1", - "es-abstract": "^1.22.3", - "es-errors": "^1.0.0" + "es-abstract": "^1.23.2" + }, + "engines": { + "node": ">= 0.4" } }, "node_modules/object.values": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.7.tgz", - "integrity": "sha512-aU6xnDFYT3x17e/f0IiiwlGPTy2jzMySGfUB4fq6z7CV8l85CWHDk5ErhyhpfDHhrOMwGFhSQkhMGHaIotA6Ng==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.0.tgz", + "integrity": "sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" }, "engines": { "node": ">= 0.4" @@ -11950,14 +12068,11 @@ } }, "node_modules/p-defer": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-4.0.0.tgz", - "integrity": "sha512-Vb3QRvQ0Y5XnF40ZUWW7JfLogicVh/EnA5gBIvKDJoYpeI82+1E3AlB9yOcKFS0AhHrWVnAQO39fbR0G99IVEQ==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-3.0.0.tgz", + "integrity": "sha512-ugZxsxmtTln604yeYd29EGrNhazN2lywetzpKhfmQjW/VJmhpDmWbiX+h0zL8V91R0UXkhb3KtPmyq9PZw3aYw==", "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=8" } }, "node_modules/p-fifo": { @@ -11969,19 +12084,10 @@ "p-defer": "^3.0.0" } }, - "node_modules/p-fifo/node_modules/p-defer": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-3.0.0.tgz", - "integrity": "sha512-ugZxsxmtTln604yeYd29EGrNhazN2lywetzpKhfmQjW/VJmhpDmWbiX+h0zL8V91R0UXkhb3KtPmyq9PZw3aYw==", - "engines": { - "node": ">=8" - } - }, "node_modules/p-limit": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "devOptional": true, "dependencies": { "yocto-queue": "^0.1.0" }, @@ -12017,6 +12123,21 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/p-queue": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/p-queue/-/p-queue-8.0.1.tgz", + "integrity": "sha512-NXzu9aQJTAzbBqOt2hwsR63ea7yvxJc0PwN/zobNAudYfb1B7R08SzB4TsLeSbUCuG467NhnoT0oO6w1qRO+BA==", + "dependencies": { + "eventemitter3": "^5.0.1", + "p-timeout": "^6.1.2" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/p-retry": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-4.6.2.tgz", @@ -12029,6 +12150,17 @@ "node": ">=8" } }, + "node_modules/p-timeout": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-6.1.2.tgz", + "integrity": "sha512-UbD77BuZ9Bc9aABo74gfXhNvzC9Tx7SxtHSh1fxvx3jTLLYvmVhiQZZrJzqqU0jKbN32kb5VOKiLEQI/3bIjgQ==", + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/p-try": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", @@ -12037,6 +12169,11 @@ "node": ">=6" } }, + "node_modules/packet-reader": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/packet-reader/-/packet-reader-1.0.0.tgz", + "integrity": "sha512-HAKu/fG3HpHFO0AA8WE8q2g+gBJaZ9MG7fcKk+IJPLTGAD6Psw4443l+9DGRbOIh3/aXr7Phy0TjilYivJo5XQ==" + }, "node_modules/parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -12124,11 +12261,96 @@ "node": ">=8" } }, + "node_modules/pg": { + "version": "8.11.5", + "resolved": "https://registry.npmjs.org/pg/-/pg-8.11.5.tgz", + "integrity": "sha512-jqgNHSKL5cbDjFlHyYsCXmQDrfIX/3RsNwYqpd4N0Kt8niLuNoRNH+aazv6cOd43gPh9Y4DjQCtb+X0MH0Hvnw==", + "dependencies": { + "pg-connection-string": "^2.6.4", + "pg-pool": "^3.6.2", + "pg-protocol": "^1.6.1", + "pg-types": "^2.1.0", + "pgpass": "1.x" + }, + "engines": { + "node": ">= 8.0.0" + }, + "optionalDependencies": { + "pg-cloudflare": "^1.1.1" + }, + "peerDependencies": { + "pg-native": ">=3.0.1" + }, + "peerDependenciesMeta": { + "pg-native": { + "optional": true + } + } + }, + "node_modules/pg-cloudflare": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/pg-cloudflare/-/pg-cloudflare-1.1.1.tgz", + "integrity": "sha512-xWPagP/4B6BgFO+EKz3JONXv3YDgvkbVrGw2mTo3D6tVDQRh1e7cqVGvyR3BE+eQgAvx1XhW/iEASj4/jCWl3Q==", + "optional": true + }, + "node_modules/pg-connection-string": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.6.2.tgz", + "integrity": "sha512-ch6OwaeaPYcova4kKZ15sbJ2hKb/VP48ZD2gE7i1J+L4MspCtBMAx8nMgz7bksc7IojCIIWuEhHibSMFH8m8oA==" + }, + "node_modules/pg-int8": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz", + "integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/pg-pool": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.6.2.tgz", + "integrity": "sha512-Htjbg8BlwXqSBQ9V8Vjtc+vzf/6fVUuak/3/XXKA9oxZprwW3IMDQTGHP+KDmVL7rtd+R1QjbnCFPuTHm3G4hg==", + "peerDependencies": { + "pg": ">=8.0" + } + }, + "node_modules/pg-protocol": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.6.1.tgz", + "integrity": "sha512-jPIlvgoD63hrEuihvIg+tJhoGjUsLPn6poJY9N5CnlPd91c2T18T/9zBtLxZSb1EhYxBRoZJtzScCaWlYLtktg==" + }, + "node_modules/pg-types": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz", + "integrity": "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==", + "dependencies": { + "pg-int8": "1.0.1", + "postgres-array": "~2.0.0", + "postgres-bytea": "~1.0.0", + "postgres-date": "~1.0.4", + "postgres-interval": "^1.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/pg/node_modules/pg-connection-string": { + "version": "2.6.4", + "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.6.4.tgz", + "integrity": "sha512-v+Z7W/0EO707aNMaAEfiGnGL9sxxumwLl2fJvCQtMn9Fxsg+lPpPkdcyBSv/KFgpGdYkMfn+EI1Or2EHjpgLCA==" + }, + "node_modules/pgpass": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/pgpass/-/pgpass-1.0.5.tgz", + "integrity": "sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug==", + "dependencies": { + "split2": "^4.1.0" + } + }, "node_modules/picocolors": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", - "dev": true + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" }, "node_modules/picomatch": { "version": "2.3.1", @@ -12179,10 +12401,45 @@ "node": ">= 0.4" } }, + "node_modules/postgres-array": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz", + "integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==", + "engines": { + "node": ">=4" + } + }, + "node_modules/postgres-bytea": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.0.tgz", + "integrity": "sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postgres-date": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.7.tgz", + "integrity": "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postgres-interval": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.2.0.tgz", + "integrity": "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==", + "dependencies": { + "xtend": "^4.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/prebuild-install": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.1.tgz", - "integrity": "sha512-jAXscXWMcCK8GgCoHOfIr0ODh5ai8mj63L2nWrjuAgXE6tDyYGnx4/8o/rCgU+B4JSyZBKbeZqzhtwtC3ovxjw==", + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.2.tgz", + "integrity": "sha512-UnNke3IQb6sgarcZIDU3gbMeTp/9SSU1DAIkil7PrqG1vZlBtY5msYccSKSHDqa3hNg436IXK+SNImReuA1wEQ==", "dependencies": { "detect-libc": "^2.0.0", "expand-template": "^2.0.3", @@ -12411,6 +12668,26 @@ "node": ">=6.0.0" } }, + "node_modules/prettier-plugin-organize-imports": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/prettier-plugin-organize-imports/-/prettier-plugin-organize-imports-3.2.4.tgz", + "integrity": "sha512-6m8WBhIp0dfwu0SkgfOxJqh+HpdyfqSSLfKKRZSFbDuEQXDDndb8fTpRWkUrX/uBenkex3MgnVk0J3b3Y5byog==", + "dev": true, + "peerDependencies": { + "@volar/vue-language-plugin-pug": "^1.0.4", + "@volar/vue-typescript": "^1.0.4", + "prettier": ">=2.0", + "typescript": ">=2.9" + }, + "peerDependenciesMeta": { + "@volar/vue-language-plugin-pug": { + "optional": true + }, + "@volar/vue-typescript": { + "optional": true + } + } + }, "node_modules/pretty-format": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", @@ -12437,14 +12714,6 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/process": { - "version": "0.11.10", - "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", - "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", - "engines": { - "node": ">= 0.6.0" - } - }, "node_modules/progress-events": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/progress-events/-/progress-events-1.0.0.tgz", @@ -12476,7 +12745,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/proto3-json-serializer/-/proto3-json-serializer-2.0.1.tgz", "integrity": "sha512-8awBvjO+FwkMd6gNoGFZyqkHZXCFd54CIYTb6De7dPaufGJ2XNW+QUNqbMr8MaAocMdb+KpsD4rxEOaTBDCffA==", - "optional": true, "dependencies": { "protobufjs": "^7.2.5" }, @@ -12542,14 +12810,15 @@ "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, "engines": { "node": ">=6" } }, "node_modules/pure-rand": { - "version": "6.0.4", - "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.0.4.tgz", - "integrity": "sha512-LA0Y9kxMYv47GIPJy6MI84fqTd2HmYZI83W/kM/SkKfDlajnZYfmXFTxkbY+xSBPkLJxltMa9hIkmdc29eguMA==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.1.0.tgz", + "integrity": "sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==", "dev": true, "funding": [ { @@ -12629,9 +12898,9 @@ } }, "node_modules/raw-body": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", - "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", + "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", "dependencies": { "bytes": "3.1.2", "http-errors": "2.0.0", @@ -12678,14 +12947,6 @@ "p-defer": "^3.0.0" } }, - "node_modules/react-native-fetch-api/node_modules/p-defer": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-3.0.0.tgz", - "integrity": "sha512-ugZxsxmtTln604yeYd29EGrNhazN2lywetzpKhfmQjW/VJmhpDmWbiX+h0zL8V91R0UXkhb3KtPmyq9PZw3aYw==", - "engines": { - "node": ">=8" - } - }, "node_modules/read-pkg": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", @@ -12777,6 +13038,17 @@ "ms": "^2.1.1" } }, + "node_modules/rechoir": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.8.0.tgz", + "integrity": "sha512-/vxpCXddiX8NGfGO/mTafwjq4aFa/71pvamip0++IQk3zG8cbCj0fifNPrjjF1XMXUne91jL9OoxmdykoEtifQ==", + "dependencies": { + "resolve": "^1.20.0" + }, + "engines": { + "node": ">= 10.13.0" + } + }, "node_modules/redent": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", @@ -12816,15 +13088,6 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", - "devOptional": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/require-from-string": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", - "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", "engines": { "node": ">=0.10.0" } @@ -12867,7 +13130,6 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", - "dev": true, "engines": { "node": ">=8" } @@ -12907,7 +13169,6 @@ "version": "7.0.2", "resolved": "https://registry.npmjs.org/retry-request/-/retry-request-7.0.2.tgz", "integrity": "sha512-dUOvLMJ0/JJYEn8NrpOaGNE7X3vpI5XlZS/u0ANjqtcZVKnIxP7IgCFwrKTxENw29emmwug53awKtaMm4i9g5w==", - "optional": true, "dependencies": { "@types/request": "^2.48.8", "extend": "^3.0.2", @@ -13016,13 +13277,13 @@ } }, "node_modules/safe-array-concat": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.0.tgz", - "integrity": "sha512-ZdQ0Jeb9Ofti4hbt5lX3T2JcAamT9hfzYU1MNB+z/jaEbB6wfFfPIR/zEORmZqobkCCJhSjodobH6WHNmJ97dg==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.2.tgz", + "integrity": "sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==", "dev": true, "dependencies": { - "call-bind": "^1.0.5", - "get-intrinsic": "^1.2.2", + "call-bind": "^1.0.7", + "get-intrinsic": "^1.2.4", "has-symbols": "^1.0.3", "isarray": "^2.0.5" }, @@ -13150,16 +13411,16 @@ } }, "node_modules/set-function-length": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.1.tgz", - "integrity": "sha512-j4t6ccc+VsKwYHso+kElc5neZpjtq9EnRICFZtWyBsLojhmeF/ZBd/elqm22WJh/BziDe/SBiOeAt0m2mfLD0g==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", "dependencies": { - "define-data-property": "^1.1.2", + "define-data-property": "^1.1.4", "es-errors": "^1.3.0", "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.3", + "get-intrinsic": "^1.2.4", "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.1" + "has-property-descriptors": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -13276,11 +13537,11 @@ } }, "node_modules/side-channel": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.5.tgz", - "integrity": "sha512-QcgiIWV4WV7qWExbN5llt6frQB/lBven9pqliLXfGPB+K9ZYXxDozp0wLkHS24kWCm+6YXH/f0HhnObZnZOBnQ==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", + "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", "dependencies": { - "call-bind": "^1.0.6", + "call-bind": "^1.0.7", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.4", "object-inspect": "^1.13.1" @@ -13489,6 +13750,14 @@ "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.17.tgz", "integrity": "sha512-sh8PWc/ftMqAAdFiBu6Fy6JUOYjqDJBJvIhpfDMyHrr0Rbp5liZqd4TjtQ/RgfLjKFZb+LMx5hpml5qOWy0qvg==" }, + "node_modules/split2": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", + "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", + "engines": { + "node": ">= 10.x" + } + }, "node_modules/sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", @@ -13528,7 +13797,6 @@ "version": "1.0.5", "resolved": "https://registry.npmjs.org/stream-events/-/stream-events-1.0.5.tgz", "integrity": "sha512-E1GUzBSgvct8Jsb3v2X15pjzN1tYebtbLaMg+eBOUOAxgbLoSbT2NS91ckc5lJD1KfLjId+jXJRgo0qnV5Nerg==", - "optional": true, "dependencies": { "stubs": "^3.0.0" } @@ -13536,8 +13804,7 @@ "node_modules/stream-shift": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.3.tgz", - "integrity": "sha512-76ORR0DO1o1hlKwTbi/DM3EXWGf3ZJYO8cXX5RJwnul2DEg2oyoZyjLNoQM8WsvZiFKCRfC1O0J7iCvie3RZmQ==", - "optional": true + "integrity": "sha512-76ORR0DO1o1hlKwTbi/DM3EXWGf3ZJYO8cXX5RJwnul2DEg2oyoZyjLNoQM8WsvZiFKCRfC1O0J7iCvie3RZmQ==" }, "node_modules/stream-to-it": { "version": "0.2.4", @@ -13588,7 +13855,6 @@ "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "devOptional": true, "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -13599,14 +13865,15 @@ } }, "node_modules/string.prototype.trim": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.8.tgz", - "integrity": "sha512-lfjY4HcixfQXOfaqCvcBuOIapyaroTXhbkfJN3gcB1OtyupngWK4sEET9Knd0cXd28kTUqu/kHoV4HKSJdnjiQ==", + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz", + "integrity": "sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.0", + "es-object-atoms": "^1.0.0" }, "engines": { "node": ">= 0.4" @@ -13616,28 +13883,31 @@ } }, "node_modules/string.prototype.trimend": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.7.tgz", - "integrity": "sha512-Ni79DqeB72ZFq1uH/L6zJ+DKZTkOtPIHovb3YZHQViE+HDouuU4mBrLOLDn5Dde3RF8qw5qVETEjhu9locMLvA==", + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.8.tgz", + "integrity": "sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/string.prototype.trimstart": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.7.tgz", - "integrity": "sha512-NGhtDFu3jCEm7B4Fy0DpLewdJQOZcQ0rGbwQ/+stjnrp2i+rlKeCvos9hOIeCmqwratM47OBxY7uFZzjxHXmrg==", + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", + "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -13647,7 +13917,6 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "devOptional": true, "dependencies": { "ansi-regex": "^5.0.1" }, @@ -13699,14 +13968,12 @@ "node_modules/strnum": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.0.5.tgz", - "integrity": "sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==", - "optional": true + "integrity": "sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==" }, "node_modules/stubs": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/stubs/-/stubs-3.0.0.tgz", - "integrity": "sha512-PdHt7hHUJKxvTCgbKX9C1V/ftOcjJQgz8BZwNfV5c4B6dcGqlpelTbJ999jBGZ2jYiPAwcX5dP6oBwVlBlUbxw==", - "optional": true + "integrity": "sha512-PdHt7hHUJKxvTCgbKX9C1V/ftOcjJQgz8BZwNfV5c4B6dcGqlpelTbJ999jBGZ2jYiPAwcX5dP6oBwVlBlUbxw==" }, "node_modules/subnet-check": { "version": "1.10.1", @@ -13717,9 +13984,9 @@ } }, "node_modules/superstruct": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/superstruct/-/superstruct-1.0.3.tgz", - "integrity": "sha512-8iTn3oSS8nRGn+C2pgXSKPI3jmpm6FExNazNpjvqS6ZUJQCej3PUXEKM8NjHBOs54ExM+LPW/FBRhymrdcCiSg==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/superstruct/-/superstruct-1.0.4.tgz", + "integrity": "sha512-7JpaAoX2NGyoFlI9NBh66BQXGONc+uE+MRS5i2iOBKuS4e+ccgMDjATgZldkah+33DakBxDHiss9kvUcGAO8UQ==", "engines": { "node": ">=14.0.0" } @@ -13836,11 +14103,18 @@ "ieee754": "^1.1.13" } }, + "node_modules/tarn": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/tarn/-/tarn-3.0.2.tgz", + "integrity": "sha512-51LAVKUSZSVfI05vjPESNc5vwqqZpbXCsU+/+wxlOrUjk2SnFTt97v9ZgQrD4YmxYW1Px6w2KjaDitCfkvgxMQ==", + "engines": { + "node": ">=8.0.0" + } + }, "node_modules/teeny-request": { "version": "9.0.0", "resolved": "https://registry.npmjs.org/teeny-request/-/teeny-request-9.0.0.tgz", "integrity": "sha512-resvxdc6Mgb7YEThw6G6bExlXKkv6+YbuzGg9xuXxSgxJF7Ozs+o8Y9+2R3sArdWdW8nOokoQb1yrpFB0pQK2g==", - "optional": true, "dependencies": { "http-proxy-agent": "^5.0.0", "https-proxy-agent": "^5.0.0", @@ -13856,7 +14130,6 @@ "version": "6.0.2", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "optional": true, "dependencies": { "debug": "4" }, @@ -13868,7 +14141,6 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", - "optional": true, "dependencies": { "agent-base": "6", "debug": "4" @@ -13881,7 +14153,6 @@ "version": "2.7.0", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", - "optional": true, "dependencies": { "whatwg-url": "^5.0.0" }, @@ -13969,6 +14240,14 @@ "resolved": "https://registry.npmjs.org/throttled-queue/-/throttled-queue-2.1.4.tgz", "integrity": "sha512-YGdk8sdmr4ge3g+doFj/7RLF5kLM+Mi7DEciu9PHxnMJZMeVuZeTj31g4VE7ekUffx/IdbvrtOCiz62afg0mkg==" }, + "node_modules/tildify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/tildify/-/tildify-2.0.0.tgz", + "integrity": "sha512-Cc+OraorugtXNfs50hU9KS369rFXCfgGLpfCfvlc+Ud5u6VWmUQsOAa9HbTvheQdYnrdJqqv1e5oIqXppMYnSw==", + "engines": { + "node": ">=8" + } + }, "node_modules/timeout-abort-controller": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/timeout-abort-controller/-/timeout-abort-controller-1.1.1.tgz", @@ -14026,9 +14305,9 @@ } }, "node_modules/ts-api-utils": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.2.1.tgz", - "integrity": "sha512-RIYA36cJn2WiH9Hy77hdF9r7oEwxAtB/TS9/S4Qd90Ap4z5FSiin5zEiTL44OII1Y3IIlEvxwxFUVgrHSZ/UpA==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz", + "integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==", "dev": true, "engines": { "node": ">=16" @@ -14037,12 +14316,6 @@ "typescript": ">=4.2.0" } }, - "node_modules/ts-deepmerge": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/ts-deepmerge/-/ts-deepmerge-2.0.7.tgz", - "integrity": "sha512-3phiGcxPSSR47RBubQxPoZ+pqXsEsozLo4G4AlSrsMKTFg9TA3l+3he5BqpUi9wiuDbaHWXH/amlzQ49uEdXtg==", - "dev": true - }, "node_modules/ts-jest": { "version": "29.1.2", "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.1.2.tgz", @@ -14347,9 +14620,9 @@ } }, "node_modules/typed-array-length": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.5.tgz", - "integrity": "sha512-yMi0PlwuznKHxKmcpoOdeLwxBoVPkqZxd7q2FgMkmD3bNwvF5VW0+UlUQ1k1vmktTu4Yu13Q0RIxEP8+B+wloA==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.6.tgz", + "integrity": "sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==", "dev": true, "dependencies": { "call-bind": "^1.0.7", @@ -14397,9 +14670,9 @@ } }, "node_modules/uint8arrays": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/uint8arrays/-/uint8arrays-5.0.2.tgz", - "integrity": "sha512-S0GaeR+orZt7LaqzTRs4ZP8QqzAauJ+0d4xvP2lJTA99jIkKsE2FgDs4tGF/K/z5O9I/2W5Yvrh7IuqNeYH+0Q==", + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/uint8arrays/-/uint8arrays-5.0.3.tgz", + "integrity": "sha512-6LBuKji28kHjgPJMkQ6GDaBb1lRwIhyOYq6pDGwYMoDPfImE9SkuYENVmR0yu9yGgs2clHUSY9fKDukR+AXfqQ==", "dependencies": { "multiformats": "^13.0.0" } @@ -14419,11 +14692,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/underscore": { - "version": "1.13.6", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.6.tgz", - "integrity": "sha512-+A5Sja4HP1M08MaXya7p5LvjuM7K6q/2EaC0+iovj/wOcMsTzMvDFbasi/oSapiwOlt252IqsKqPjCl7huKS0A==" - }, "node_modules/undici-types": { "version": "5.26.5", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", @@ -14471,6 +14739,7 @@ "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, "dependencies": { "punycode": "^2.1.0" } @@ -14711,15 +14980,15 @@ } }, "node_modules/which-typed-array": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.14.tgz", - "integrity": "sha512-VnXFiIW8yNn9kIHN88xvZ4yOWchftKDsRJ8fEPacX/wl1lOvBrhsJ/OeJCXq7B0AaijRuqgzSKalJoPk+D8MPg==", + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.15.tgz", + "integrity": "sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==", "dependencies": { - "available-typed-arrays": "^1.0.6", - "call-bind": "^1.0.5", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", "for-each": "^0.3.3", "gopd": "^1.0.1", - "has-tostringtag": "^1.0.1" + "has-tostringtag": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -14732,7 +15001,6 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "devOptional": true, "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", @@ -14749,7 +15017,6 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "devOptional": true, "dependencies": { "color-convert": "^2.0.1" }, @@ -14764,7 +15031,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "devOptional": true, "dependencies": { "color-name": "~1.1.4" }, @@ -14775,8 +15041,7 @@ "node_modules/wrap-ansi/node_modules/color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "devOptional": true + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, "node_modules/wrappy": { "version": "1.0.2", @@ -14816,17 +15081,18 @@ } } }, - "node_modules/xml": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/xml/-/xml-1.0.1.tgz", - "integrity": "sha512-huCv9IH9Tcf95zuYCsQraZtWnJvBtLVE0QHMOs8bWyZAFZNDcYjsPq1nEx8jKA9y+Beo9v+7OBPRisQTjinQMw==", - "dev": true + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "engines": { + "node": ">=0.4" + } }, "node_modules/y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "devOptional": true, "engines": { "node": ">=10" } @@ -14841,7 +15107,6 @@ "version": "17.7.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", - "devOptional": true, "dependencies": { "cliui": "^8.0.1", "escalade": "^3.1.1", @@ -14867,7 +15132,6 @@ "version": "21.1.1", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "devOptional": true, "engines": { "node": ">=12" } @@ -14885,7 +15149,6 @@ "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "devOptional": true, "engines": { "node": ">=10" }, @@ -14899,15 +15162,19 @@ "license": "Apache-2.0", "dependencies": { "@build-5/interfaces": "*", + "@google-cloud/pubsub": "4.3.3", + "@google-cloud/storage": "7.9.0", "dayjs": "1.11.10", - "firebase-admin": "12.0.0", "jsonwebtoken": "9.0.2", - "lodash": "4.17.21" + "knex": "^3.1.0", + "lodash": "4.17.21", + "pg": "^8.11.3" }, "devDependencies": { "@types/lodash": "4.14.202", "dotenv": "16.4.5", "glob": "8.0.3", + "prettier-plugin-organize-imports": "3.2.4", "typescript": "5.3.3" } }, @@ -14928,20 +15195,18 @@ "@iota/util.js": "1.8.6", "@iota/util.js-next": "npm:@iota/util.js@2.0.0-rc.2", "@metamask/eth-sig-util": "7.0.1", + "@types/express": "4.17.21", "algoliasearch": "4.22.1", "axios": "1.6.7", "bip39": "3.1.0", "busboy": "1.6.0", "child-process-promise": "2.2.1", - "cloudevents": "8.0.0", "cors": "2.8.5", "crypto-js": "4.2.0", "dayjs": "1.11.10", "ethers": "6.11.1", + "express": "4.19.2", "files-from-path": "^1.0.4", - "firebase-admin": "12.0.0", - "firebase-functions": "4.7.0", - "interfaces": "0.0.3", "is-ipfs": "8.0.4", "joi": "17.12.1", "js-big-decimal": "2.0.7", @@ -14950,11 +15215,10 @@ "mime-types": "2.1.35", "nft.storage": "7.1.1", "node-ipinfo": "3.5.1", - "protobufjs": "7.2.6", - "rxjs": "7.8.1", "sharp": "0.33.2" }, "devDependencies": { + "@google-cloud/pubsub": "4.3.3", "@types/busboy": "1.5.3", "@types/chai": "4.3.11", "@types/chance": "1.1.6", @@ -14981,10 +15245,8 @@ "eslint-plugin-jsdoc": "48.1.0", "eslint-plugin-prefer-arrow": "1.2.3", "eslint-plugin-prettier": "5.1.3", - "firebase-functions-test": "3.1.1", "glob": "8.0.3", "jest": "29.7.0", - "jest-junit": "16.0.0", "prettier": "3.2.5", "prettier-eslint": "16.3.0", "ts-jest": "29.1.2", @@ -14996,6 +15258,18 @@ "node": "20" } }, + "packages/functions/node_modules/joi": { + "version": "17.12.1", + "resolved": "https://registry.npmjs.org/joi/-/joi-17.12.1.tgz", + "integrity": "sha512-vtxmq+Lsc5SlfqotnfVjlViWfOL9nt/avKNbKYizwf6gsCfq9NYY/ceYRMFD8XDdrjJ9abJyScWmhmIiy+XRtQ==", + "dependencies": { + "@hapi/hoek": "^9.3.0", + "@hapi/topo": "^5.1.0", + "@sideway/address": "^4.1.5", + "@sideway/formula": "^3.0.1", + "@sideway/pinpoint": "^2.0.0" + } + }, "packages/indexes": { "name": "@build-5/indexes", "version": "0.0.0", @@ -15011,6 +15285,68 @@ "typescript": "5.3.3" } }, + "packages/notifier": { + "name": "@build-5/notifier", + "version": "0.0.0", + "license": "Apache-2.0", + "dependencies": { + "@google-cloud/pubsub": "4.3.3", + "dotenv": "16.4.5", + "knex": "3.1.0", + "pg": "8.11.3" + }, + "devDependencies": { + "@types/lodash": "4.17.0", + "typescript": "5.4.5" + } + }, + "packages/notifier/node_modules/@types/lodash": { + "version": "4.17.0", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.0.tgz", + "integrity": "sha512-t7dhREVv6dbNj0q17X12j7yDG4bD/DHYX7o5/DbDxobP0HnGPgpRz2Ej77aL7TZT3DSw13fqUTj8J4mMnqa7WA==", + "dev": true + }, + "packages/notifier/node_modules/pg": { + "version": "8.11.3", + "resolved": "https://registry.npmjs.org/pg/-/pg-8.11.3.tgz", + "integrity": "sha512-+9iuvG8QfaaUrrph+kpF24cXkH1YOOUeArRNYIxq1viYHZagBxrTno7cecY1Fa44tJeZvaoG+Djpkc3JwehN5g==", + "dependencies": { + "buffer-writer": "2.0.0", + "packet-reader": "1.0.0", + "pg-connection-string": "^2.6.2", + "pg-pool": "^3.6.1", + "pg-protocol": "^1.6.0", + "pg-types": "^2.1.0", + "pgpass": "1.x" + }, + "engines": { + "node": ">= 8.0.0" + }, + "optionalDependencies": { + "pg-cloudflare": "^1.1.1" + }, + "peerDependencies": { + "pg-native": ">=3.0.1" + }, + "peerDependenciesMeta": { + "pg-native": { + "optional": true + } + } + }, + "packages/notifier/node_modules/typescript": { + "version": "5.4.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz", + "integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, "packages/sdk": { "name": "@build-5/sdk", "version": "0.0.0", @@ -15077,6 +15413,117 @@ "@types/ws": "8.5.10", "typescript": "5.3.3" } + }, + "packages/search/node_modules/body-parser": { + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", + "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", + "dependencies": { + "bytes": "3.1.2", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.11.0", + "raw-body": "2.5.1", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "packages/search/node_modules/cookie": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", + "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", + "engines": { + "node": ">= 0.6" + } + }, + "packages/search/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "packages/search/node_modules/express": { + "version": "4.18.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", + "integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==", + "dependencies": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.1", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.5.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.2.0", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.7", + "qs": "6.11.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.18.0", + "serve-static": "1.15.0", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "packages/search/node_modules/joi": { + "version": "17.12.1", + "resolved": "https://registry.npmjs.org/joi/-/joi-17.12.1.tgz", + "integrity": "sha512-vtxmq+Lsc5SlfqotnfVjlViWfOL9nt/avKNbKYizwf6gsCfq9NYY/ceYRMFD8XDdrjJ9abJyScWmhmIiy+XRtQ==", + "dependencies": { + "@hapi/hoek": "^9.3.0", + "@hapi/topo": "^5.1.0", + "@sideway/address": "^4.1.5", + "@sideway/formula": "^3.0.1", + "@sideway/pinpoint": "^2.0.0" + } + }, + "packages/search/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "packages/search/node_modules/raw-body": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", + "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } } } } diff --git a/package.json b/package.json index 0ce07ab400..03feb848b9 100644 --- a/package.json +++ b/package.json @@ -2,6 +2,7 @@ "name": "root", "private": true, "workspaces": [ + "packages/notifier", "packages/indexes", "packages/interfaces", "packages/sdk", @@ -10,12 +11,13 @@ "packages/functions" ], "scripts": { - "build:functions": "npm run build:database && npm i --workspace=packages/functions && npm run build --workspace=packages/functions", + "build:functions": "npm run build:notifier && npm run build:database && npm i --workspace=packages/functions && npm run build --workspace=packages/functions", "build:interfaces": "npm i --workspace=packages/interfaces && npm run build --workspace=packages/interfaces", "build:sdk": "npm run build:interfaces && npm i --workspace=packages/sdk && npm run build --workspace=packages/sdk", "build:indexes": "npm i --workspace=packages/indexes && npm run build --workspace=packages/indexes", "build:database": "npm run build:interfaces && npm i --workspace=packages/database && npm run build --workspace=packages/database", "build:search": "npm run build:database && npm i --workspace=packages/search && npm run build --workspace=packages/search", + "build:notifier": "npm i --workspace=packages/notifier && npm run build --workspace=packages/notifier", "build": "npm i --workspaces && npm run build --workspaces", "clean:search": "rm -rf packages/search/lib; rm -rf packages/search/node_modules", "clean:database": "rm -rf packages/database/lib; rm -rf packages/database/node_modules", @@ -23,7 +25,8 @@ "clean:interfaces": "rm -rf packages/interfaces/lib; rm -rf packages/interfaces/node_modules", "clean:sdk": "rm -rf packages/sdk/lib; rm -rf packages/sdk/node_modules", "clean:indexes": "rm -rf packages/indexes/lib; rm -rf packages/indexes/node_modules", - "clean": "npm run clean:functions; npm run clean:interfaces; npm run clean:indexes; npm run clean:sdk; npm run clean:search; npm run clean:database; rm -rf node_modules", + "clean:notifier": "rm -rf packages/notifier/lib; rm -rf packages/notifier/node_modules", + "clean": "npm run clean:functions; npm run clean:interfaces; npm run clean:indexes; npm run clean:sdk; npm run clean:search; npm run clean:database; npm run clean:notifier; rm -rf node_modules", "prettier": "npx prettier --write ./packages/**", "joi-to-types": "ts-node ./scripts/joi-generator-post.ts && ts-node ./scripts/joi-generator-tangle.ts && npm run prettier", "rebuild": "npm run clean; npm run build", diff --git a/packages/database/.env b/packages/database/.env new file mode 100644 index 0000000000..17d351ff7f --- /dev/null +++ b/packages/database/.env @@ -0,0 +1,6 @@ +DB_USER="postgres" +DB_USER_PWD="postgres" +DB_NAME="build5db" +DB_HOST=localhost +DB_PORT=5432 + \ No newline at end of file diff --git a/packages/database/.gitignore b/packages/database/.gitignore index 97dba69de2..626c4f31ee 100644 --- a/packages/database/.gitignore +++ b/packages/database/.gitignore @@ -1,2 +1,2 @@ /lib -node_modules/ +/node_modules diff --git a/packages/database/generators/generator.ts b/packages/database/generators/generator.ts new file mode 100644 index 0000000000..3972f4852e --- /dev/null +++ b/packages/database/generators/generator.ts @@ -0,0 +1,7 @@ +import { generatePgInterfaces } from './pg.interface.generator'; + +const main = async () => { + await generatePgInterfaces(); +}; + +main(); diff --git a/packages/database/generators/pg.interface.generator.ts b/packages/database/generators/pg.interface.generator.ts new file mode 100644 index 0000000000..89d90a5fb8 --- /dev/null +++ b/packages/database/generators/pg.interface.generator.ts @@ -0,0 +1,277 @@ +import fs from 'fs'; +import Knex from 'knex'; +import { camelCase, uniq, upperFirst } from 'lodash'; +import * as knexfile from '../knexfile'; + +const baseFolder = './src/pg/models/'; + +const createEnums = async (knex: Knex.Knex) => { + const filePath = baseFolder + 'enums.ts'; + let content = setWarningText(filePath); + + const enums = await knex + .table('pg_type') + .join('pg_enum', 'pg_enum.enumtypid', 'pg_type.oid') + .orderBy('pg_type.typname') + .orderBy('pg_enum.enumsortorder') + .select('pg_type.typname as key', 'pg_enum.enumlabel as value'); + + const keys = uniq(enums.map((e) => e.key)); + for (const key of keys) { + const enumName = getInterfaceName(key, ''); + content += `\nexport enum Pg${enumName} {\n`; + for (const en of enums) { + if (en.key !== key) { + continue; + } + const enumKey = en.value || 'None'; + const getEnumName = (key: string) => { + switch (key) { + case '3d': + return 'three_d'; + case 'in24h': + return 'IN_24_H'; + case 'in48h': + return 'IN_48_H'; + case 'in7d': + return 'IN_7_D'; + default: + return enumKey; + } + }; + content += ` ${getEnumName(enumKey).toUpperCase()} = '${en.value.toLowerCase()}',\n`; + } + content += `}\n`; + } + fs.appendFileSync(filePath, content); + return enums; +}; + +const createCommons = async (isUpdate: boolean) => { + const filePath = baseFolder + `common${isUpdate ? '_update' : ''}.ts`; + let content = setWarningText(filePath); + + if (isUpdate) { + content += 'export interface Update {}\n'; + } + + content += + `export interface BaseRecord${isUpdate ? 'Update extends Update' : ''} {\n` + + (isUpdate ? '' : ' uid: string;') + + ' project?: string;' + + ' createdOn?: Date;' + + ' updatedOn?: Date ;' + + ' createdBy?: string;\n}\n'; + + content += + `export interface BaseSubRecord${isUpdate ? 'Update extends Update' : ''} extends BaseRecord${isUpdate ? 'Update' : ''} {\n` + + `parentId${isUpdate ? '?' : ''}: string;}`; + + fs.writeFileSync(filePath, content); +}; + +const excludeProps = ['uid', 'project', 'createdOn', 'updatedOn', 'createdBy', 'parentId']; + +const createInterfaces = async (tables: { [key: string]: any }) => { + for (const [tableName, props] of Object.entries(tables)) { + const filePath = baseFolder + `${getFileName(tableName)}.ts`; + let content = setWarningText(filePath); + + const interfaceName = getInterfaceName(tableName); + + content += `\nexport interface ${interfaceName} `; + const columns = props.map((p: any) => p.column); + + if (columns.includes('parentId')) { + content += 'extends commons.BaseSubRecord {\n'; + } else { + content += 'extends commons.BaseRecord {\n'; + } + + for (const prop of props) { + if (excludeProps.includes(prop.column)) { + continue; + } + content += + ` ${prop.column}` + + `${prop.nullable ? '?' : ''}` + + `: ${getType(prop.udt, prop.default)}` + + `;\n`; + } + content += `}\n`; + fs.appendFileSync(filePath, content); + + fs.appendFileSync(baseFolder + 'index.ts', `export * from "./${getFileName(tableName)}";\n`); + fs.appendFileSync( + baseFolder + 'index.ts', + `export * from "./${getFileName(tableName)}_update";\n`, + ); + } +}; + +const createUpdateInterfaces = async (tables: { [key: string]: any }) => { + for (const [tableName, props] of Object.entries(tables)) { + const filePath = baseFolder + `${getFileName(tableName)}_update.ts`; + let content = setWarningText(filePath, true); + + const interfaceName = getInterfaceName(tableName); + + content += `\nexport interface ${interfaceName}Update `; + const columns = props.map((p: any) => p.column); + + if (columns.includes('parentId')) { + content += 'extends commons.BaseSubRecordUpdate {\n'; + } else { + content += 'extends commons.BaseRecordUpdate {\n'; + } + + for (const prop of props) { + if (excludeProps.includes(prop.column)) { + continue; + } + const type = getType(prop.udt, prop.default, true); + content += ` ${prop.column}`; + content += '?'; + content += `: ${type}`; + content += `${prop.nullable ? '| null ' : ''}`; + content += type === 'number' ? ' | Increment' : ''; + content += type === 'string[]' ? ' | ArrayUnion | ArrayRemove' : ''; + content += `;\n`; + } + content += `}\n`; + fs.appendFileSync(filePath, content); + + fs.appendFileSync(baseFolder + 'index.ts', `export * from "./${getFileName(tableName)}";\n`); + } +}; + +const getFileName = (tableName: string) => { + const index = tableName.indexOf('_'); + if (index === 0) { + return tableName.substring(1, tableName.length); + } + if (index > -1) { + return tableName.substring(0, index); + } + return tableName; +}; + +const setWarningText = (filePath: string, isUpdate = false) => { + const exists = fs.existsSync(filePath); + if (exists) { + return ''; + } + return ( + '/**\n' + + ' * This file was automatically generated by knex\n' + + ' * Do not modify this file manually\n' + + ' */\n' + + 'import { Increment, ArrayUnion, ArrayRemove } from "../interfaces";\n' + + 'import * as enums from "./enums";\n' + + (isUpdate + ? 'import * as commons from "./common_update";\n' + : 'import * as commons from "./common";\n') + ); +}; + +const getInterfaceName = (key: string, prefix = 'Pg') => + prefix + + (key.charAt(0).toUpperCase() + key.slice(1)) + .replace(/_([a-z])/g, (_match, p1) => p1.toUpperCase()) + .replace('_', ''); + +const getType = (udt: string, defaultValue: string, isUpdate = false) => { + switch (udt) { + case 'bool': + return 'boolean'; + case '_varchar': + return 'string[]'; + case 'text': + case 'citext': + case 'money': + case 'numeric': + case 'int8': + case 'char': + case 'character': + case 'bpchar': + case 'varchar': + case 'time': + case 'tsquery': + case 'tsvector': + case 'uuid': + case 'xml': + case 'cidr': + case 'inet': + case 'macaddr': + return 'string'; + case 'smallint': + case 'integer': + case 'int': + case 'int2': + case 'int4': + case 'real': + case 'float': + case 'float4': + case 'float8': + return 'number'; + case '_int4': + case '_float8': + return 'number[]'; + case 'date': + case 'timestamp': + case 'timestamptz': + return 'Date'; + case 'json': + case 'jsonb': + const isArray = defaultValue?.startsWith("'["); + if (isUpdate) { + return 'string' + (isArray ? '' : ' | any'); + } + return 'Record' + (isArray ? '[]' : ''); + case 'bytea': + return 'Buffer'; + case 'interval': + return 'PostgresInterval'; + case '_text': + return 'string[]'; + default: + return 'enums.Pg' + upperFirst(camelCase(udt)); + } +}; + +export const generatePgInterfaces = async () => { + const knex = Knex(knexfile.default); + createCommons(false); + createCommons(true); + await createEnums(knex); + + const columns = await knex + .withSchema('information_schema') + .table('columns') + .whereIn('table_schema', ['public']) + .whereNotIn('table_name', ['knex_migrations', 'knex_migrations_lock', 'pg_stat_statements']) + .orderBy('table_schema') + .orderBy('table_name', 'desc') + .orderBy('ordinal_position') + .select( + 'table_schema as schema', + 'table_name as table', + 'column_name as column', + knex.raw("(is_nullable = 'YES') as nullable"), + 'column_default as default', + 'data_type as type', + 'udt_name as udt', + ); + const tables: { [key: string]: any } = columns.reduce( + (acc, act) => ({ + ...acc, + [act.table]: [...(acc[act.table] || []), act], + }), + {} as { [key: string]: any }, + ); + + await createInterfaces(tables); + await createUpdateInterfaces(tables); + await knex.destroy(); + process.exit(); +}; diff --git a/packages/database/knexfile.ts b/packages/database/knexfile.ts new file mode 100644 index 0000000000..0dc38e63b7 --- /dev/null +++ b/packages/database/knexfile.ts @@ -0,0 +1,15 @@ +require('dotenv').config(); +export default { + client: 'pg', + connection: { + user: process.env.DB_USER, + password: process.env.DB_USER_PWD, + database: process.env.DB_NAME, + host: process.env.DB_HOST, + port: Number(process.env.DB_PORT), + }, + migrations: { + directory: './migrations', + extension: 'ts', + }, +}; diff --git a/packages/database/migrations/20240129091246_common.ts b/packages/database/migrations/20240129091246_common.ts new file mode 100644 index 0000000000..c9f65f25d3 --- /dev/null +++ b/packages/database/migrations/20240129091246_common.ts @@ -0,0 +1,126 @@ +import type { Knex } from 'knex'; + +export const createTable = async ( + knex: Knex, + col: string, + subCol: string | undefined, + callback: (tableBuilder: Knex.CreateTableBuilder) => any, +) => { + const table = col + (subCol ? `_${subCol}` : '').toLowerCase(); + await knex.schema.createTable(table, callback); + + await knex.raw(` + CREATE OR REPLACE TRIGGER set_updated_on + BEFORE UPDATE ON ${table} + FOR EACH ROW EXECUTE FUNCTION set_updated_on_func(); + `); + + await knex.raw(` + CREATE OR REPLACE FUNCTION ${table}_upsert_func() RETURNS TRIGGER AS $$ + DECLARE + payload JSONB; + BEGIN + payload := jsonb_build_object( + 'table', TG_TABLE_NAME, + 'uid', NEW.uid + ${subCol ? ',\'parentId\', NEW."parentId"' : ''} + ); + + PERFORM pg_notify('onupsert', payload::text); + + RETURN NEW; + END; + $$ LANGUAGE plpgsql; + + CREATE OR REPLACE TRIGGER on_upsert_trigger + AFTER INSERT OR UPDATE ON ${table} + FOR EACH ROW EXECUTE FUNCTION ${table}_upsert_func(); + `); +}; + +export const baseRecord = (knex: Knex, t: Knex.CreateTableBuilder) => { + t.text('uid'); + t.text('project'); + t.timestamp('createdOn').defaultTo(knex.raw('CURRENT_TIMESTAMP')); + t.timestamp('updatedOn').defaultTo(knex.raw('CURRENT_TIMESTAMP')); + t.text('createdBy'); + t.primary(['uid']); +}; + +export const baseSubCollection = (knex: Knex, t: Knex.CreateTableBuilder) => { + t.text('uid'); + t.text('parentId'); + t.text('project'); + t.timestamp('createdOn').defaultTo(knex.raw('CURRENT_TIMESTAMP')); + t.timestamp('updatedOn').defaultTo(knex.raw('CURRENT_TIMESTAMP')); + t.text('createdBy'); + t.primary(['uid', 'parentId']); +}; + +export const mintingData = (t: Knex.CreateTableBuilder, base = 'mintingData_') => { + t.text(base + 'address'); + t.specificType(base + 'network', 'network'); + + t.timestamp(base + 'mintedOn'); + t.text(base + 'mintedBy'); + + t.text(base + 'blockId'); + t.text(base + 'nftId'); + t.double(base + 'storageDeposit'); + + t.text(base + 'aliasBlockId'); + t.text(base + 'aliasId'); + t.double(base + 'aliasStorageDeposit'); + + t.text(base + 'mintingOrderId'); + + t.double(base + 'nftsToMint'); + t.double(base + 'nftMediaToUpload'); + t.double(base + 'nftMediaToPrepare'); + + t.specificType(base + 'unsoldMintingOptions', 'unsold_minting_options'); + + t.double(base + 'newPrice'); + t.double(base + 'nftsStorageDeposit'); +}; + +export const createEnumType = (knex: Knex, name: string, values: string[]) => + knex.raw(`CREATE TYPE ${name} AS ENUM (${values.map((t) => `'${t}'`).join(', ')})`); + +export const networkEnum = ['smr', 'rms', 'iota', 'atoi']; + +export const mediaStatusEnum = ['uploaded', 'pending_upload', 'error', 'prepare_ipfs']; + +export const accessEnum = [ + 'open', + 'members_only', + 'guardians_only', + 'members_with_badge', + 'members_with_nft_from_collection', +]; + +export const unsoldMintingOptionsEnum = [ + 'burn_unsold', + 'set_new_price', + 'keep_price', + 'take_ownership', +]; + +export async function up(knex: Knex): Promise { + await createEnumType(knex, 'network', networkEnum); + await createEnumType(knex, 'media_status', mediaStatusEnum); + await createEnumType(knex, 'access', accessEnum); + await createEnumType(knex, 'unsold_minting_options', unsoldMintingOptionsEnum); + + await knex.raw(` + CREATE OR REPLACE FUNCTION set_updated_on_func() + RETURNS TRIGGER AS $$ + BEGIN + NEW."updatedOn" = NOW(); + RETURN NEW; + END; + $$ LANGUAGE plpgsql; + `); +} + +export async function down(): Promise {} diff --git a/packages/database/migrations/20240129135000_auction.ts b/packages/database/migrations/20240129135000_auction.ts new file mode 100644 index 0000000000..2caba50ad8 --- /dev/null +++ b/packages/database/migrations/20240129135000_auction.ts @@ -0,0 +1,35 @@ +import { COL } from '@build-5/interfaces'; +import { Knex } from 'knex'; +import { baseRecord, createEnumType, createTable } from './20240129091246_common'; + +const auctionTypes = ['open', 'nft']; + +export async function up(knex: Knex): Promise { + await createEnumType(knex, 'auction_type', auctionTypes); + + await createTable(knex, COL.AUCTION, undefined, (table) => { + baseRecord(knex, table); + table.text('space'); + table.timestamp('auctionFrom'); + table.timestamp('auctionTo'); + table.double('auctionLength'); + table.timestamp('extendedAuctionTo'); + table.double('extendedAuctionLength'); + table.double('extendAuctionWithin'); + table.double('auctionFloorPrice'); + table.double('minimalBidIncrement'); + table.text('auctionHighestBidder'); + table.double('auctionHighestBid'); + table.double('maxBids'); + table.specificType('type', 'auction_type'); + table.specificType('network', 'network'); + table.text('nftId'); + table.text('targetAddress'); + table.boolean('active'); + table.boolean('topUpBased'); + + table.jsonb('bids').defaultTo([]); + }); +} + +export async function down(_knex: Knex): Promise {} diff --git a/packages/database/migrations/20240129135000_award.ts b/packages/database/migrations/20240129135000_award.ts new file mode 100644 index 0000000000..6851b84574 --- /dev/null +++ b/packages/database/migrations/20240129135000_award.ts @@ -0,0 +1,72 @@ +import { COL, SUB_COL } from '@build-5/interfaces'; +import type { Knex } from 'knex'; +import { + baseRecord, + baseSubCollection, + createEnumType, + createTable, +} from './20240129091246_common'; + +const awardBadgeType = ['native', 'base']; + +export async function up(knex: Knex): Promise { + await createEnumType(knex, 'award_badge_type', awardBadgeType); + + await createTable(knex, COL.AWARD, undefined, (table) => { + baseRecord(knex, table); + + table.text('name'); + table.text('description'); + table.text('space'); + table.timestamp('endDate'); + table.double('issued'); + table.double('badgesMinted'); + table.boolean('approved'); + table.boolean('rejected'); + table.boolean('completed'); + table.specificType('network', 'network'); + table.double('aliasStorageDeposit'); + table.double('collectionStorageDeposit'); + table.double('nttStorageDeposit'); + table.double('nativeTokenStorageDeposit'); + table.boolean('funded'); + table.text('fundingAddress'); + table.text('fundedBy'); + table.text('address'); + table.double('airdropClaimed'); + table.text('aliasBlockId'); + table.text('aliasId'); + table.text('collectionBlockId'); + table.text('collectionId'); + table.specificType('mediaStatus', 'media_status'); + table.double('mediaUploadErrorCount'); + table.boolean('isLegacy'); + table.text('badge_name'); + table.text('badge_description'); + table.double('badge_total'); + table.specificType('badge_type', 'award_badge_type'); + table.double('badge_tokenReward'); + table.text('badge_tokenUid'); + table.text('badge_tokenId'); + table.text('badge_tokenSymbol'); + table.text('badge_image'); + table.text('badge_ipfsMedia'); + table.text('badge_ipfsMetadata'); + table.text('badge_ipfsRoot'); + table.double('badge_lockTime'); + }); + + await createTable(knex, COL.AWARD, SUB_COL.OWNERS, (table) => { + baseSubCollection(knex, table); + }); + + await createTable(knex, COL.AWARD, SUB_COL.PARTICIPANTS, (table) => { + baseSubCollection(knex, table); + table.text('comment'); + table.boolean('completed'); + table.double('count'); + table.double('tokenReward'); + }); +} + +export async function down(): Promise {} diff --git a/packages/database/migrations/20240129135000_change.ts b/packages/database/migrations/20240129135000_change.ts new file mode 100644 index 0000000000..4487e2f018 --- /dev/null +++ b/packages/database/migrations/20240129135000_change.ts @@ -0,0 +1,10 @@ +import type { Knex } from 'knex'; + +export async function up(knex: Knex): Promise { + await knex.schema.createTable('changes', (t) => { + t.increments('uid').primary(); + t.jsonb('change').defaultTo({}); + }); +} + +export async function down(): Promise {} diff --git a/packages/database/migrations/20240129135000_collection.ts b/packages/database/migrations/20240129135000_collection.ts new file mode 100644 index 0000000000..7515acec5a --- /dev/null +++ b/packages/database/migrations/20240129135000_collection.ts @@ -0,0 +1,125 @@ +import { COL, SUB_COL } from '@build-5/interfaces'; +import type { Knex } from 'knex'; +import { + baseRecord, + baseSubCollection, + createEnumType, + createTable, + mintingData, +} from './20240129091246_common'; + +const collectionTypeEnum = ['classic', 'generated', 'sft', 'metadata']; + +const collectionCategoriesEnum = [ + 'collectible', + 'pfp', + 'photography', + 'animation', + '3d', + 'generative', + 'single', + 'interactive', + 'abstract', + 'pixelart', + 'game', + 'art', +]; + +const collectionStatusEnum = ['pre_minted', 'minting', 'minted']; + +export async function up(knex: Knex): Promise { + await createEnumType(knex, 'collection_type', collectionTypeEnum); + await createEnumType(knex, 'Categories', collectionCategoriesEnum); + await createEnumType(knex, 'collection_status', collectionStatusEnum); + + await createTable(knex, COL.COLLECTION, SUB_COL.STATS, (table) => { + baseSubCollection(knex, table); + + table.double('votes_upvotes'); + table.double('votes_downvotes'); + table.double('votes_voteDiff'); + + table.double('ranks_count'); + table.double('ranks_sum'); + table.double('ranks_avg'); + }); + + await createTable(knex, COL.COLLECTION, undefined, (table) => { + baseRecord(knex, table); + table.text('name'); + table.text('description'); + table.text('bannerUrl'); + table.double('royaltiesFee'); + table.text('royaltiesSpace'); + + table.double('total'); + table.double('totalTrades'); + table.timestamp('lastTradedOn'); + table.double('sold'); + table.text('discord'); + table.text('url'); + table.text('twitter'); + table.boolean('approved'); + table.boolean('rejected'); + table.boolean('limitedEdition'); + table.text('ipfsMedia'); + table.text('ipfsMetadata'); + table + .text('ipfsRoot') + .comment( + 'IPFS link to root directory that contains both {@link ipfsMedia} & {@link ipfsMetadata}', + ); + + table.specificType('category', 'Categories'); + table.specificType('type', 'collection_type'); + table.specificType('access', 'access'); + table + .specificType('accessAwards', 'TEXT[]') + + .defaultTo('{}'); + table + .specificType('accessCollections', 'TEXT[]') + + .defaultTo('{}'); + + table.text('space'); + table.timestamp('availableFrom'); + table.double('price'); + table.double('availablePrice'); + table.boolean('onePerMemberOnly'); + table.text('placeholderNft'); + table.text('placeholderUrl'); + table.specificType('status', 'collection_status'); + + mintingData(table); + + table.double('rankCount'); + table.double('rankSum'); + table.double('rankAvg'); + table.specificType('mediaStatus', 'media_status'); + table.double('mediaUploadErrorCount'); + table.double('stakedNft'); + table.double('nftsOnSale'); + table.double('nftsOnAuction'); + table.double('availableNfts'); + table.double('floorPrice'); + + table.double('votes_upvotes'); + table.double('votes_downvotes'); + table.double('votes_voteDiff'); + + table.jsonb('discounts').defaultTo([]); + }); + + await createTable(knex, COL.COLLECTION, SUB_COL.RANKS, (t) => { + baseSubCollection(knex, t); + t.double('rank'); + }); + + await createTable(knex, COL.COLLECTION, SUB_COL.VOTES, (t) => { + baseSubCollection(knex, t); + t.double('direction'); + }); +} + +export async function down(): Promise {} diff --git a/packages/database/migrations/20240129135000_member.ts b/packages/database/migrations/20240129135000_member.ts new file mode 100644 index 0000000000..af47a38e36 --- /dev/null +++ b/packages/database/migrations/20240129135000_member.ts @@ -0,0 +1,31 @@ +import { COL } from '@build-5/interfaces'; +import type { Knex } from 'knex'; +import { baseRecord, createTable } from './20240129091246_common'; + +export async function up(knex: Knex): Promise { + await createTable(knex, COL.MEMBER, undefined, (table) => { + baseRecord(knex, table); + table.text('nonce'); + table.text('name'); + table.text('about'); + table.text('avatarNft'); + table.text('avatar'); + table.text('discord'); + table.text('twitter'); + table.text('github'); + + table.text('smrAddress').defaultTo(''); + table.text('rmsAddress').defaultTo(''); + table.text('iotaAddress').defaultTo(''); + table.text('atoiAddress').defaultTo(''); + + table.specificType('prevValidatedAddresses', 'TEXT[]').defaultTo('{}'); + table.double('tokenTradingFeePercentage'); + table.double('tokenPurchaseFeePercentage'); + table.double('awardsCompleted'); + + table.jsonb('spaces').defaultTo({}); + }); +} + +export async function down(): Promise {} diff --git a/packages/database/migrations/20240129135000_milestone.ts b/packages/database/migrations/20240129135000_milestone.ts new file mode 100644 index 0000000000..651451f934 --- /dev/null +++ b/packages/database/migrations/20240129135000_milestone.ts @@ -0,0 +1,35 @@ +import { COL, SUB_COL } from '@build-5/interfaces'; +import type { Knex } from 'knex'; +import { baseRecord, baseSubCollection, createTable } from './20240129091246_common'; + +export async function up(knex: Knex): Promise { + for (const col of [COL.MILESTONE, COL.MILESTONE_SMR, COL.MILESTONE_RMS]) { + await createTable(knex, col, undefined, (t) => { + baseRecord(knex, t); + + t.boolean('completed'); + t.timestamp('completedOn'); + + t.string('listenerNodeId'); + + t.integer('milestone'); + t.timestamp('milestoneTimestamp'); + + t.integer('trxConflictCount'); + t.integer('trxFailedCount'); + t.integer('trxValidCount'); + }); + + await createTable(knex, col, SUB_COL.TRANSACTIONS, (t) => { + baseSubCollection(knex, t); + t.integer('PayloadSize'); + t.text('blockId'); + t.integer('milestone'); + t.jsonb('payload').defaultTo({}); + t.boolean('processed').defaultTo(false); + t.timestamp('processedOn'); + }); + } +} + +export async function down(): Promise {} diff --git a/packages/database/migrations/20240129135000_mnemonic.ts b/packages/database/migrations/20240129135000_mnemonic.ts new file mode 100644 index 0000000000..9d6e15f8da --- /dev/null +++ b/packages/database/migrations/20240129135000_mnemonic.ts @@ -0,0 +1,17 @@ +import { COL } from '@build-5/interfaces'; +import type { Knex } from 'knex'; +import { baseRecord, createTable } from './20240129091246_common'; + +export async function up(knex: Knex): Promise { + await createTable(knex, COL.MNEMONIC, undefined, (table) => { + baseRecord(knex, table); + table.text('mnemonic'); + table.specificType('network', 'network'); + table.text('lockedBy').defaultTo(''); + table.specificType('consumedOutputIds', 'TEXT[]').defaultTo('{}'); + table.specificType('consumedNftOutputIds', 'TEXT[]').defaultTo('{}'); + table.specificType('consumedAliasOutputIds', 'TEXT[]').defaultTo('{}'); + }); +} + +export async function down(): Promise {} diff --git a/packages/database/migrations/20240129135000_nft.ts b/packages/database/migrations/20240129135000_nft.ts new file mode 100644 index 0000000000..b2f729bb2f --- /dev/null +++ b/packages/database/migrations/20240129135000_nft.ts @@ -0,0 +1,69 @@ +import { COL } from '@build-5/interfaces'; +import type { Knex } from 'knex'; +import { baseRecord, createEnumType, createTable, mintingData } from './20240129091246_common'; + +const nftAccessEnum = ['open', 'members']; + +const nftAvailableEnum = ['unavailable', 'sale', 'auction', 'auction_and_sale']; + +const nftStatusEnum = ['pre_minted', 'minted', 'withdrawn', 'staked']; + +export async function up(knex: Knex): Promise { + await createEnumType(knex, 'nft_access', nftAccessEnum); + await createEnumType(knex, 'nft_available', nftAvailableEnum); + await createEnumType(knex, 'nft_status', nftStatusEnum); + + await createTable(knex, COL.NFT, undefined, (table) => { + baseRecord(knex, table); + table.text('name'); + table.text('description'); + table.text('collection'); + table.text('owner'); + table.boolean('isOwned'); + table.text('media'); + table.text('ipfsMedia'); + table.text('ipfsMetadata'); + table.text('ipfsRoot'); + table.specificType('saleAccess', 'nft_access'); + table.specificType('saleAccessMembers', 'TEXT[]').defaultTo('{}'); + table.specificType('available', 'nft_available'); + table.timestamp('availableFrom'); + table.timestamp('auctionFrom'); + table.timestamp('auctionTo'); + table.timestamp('extendedAuctionTo'); + table.double('auctionHighestBid'); + table.text('auctionHighestBidder'); + table.double('price'); + table.double('totalTrades'); + table.timestamp('lastTradedOn'); + table.double('availablePrice'); + table.double('auctionFloorPrice'); + table.double('auctionLength'); + table.double('extendedAuctionLength'); + table.double('extendAuctionWithin'); + + table.specificType('type', 'collection_type'); + table.text('space'); + table.text('url'); + table.boolean('approved'); + table.boolean('rejected'); + table.jsonb('properties').defaultTo({}); + table.jsonb('stats').defaultTo({}); + table.boolean('placeholderNft'); + table.double('position'); + table.boolean('locked'); + table.text('lockedBy'); + table.boolean('sold'); + mintingData(table); + mintingData(table, 'depositData_'); + table.specificType('status', 'nft_status'); + table.boolean('hidden'); + table.specificType('mediaStatus', 'media_status'); + table.double('mediaUploadErrorCount'); + table.timestamp('soldOn'); + table.boolean('setAsAvatar'); + table.text('auction'); + }); +} + +export async function down(): Promise {} diff --git a/packages/database/migrations/20240129135000_nft_stake.ts b/packages/database/migrations/20240129135000_nft_stake.ts new file mode 100644 index 0000000000..ab3e3f25a5 --- /dev/null +++ b/packages/database/migrations/20240129135000_nft_stake.ts @@ -0,0 +1,23 @@ +import { COL } from '@build-5/interfaces'; +import type { Knex } from 'knex'; +import { baseRecord, createEnumType, createTable } from './20240129091246_common'; + +const stakeTypeEnum = ['static', 'dynamic']; + +export async function up(knex: Knex): Promise { + await createEnumType(knex, 'stake_type', stakeTypeEnum); + + await createTable(knex, COL.NFT_STAKE, undefined, (table) => { + baseRecord(knex, table); + table.text('member'); + table.text('space'); + table.text('collection'); + table.text('nft'); + table.double('weeks'); + table.timestamp('expiresAt'); + table.boolean('expirationProcessed'); + table.specificType('type', 'stake_type'); + }); +} + +export async function down(): Promise {} diff --git a/packages/database/migrations/20240129135000_notification.ts b/packages/database/migrations/20240129135000_notification.ts new file mode 100644 index 0000000000..2c4baaf648 --- /dev/null +++ b/packages/database/migrations/20240129135000_notification.ts @@ -0,0 +1,19 @@ +import { COL } from '@build-5/interfaces'; +import { Knex } from 'knex'; +import { baseRecord, createEnumType, createTable } from './20240129091246_common'; + +const notificationType = ['new_bid', 'lost_bid', 'win_bid']; + +export async function up(knex: Knex): Promise { + await createEnumType(knex, 'notification_type', notificationType); + await createTable(knex, COL.NOTIFICATION, undefined, (table) => { + baseRecord(knex, table); + + table.text('space'); + table.text('member'); + table.specificType('type', 'notification_type'); + table.jsonb('params').defaultTo({}); + }); +} + +export async function down(_knex: Knex): Promise {} diff --git a/packages/database/migrations/20240129135000_project.ts b/packages/database/migrations/20240129135000_project.ts new file mode 100644 index 0000000000..b3301225c7 --- /dev/null +++ b/packages/database/migrations/20240129135000_project.ts @@ -0,0 +1,39 @@ +import { COL, SUB_COL } from '@build-5/interfaces'; +import type { Knex } from 'knex'; +import { + baseRecord, + baseSubCollection, + createEnumType, + createTable, +} from './20240129091246_common'; + +const projectBillingEnum = ['token_based', 'volume_based']; + +export async function up(knex: Knex): Promise { + await createEnumType(knex, 'project_billing', projectBillingEnum); + + await createTable(knex, COL.PROJECT, undefined, (table) => { + baseRecord(knex, table); + + table.text('name'); + table.text('contactEmail'); + table.boolean('deactivated'); + table.specificType('config_billing', 'project_billing'); + table.specificType('config_tiers', 'FLOAT[]'); + table.specificType('config_tokenTradingFeeDiscountPercentage', 'FLOAT[]'); + table.text('config_nativeTokenSymbol'); + table.text('config_nativeTokenUid'); + table.jsonb('otr').defaultTo({}); + }); + + await createTable(knex, COL.PROJECT, SUB_COL.ADMINS, (table) => { + baseSubCollection(knex, table); + }); + + await createTable(knex, COL.PROJECT, SUB_COL._API_KEY, (table) => { + baseSubCollection(knex, table); + table.text('token'); + }); +} + +export async function down(): Promise {} diff --git a/packages/database/migrations/20240129135000_proposal.ts b/packages/database/migrations/20240129135000_proposal.ts new file mode 100644 index 0000000000..490ee3a127 --- /dev/null +++ b/packages/database/migrations/20240129135000_proposal.ts @@ -0,0 +1,68 @@ +import { COL, SUB_COL } from '@build-5/interfaces'; +import type { Knex } from 'knex'; +import { + baseRecord, + baseSubCollection, + createEnumType, + createTable, +} from './20240129091246_common'; + +const proposalTypeEnum = [ + 'native', + 'members', + 'add_guardian', + 'remove_guardian', + 'edit_space', + 'remove_stake_reward', +]; + +export async function up(knex: Knex): Promise { + await createEnumType(knex, 'proposal_type', proposalTypeEnum); + + await createTable(knex, COL.PROPOSAL, SUB_COL.MEMBERS, (t) => { + baseSubCollection(knex, t); + t.boolean('voted'); + t.double('weight'); + t.text('tranId'); + t.jsonb('values').defaultTo({}); + }); + + await createTable(knex, COL.PROPOSAL, SUB_COL.OWNERS, (t) => { + baseSubCollection(knex, t); + }); + + await createTable(knex, COL.PROPOSAL, undefined, (t) => { + baseRecord(knex, t); + t.text('space'); + t.text('name'); + t.text('description'); + t.text('additionalInfo'); + t.specificType('type', 'proposal_type'); + t.boolean('approved'); + t.boolean('rejected'); + t.text('approvedBy'); + t.text('rejectedBy'); + t.text('eventId'); + t.double('totalWeight'); + t.text('token'); + t.boolean('completed'); + t.double('rank'); + + t.timestamp('settings_startDate'); + t.timestamp('settings_endDate'); + t.boolean('settings_guardiansOnly'); + t.text('settings_addRemoveGuardian'); + t.jsonb('settings_spaceUpdateData').defaultTo({}); + t.boolean('settings_onlyGuardians'); + t.specificType('settings_stakeRewardIds', 'TEXT[]').defaultTo('{}'); + + t.specificType('settings_awards', 'TEXT[]').defaultTo('{}'); + + t.jsonb('questions').defaultTo([]); + t.jsonb('members').defaultTo([]); + + t.jsonb('results').defaultTo({}); + }); +} + +export async function down(): Promise {} diff --git a/packages/database/migrations/20240129135000_soon_snap.ts b/packages/database/migrations/20240129135000_soon_snap.ts new file mode 100644 index 0000000000..1b4a976a11 --- /dev/null +++ b/packages/database/migrations/20240129135000_soon_snap.ts @@ -0,0 +1,16 @@ +import { COL } from '@build-5/interfaces'; +import type { Knex } from 'knex'; +import { baseRecord, createTable } from './20240129091246_common'; + +export async function up(knex: Knex): Promise { + await createTable(knex, COL.SOON_SNAP, undefined, (t) => { + baseRecord(knex, t); + t.double('count').notNullable(); + t.double('paidOut').notNullable(); + t.timestamp('lastPaidOutOn'); + t.text('ethAddress').notNullable(); + t.boolean('ethAddressVerified').notNullable(); + }); +} + +export async function down(): Promise {} diff --git a/packages/database/migrations/20240129135000_space.ts b/packages/database/migrations/20240129135000_space.ts new file mode 100644 index 0000000000..409c08594f --- /dev/null +++ b/packages/database/migrations/20240129135000_space.ts @@ -0,0 +1,60 @@ +import { COL, SUB_COL } from '@build-5/interfaces'; +import type { Knex } from 'knex'; +import { baseRecord, baseSubCollection, createTable } from './20240129091246_common'; + +export async function up(knex: Knex): Promise { + await createTable(knex, COL.SPACE, undefined, (table) => { + baseRecord(knex, table); + table.text('name'); + table.text('about'); + table.boolean('open'); + table.boolean('tokenBased'); + table.double('minStakedValue'); + table.text('github'); + table.text('twitter'); + table.text('discord'); + table.text('avatarUrl'); + table.text('bannerUrl'); + table.double('totalGuardians'); + table.double('totalMembers'); + table.double('totalPendingMembers'); + + table.text('smrAddress').defaultTo(''); + table.text('rmsAddress').defaultTo(''); + table.text('iotaAddress').defaultTo(''); + table.text('atoiAddress').defaultTo(''); + + table.specificType('prevValidatedAddresses', 'TEXT[]').defaultTo('{}'); + table.text('vaultAddress'); + table.text('collectionId'); + table.boolean('claimed'); + table.text('ipfsMedia'); + table.text('ipfsMetadata'); + table.text('ipfsRoot'); + table.specificType('mediaStatus', 'media_status'); + table.double('mediaUploadErrorCount'); + table.text('alias_address'); + table.text('alias_aliasId'); + table.text('alias_blockId'); + table.timestamp('alias_mintedOn'); + table.text('alias_mintedBy'); + }); + + await createTable(knex, COL.SPACE, SUB_COL.GUARDIANS, (table) => { + baseSubCollection(knex, table); + }); + + await createTable(knex, COL.SPACE, SUB_COL.MEMBERS, (table) => { + baseSubCollection(knex, table); + }); + + await createTable(knex, COL.SPACE, SUB_COL.BLOCKED_MEMBERS, (table) => { + baseSubCollection(knex, table); + }); + + await createTable(knex, COL.SPACE, SUB_COL.KNOCKING_MEMBERS, (table) => { + baseSubCollection(knex, table); + }); +} + +export async function down(): Promise {} diff --git a/packages/database/migrations/20240129135000_stake.ts b/packages/database/migrations/20240129135000_stake.ts new file mode 100644 index 0000000000..adf6fe31a2 --- /dev/null +++ b/packages/database/migrations/20240129135000_stake.ts @@ -0,0 +1,25 @@ +import { COL } from '@build-5/interfaces'; +import type { Knex } from 'knex'; +import { baseRecord, createTable } from './20240129091246_common'; + +export async function up(knex: Knex): Promise { + await createTable(knex, COL.STAKE, undefined, (table) => { + baseRecord(knex, table); + table.text('member'); + table.text('space'); + table.text('token'); + table.double('amount'); + table.double('value'); + table.double('weeks'); + + table.timestamp('expiresAt'); + table.boolean('expirationProcessed'); + + table.text('orderId'); + table.text('billPaymentId'); + table.specificType('type', 'stake_type'); + table.jsonb('customMetadata').defaultTo({}); + }); +} + +export async function down(): Promise {} diff --git a/packages/database/migrations/20240129135000_stake_reward.ts b/packages/database/migrations/20240129135000_stake_reward.ts new file mode 100644 index 0000000000..fbfbfa8cf3 --- /dev/null +++ b/packages/database/migrations/20240129135000_stake_reward.ts @@ -0,0 +1,23 @@ +import { COL } from '@build-5/interfaces'; +import type { Knex } from 'knex'; +import { baseRecord, createEnumType, createTable } from './20240129091246_common'; + +const stakeRewardStatus = ['unprocessed', 'processed', 'processed_no_stakes', 'error', 'deleted']; + +export async function up(knex: Knex): Promise { + await createEnumType(knex, 'stake_reward_status', stakeRewardStatus); + await createTable(knex, COL.STAKE_REWARD, undefined, (t) => { + baseRecord(knex, t); + + t.timestamp('startDate'); + t.timestamp('endDate'); + t.timestamp('tokenVestingDate'); + t.double('tokensToDistribute'); + t.text('token'); + t.double('totalStaked'); + t.double('totalAirdropped'); + t.specificType('status', 'stake_reward_status'); + }); +} + +export async function down(): Promise {} diff --git a/packages/database/migrations/20240129135000_stamp.ts b/packages/database/migrations/20240129135000_stamp.ts new file mode 100644 index 0000000000..ed0a55b832 --- /dev/null +++ b/packages/database/migrations/20240129135000_stamp.ts @@ -0,0 +1,34 @@ +import { COL } from '@build-5/interfaces'; +import type { Knex } from 'knex'; +import { baseRecord, createTable } from './20240129091246_common'; + +export async function up(knex: Knex): Promise { + await createTable(knex, COL.STAMP, undefined, (table) => { + baseRecord(knex, table); + + table.text('space'); + table.text('build5Url'); + table.text('originUri'); + table.text('checksum'); + table.text('extension'); + table.double('bytes'); + table.double('costPerMb'); + table.specificType('network', 'network'); + + table.text('ipfsMedia'); + table.text('ipfsRoot'); + + table.timestamp('expiresAt'); + table.text('order'); + table.boolean('funded'); + table.boolean('expired'); + + table.specificType('mediaStatus', 'media_status'); + table.double('mediaUploadErrorCount'); + + table.text('aliasId'); + table.text('nftId'); + }); +} + +export async function down(): Promise {} diff --git a/packages/database/migrations/20240129135000_swap.ts b/packages/database/migrations/20240129135000_swap.ts new file mode 100644 index 0000000000..201804fa81 --- /dev/null +++ b/packages/database/migrations/20240129135000_swap.ts @@ -0,0 +1,26 @@ +import { COL } from '@build-5/interfaces'; +import type { Knex } from 'knex'; +import { baseRecord, createEnumType, createTable } from './20240129091246_common'; + +const swapStatusEnum = ['draft', 'funded', 'fulfilled', 'rejected']; + +export async function up(knex: Knex): Promise { + await createEnumType(knex, 'swap_status', swapStatusEnum); + await createTable(knex, COL.SWAP, undefined, (t) => { + baseRecord(knex, t); + + t.text('recipient'); + t.specificType('network', 'network'); + t.text('address'); + t.text('orderId'); + t.specificType('nftIdsAsk', 'TEXT[]'); + t.double('baseTokenAmountAsk'); + t.jsonb('nativeTokensAsk').defaultTo('[]'); + t.specificType('status', 'swap_status'); + + t.jsonb('bidOutputs').defaultTo('[]'); + t.jsonb('askOutputs').defaultTo('[]'); + }); +} + +export async function down(): Promise {} diff --git a/packages/database/migrations/20240129135000_system.ts b/packages/database/migrations/20240129135000_system.ts new file mode 100644 index 0000000000..e378082d6b --- /dev/null +++ b/packages/database/migrations/20240129135000_system.ts @@ -0,0 +1,13 @@ +import { COL } from '@build-5/interfaces'; +import type { Knex } from 'knex'; +import { baseRecord, createTable } from './20240129091246_common'; + +export async function up(knex: Knex): Promise { + await createTable(knex, COL.SYSTEM, undefined, (table) => { + baseRecord(knex, table); + table.double('tokenTradingFeePercentage'); + table.double('tokenPurchaseFeePercentage'); + }); +} + +export async function down(): Promise {} diff --git a/packages/database/migrations/20240129135000_ticker.ts b/packages/database/migrations/20240129135000_ticker.ts new file mode 100644 index 0000000000..51a0e252a1 --- /dev/null +++ b/packages/database/migrations/20240129135000_ticker.ts @@ -0,0 +1,12 @@ +import { COL } from '@build-5/interfaces'; +import type { Knex } from 'knex'; +import { baseRecord, createTable } from './20240129091246_common'; + +export async function up(knex: Knex): Promise { + await createTable(knex, COL.TICKER, undefined, (t) => { + baseRecord(knex, t); + t.double('price'); + }); +} + +export async function down(): Promise {} diff --git a/packages/database/migrations/20240129135000_token.ts b/packages/database/migrations/20240129135000_token.ts new file mode 100644 index 0000000000..2cfa09a258 --- /dev/null +++ b/packages/database/migrations/20240129135000_token.ts @@ -0,0 +1,190 @@ +import { COL, SUB_COL, StakeType, TokenStatus } from '@build-5/interfaces'; +import type { Knex } from 'knex'; +import { + baseRecord, + baseSubCollection, + createEnumType, + createTable, +} from './20240129091246_common'; +import { ageEmum } from './20240129135000_token_purchase'; + +const tokenStatusEnum = [ + 'available', + 'cancel_sale', + 'processing', + 'pre_minted', + 'error', + 'minting', + 'minted', + 'minting_error', + 'base', +]; + +const airdropStatus = ['deposit_needed', 'unclaimed', 'claimed']; + +export async function up(knex: Knex): Promise { + await createEnumType(knex, 'token_status', tokenStatusEnum); + await createEnumType(knex, 'token_drop_status', airdropStatus); + + await createTable(knex, COL.TOKEN, undefined, (t) => { + baseRecord(knex, t); + + t.text('name').defaultTo(''); + t.text('symbol').defaultTo(''); + t.text('title'); + t.text('description'); + t.text('shortDescriptionTitle'); + t.text('shortDescription'); + t.text('space'); + t.double('pricePerToken'); + + t.double('totalSupply'); + t.jsonb('allocations').defaultTo([]); + + t.timestamp('saleStartDate'); + t.double('saleLength'); + t.timestamp('coolDownEnd'); + t.boolean('autoProcessAt100Percent'); + t.boolean('approved').defaultTo(false); + t.boolean('rejected').defaultTo(false); + t.boolean('public'); + t.specificType('links', 'TEXT[]').defaultTo('{}'); + t.text('icon'); + t.text('overviewGraphics'); + t.specificType('status', 'token_status').defaultTo(TokenStatus.PRE_MINTED); + + t.double('totalDeposit'); + + t.double('tokensOrdered'); + t.double('totalAirdropped'); + t.text('termsAndConditions').defaultTo(''); + t.specificType('access', 'access'); + t.specificType('accessAwards', 'TEXT[]').defaultTo('{}'); + + t.specificType('accessCollections', 'TEXT[]').defaultTo('{}'); + + t.text('ipfsMedia'); + t.text('ipfsMetadata'); + t.text('ipfsRoot'); + + t.text('mintingData_mintedBy'); + t.timestamp('mintingData_mintedOn'); + t.text('mintingData_aliasBlockId'); + t.text('mintingData_aliasId'); + t.double('mintingData_aliasStorageDeposit'); + t.text('mintingData_tokenId'); + t.text('mintingData_blockId'); + t.double('mintingData_foundryStorageDeposit'); + + t.specificType('mintingData_network', 'network'); + t.text('mintingData_networkFormat'); + + t.text('mintingData_vaultAddress'); + t.double('mintingData_tokensInVault'); + t.double('mintingData_vaultStorageDeposit'); + t.double('mintingData_guardianStorageDeposit'); + t.double('mintingData_meltedTokens'); + t.double('mintingData_circulatingSupply'); + + t.double('rankCount'); + t.double('rankSum'); + t.double('rankAvg'); + t.specificType('mediaStatus', 'media_status'); + t.double('mediaUploadErrorCount'); + t.boolean('tradingDisabled'); + t.double('decimals').defaultTo(6); + + t.double('votes_upvotes'); + t.double('votes_downvotes'); + t.double('votes_voteDiff'); + }); + + await createTable(knex, COL.AIRDROP, undefined, (t) => { + baseRecord(knex, t); + t.text('member'); + t.text('token'); + t.text('award'); + t.timestamp('vestingAt'); + t.double('count'); + t.specificType('status', 'token_drop_status'); + t.text('orderId'); + t.text('billPaymentId'); + t.text('sourceAddress'); + t.text('stakeRewardId'); + t.specificType('stakeType', 'stake_type'); + t.boolean('isBaseToken'); + }); + + await createTable(knex, COL.TOKEN, SUB_COL.DISTRIBUTION, (t) => { + baseSubCollection(knex, t); + t.double('totalDeposit'); + t.double('totalPaid'); + t.double('refundedAmount'); + t.double('totalBought'); + t.boolean('reconciled'); + t.text('billPaymentId'); + t.text('creditPaymentId'); + t.text('royaltyBillPaymentId'); + t.double('tokenClaimed'); + t.double('lockedForSale'); + t.double('sold'); + t.double('totalPurchased'); + t.double('tokenOwned'); + t.timestamp('mintedClaimedOn'); + + t.specificType('mintingTransactions', 'TEXT[]').defaultTo('{}'); + + t.double('stakeRewards'); + t.double('extraStakeRewards'); + t.double('totalUnclaimedAirdrop'); + t.text('stakeVoteTransactionId'); + + for (const type of Object.values(StakeType)) { + t.double('stakes_' + type + '_amount'); + t.double('stakes_' + type + '_totalAmount'); + t.double('stakes_' + type + '_value'); + t.double('stakes_' + type + '_totalValue'); + t.double('stakes_' + type + '_stakingMembersCount'); + } + + t.jsonb('stakeExpiry').defaultTo({}); + }); + + await createTable(knex, COL.TOKEN, SUB_COL.STATS, (t) => { + baseSubCollection(knex, t); + t.double('votes_upvotes'); + t.double('votes_downvotes'); + t.double('votes_voteDiff'); + + t.double('ranks_count'); + t.double('ranks_sum'); + t.double('ranks_avg'); + + t.double('volumeTotal'); + for (const age of ageEmum) { + t.double('volume_' + age); + } + + for (const type of Object.values(StakeType)) { + t.double('stakes_' + type + '_amount'); + t.double('stakes_' + type + '_totalAmount'); + t.double('stakes_' + type + '_value'); + t.double('stakes_' + type + '_totalValue'); + t.double('stakes_' + type + '_stakingMembersCount'); + } + + t.jsonb('stakeExpiry').defaultTo({}); + }); + + await createTable(knex, COL.TOKEN, SUB_COL.RANKS, (t) => { + baseSubCollection(knex, t); + t.double('rank'); + }); + + await createTable(knex, COL.TOKEN, SUB_COL.VOTES, (t) => { + baseSubCollection(knex, t); + t.double('direction'); + }); +} + +export async function down(): Promise {} diff --git a/packages/database/migrations/20240129135000_token_market.ts b/packages/database/migrations/20240129135000_token_market.ts new file mode 100644 index 0000000000..cee87c8df0 --- /dev/null +++ b/packages/database/migrations/20240129135000_token_market.ts @@ -0,0 +1,43 @@ +import { COL } from '@build-5/interfaces'; +import type { Knex } from 'knex'; +import { baseRecord, createEnumType, createTable } from './20240129091246_common'; + +const tradeOrderType = ['buy', 'sell']; + +const tokenTradeOrderStatus = [ + 'active', + 'settled', + 'cancelled', + 'partially_settled_and_cancelled', + 'expired', + 'cancelled_unfulfillable', + 'cancelled_minting_token', +]; +export async function up(knex: Knex): Promise { + await createEnumType(knex, 'token_trade_order_type', tradeOrderType); + await createEnumType(knex, 'token_trade_order_status', tokenTradeOrderStatus); + await createTable(knex, COL.TOKEN_MARKET, undefined, (t) => { + baseRecord(knex, t); + + t.text('owner'); + t.text('token'); + t.specificType('tokenStatus', 'token_status'); + t.specificType('type', 'token_trade_order_type'); + t.double('count'); + t.double('price'); + t.double('totalDeposit'); + t.double('balance'); + t.double('fulfilled'); + t.specificType('status', 'token_trade_order_status'); + t.text('orderTransactionId'); + t.text('paymentTransactionId'); + t.text('creditTransactionId'); + t.timestamp('expiresAt'); + t.boolean('shouldRetry'); + t.specificType('sourceNetwork', 'network'); + t.specificType('targetNetwork', 'network'); + t.text('targetAddress'); + }); +} + +export async function down(): Promise {} diff --git a/packages/database/migrations/20240129135000_token_purchase.ts b/packages/database/migrations/20240129135000_token_purchase.ts new file mode 100644 index 0000000000..33f686955c --- /dev/null +++ b/packages/database/migrations/20240129135000_token_purchase.ts @@ -0,0 +1,33 @@ +import { COL } from '@build-5/interfaces'; +import type { Knex } from 'knex'; +import { baseRecord, createEnumType, createTable } from './20240129091246_common'; + +export const ageEmum = ['in24h', 'in48h', 'in7d']; + +export async function up(knex: Knex): Promise { + await createEnumType(knex, 'token_purchase_age', ageEmum); + await createTable(knex, COL.TOKEN_PURCHASE, undefined, (t) => { + baseRecord(knex, t); + + t.text('token'); + t.specificType('tokenStatus', 'token_status'); + t.text('sell'); + t.text('buy'); + t.double('count'); + t.double('price'); + t.specificType('triggeredBy', 'token_trade_order_type'); + t.text('billPaymentId'); + t.text('buyerBillPaymentId'); + t.specificType('royaltyBillPayments', 'TEXT[]'); + t.specificType('sourceNetwork', 'network'); + t.specificType('targetNetwork', 'network'); + t.double('sellerTokenTradingFeePercentage'); + t.double('sellerTier'); + + t.boolean('in24h').defaultTo(false); + t.boolean('in48h').defaultTo(false); + t.boolean('in7d').defaultTo(false); + }); +} + +export async function down(): Promise {} diff --git a/packages/database/migrations/20240129135000_transaction.ts b/packages/database/migrations/20240129135000_transaction.ts new file mode 100644 index 0000000000..8f3625e58c --- /dev/null +++ b/packages/database/migrations/20240129135000_transaction.ts @@ -0,0 +1,259 @@ +import { COL } from '@build-5/interfaces'; +import type { Knex } from 'knex'; +import { baseRecord, createEnumType, createTable } from './20240129091246_common'; + +const transactionTypeEnum = [ + 'vote', + 'order', + 'payment', + 'bill_payment', + 'credit', + 'credit_tangle_request', + 'credit_storage_deposit_locked', + 'mint_collection', + 'credit_nft', + 'withdraw_nft', + 'mint_token', + 'award', + 'unlock', + 'metadata_nft', + 'stamp', + 'nft_transfer', +]; + +const transactionPayloadType = [ + 'nft_purchase', + 'nft_purchase_bulk', + 'nft_bid', + 'auction_bid', + 'space_address_validation', + 'member_address_validation', + 'token_purchase', + 'token_airdrop', + 'mint_token', + 'claim_minted_token', + 'claim_base_token', + 'sell_token', + 'buy_token', + 'mint_collection', + 'deposit_nft', + 'airdrop_minted_token', + 'credit_locked_funds', + 'stake', + 'tangle_request', + 'proposal_vote', + 'claim_space', + 'stake_nft', + 'fund_award', + 'import_token', + 'mint_metadata_nft', + 'mint_alias', + 'badge', + 'burn_alias', + '', + 'token_buy', + 'award_completed', + 'token_vault_emptied', + 'token_trade_fullfillment', + 'address_validation', + 'transaction_already_unlocked', + 'invalid_amount', + 'invalid_payment', + 'token_vote', + 'data_no_longer_valid', + 'space_calimed', + 'pre_minted_claim', + 'unlock_funds', + 'unlock_nft', + 'tangle_transfer', + 'tangle_transfer_many', + 'mint_nft', + 'update_minted_nft', + 'mint_nfts', + 'lock_collection', + 'send_alias_to_guardian', + 'mint_foundry', + 'minted_airdrop_claim', + 'pre_minted_airdrop_claim', + 'pre_minted_token_trade', + 'minted_token_trade', + 'base_token_trade', + 'base_airdrop_claim', + 'stamp', + 'swap', +]; + +const ignoreWalletReasonEnum = [ + '', + 'unrefundable_due_unlock_conditions', + 'unrefundable_due_timelock_condition', + 'unrefundable_due_storage_deposit_condition', + 'pre_minted_airdrop_claim', + 'extra_stake_reward', + 'missing_target_address', +]; + +const transactionValidationTypeEnum = ['address', 'address_and_amount']; + +const entityEnum = ['space', 'member']; + +const creditPaymentReasonEnum = ['trade_cancelled']; + +export async function up(knex: Knex): Promise { + await createEnumType(knex, 'transaction_type', transactionTypeEnum); + await createEnumType(knex, 'transaction_payload_type', transactionPayloadType); + await createEnumType(knex, 'ignore_wallet_reason', ignoreWalletReasonEnum); + await createEnumType(knex, 'transaction_validation_type', transactionValidationTypeEnum); + await createEnumType(knex, 'entity', entityEnum); + await createEnumType(knex, 'credit_payment_reason', creditPaymentReasonEnum); + + await createTable(knex, COL.TRANSACTION, undefined, (table) => { + baseRecord(knex, table); + table.specificType('network', 'network'); + table.specificType('type', 'transaction_type'); + table.boolean('isOrderType'); + table.text('member'); + table.text('space'); + table.boolean('shouldRetry'); + table.boolean('ignoreWallet'); + table.specificType('linkedTransactions', 'TEXT[]').defaultTo('{}'); + table.specificType('ignoreWalletReason', 'ignore_wallet_reason'); + + table.specificType('payload_type', 'transaction_payload_type'); + table.double('payload_amount'); + table.text('payload_sourceAddress'); + table.text('payload_targetAddress'); + table.jsonb('payload_targetAddresses').defaultTo([]); + table.specificType('payload_sourceTransaction', 'TEXT[]').defaultTo('{}'); + table.specificType('payload_validationType', 'transaction_validation_type'); + table + .timestamp('payload_expiresOn') + .comment( + 'Order will expire on this date. Once order is expired, it can not receive any more requests.', + ); + table.boolean('payload_reconciled'); + table.boolean('payload_void'); + + table.text('payload_collection'); + table.specificType('payload_unsoldMintingOptions', 'unsold_minting_options'); + table.double('payload_newPrice'); + table.double('payload_collectionStorageDeposit'); + table.double('payload_nftsStorageDeposit'); + table.double('payload_aliasStorageDeposit'); + table.double('payload_nftsToMint'); + + table.text('payload_transaction'); + table.text('payload_unlockedBy'); + + table.specificType('payload_beneficiary', 'entity'); + table.text('payload_beneficiaryUid'); + table.text('payload_beneficiaryAddress'); + + table.double('payload_royaltiesFee'); + table.text('payload_royaltiesSpace'); + table.text('payload_royaltiesSpaceAddress'); + table.text('payload_chainReference'); + table.text('payload_nft'); + table.jsonb('payload_restrictions').defaultTo({}); + table.text('payload_token'); + table.double('payload_quantity'); + table.text('payload_tokenSymbol'); + + table.double('payload_unclaimedAirdrops'); + table.double('payload_totalAirdropCount'); + table.text('payload_tokenId'); + + table.double('payload_foundryStorageDeposit'); + table.double('payload_vaultStorageDeposit'); + table.double('payload_guardianStorageDeposit'); + table.double('payload_tokensInVault'); + table.text('payload_orderId'); + table.double('payload_collectionOutputAmount'); + table.double('payload_aliasOutputAmount'); + table.double('payload_nftOutputAmount'); + + table.text('payload_aliasId'); + table.text('payload_aliasBlockId'); + table.text('payload_aliasGovAddress'); + table.text('payload_collectionId'); + table.text('payload_nftId'); + table.jsonb('payload_nativeTokens').defaultTo([]); + + table.specificType('payload_previousOwnerEntity', 'entity'); + table.text('payload_previousOwner'); + table.specificType('payload_ownerEntity', 'entity'); + table.text('payload_owner'); + + table.boolean('payload_royalty'); + table.timestamp('payload_vestingAt'); + + table.jsonb('payload_customMetadata').defaultTo({}); + table.text('payload_stake'); + table.text('payload_award'); + table.text('payload_legacyAwardFundRequestId'); + table.double('payload_legacyAwardsBeeingFunded'); + table.double('payload_weeks'); + table.specificType('payload_stakeType', 'stake_type'); + + table.double('payload_count'); + table.double('payload_price'); + table.double('payload_tokenReward'); + table.double('payload_edition'); + table.timestamp('payload_participatedOn'); + table.text('payload_proposalId'); + table.specificType('payload_voteValues', 'FLOAT[]'); + table.text('payload_storageDepositSourceAddress'); + table.jsonb('payload_storageReturn').defaultTo({}); + table.text('payload_airdropId'); + + table.specificType('payload_nfts', 'TEXT[]').defaultTo('{}'); + table.text('payload_tag'); + table.jsonb('payload_metadata').defaultTo({}); + table.jsonb('payload_response').defaultTo({}); + + table.specificType('payload_reason', 'credit_payment_reason'); + table.boolean('payload_invalidPayment'); + table.text('payload_outputToConsume'); + table.boolean('payload_dependsOnBillPayment'); + table.text('payload_milestoneTransactionPath'); + table.double('payload_tokenAmount'); + table.double('payload_weight'); + table.double('payload_weightMultiplier'); + table.specificType('payload_votes', 'FLOAT[]'); + table.specificType('payload_values', 'FLOAT[]'); + table.text('payload_creditId'); + table.boolean('payload_outputConsumed'); + table.timestamp('payload_outputConsumedOn'); + table.specificType('payload_stakes', 'TEXT[]').defaultTo('{}'); + table.text('payload_stakeReward'); + table.boolean('payload_tanglePuchase'); + table.boolean('payload_disableWithdraw'); + table.boolean('payload_lockCollectionNft'); + + table.text('payload_stamp'); + table.text('payload_tokenTradeOderTargetAddress'); + table.text('payload_auction'); + + table.double('payload_days'); + table.double('payload_dailyCost'); + + table.jsonb('payload_nftOrders').defaultTo([]); + table.text('payload_swap'); + + table.timestamp('payload_walletReference_createdOn'); + table.timestamp('payload_walletReference_processedOn'); + table.text('payload_walletReference_chainReference'); + table.specificType('payload_walletReference_chainReferences', 'TEXT[]').defaultTo('{}'); + table.text('payload_walletReference_error'); + table.boolean('payload_walletReference_confirmed'); + table.timestamp('payload_walletReference_confirmedOn'); + table.text('payload_walletReference_milestoneTransactionPath'); + table.double('payload_walletReference_count'); + table.boolean('payload_walletReference_inProgress'); + table.double('payload_walletReference_nodeIndex'); + + table.text('payload_outputId'); + }); +} + +export async function down(): Promise {} diff --git a/packages/database/package.json b/packages/database/package.json index 22fc88e195..be93a3ddab 100644 --- a/packages/database/package.json +++ b/packages/database/package.json @@ -12,19 +12,25 @@ ], "private": true, "scripts": { - "build": "tsc" + "build": "tsc", + "migrate": "knex migrate:latest --knexfile knexfile.ts", + "generate": "rm -rf ./src/pg/models/* && ts-node ./generators/generator.ts && npx prettier . --write" }, "dependencies": { "@build-5/interfaces": "*", + "@google-cloud/pubsub": "4.3.3", + "@google-cloud/storage": "7.9.0", "dayjs": "1.11.10", - "firebase-admin": "12.0.0", "jsonwebtoken": "9.0.2", - "lodash": "4.17.21" + "knex": "^3.1.0", + "lodash": "4.17.21", + "pg": "^8.11.3" }, "devDependencies": { "@types/lodash": "4.14.202", "dotenv": "16.4.5", "glob": "8.0.3", + "prettier-plugin-organize-imports": "3.2.4", "typescript": "5.3.3" } } diff --git a/packages/database/src/app/app.ts b/packages/database/src/app/app.ts deleted file mode 100644 index 37daffe138..0000000000 --- a/packages/database/src/app/app.ts +++ /dev/null @@ -1,11 +0,0 @@ -import admin from 'firebase-admin'; -import { IApp } from './interface'; - -export class FirebaseApp implements IApp { - constructor(private readonly app: admin.app.App) {} - - /* eslint-disable @typescript-eslint/no-explicit-any */ - public getInstance = (): any => this.app; - - public getName = () => this.app.options.projectId!; -} diff --git a/packages/database/src/app/build5App.ts b/packages/database/src/app/build5App.ts deleted file mode 100644 index 8986dfde57..0000000000 --- a/packages/database/src/app/build5App.ts +++ /dev/null @@ -1,6 +0,0 @@ -import admin from 'firebase-admin'; -import { FirebaseApp } from './app'; - -const defaultApp = admin.initializeApp(undefined, 'defaultApp'); - -export const build5App = new FirebaseApp(defaultApp); diff --git a/packages/database/src/app/index.ts b/packages/database/src/app/index.ts deleted file mode 100644 index 473861e4f4..0000000000 --- a/packages/database/src/app/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export * from './app'; -export * from './build5App'; -export * from './interface'; diff --git a/packages/database/src/app/interface.ts b/packages/database/src/app/interface.ts deleted file mode 100644 index de8e3866b7..0000000000 --- a/packages/database/src/app/interface.ts +++ /dev/null @@ -1,5 +0,0 @@ -export interface IApp { - /* eslint-disable @typescript-eslint/no-explicit-any */ - getInstance: () => any; - getName: () => string; -} diff --git a/packages/database/src/firestore/build5Db.ts b/packages/database/src/firestore/build5Db.ts deleted file mode 100644 index abf37e1d1b..0000000000 --- a/packages/database/src/firestore/build5Db.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { COL, Dataset, SUB_COL, Subset } from '@build-5/interfaces'; -import { build5App } from '../app/build5App'; -import { Firestore } from './firestore'; -import { IDatabase } from './interfaces'; - -export const build5Db = (): IDatabase => new Firestore(build5App); - -export const getSnapshot = ( - col: COL | Dataset, - id?: string, - subCol?: SUB_COL | Subset, - childId?: string, -) => { - if (!id) { - return; - } - let doc = build5Db().doc(`${col}/${id}`); - if (subCol && childId) { - doc = doc.collection(subCol).doc(childId); - } - return doc.getSnapshot(); -}; diff --git a/packages/database/src/firestore/common.ts b/packages/database/src/firestore/common.ts deleted file mode 100644 index 4f9fe73400..0000000000 --- a/packages/database/src/firestore/common.ts +++ /dev/null @@ -1,11 +0,0 @@ -import dayjs from 'dayjs'; -import { get } from 'lodash'; -import { IDocument } from './interfaces'; - -export const cOn = (doc: IDocument, data: T) => ({ - ...data, - createdOn: get(data, 'createdOn') || dayjs().toDate(), - updatedOn: get(data, 'updatedOn') || dayjs().toDate(), -}); - -export const uOn = (data: T) => ({ ...data, updatedOn: dayjs().toDate() }); diff --git a/packages/database/src/firestore/firestore.ts b/packages/database/src/firestore/firestore.ts deleted file mode 100644 index 44692016ef..0000000000 --- a/packages/database/src/firestore/firestore.ts +++ /dev/null @@ -1,294 +0,0 @@ -/* eslint-disable @typescript-eslint/no-explicit-any */ -import { COL, Dataset, SUB_COL, Subset } from '@build-5/interfaces'; -import admin from 'firebase-admin'; -import { Filter } from 'firebase-admin/firestore'; -import { isEmpty } from 'lodash'; -import { FirebaseApp } from '../app/app'; -import { cOn, uOn } from './common'; -import { - IBatch, - ICollection, - ICollectionGroup, - IDatabase, - IDocument, - IDocumentSnapshot, - IQuery, - ITransaction, -} from './interfaces'; - -export class Firestore implements IDatabase { - private db: admin.firestore.Firestore; - - constructor(private readonly app: FirebaseApp) { - this.db = this.app.getInstance().firestore(); - } - - public collection = (col: COL | Dataset) => - new FirestoreCollection(this.db, this.db.collection(col)); - - public collectionGroup = (col: SUB_COL | Subset) => - new FirestoreCollectionGroup(this.db.collectionGroup(col)); - - public doc = (documentPath: string) => new FirestoreDocument(this.db, this.db.doc(documentPath)); - - public batch = (): IBatch => new FirestoreBatch(this.db); - - public runTransaction = ( - func: (transaction: FirestoreTransaction) => Promise, - ): Promise => - this.db.runTransaction((transaction) => func(new FirestoreTransaction(this.db, transaction))); - - public inc = (value: number) => admin.firestore.FieldValue.increment(value); - - public arrayUnion = (...value: T[]) => admin.firestore.FieldValue.arrayUnion(...value); - - public arrayRemove = (...value: T[]) => admin.firestore.FieldValue.arrayRemove(...value); - - public deleteField = () => admin.firestore.FieldValue.delete(); - - public get = async (col: COL, uid: string) => { - const docRef = this.db.doc(`${col}/${uid}`); - return (await docRef.get()).data() as T; - }; -} - -export class FirestoreBatch implements IBatch { - private batch: admin.firestore.WriteBatch; - - constructor(private readonly db: admin.firestore.Firestore) { - this.batch = db.batch(); - } - - public create = (docRef: IDocument, data: any) => { - const ref = this.db.doc(docRef.getPath()); - this.batch.create(ref, cOn(docRef, data)); - }; - - public update = (docRef: IDocument, data: any) => { - const ref = this.db.doc(docRef.getPath()); - this.batch.update(ref, uOn(data)); - }; - - public set = (docRef: IDocument, data: any, merge = false) => { - const ref = this.db.doc(docRef.getPath()); - this.batch.set(ref, merge ? uOn(data) : cOn(docRef, data), { merge }); - }; - - public delete = (docRef: IDocument) => { - const ref = this.db.doc(docRef.getPath()); - this.batch.delete(ref); - }; - - public commit = async () => { - await this.batch.commit(); - }; -} - -export class FirestoreTransaction implements ITransaction { - constructor( - private readonly db: admin.firestore.Firestore, - private readonly transaction: admin.firestore.Transaction, - ) {} - - public get = async (docRef: IDocument) => { - const refs = this.db.doc(docRef.getPath()); - const doc = await this.transaction.get(refs); - return doc.data(); - }; - - public getAll = async (...docRefs: IDocument[]) => { - if (isEmpty(docRefs)) { - return []; - } - const refs = docRefs.map((docRef) => this.db.doc(docRef.getPath())); - const snap = await this.transaction.getAll(...refs); - return snap.map((doc) => doc.data() as T | undefined); - }; - - public getByQuery = async (query: IQuery) => { - const snap = await this.transaction.get(query.getInstance()); - return snap.docs.map((d) => d.data() as T); - }; - - public create = (docRef: IDocument, data: any) => { - const ref = this.db.doc(docRef.getPath()); - this.transaction.create(ref, cOn(docRef, data)); - }; - - public update = (docRef: IDocument, data: any) => { - const ref = this.db.doc(docRef.getPath()); - this.transaction.update(ref, uOn(data)); - }; - - public set = (docRef: IDocument, data: any, merge = false) => { - const ref = this.db.doc(docRef.getPath()); - const uData = merge ? uOn(data) : cOn(docRef, data); - this.transaction.set(ref, uData, { merge }); - }; - - public delete = (docRef: IDocument) => { - const ref = this.db.doc(docRef.getPath()); - this.transaction.delete(ref); - }; -} - -class FirestoreCollectionGroup implements ICollectionGroup { - constructor( - protected readonly collection: - | admin.firestore.CollectionGroup - | admin.firestore.CollectionReference, - ) {} - - public get = async () => { - const snap = await this.collection.get(); - return snap.docs.map((d) => d.data() as T); - }; - - public where = (fieldPath: string, operator: admin.firestore.WhereFilterOp, value: any) => - new FirestoreQuery(this.collection.where(fieldPath, operator, value)); - - public or = (filters: { fieldPath: string; value: any }[]) => { - const compositFilter = Filter.or( - ...filters.map((f) => Filter.where(f.fieldPath, '==', f.value)), - ); - return new FirestoreQuery(this.collection.where(compositFilter)); - }; - - public limit = (value: number) => new FirestoreQuery(this.collection.limit(value)); - - public limitToLast = (value: number) => new FirestoreQuery(this.collection.limitToLast(value)); - - public startAfter = (value?: IDocumentSnapshot | string | number | Date) => { - if (!value) { - return new FirestoreQuery(this.collection); - } - return new FirestoreQuery(this.collection.startAfter(value)); - }; - - public orderBy = (field: string, dir: 'asc' | 'desc' = 'asc') => - new FirestoreQuery(this.collection.orderBy(field, dir)); - - public count = async () => (await this.collection.count().get()).data().count; -} - -export class FirestoreCollection extends FirestoreCollectionGroup implements ICollection { - constructor( - private readonly db: admin.firestore.Firestore, - collection: admin.firestore.CollectionReference, - ) { - super(collection); - } - - public doc = (documentPath = '') => { - const colRef = this.collection as admin.firestore.CollectionReference; - const docRef = documentPath ? colRef.doc(documentPath) : colRef.doc(); - return new FirestoreDocument(this.db, docRef); - }; -} - -export class FirestoreDocument implements IDocument { - constructor( - private readonly db: admin.firestore.Firestore, - private readonly document: admin.firestore.DocumentReference, - ) {} - - public create = async (data: any) => { - await this.document.create(cOn(this, data)); - }; - - public update = async (data: any) => { - await this.document.update(uOn(data)); - }; - - public set = async (data: any, merge = false) => { - await this.document.set(merge ? uOn(data) : cOn(this, data), { merge }); - }; - - public delete = async () => { - await this.document.delete(); - }; - - public onSnapshot = ( - callback: (data: T | undefined) => void, - onError?: (error: Error) => void, - ) => - this.document.onSnapshot( - (snap) => { - callback(snap.exists ? ({ ...snap.data(), uid: snap.id } as T) : undefined); - }, - (error) => { - onError && onError(error); - }, - ); - - public collection = (subCol: SUB_COL | Subset): ICollection => - new FirestoreCollection(this.db, this.document.collection(subCol)); - - public get = async (): Promise => { - const doc = await this.document.get(); - return doc.data(); - }; - - public getPath = () => this.document.path; - - public getSnapshot = () => this.document.get(); - - public getId = () => this.document.id; -} - -export class FirestoreQuery implements IQuery { - constructor(private query: admin.firestore.Query) {} - - public get = async (): Promise => { - const snap = await this.query.get(); - return snap.docs.map((d) => ({ ...d.data(), uid: d.id }) as T); - }; - - public where = ( - fieldPath: string, - operator: admin.firestore.WhereFilterOp, - value: any, - ): IQuery => { - this.query = this.query.where(fieldPath, operator, value); - return this; - }; - - public limit = (value: number) => { - this.query = this.query.limit(value); - return this; - }; - - public limitToLast = (value: number) => { - this.query = this.query.limitToLast(value); - return this; - }; - - public startAfter = (value?: IDocumentSnapshot | string | number | Date) => { - if (value) { - this.query = this.query.startAfter(value); - } - return this; - }; - - public orderBy = (field: string, dir: 'asc' | 'desc' = 'asc') => { - this.query = this.query.orderBy(field, dir); - return this; - }; - - public select = (...fields: string[]) => { - this.query = this.query.select(...fields); - return this; - }; - - public onSnapshot = (callback: (data: T[]) => void, onError?: (error: Error) => void) => - this.query.onSnapshot( - (snap) => { - callback(snap.docs.map((d) => ({ ...d.data(), uid: d.id }) as T)); - }, - (error) => { - onError && onError(error); - }, - ); - - public getInstance = () => this.query; -} diff --git a/packages/database/src/firestore/index.ts b/packages/database/src/firestore/index.ts deleted file mode 100644 index b62641cb9d..0000000000 --- a/packages/database/src/firestore/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -export * from './build5Db'; -export * from './common'; -export * from './firestore'; -export * from './interfaces'; diff --git a/packages/database/src/firestore/interfaces.ts b/packages/database/src/firestore/interfaces.ts deleted file mode 100644 index ba89abbb6e..0000000000 --- a/packages/database/src/firestore/interfaces.ts +++ /dev/null @@ -1,103 +0,0 @@ -/* eslint-disable @typescript-eslint/no-explicit-any */ -import { COL, Dataset, SUB_COL, Subset } from '@build-5/interfaces'; - -export interface IDatabase { - collection: (col: COL | Dataset) => ICollection; - collectionGroup: (col: SUB_COL | Subset) => ICollectionGroup; - doc: (documentPath: string) => IDocument; - - batch: () => IBatch; - runTransaction: (func: (transaction: ITransaction) => Promise) => Promise; - - inc: (value: number) => any; - arrayUnion: (...value: T[]) => any; - arrayRemove: (...value: T[]) => any; - deleteField: () => any; - - get: (col: COL, uid: string) => Promise; -} - -export interface ICollectionGroup { - get: () => Promise; - where: (fieldPath: string, operator: WhereFilterOp, value: any) => IQuery; - or: (filters: { fieldPath: string; value: any }[]) => IQuery; - limit: (value: number) => IQuery; - limitToLast: (value: number) => IQuery; - startAfter: (value?: IDocumentSnapshot | string | number | Date) => IQuery; - orderBy: (field: string, dir?: 'asc' | 'desc') => IQuery; - count: () => Promise; -} - -export interface ICollection extends ICollectionGroup { - doc: (documentPath?: string) => IDocument; -} - -export interface IDocument { - create: (data: any) => Promise; - update: (data: any) => Promise; - set: (data: any, merge?: boolean) => Promise; - delete: () => Promise; - - onSnapshot: ( - callback: (data: T | undefined) => void, - error?: (error: Error) => void, - ) => () => void; - - collection: (subCol: SUB_COL | Subset) => ICollection; - get: () => Promise; - - getPath: () => string; - getSnapshot: () => Promise; - - getId: () => string; -} - -export interface IDocumentSnapshot { - readonly id: string; -} - -export interface IQuery { - get: () => Promise; - where: (fieldPath: string, operator: WhereFilterOp, value: any) => IQuery; - - limit: (value: number) => IQuery; - limitToLast: (value: number) => IQuery; - startAfter: (value?: IDocumentSnapshot | string | number | Date) => IQuery; - onSnapshot: (callback: (data: T[]) => void, error?: (error: Error) => void) => () => void; - - getInstance: () => any; - - orderBy: (field: string, dir?: 'asc' | 'desc') => IQuery; - - select: (...fields: string[]) => IQuery; -} - -export interface IBatch { - create: (docRef: IDocument, data: any) => void; - update: (docRef: IDocument, data: any) => void; - set: (docRef: IDocument, data: any, merge?: boolean) => void; - delete: (docRef: IDocument) => void; - commit: () => Promise; -} - -export interface ITransaction { - get: (docRef: IDocument) => Promise; - getAll: (...docRefs: IDocument[]) => Promise<(T | undefined)[]>; - getByQuery: (query: IQuery) => Promise; - create: (docRef: IDocument, data: any) => void; - update: (docRef: IDocument, data: any) => void; - set: (docRef: IDocument, data: any, merge?: boolean) => void; - delete: (docRef: IDocument) => void; -} - -export type WhereFilterOp = - | '<' - | '<=' - | '==' - | '!=' - | '>=' - | '>' - | 'array-contains' - | 'in' - | 'not-in' - | 'array-contains-any'; diff --git a/packages/database/src/index.ts b/packages/database/src/index.ts index de2baa4b9f..8e9f78f42d 100644 --- a/packages/database/src/index.ts +++ b/packages/database/src/index.ts @@ -1,3 +1,2 @@ -export * from './app/index'; -export * from './firestore/index'; +export * from './pg/index'; export * from './storage/index'; diff --git a/packages/database/src/pg/impl/common.ts b/packages/database/src/pg/impl/common.ts new file mode 100644 index 0000000000..904a66cf6d --- /dev/null +++ b/packages/database/src/pg/impl/common.ts @@ -0,0 +1,40 @@ +import { Timestamp } from '@build-5/interfaces'; +import { isNull, isUndefined } from 'lodash'; + +export const convertEnum = ( + value: T | undefined | null, + fromEnum: Record, + toEnum: Record, +): U | undefined => { + if (isUndefined(value) || isNull(value)) { + return undefined; + } + const key = Object.keys(fromEnum).find((key) => (fromEnum[key] as any) === value)!; + return toEnum[key!] as U; +}; + +export const removeNulls = (data: T) => { + const result: T = Object.entries(data as any).reduce((acc, [key, value]) => { + if (isNull(value) || isUndefined(value)) { + return acc; + } + if (value instanceof Timestamp || Array.isArray(value)) { + return { ...acc, [key]: value }; + } + if (value instanceof Object) { + return { ...acc, [key]: removeNulls(value) }; + } + return { ...acc, [key]: value }; + }, {} as T); + return result; +}; + +export const undefinedToNull = (data: T) => { + const result: T = Object.entries(data as any).reduce((acc, [key, value]) => { + if (isNull(value) || isUndefined(value)) { + return { ...acc, [key]: null }; + } + return { ...acc, [key]: value }; + }, {} as T); + return result; +}; diff --git a/packages/database/src/pg/impl/instance.ts b/packages/database/src/pg/impl/instance.ts new file mode 100644 index 0000000000..48deb0d731 --- /dev/null +++ b/packages/database/src/pg/impl/instance.ts @@ -0,0 +1,4 @@ +import { IDatabase } from '../interfaces'; +import { PgDatabase } from './postgres'; + +export const build5Db = (): IDatabase => new PgDatabase(); diff --git a/packages/database/src/pg/impl/knex.ts b/packages/database/src/pg/impl/knex.ts new file mode 100644 index 0000000000..1ae2ba82f8 --- /dev/null +++ b/packages/database/src/pg/impl/knex.ts @@ -0,0 +1,45 @@ +import Knex from 'knex'; + +export let knex: Knex.Knex | undefined = undefined; + +export const getKnex = () => { + if (!knex) { + knex = Knex({ + client: 'pg', + connection: { + user: process.env.DB_USER, + password: process.env.DB_USER_PWD, + database: process.env.DB_NAME, + host: process.env.DB_HOST, + port: Number(process.env.DB_PORT), + }, + pool: { + min: Number(process.env.DB_POOL_MAX || 1), + max: Number(process.env.DB_POOL_MAX || 10), + }, + }); + } + return knex; +}; + +export let knextran: Knex.Knex | undefined = undefined; + +export const getKnexTran = () => { + if (!knextran) { + knextran = Knex({ + client: 'pg', + connection: { + user: process.env.DB_USER, + password: process.env.DB_USER_PWD, + database: process.env.DB_NAME, + host: process.env.DB_HOST, + port: Number(process.env.DB_PORT), + }, + pool: { + min: Number(process.env.DB_POOL_MAX || 1), + max: Number(process.env.DB_POOL_MAX || 10), + }, + }); + } + return knextran; +}; diff --git a/packages/database/src/pg/impl/postgres.ts b/packages/database/src/pg/impl/postgres.ts new file mode 100644 index 0000000000..267dc7bf64 --- /dev/null +++ b/packages/database/src/pg/impl/postgres.ts @@ -0,0 +1,650 @@ +import { + Auction, + Award, + AwardOwner, + AwardParticipant, + COL, + Collection, + CollectionStats, + Member, + Mnemonic, + Nft, + NftStake, + Notification, + Project, + ProjectAdmin, + ProjectApiKey, + Proposal, + ProposalMember, + Rank, + SUB_COL, + SoonSnap, + Space, + SpaceGuardian, + SpaceMember, + Stake, + StakeReward, + Stamp, + Swap, + SystemConfig, + Ticker, + Timestamp, + Token, + TokenDistribution, + TokenDrop, + TokenPurchase, + TokenStats, + TokenTradeOrder, + Transaction, + Vote, +} from '@build-5/interfaces'; +import dayjs from 'dayjs'; +import { Knex } from 'knex'; +import { + ArrayRemove, + ArrayUnion, + Converter, + IBatch, + ICollection, + IDatabase, + IDocument, + ISubCollection, + ISubDocument, + ITransaction, + Increment, +} from '../interfaces'; +import { + PgAirdrop, + PgAuction, + PgAward, + PgAwardOwners, + PgAwardParticipants, + PgCollection, + PgCollectionRanks, + PgCollectionStats, + PgCollectionVotes, + PgMember, + PgMilestone, + PgMilestoneTransactions, + PgMilestoneTransactionsUpdate, + PgMilestoneUpdate, + PgMnemonic, + PgNft, + PgNftStake, + PgNotification, + PgProject, + PgProjectAdmins, + PgProjectApiKey, + PgProposal, + PgProposalMembers, + PgProposalOwners, + PgSoonSnapshot, + PgSoonSnapshotUpdate, + PgSpace, + PgSpaceGuardians, + PgSpaceMembers, + PgStake, + PgStakeReward, + PgStamp, + PgSwap, + PgSystem, + PgTicker, + PgToken, + PgTokenDistribution, + PgTokenMarket, + PgTokenPurchase, + PgTokenRanks, + PgTokenStats, + PgTokenVotes, + PgTransaction, +} from '../models'; +import { PgAirdropUpdate } from '../models/airdrop_update'; +import { PgAuctionUpdate } from '../models/auction_update'; +import { + PgAwardOwnersUpdate, + PgAwardParticipantsUpdate, + PgAwardUpdate, +} from '../models/award_update'; +import { + PgCollectionRanksUpdate, + PgCollectionStatsUpdate, + PgCollectionUpdate, + PgCollectionVotesUpdate, +} from '../models/collection_update'; +import { BaseRecord } from '../models/common'; +import { Update } from '../models/common_update'; +import { PgMemberUpdate } from '../models/member_update'; +import { PgMnemonicUpdate } from '../models/mnemonic_update'; +import { PgNftStakeUpdate, PgNftUpdate } from '../models/nft_update'; +import { PgNotificationUpdate } from '../models/notification_update'; +import { + PgProjectAdminsUpdate, + PgProjectApiKeyUpdate, + PgProjectUpdate, +} from '../models/project_update'; +import { + PgProposalMembersUpdate, + PgProposalOwnersUpdate, + PgProposalUpdate, +} from '../models/proposal_update'; +import { + PgSpaceGuardiansUpdate, + PgSpaceMembersUpdate, + PgSpaceUpdate, +} from '../models/space_update'; +import { PgStakeRewardUpdate, PgStakeUpdate } from '../models/stake_update'; +import { PgStampUpdate } from '../models/stamp_update'; +import { PgSwapUpdate } from '../models/swap_update'; +import { PgSystemUpdate } from '../models/system_update'; +import { PgTickerUpdate } from '../models/ticker_update'; +import { + PgTokenDistributionUpdate, + PgTokenMarketUpdate, + PgTokenPurchaseUpdate, + PgTokenRanksUpdate, + PgTokenStatsUpdate, + PgTokenUpdate, + PgTokenVotesUpdate, +} from '../models/token_update'; +import { PgTransactionUpdate } from '../models/transaction_update'; +import { getKnex, getKnexTran, knex, knextran } from './knex'; +import { subscriptions } from './pubsub'; +import { AirdropConverter, PgAirdropCollection } from './tables/airdrop'; +import { AuctionConverter } from './tables/auction'; +import { AwardConverter } from './tables/award'; +import { AwardOwnerConverter } from './tables/award_owner'; +import { AwardParticipantConverter } from './tables/award_participant'; +import { CollectionConverter, PgCollectionCollection } from './tables/collection'; +import { CollectionRankConverter } from './tables/collection_rank'; +import { CollectionStatsConverter } from './tables/collection_stats'; +import { CollectionVotesConverter } from './tables/collection_vote'; +import { MemberConverter } from './tables/member'; +import { MilestoneConverter } from './tables/milestone'; +import { + MilestoneTransactionConverter, + MilestoneTransactions, +} from './tables/milestone_transactions'; +import { MnemonicConverter } from './tables/mnemonic'; +import { NftConverter } from './tables/nft'; +import { NftStakeConverter } from './tables/nft_stake'; +import { NotificationConverter } from './tables/notification'; +import { ProjectConverter } from './tables/project'; +import { ProjectAdminConverter } from './tables/project_admin'; +import { ProjectApiKeyConverter } from './tables/project_api_key'; +import { ProposalConverter } from './tables/proposal'; +import { ProposalMemberConverter } from './tables/proposal_member'; +import { ProposalOwnerConverter } from './tables/proposal_owner'; +import { SoonSnapshotConverter } from './tables/soon_snapshot'; +import { SpaceConverter } from './tables/space'; +import { SpaceMemberConverter } from './tables/space_member'; +import { PgStakeCollection, StakeConverter } from './tables/stake'; +import { StakeRewardConverter } from './tables/stake_reward'; +import { StampConverter } from './tables/stamp'; +import { SwapConverter } from './tables/swap'; +import { SystemConverter } from './tables/system'; +import { TickerConverter } from './tables/ticker'; +import { TokenConverter } from './tables/token'; +import { + PgTokenDistributionCollection, + TokenDistributionConverter, +} from './tables/token_distribution'; +import { TokenTradeOrderConverter } from './tables/token_market'; +import { TokenPurchaseConverter } from './tables/token_purchase'; +import { TokenRankConverter } from './tables/token_rank'; +import { TokenStatsConverter } from './tables/token_stats'; +import { TokenVotesConverter } from './tables/token_vote'; +import { TransactionConverter } from './tables/transaction'; + +// prettier-ignore +export type IColType = + S extends undefined ? + T extends COL.MEMBER ? ICollection : + T extends COL.SPACE ? ICollection : + T extends COL.PROJECT ? ICollection : + T extends COL.COLLECTION ? PgCollectionCollection : + T extends COL.NFT ? ICollection : + T extends COL.NFT_STAKE ? ICollection : + T extends COL.TRANSACTION ? ICollection : + T extends COL.AUCTION ? ICollection : + T extends COL.AWARD ? ICollection : + T extends COL.TOKEN ? ICollection : + T extends COL.PROPOSAL ? ICollection : + T extends COL.STAKE_REWARD ? ICollection : + T extends COL.STAMP ? ICollection : + T extends COL.SWAP ? ICollection : + T extends COL.AIRDROP ? PgAirdropCollection : + T extends COL.TOKEN_MARKET ? ICollection : + T extends COL.STAKE ? PgStakeCollection : + T extends COL.TOKEN_PURCHASE ? ICollection : + T extends COL.MNEMONIC ? ICollection : + T extends COL.NOTIFICATION ? ICollection : + T extends COL.SYSTEM ? ICollection : + T extends COL.TICKER ? ICollection : + T extends COL.SOON_SNAP ? ICollection : + T extends COL.MILESTONE ? ICollection : + T extends COL.MILESTONE_RMS ? ICollection : + T extends COL.MILESTONE_SMR ? ICollection : + undefined : + S extends SUB_COL.OWNERS ? + T extends COL.AWARD ? ICollection : + T extends COL.PROPOSAL ? ICollection : + undefined: + S extends SUB_COL.PARTICIPANTS ? + T extends COL.AWARD ? ICollection : + undefined : + S extends SUB_COL.MEMBERS ? + T extends COL.SPACE ? ICollection : + T extends COL.PROPOSAL ? ICollection : + undefined : + S extends SUB_COL.BLOCKED_MEMBERS ? + T extends COL.SPACE ? ICollection : + undefined : + S extends SUB_COL.KNOCKING_MEMBERS ? + T extends COL.SPACE ? ICollection : + undefined : + S extends SUB_COL.GUARDIANS ? + T extends COL.SPACE ? ICollection : + undefined : + S extends SUB_COL.DISTRIBUTION ? + T extends COL.TOKEN ? PgTokenDistributionCollection : + undefined : + S extends SUB_COL.STATS ? + T extends COL.COLLECTION ? ICollection : + T extends COL.TOKEN ? ICollection : + undefined : + S extends SUB_COL.RANKS ? + T extends COL.TOKEN ? ICollection : + T extends COL.COLLECTION ? ICollection : + undefined : + S extends SUB_COL.VOTES ? + T extends COL.TOKEN ? ICollection : + T extends COL.COLLECTION ? ICollection : + undefined : + S extends SUB_COL.ADMINS ? + T extends COL.PROJECT ? ICollection : + undefined : + S extends SUB_COL._API_KEY ? + T extends COL.PROJECT ? ICollection : + undefined : + S extends SUB_COL.TRANSACTIONS ? ISubCollection : + undefined; + +// prettier-ignore +export type IDocType = + S extends undefined ? + T extends COL.MEMBER ? IDocument : + T extends COL.SPACE ? IDocument : + T extends COL.PROJECT ? IDocument : + T extends COL.COLLECTION ? IDocument : + T extends COL.NFT ? IDocument : + T extends COL.NFT_STAKE ? IDocument : + T extends COL.TRANSACTION ? IDocument : + T extends COL.AUCTION ? IDocument : + T extends COL.AWARD ? IDocument : + T extends COL.TOKEN ? IDocument : + T extends COL.PROPOSAL ? IDocument : + T extends COL.STAKE_REWARD ? IDocument : + T extends COL.STAMP ? IDocument : + T extends COL.SWAP ? IDocument : + T extends COL.AIRDROP ? IDocument : + T extends COL.TOKEN_MARKET ? IDocument : + T extends COL.STAKE ? IDocument : + T extends COL.TOKEN_PURCHASE ? IDocument : + T extends COL.MNEMONIC ? IDocument : + T extends COL.NOTIFICATION ? IDocument : + T extends COL.SYSTEM ? IDocument : + T extends COL.TICKER ? IDocument : + T extends COL.SOON_SNAP ? IDocument : + T extends COL.MILESTONE ? IDocument : + T extends COL.MILESTONE_SMR ? IDocument : + T extends COL.MILESTONE_RMS ? IDocument : + unknown : + S extends SUB_COL.OWNERS ? + T extends COL.AWARD ? IDocument : + T extends COL.PROPOSAL ? IDocument : + undefined: + S extends SUB_COL.PARTICIPANTS ? + T extends COL.AWARD ? IDocument : + undefined : + S extends SUB_COL.MEMBERS ? + T extends COL.SPACE ? IDocument : + T extends COL.PROPOSAL ? IDocument : + undefined : + S extends SUB_COL.BLOCKED_MEMBERS ? + T extends COL.SPACE ? IDocument : + undefined : + S extends SUB_COL.KNOCKING_MEMBERS ? + T extends COL.SPACE ? IDocument : + undefined : + S extends SUB_COL.GUARDIANS ? + T extends COL.SPACE ? IDocument : + undefined : + S extends SUB_COL.DISTRIBUTION ? + T extends COL.TOKEN ? ISubDocument : + undefined : + S extends SUB_COL.STATS ? + T extends COL.TOKEN ? IDocument : + T extends COL.COLLECTION ? IDocument : + undefined : + S extends SUB_COL.RANKS ? + T extends COL.TOKEN ? IDocument : + T extends COL.COLLECTION ? IDocument : + undefined : + S extends SUB_COL.VOTES ? + T extends COL.TOKEN ? IDocument : + T extends COL.COLLECTION ? IDocument : + undefined : + S extends SUB_COL.ADMINS ? + T extends COL.PROJECT ? IDocument : + undefined : + S extends SUB_COL._API_KEY ? + T extends COL.PROJECT ? IDocument : + undefined : + S extends SUB_COL.TRANSACTIONS ? ISubDocument : +undefined; + +export class PgDatabase implements IDatabase { + private readonly con: Knex; + + constructor() { + this.con = getKnex(); + } + + private getConverter = (col: COL, subCol?: SUB_COL) => { + if (!subCol) { + switch (col) { + case COL.MEMBER: + return new MemberConverter(); + case COL.SPACE: + return new SpaceConverter(); + case COL.PROJECT: + return new ProjectConverter(); + case COL.COLLECTION: + return new CollectionConverter(); + case COL.NFT: + return new NftConverter(); + case COL.NFT_STAKE: + return new NftStakeConverter(); + case COL.TRANSACTION: + return new TransactionConverter(); + case COL.AUCTION: + return new AuctionConverter(); + case COL.AWARD: + return new AwardConverter(); + case COL.TOKEN: + return new TokenConverter(); + case COL.PROPOSAL: + return new ProposalConverter(); + case COL.STAKE_REWARD: + return new StakeRewardConverter(); + case COL.STAMP: + return new StampConverter(); + case COL.SWAP: + return new SwapConverter(); + case COL.AIRDROP: + return new AirdropConverter(); + case COL.TOKEN_MARKET: + return new TokenTradeOrderConverter(); + case COL.STAKE: + return new StakeConverter(); + case COL.TOKEN_PURCHASE: + return new TokenPurchaseConverter(); + case COL.MNEMONIC: + return new MnemonicConverter(); + case COL.NOTIFICATION: + return new NotificationConverter(); + case COL.SYSTEM: + return new SystemConverter(); + case COL.TICKER: + return new TickerConverter(); + case COL.SOON_SNAP: + return new SoonSnapshotConverter(); + case COL.MILESTONE: + return new MilestoneConverter(); + case COL.MILESTONE_RMS: + return new MilestoneConverter(); + case COL.MILESTONE_SMR: + return new MilestoneConverter(); + default: + throw Error(`Invalid paramas ${col}, ${subCol}`); + } + } + if (col === COL.SPACE) { + if (subCol === SUB_COL.MEMBERS) return new SpaceMemberConverter(); + if (subCol === SUB_COL.BLOCKED_MEMBERS) return new SpaceMemberConverter(); + if (subCol === SUB_COL.KNOCKING_MEMBERS) return new SpaceMemberConverter(); + if (subCol === SUB_COL.GUARDIANS) return new SpaceMemberConverter(); + } + if (col === COL.AWARD) { + if (subCol === SUB_COL.OWNERS) return new AwardOwnerConverter(); + if (subCol === SUB_COL.PARTICIPANTS) return new AwardParticipantConverter(); + } + if (col === COL.PROPOSAL) { + if (subCol === SUB_COL.OWNERS) return new ProposalOwnerConverter(); + if (subCol === SUB_COL.MEMBERS) return new ProposalMemberConverter(); + } + if (col === COL.TOKEN) { + if (subCol === SUB_COL.DISTRIBUTION) return new TokenDistributionConverter(); + if (subCol === SUB_COL.STATS) return new TokenStatsConverter(); + if (subCol === SUB_COL.RANKS) return new TokenRankConverter(); + if (subCol === SUB_COL.VOTES) return new TokenVotesConverter(); + } + if (col === COL.COLLECTION) { + if (subCol === SUB_COL.STATS) return new CollectionStatsConverter(); + if (subCol === SUB_COL.RANKS) return new CollectionRankConverter(); + if (subCol === SUB_COL.VOTES) return new CollectionVotesConverter(); + } + if (col === COL.PROJECT) { + if (subCol === SUB_COL.ADMINS) return new ProjectAdminConverter(); + if (subCol === SUB_COL._API_KEY) return new ProjectApiKeyConverter(); + } + if (subCol === SUB_COL.TRANSACTIONS) { + return new MilestoneTransactionConverter(); + } + throw Error(`No converter ${col}, ${subCol}`); + }; + + collection = ( + col: C, + colId?: string, + subCol?: S, + ): IColType => { + const converter: Converter = this.getConverter(col, subCol); + if (colId && subCol) { + if (col === COL.TOKEN && subCol === SUB_COL.DISTRIBUTION) { + return new PgTokenDistributionCollection( + this.con, + col, + colId!, + subCol, + converter, + ) as unknown as IColType; + } + return new ISubCollection(this.con, col, colId, subCol, converter) as IColType; + } + + if (col === COL.AIRDROP) { + return new PgAirdropCollection(this.con, col, converter) as IColType; + } + if (col === COL.COLLECTION) { + return new PgCollectionCollection(this.con, col, converter) as IColType; + } + if (col === COL.STAKE) { + return new PgStakeCollection(this.con, col, converter) as unknown as IColType; + } + + return new ICollection(this.con, col, converter) as IColType; + }; + + doc = ( + col: C, + colId: string, + subCol?: S, + subColId?: string, + ): IDocType => { + return subCol && subColId + ? (this.collection(col, colId, subCol)!.doc(subColId) as IDocType) + : (this.collection(col)!.doc(colId) as IDocType); + }; + + batch = (): IBatch => new PgBatch(this.con); + + runTransaction = async (func: (transaction: ITransaction) => Promise) => { + for (let i = 0; i < 240; ++i) { + let con: Knex.Transaction | undefined = undefined; + try { + con = await getKnexTran().transaction(); + const trx = new PgRunTransaction(con); + const result = await func(trx); + if (trx.allLocksAquired) { + await con.commit(); + return result; + } else { + await con.rollback(); + await new Promise((resolve) => setTimeout(resolve, Math.floor(Math.random() * 300))); + } + } catch (err) { + await con?.rollback(); + throw err; + } + } + throw { code: 500, key: 'Failed to execute transaction' }; + }; + + inc = (value: number) => new Increment(value); + + arrayUnion = (value: T) => new ArrayUnion(value); + + arrayRemove = (value: T) => new ArrayRemove(value); + + destroy = async () => { + const promises: any[] = [knex?.destroy(), knextran?.destroy()]; + + for (const subs of Object.values(subscriptions)) { + promises.push((await subs).delete()); + } + + await Promise.allSettled(promises); + }; + + getCon = () => this.con; +} + +export const pgDateToTimestamp = (date: Date | string | undefined) => + date ? Timestamp.fromDate(dayjs(date).toDate()) : undefined; + +enum BatchAction { + C = 'create', + U = 'update', + UPS = 'upsert', + D = 'delete', +} + +export class PgBatch implements IBatch { + private changes: { docRef: IDocument; data: any; action: BatchAction }[] = []; + constructor(private readonly con: Knex) {} + + create = (docRef: IDocument, data: C) => { + this.changes.push({ docRef, data, action: BatchAction.C }); + }; + + update = (docRef: IDocument, data: U) => { + this.changes.push({ docRef, data, action: BatchAction.U }); + }; + + upsert = (docRef: IDocument, data: U) => { + this.changes.push({ docRef, data, action: BatchAction.UPS }); + }; + + delete = (docRef: IDocument) => { + this.changes.push({ docRef, data: undefined, action: BatchAction.D }); + }; + + commit = async () => { + const trx = await this.con.transaction(); + try { + for (const { docRef, data, action } of this.changes) { + switch (action) { + case BatchAction.C: + await docRef.useTransaction(trx, (doc) => doc.create(data)); + break; + case BatchAction.U: + await docRef.useTransaction(trx, (doc) => doc.update(data)); + break; + case BatchAction.UPS: + await docRef.useTransaction(trx, (doc) => doc.upsert(data)); + break; + case BatchAction.D: + await docRef.useTransaction(trx, (doc) => doc.delete()); + break; + } + } + await trx.commit(); + } catch (err) { + await trx.rollback(); + throw err; + } + }; +} + +export class PgRunTransaction implements ITransaction { + public allLocksAquired = true; + constructor(private readonly trx: Knex.Transaction) {} + + create = async ( + docRef: IDocument, + data: C, + ) => { + if (!this.allLocksAquired) { + return; + } + await docRef.useTransaction(this.trx, (doc) => doc.create(data)); + }; + + update = async ( + docRef: IDocument, + data: U, + ) => { + if (!this.allLocksAquired) { + return; + } + await docRef.useTransaction(this.trx, (doc) => doc.update(data)); + }; + + upsert = async ( + docRef: IDocument, + data: U, + ) => { + if (!this.allLocksAquired) { + return; + } + await docRef.useTransaction(this.trx, (doc) => doc.upsert(data)); + }; + + delete = async (docRef: IDocument) => { + if (!this.allLocksAquired) { + return; + } + await docRef.useTransaction(this.trx, (doc) => doc.delete()); + }; + + get = async (docRef: IDocument) => { + if (!this.allLocksAquired) { + return await docRef.get(); + } + try { + return await docRef.useTransaction(this.trx, (doc) => doc.get()); + } catch (err) { + this.allLocksAquired = false; + return await docRef.get(); + } + }; + + getAll = async (...docRefs: IDocument[]) => { + if (!this.allLocksAquired) { + return []; + } + const promises = docRefs.map((docRef) => this.get(docRef)); + return await Promise.all(promises); + }; +} diff --git a/packages/database/src/pg/impl/pubsub.ts b/packages/database/src/pg/impl/pubsub.ts new file mode 100644 index 0000000000..d6923e5eed --- /dev/null +++ b/packages/database/src/pg/impl/pubsub.ts @@ -0,0 +1,20 @@ +import { PubSub, Subscription } from '@google-cloud/pubsub'; + +const pubSub = new PubSub(); + +const subsName = Math.random().toString().replace('0.', 'subs'); + +export const subscriptions: { [key: string]: Promise } = {}; + +export const getSubscription = (table: string) => { + if (!subscriptions[table]) { + subscriptions[table] = new Promise(async (res) => { + const topic = pubSub.topic('onupsert'); + const [subscription] = await topic.createSubscription(subsName, { + filter: `attributes.table="${table}"`, + }); + res(subscription); + }); + } + return subscriptions[table]; +}; diff --git a/packages/database/src/pg/impl/tables/airdrop.ts b/packages/database/src/pg/impl/tables/airdrop.ts new file mode 100644 index 0000000000..3281a9c365 --- /dev/null +++ b/packages/database/src/pg/impl/tables/airdrop.ts @@ -0,0 +1,62 @@ +import { StakeType, TokenDrop, TokenDropStatus } from '@build-5/interfaces'; +import { head } from 'lodash'; +import { Converter, ICollection } from '../../interfaces'; +import { PgAirdrop } from '../../models'; +import { PgAirdropUpdate } from '../../models/airdrop_update'; +import { PgStakeType, PgTokenDropStatus } from '../../models/enums'; +import { convertEnum, removeNulls } from '../common'; +import { pgDateToTimestamp } from '../postgres'; + +export class PgAirdropCollection extends ICollection { + getUnclaimedAirdropTotalValue = async (token: string) => { + const snap = await this.con(this.table) + .select(this.con.raw('SUM(count)::integer as count')) + .where({ token, status: PgTokenDropStatus.UNCLAIMED }); + return head(snap).count || 0; + }; +} + +export class AirdropConverter implements Converter { + toPg = (airdrop: TokenDrop): PgAirdrop => ({ + uid: airdrop.uid, + project: airdrop.project, + createdOn: airdrop.createdOn?.toDate(), + updatedOn: airdrop.updatedOn?.toDate(), + createdBy: airdrop.createdBy, + + member: airdrop.member, + token: airdrop.token, + award: airdrop.award, + vestingAt: airdrop.vestingAt?.toDate(), + count: airdrop.count, + status: convertEnum(airdrop.status, TokenDropStatus, PgTokenDropStatus), + orderId: airdrop.orderId, + billPaymentId: airdrop.billPaymentId, + sourceAddress: airdrop.sourceAddress, + stakeRewardId: airdrop.stakeRewardId, + stakeType: convertEnum(airdrop.stakeType, StakeType, PgStakeType), + isBaseToken: airdrop.isBaseToken, + }); + + fromPg = (pg: PgAirdrop): TokenDrop => + removeNulls({ + uid: pg.uid, + project: pg.project, + createdOn: pgDateToTimestamp(pg.createdOn), + updatedOn: pgDateToTimestamp(pg.updatedOn), + createdBy: pg.createdBy || '', + + member: pg.member!, + token: pg.token!, + award: pg.award, + vestingAt: pgDateToTimestamp(pg.vestingAt)!, + count: pg.count!, + status: convertEnum(pg.status, PgTokenDropStatus, TokenDropStatus)!, + orderId: pg.orderId, + billPaymentId: pg.billPaymentId, + sourceAddress: pg.sourceAddress, + stakeRewardId: pg.stakeRewardId, + stakeType: convertEnum(pg.stakeType, PgStakeType, StakeType), + isBaseToken: pg.isBaseToken, + }); +} diff --git a/packages/database/src/pg/impl/tables/auction.ts b/packages/database/src/pg/impl/tables/auction.ts new file mode 100644 index 0000000000..93eafc8737 --- /dev/null +++ b/packages/database/src/pg/impl/tables/auction.ts @@ -0,0 +1,64 @@ +import { Auction, AuctionBid, AuctionType, Network } from '@build-5/interfaces'; +import { Converter } from '../../interfaces'; +import { PgAuction } from '../../models'; +import { PgAuctionType, PgNetwork } from '../../models/enums'; +import { convertEnum, removeNulls } from '../common'; +import { pgDateToTimestamp } from '../postgres'; + +export class AuctionConverter implements Converter { + toPg = (auction: Auction): PgAuction => ({ + uid: auction.uid, + project: auction.project, + createdOn: auction.createdOn?.toDate(), + updatedOn: auction.updatedOn?.toDate(), + createdBy: auction.createdBy, + space: auction.space, + auctionFrom: auction.auctionFrom?.toDate(), + auctionTo: auction.auctionTo?.toDate(), + auctionLength: auction.auctionLength, + extendedAuctionTo: auction.extendedAuctionTo?.toDate(), + extendedAuctionLength: auction.extendedAuctionLength || undefined, + extendAuctionWithin: auction.extendAuctionWithin || undefined, + auctionFloorPrice: auction.auctionFloorPrice, + minimalBidIncrement: auction.minimalBidIncrement, + auctionHighestBidder: auction.auctionHighestBidder, + auctionHighestBid: auction.auctionHighestBid, + maxBids: auction.maxBids, + type: convertEnum(auction.type, AuctionType, PgAuctionType), + network: convertEnum(auction.network, Network, PgNetwork), + nftId: auction.nftId, + targetAddress: auction.targetAddress, + active: auction.active, + topUpBased: auction.topUpBased, + bids: JSON.stringify(auction.bids) as any, + }); + + fromPg = (pg: PgAuction): Auction => + removeNulls({ + uid: pg.uid, + project: pg.project, + createdOn: pgDateToTimestamp(pg.createdOn), + updatedOn: pgDateToTimestamp(pg.updatedOn), + createdBy: pg.createdBy || '', + + space: pg.space!, + auctionFrom: pgDateToTimestamp(pg.auctionFrom)!, + auctionTo: pgDateToTimestamp(pg.auctionTo)!, + auctionLength: pg.auctionLength || 0, + extendedAuctionTo: pgDateToTimestamp(pg.extendedAuctionTo), + extendedAuctionLength: pg.extendedAuctionLength, + extendAuctionWithin: pg.extendAuctionWithin, + auctionFloorPrice: pg.auctionFloorPrice || 0, + minimalBidIncrement: pg.minimalBidIncrement || 0, + bids: pg.bids as unknown as AuctionBid[], + auctionHighestBidder: pg.auctionHighestBidder, + auctionHighestBid: pg.auctionHighestBid, + maxBids: pg.maxBids || 0, + type: convertEnum(pg.type, PgAuctionType, AuctionType)!, + network: convertEnum(pg.network, PgNetwork, Network)!, + nftId: pg.nftId, + targetAddress: pg.targetAddress, + active: pg.active || false, + topUpBased: pg.topUpBased, + }); +} diff --git a/packages/database/src/pg/impl/tables/award.ts b/packages/database/src/pg/impl/tables/award.ts new file mode 100644 index 0000000000..97dd91f1b9 --- /dev/null +++ b/packages/database/src/pg/impl/tables/award.ts @@ -0,0 +1,108 @@ +import { Award, AwardBadgeType, MediaStatus, Network } from '@build-5/interfaces'; +import { Converter } from '../../interfaces'; +import { PgAward } from '../../models'; +import { PgAwardBadgeType, PgMediaStatus, PgNetwork } from '../../models/enums'; +import { convertEnum, removeNulls } from '../common'; +import { pgDateToTimestamp } from '../postgres'; + +export class AwardConverter implements Converter { + toPg = (award: Award): PgAward => ({ + uid: award.uid, + project: award.project, + createdOn: award.createdOn?.toDate(), + updatedOn: award.updatedOn?.toDate(), + createdBy: award.createdBy, + + name: award.name, + description: award.description, + space: award.space, + endDate: award.endDate?.toDate(), + issued: award.issued, + badgesMinted: award.badgesMinted, + approved: award.approved, + rejected: award.rejected, + completed: award.completed, + network: convertEnum(award.network, Network, PgNetwork), + aliasStorageDeposit: award.aliasStorageDeposit, + collectionStorageDeposit: award.collectionStorageDeposit, + nttStorageDeposit: award.nttStorageDeposit, + nativeTokenStorageDeposit: award.nativeTokenStorageDeposit, + funded: award.funded, + fundingAddress: award.fundingAddress, + fundedBy: award.fundedBy, + address: award.address, + airdropClaimed: award.airdropClaimed, + aliasBlockId: award.aliasBlockId, + aliasId: award.aliasId, + collectionBlockId: award.collectionBlockId, + collectionId: award.collectionId, + mediaStatus: convertEnum(award.mediaStatus, MediaStatus, PgMediaStatus), + mediaUploadErrorCount: award.mediaUploadErrorCount, + isLegacy: award.isLegacy, + badge_name: award.badge.name, + badge_description: award.badge?.description, + badge_total: award.badge?.total, + badge_type: convertEnum(award.badge?.type, AwardBadgeType, PgAwardBadgeType), + badge_tokenReward: award.badge?.tokenReward, + badge_tokenUid: award.badge?.tokenUid, + badge_tokenId: award.badge?.tokenId, + badge_tokenSymbol: award.badge?.tokenSymbol, + badge_image: award.badge?.image, + badge_ipfsMedia: award.badge?.ipfsMedia, + badge_ipfsMetadata: award.badge?.ipfsMetadata, + badge_ipfsRoot: award.badge?.ipfsRoot, + badge_lockTime: award.badge?.lockTime, + }); + + fromPg = (pg: PgAward): Award => + removeNulls({ + uid: pg.uid, + project: pg.project, + createdOn: pgDateToTimestamp(pg.createdOn), + updatedOn: pgDateToTimestamp(pg.updatedOn), + createdBy: pg.createdBy || '', + + name: pg.name || '', + description: pg.description || '', + space: pg.space || '', + endDate: pgDateToTimestamp(pg.endDate)!, + badge: { + name: pg.badge_name!, + description: pg.badge_description!, + total: pg.badge_total!, + type: convertEnum(pg.badge_type, PgAwardBadgeType, AwardBadgeType)!, + tokenReward: pg.badge_tokenReward!, + tokenUid: pg.badge_tokenUid!, + tokenId: pg.badge_tokenId, + tokenSymbol: pg.badge_tokenSymbol!, + image: pg.badge_image, + ipfsMedia: pg.badge_ipfsMedia, + ipfsMetadata: pg.badge_ipfsMetadata, + ipfsRoot: pg.badge_ipfsRoot, + lockTime: pg.badge_lockTime || 0, + }, + + issued: pg.issued!, + badgesMinted: pg.badgesMinted!, + approved: pg.approved!, + rejected: pg.rejected!, + completed: pg.completed!, + network: convertEnum(pg.network, PgNetwork, Network)!, + aliasStorageDeposit: pg.aliasStorageDeposit!, + collectionStorageDeposit: pg.collectionStorageDeposit!, + nttStorageDeposit: pg.nttStorageDeposit!, + nativeTokenStorageDeposit: pg.nativeTokenStorageDeposit!, + funded: pg.funded!, + fundedBy: pg.fundedBy, + fundingAddress: pg.fundingAddress, + address: pg.address, + airdropClaimed: pg.airdropClaimed, + aliasBlockId: pg.aliasBlockId, + aliasId: pg.aliasId, + collectionBlockId: pg.collectionBlockId, + collectionId: pg.collectionId, + mediaStatus: convertEnum(pg.mediaStatus, PgMediaStatus, MediaStatus), + mediaUploadErrorCount: pg.mediaUploadErrorCount, + isLegacy: pg.isLegacy, + }); +} diff --git a/packages/database/src/pg/impl/tables/award_owner.ts b/packages/database/src/pg/impl/tables/award_owner.ts new file mode 100644 index 0000000000..e02b3d641e --- /dev/null +++ b/packages/database/src/pg/impl/tables/award_owner.ts @@ -0,0 +1,23 @@ +import { AwardOwner, COL } from '@build-5/interfaces'; +import { Converter } from '../../interfaces'; +import { PgAwardOwners } from '../../models'; +import { removeNulls } from '../common'; +import { pgDateToTimestamp } from '../postgres'; + +export class AwardOwnerConverter implements Converter { + toPg = (awardOwner: AwardOwner): PgAwardOwners => ({ + uid: awardOwner.uid, + project: awardOwner.project, + createdOn: awardOwner.createdOn?.toDate(), + parentId: awardOwner.parentId, + }); + + fromPg = (pg: PgAwardOwners): AwardOwner => + removeNulls({ + project: pg.project, + parentId: pg.parentId, + parentCol: COL.AWARD, + uid: pg.uid, + createdOn: pgDateToTimestamp(pg.createdOn), + }); +} diff --git a/packages/database/src/pg/impl/tables/award_participant.ts b/packages/database/src/pg/impl/tables/award_participant.ts new file mode 100644 index 0000000000..1019c35256 --- /dev/null +++ b/packages/database/src/pg/impl/tables/award_participant.ts @@ -0,0 +1,31 @@ +import { AwardParticipant, COL } from '@build-5/interfaces'; +import { Converter } from '../../interfaces'; +import { PgAwardParticipants } from '../../models'; +import { removeNulls } from '../common'; +import { pgDateToTimestamp } from '../postgres'; + +export class AwardParticipantConverter implements Converter { + toPg = (awardParticipant: AwardParticipant): PgAwardParticipants => ({ + uid: awardParticipant.uid, + project: awardParticipant.project, + createdOn: awardParticipant.createdOn?.toDate(), + parentId: awardParticipant.parentId, + comment: awardParticipant.comment || undefined, + completed: awardParticipant.completed, + count: awardParticipant.count, + tokenReward: awardParticipant.tokenReward, + }); + + fromPg = (pg: PgAwardParticipants): AwardParticipant => + removeNulls({ + uid: pg.uid, + project: pg.project, + parentId: pg.parentId, + parentCol: COL.AWARD, + comment: pg.comment, + completed: pg.completed || false, + createdOn: pgDateToTimestamp(pg.createdOn)!, + count: pg.count || 0, + tokenReward: pg.tokenReward || 0, + }); +} diff --git a/packages/database/src/pg/impl/tables/collection.ts b/packages/database/src/pg/impl/tables/collection.ts new file mode 100644 index 0000000000..9e687bbdae --- /dev/null +++ b/packages/database/src/pg/impl/tables/collection.ts @@ -0,0 +1,206 @@ +import { + Access, + Categories, + Collection, + CollectionStatus, + CollectionType, + DiscountLine, + MediaStatus, + Network, + UnsoldMintingOptions, +} from '@build-5/interfaces'; +import { get } from 'lodash'; +import { Converter, ICollection } from '../../interfaces'; +import { PgCollection } from '../../models'; +import { PgCollectionUpdate } from '../../models/collection_update'; +import { + PgAccess, + PgCategories, + PgCollectionStatus, + PgCollectionType, + PgMediaStatus, + PgNetwork, + PgUnsoldMintingOptions, +} from '../../models/enums'; +import { convertEnum, removeNulls } from '../common'; +import { pgDateToTimestamp } from '../postgres'; + +export class PgCollectionCollection extends ICollection< + Collection, + PgCollection, + PgCollectionUpdate +> { + updateFloorPrie = async () => { + await this.con(this.table).update({ + floorPrice: this.con.raw(`( + SELECT MIN("availablePrice") + FROM nft + WHERE collection = collection.uid AND + nft."saleAccess" = 'open' AND + available IN ('sale', 'auction_and_sale') + )`), + }); + }; +} + +export class CollectionConverter implements Converter { + toPg = (collection: Collection): PgCollection => ({ + uid: collection.uid, + project: collection.project, + createdOn: collection.createdOn?.toDate(), + updatedOn: collection.updatedOn?.toDate(), + createdBy: collection.createdBy, + name: collection.name, + description: collection.description, + bannerUrl: collection.bannerUrl, + royaltiesFee: collection.royaltiesFee, + royaltiesSpace: collection.royaltiesSpace, + total: collection.total, + totalTrades: collection.totalTrades, + lastTradedOn: collection.lastTradedOn?.toDate(), + sold: collection.sold, + discord: collection.discord, + url: collection.url, + twitter: collection.twitter, + approved: collection.approved, + rejected: collection.rejected, + limitedEdition: collection.limitedEdition, + ipfsMedia: collection.ipfsMedia, + ipfsMetadata: collection.ipfsMetadata, + ipfsRoot: collection.ipfsRoot, + category: convertEnum(collection.category, Categories, PgCategories), + type: convertEnum(collection.type, CollectionType, PgCollectionType), + access: convertEnum(collection.access, Access, PgAccess), + accessAwards: collection.accessAwards, + accessCollections: collection.accessCollections, + space: collection.space, + availableFrom: collection.availableFrom?.toDate(), + price: collection.price, + availablePrice: collection.availablePrice, + onePerMemberOnly: collection.onePerMemberOnly, + placeholderNft: collection.placeholderNft, + placeholderUrl: collection.placeholderUrl, + status: convertEnum(collection.status, CollectionStatus, PgCollectionStatus), + mintingData_address: collection.mintingData?.address, + mintingData_network: convertEnum(collection.mintingData?.network, Network, PgNetwork), + mintingData_mintedOn: collection.mintingData?.mintedOn?.toDate(), + mintingData_mintedBy: collection.mintingData?.mintedBy, + mintingData_blockId: collection.mintingData?.blockId, + mintingData_nftId: collection.mintingData?.nftId, + mintingData_storageDeposit: collection.mintingData?.storageDeposit, + mintingData_aliasBlockId: collection.mintingData?.aliasBlockId, + mintingData_aliasId: collection.mintingData?.aliasId, + mintingData_aliasStorageDeposit: collection.mintingData?.aliasStorageDeposit, + mintingData_mintingOrderId: collection.mintingData?.mintingOrderId, + mintingData_nftsToMint: collection.mintingData?.nftsToMint, + mintingData_nftMediaToUpload: collection.mintingData?.nftMediaToUpload, + mintingData_nftMediaToPrepare: collection.mintingData?.nftMediaToPrepare, + mintingData_unsoldMintingOptions: convertEnum( + collection.mintingData?.unsoldMintingOptions, + UnsoldMintingOptions, + PgUnsoldMintingOptions, + ), + mintingData_newPrice: collection.mintingData?.newPrice, + mintingData_nftsStorageDeposit: collection.mintingData?.nftsStorageDeposit, + rankCount: collection.rankCount, + rankSum: collection.rankSum, + rankAvg: collection.rankAvg, + mediaStatus: convertEnum(collection.mediaStatus, MediaStatus, PgMediaStatus), + mediaUploadErrorCount: collection.mediaUploadErrorCount, + stakedNft: collection.stakedNft, + nftsOnSale: collection.nftsOnSale, + nftsOnAuction: collection.nftsOnAuction, + availableNfts: collection.availableNfts, + floorPrice: collection.floorPrice, + votes_upvotes: collection.votes?.upvotes, + votes_downvotes: collection.votes?.downvotes, + votes_voteDiff: collection.votes?.voteDiff, + }); + + fromPg = (pg: PgCollection): Collection => + removeNulls({ + uid: pg.uid, + project: pg.project, + createdOn: pgDateToTimestamp(pg.createdOn), + updatedOn: pgDateToTimestamp(pg.updatedOn), + createdBy: pg.createdBy, + name: pg.name || '', + description: pg.description || '', + bannerUrl: pg.bannerUrl || '', + royaltiesFee: pg.royaltiesFee || 0, + royaltiesSpace: pg.royaltiesSpace, + discounts: ((pg.discounts as any) || []).map( + (d: any) => + ({ + tokenUid: get(d, 'tokenUid', ''), + tokenSymbol: get(d, 'tokenSymbol', ''), + tokenReward: get(d, 'tokenReward', 0), + amount: get(d, 'amount', 0), + }) as DiscountLine, + ), + total: pg.total || 0, + totalTrades: pg.totalTrades || 0, + lastTradedOn: pgDateToTimestamp(pg.lastTradedOn) || null, + sold: pg.sold || 0, + discord: pg.discord || '', + url: pg.url || '', + twitter: pg.twitter || '', + approved: pg.approved || false, + rejected: pg.rejected || false, + limitedEdition: pg.limitedEdition, + ipfsMedia: pg.ipfsMedia, + ipfsMetadata: pg.ipfsMetadata, + ipfsRoot: pg.ipfsRoot, + category: convertEnum(pg.category, PgCategories, Categories)!, + type: convertEnum(pg.type, PgCollectionType, CollectionType)! as CollectionType, + access: convertEnum(pg.access, PgAccess, Access)! as Access, + accessAwards: pg.accessAwards || [], + accessCollections: pg.accessCollections || [], + space: pg.space, + availableFrom: pgDateToTimestamp(pg.availableFrom)!, + price: pg.price || 0, + availablePrice: pg.availablePrice || 0, + onePerMemberOnly: pg.onePerMemberOnly || false, + placeholderNft: pg.placeholderNft || '', + placeholderUrl: pg.placeholderUrl || '', + status: convertEnum(pg.status, PgCollectionStatus, CollectionStatus), + mintingData: { + address: pg.mintingData_address, + network: convertEnum(pg.mintingData_network, PgNetwork, Network), + mintedOn: pgDateToTimestamp(pg.mintingData_mintedOn), + mintedBy: pg.mintingData_mintedBy, + blockId: pg.mintingData_blockId, + nftId: pg.mintingData_nftId, + storageDeposit: pg.mintingData_storageDeposit, + aliasBlockId: pg.mintingData_aliasBlockId, + aliasId: pg.mintingData_aliasId, + aliasStorageDeposit: pg.mintingData_aliasStorageDeposit, + mintingOrderId: pg.mintingData_mintingOrderId, + nftsToMint: pg.mintingData_nftsToMint, + nftMediaToUpload: pg.mintingData_nftMediaToUpload, + nftMediaToPrepare: pg.mintingData_nftMediaToPrepare, + unsoldMintingOptions: convertEnum( + pg.mintingData_unsoldMintingOptions, + PgUnsoldMintingOptions, + UnsoldMintingOptions, + ), + newPrice: pg.mintingData_newPrice, + nftsStorageDeposit: pg.mintingData_nftsStorageDeposit, + }, + rankCount: pg.rankCount, + rankSum: pg.rankSum, + rankAvg: pg.rankAvg, + mediaStatus: convertEnum(pg.mediaStatus, PgMediaStatus, MediaStatus), + mediaUploadErrorCount: pg.mediaUploadErrorCount, + stakedNft: pg.stakedNft, + nftsOnSale: pg.nftsOnSale, + nftsOnAuction: pg.nftsOnAuction, + availableNfts: pg.availableNfts, + floorPrice: pg.floorPrice, + votes: { + upvotes: pg.votes_upvotes || 0, + downvotes: pg.votes_downvotes || 0, + voteDiff: pg.votes_voteDiff || 0, + }, + }); +} diff --git a/packages/database/src/pg/impl/tables/collection_rank.ts b/packages/database/src/pg/impl/tables/collection_rank.ts new file mode 100644 index 0000000000..4e90b141c4 --- /dev/null +++ b/packages/database/src/pg/impl/tables/collection_rank.ts @@ -0,0 +1,22 @@ +import { COL, Rank } from '@build-5/interfaces'; +import { Converter } from '../../interfaces'; +import { PgCollectionRanks } from '../../models'; +import { removeNulls } from '../common'; + +export class CollectionRankConverter implements Converter { + toPg = (r: Rank): PgCollectionRanks => ({ + uid: r.uid!, + project: r.project, + parentId: r.parentId, + rank: r.rank, + }); + + fromPg = (pg: PgCollectionRanks): Rank => + removeNulls({ + uid: pg.uid, + project: pg.project, + parentId: pg.parentId, + parentCol: COL.COLLECTION, + rank: pg.rank!, + }); +} diff --git a/packages/database/src/pg/impl/tables/collection_stats.ts b/packages/database/src/pg/impl/tables/collection_stats.ts new file mode 100644 index 0000000000..100e6c3e1f --- /dev/null +++ b/packages/database/src/pg/impl/tables/collection_stats.ts @@ -0,0 +1,36 @@ +import { COL, CollectionStats } from '@build-5/interfaces'; +import { Converter } from '../../interfaces'; +import { PgCollectionStats } from '../../models'; +import { removeNulls } from '../common'; + +export class CollectionStatsConverter implements Converter { + toPg = (s: CollectionStats): PgCollectionStats => ({ + uid: s.uid!, + project: s.project, + parentId: s.parentId, + votes_upvotes: s.votes?.upvotes, + votes_downvotes: s.votes?.downvotes, + votes_voteDiff: s.votes?.voteDiff, + ranks_count: s.ranks?.count, + ranks_sum: s.ranks?.sum, + ranks_avg: s.ranks?.avg, + }); + + fromPg = (pg: PgCollectionStats): CollectionStats => + removeNulls({ + uid: pg.uid, + project: pg.project, + parentId: pg.parentId, + parentCol: COL.COLLECTION, + votes: { + upvotes: pg.votes_upvotes || 0, + downvotes: pg.votes_downvotes || 0, + voteDiff: pg.votes_voteDiff || 0, + }, + ranks: { + count: pg.ranks_count || 0, + sum: pg.ranks_sum || 0, + avg: pg.ranks_avg || 0, + }, + }); +} diff --git a/packages/database/src/pg/impl/tables/collection_vote.ts b/packages/database/src/pg/impl/tables/collection_vote.ts new file mode 100644 index 0000000000..4261caa62e --- /dev/null +++ b/packages/database/src/pg/impl/tables/collection_vote.ts @@ -0,0 +1,22 @@ +import { COL, Vote } from '@build-5/interfaces'; +import { Converter } from '../../interfaces'; +import { PgCollectionVotes } from '../../models'; +import { removeNulls } from '../common'; + +export class CollectionVotesConverter implements Converter { + toPg = (r: Vote): PgCollectionVotes => ({ + uid: r.uid!, + project: r.project, + parentId: r.parentId, + direction: r.direction, + }); + + fromPg = (pg: PgCollectionVotes): Vote => + removeNulls({ + uid: pg.uid, + project: pg.project, + parentId: pg.parentId, + parentCol: COL.COLLECTION, + direction: pg.direction! as 1 | -1, + }); +} diff --git a/packages/database/src/pg/impl/tables/member.ts b/packages/database/src/pg/impl/tables/member.ts new file mode 100644 index 0000000000..70cb339db5 --- /dev/null +++ b/packages/database/src/pg/impl/tables/member.ts @@ -0,0 +1,67 @@ +import { Member, Network } from '@build-5/interfaces'; +import { Converter } from '../../interfaces'; +import { PgMember } from '../../models'; +import { removeNulls } from '../common'; +import { pgDateToTimestamp } from '../postgres'; + +export class MemberConverter implements Converter { + toPg = (member: Member): PgMember => ({ + uid: member.uid, + project: member.project, + createdOn: member.createdOn?.toDate(), + updatedOn: member.updatedOn?.toDate(), + createdBy: member.createdBy, + nonce: member.nonce, + name: member.name, + about: member.about, + avatarNft: member.avatarNft, + avatar: member.avatar, + discord: member.discord, + twitter: member.twitter, + github: member.github, + + smrAddress: (member.validatedAddress || {})[Network.SMR], + rmsAddress: (member.validatedAddress || {})[Network.RMS], + iotaAddress: (member.validatedAddress || {})[Network.IOTA], + atoiAddress: (member.validatedAddress || {})[Network.ATOI], + + prevValidatedAddresses: member.prevValidatedAddresses, + tokenTradingFeePercentage: member.tokenTradingFeePercentage, + tokenPurchaseFeePercentage: member.tokenPurchaseFeePercentage, + awardsCompleted: member.awardsCompleted, + + spaces: member.spaces, + }); + + fromPg = (member: PgMember): Member => + removeNulls({ + uid: member.uid, + project: member.project || '', + createdOn: pgDateToTimestamp(member.createdOn), + updatedOn: pgDateToTimestamp(member.updatedOn), + createdBy: member.createdBy || '', + nonce: member.nonce || '', + name: member.name || '', + about: member.about || '', + avatarNft: member.avatarNft || '', + avatar: member.avatar || '', + discord: member.discord || '', + twitter: member.twitter || '', + github: member.github || '', + + validatedAddress: { + [Network.SMR]: member.smrAddress || '', + [Network.RMS]: member.rmsAddress || '', + [Network.IOTA]: member.iotaAddress || '', + [Network.ATOI]: member.atoiAddress || '', + }, + + prevValidatedAddresses: member.prevValidatedAddresses, + + spaces: member.spaces as any, + + tokenTradingFeePercentage: member.tokenTradingFeePercentage, + tokenPurchaseFeePercentage: member.tokenPurchaseFeePercentage, + awardsCompleted: member.awardsCompleted, + }); +} diff --git a/packages/database/src/pg/impl/tables/milestone.ts b/packages/database/src/pg/impl/tables/milestone.ts new file mode 100644 index 0000000000..2056aad304 --- /dev/null +++ b/packages/database/src/pg/impl/tables/milestone.ts @@ -0,0 +1,36 @@ +import { Milestone } from '@build-5/interfaces'; +import { get } from 'lodash'; +import { Converter } from '../../interfaces'; +import { PgMilestone } from '../../models'; +import { pgDateToTimestamp } from '../postgres'; + +export class MilestoneConverter implements Converter { + toPg = (milestone: Milestone): PgMilestone => ({ + uid: get(milestone, 'uid', ''), + createdOn: milestone.createdOn?.toDate(), + completed: milestone.completed, + completedOn: milestone.completedOn.toDate(), + listenerNodeId: milestone.listenerNodeId, + milestone: milestone.milestone, + milestoneTimestamp: milestone.milestoneTimestamp.toDate(), + trxConflictCount: milestone.trxConflictCount, + trxFailedCount: milestone.trxFailedCount, + trxValidCount: milestone.trxValidCount, + }); + + fromPg = (pg: PgMilestone): Milestone => ({ + createdOn: pgDateToTimestamp(pg.createdOn)!, + completedOn: pgDateToTimestamp(pg.completedOn)!, + milestone: pg.milestone!, + completed: pg.completed!, + listenerNodeId: pg.listenerNodeId!, + milestoneTimestamp: pgDateToTimestamp(pg.milestoneTimestamp)!, + trxConflictCount: pg.trxConflictCount!, + trxFailedCount: pg.trxFailedCount!, + trxValidCount: pg.trxValidCount!, + + transactions: {}, + cmi: 0, + processed: true, + }); +} diff --git a/packages/database/src/pg/impl/tables/milestone_transactions.ts b/packages/database/src/pg/impl/tables/milestone_transactions.ts new file mode 100644 index 0000000000..bc0258d306 --- /dev/null +++ b/packages/database/src/pg/impl/tables/milestone_transactions.ts @@ -0,0 +1,53 @@ +import { Timestamp } from '@build-5/interfaces'; +import { Converter } from '../../interfaces'; +import { PgMilestoneTransactions } from '../../models'; +import { pgDateToTimestamp } from '../postgres'; + +export interface MilestoneTransactions { + uid: string; + parentId: string; + + createdOn: Timestamp; + updatedOn: Timestamp; + + PayloadSize: number; + + blockId: string; + milestone: number; + payload: any; + processed: boolean; + processedOn: Timestamp; +} + +export class MilestoneTransactionConverter + implements Converter +{ + toPg = (mt: MilestoneTransactions): PgMilestoneTransactions => ({ + uid: mt.uid, + parentId: mt.parentId, + createdOn: mt.createdOn.toDate(), + updatedOn: mt.updatedOn.toDate(), + PayloadSize: mt.PayloadSize, + blockId: mt.blockId, + milestone: mt.milestone, + payload: JSON.stringify(mt.payload) as any, + processed: mt.processed, + processedOn: mt.processedOn.toDate(), + }); + + fromPg = (pg: PgMilestoneTransactions): MilestoneTransactions => ({ + uid: pg.uid, + parentId: pg.parentId, + + createdOn: pgDateToTimestamp(pg.createdOn)!, + updatedOn: pgDateToTimestamp(pg.updatedOn)!, + + PayloadSize: pg.PayloadSize!, + + blockId: pg.blockId!, + milestone: pg.milestone!, + payload: pg.payload, + processed: pg.processed!, + processedOn: pgDateToTimestamp(pg.processedOn)!, + }); +} diff --git a/packages/database/src/pg/impl/tables/mnemonic.ts b/packages/database/src/pg/impl/tables/mnemonic.ts new file mode 100644 index 0000000000..533acab487 --- /dev/null +++ b/packages/database/src/pg/impl/tables/mnemonic.ts @@ -0,0 +1,39 @@ +import { Mnemonic, Network } from '@build-5/interfaces'; +import { Converter } from '../../interfaces'; +import { PgMnemonic } from '../../models'; +import { PgNetwork } from '../../models/enums'; +import { convertEnum, removeNulls } from '../common'; +import { pgDateToTimestamp } from '../postgres'; + +export class MnemonicConverter implements Converter { + toPg = (mnemonic: Mnemonic): PgMnemonic => ({ + uid: mnemonic.uid, + project: mnemonic.project, + createdOn: mnemonic.createdOn?.toDate(), + updatedOn: mnemonic.updatedOn?.toDate(), + createdBy: mnemonic.createdBy, + + mnemonic: mnemonic.mnemonic, + network: convertEnum(mnemonic.network, Network, PgNetwork), + lockedBy: mnemonic.lockedBy, + consumedOutputIds: mnemonic.consumedOutputIds, + consumedNftOutputIds: mnemonic.consumedNftOutputIds, + consumedAliasOutputIds: mnemonic.consumedAliasOutputIds, + }); + + fromPg = (pg: PgMnemonic): Mnemonic => + removeNulls({ + uid: pg.uid, + project: pg.project, + createdOn: pgDateToTimestamp(pg.createdOn), + updatedOn: pgDateToTimestamp(pg.updatedOn), + createdBy: pg.createdBy || '', + + mnemonic: pg.mnemonic, + network: convertEnum(pg.network, PgNetwork, Network), + lockedBy: pg.lockedBy, + consumedOutputIds: pg.consumedOutputIds, + consumedNftOutputIds: pg.consumedNftOutputIds, + consumedAliasOutputIds: pg.consumedAliasOutputIds, + }); +} diff --git a/packages/database/src/pg/impl/tables/nft.ts b/packages/database/src/pg/impl/tables/nft.ts new file mode 100644 index 0000000000..596aabafd8 --- /dev/null +++ b/packages/database/src/pg/impl/tables/nft.ts @@ -0,0 +1,223 @@ +import { + CollectionType, + MediaStatus, + Network, + Nft, + NftAccess, + NftAvailable, + NftStatus, + PropStats, + UnsoldMintingOptions, +} from '@build-5/interfaces'; +import { Converter } from '../../interfaces'; +import { PgNft } from '../../models'; +import { + PgCollectionType, + PgMediaStatus, + PgNetwork, + PgNftAccess, + PgNftAvailable, + PgNftStatus, + PgUnsoldMintingOptions, +} from '../../models/enums'; +import { convertEnum, removeNulls } from '../common'; +import { pgDateToTimestamp } from '../postgres'; + +export class NftConverter implements Converter { + toPg = (nft: Nft): PgNft => ({ + uid: nft.uid, + project: nft.project, + createdOn: nft.createdOn?.toDate(), + updatedOn: nft.updatedOn?.toDate(), + createdBy: nft.createdBy, + name: nft.name, + description: nft.description, + collection: nft.collection, + owner: nft.owner, + isOwned: nft.isOwned, + media: nft.media, + ipfsMedia: nft.ipfsMedia, + ipfsMetadata: nft.ipfsMetadata, + ipfsRoot: nft.ipfsRoot, + saleAccess: convertEnum(nft.saleAccess, NftAccess, PgNftAccess), + saleAccessMembers: nft.saleAccessMembers, + available: convertEnum(nft.available, NftAvailable, PgNftAvailable), + availableFrom: nft.availableFrom?.toDate(), + auctionFrom: nft.auctionFrom?.toDate(), + auctionTo: nft.auctionTo?.toDate(), + extendedAuctionTo: nft.extendedAuctionTo?.toDate(), + auctionHighestBid: nft.auctionHighestBid || 0, + auctionHighestBidder: nft.auctionHighestBidder || '', + price: nft.price, + totalTrades: nft.totalTrades, + lastTradedOn: nft.lastTradedOn?.toDate(), + availablePrice: nft.availablePrice || 0, + auctionFloorPrice: nft.auctionFloorPrice || 0, + auctionLength: nft.auctionLength || 0, + extendedAuctionLength: nft.extendedAuctionLength || 0, + extendAuctionWithin: nft.extendAuctionWithin || 0, + type: convertEnum(nft.type, CollectionType, PgCollectionType), + space: nft.space, + url: nft.url, + approved: nft.approved, + rejected: nft.rejected, + properties: nft.properties ? (JSON.stringify(nft.properties) as any) : undefined, + stats: nft.stats ? (JSON.stringify(nft.stats) as any) : undefined, + placeholderNft: nft.placeholderNft, + position: nft.position, + locked: nft.locked, + lockedBy: nft.lockedBy || '', + sold: nft.sold, + mintingData_address: nft.mintingData?.address, + mintingData_network: convertEnum(nft.mintingData?.network, Network, PgNetwork), + mintingData_mintedOn: nft.mintingData?.mintedOn?.toDate(), + mintingData_mintedBy: nft.mintingData?.mintedBy, + mintingData_blockId: nft.mintingData?.blockId, + mintingData_nftId: nft.mintingData?.nftId, + mintingData_storageDeposit: nft.mintingData?.storageDeposit, + mintingData_aliasBlockId: nft.mintingData?.aliasBlockId, + mintingData_aliasId: nft.mintingData?.aliasId, + mintingData_aliasStorageDeposit: nft.mintingData?.aliasStorageDeposit, + mintingData_mintingOrderId: nft.mintingData?.mintingOrderId, + mintingData_nftsToMint: nft.mintingData?.nftsToMint, + mintingData_nftMediaToUpload: nft.mintingData?.nftMediaToUpload, + mintingData_nftMediaToPrepare: nft.mintingData?.nftMediaToPrepare, + mintingData_unsoldMintingOptions: convertEnum( + nft.mintingData?.unsoldMintingOptions, + UnsoldMintingOptions, + PgUnsoldMintingOptions, + ), + mintingData_newPrice: nft.mintingData?.newPrice, + mintingData_nftsStorageDeposit: nft.mintingData?.nftsStorageDeposit, + depositData_address: nft.depositData?.address, + depositData_network: convertEnum(nft.depositData?.network, Network, PgNetwork), + depositData_mintedOn: nft.depositData?.mintedOn?.toDate(), + depositData_mintedBy: nft.depositData?.mintedBy, + depositData_blockId: nft.depositData?.blockId, + depositData_nftId: nft.depositData?.nftId, + depositData_storageDeposit: nft.depositData?.storageDeposit, + depositData_aliasBlockId: nft.depositData?.aliasBlockId, + depositData_aliasId: nft.depositData?.aliasId, + depositData_aliasStorageDeposit: nft.depositData?.aliasStorageDeposit, + depositData_mintingOrderId: nft.depositData?.mintingOrderId, + depositData_nftsToMint: nft.depositData?.nftsToMint, + depositData_nftMediaToUpload: nft.depositData?.nftMediaToUpload, + depositData_nftMediaToPrepare: nft.depositData?.nftMediaToPrepare, + depositData_unsoldMintingOptions: convertEnum( + nft.depositData?.unsoldMintingOptions, + UnsoldMintingOptions, + PgUnsoldMintingOptions, + ), + depositData_newPrice: nft.depositData?.newPrice, + depositData_nftsStorageDeposit: nft.depositData?.nftsStorageDeposit, + status: convertEnum(nft.status, NftStatus, PgNftStatus), + hidden: nft.hidden, + mediaStatus: convertEnum(nft.mediaStatus, MediaStatus, PgMediaStatus), + mediaUploadErrorCount: nft.mediaUploadErrorCount, + soldOn: nft.soldOn?.toDate(), + setAsAvatar: nft.setAsAvatar, + auction: nft.auction || undefined, + }); + + fromPg = (nft: PgNft): Nft => + removeNulls({ + uid: nft.uid, + project: nft.project, + createdOn: pgDateToTimestamp(nft.createdOn), + updatedOn: pgDateToTimestamp(nft.updatedOn), + createdBy: nft.createdBy || '', + name: nft.name || '', + description: nft.description || '', + collection: nft.collection || '', + owner: nft.owner, + isOwned: nft.isOwned, + media: nft.media || '', + ipfsMedia: nft.ipfsMedia || '', + ipfsMetadata: nft.ipfsMetadata || '', + ipfsRoot: nft.ipfsRoot || '', + saleAccess: convertEnum(nft.saleAccess, PgNftAccess, NftAccess) as NftAccess, + saleAccessMembers: nft.saleAccessMembers, + available: convertEnum(nft.available, PgNftAvailable, NftAvailable) as NftAvailable, + availableFrom: pgDateToTimestamp(nft.availableFrom) || null, + auctionFrom: pgDateToTimestamp(nft.auctionFrom) || null, + auctionTo: pgDateToTimestamp(nft.auctionTo), + extendedAuctionTo: pgDateToTimestamp(nft.extendedAuctionTo), + auctionHighestBid: nft.auctionHighestBid, + auctionHighestBidder: nft.auctionHighestBidder, + price: nft.price || 0, + totalTrades: nft.totalTrades || 0, + lastTradedOn: pgDateToTimestamp(nft.lastTradedOn) || null, + availablePrice: nft.availablePrice, + auctionFloorPrice: nft.auctionFloorPrice, + auctionLength: nft.auctionLength, + extendedAuctionLength: nft.extendedAuctionLength, + extendAuctionWithin: nft.extendAuctionWithin, + type: convertEnum(nft.type, PgCollectionType, CollectionType) as CollectionType, + space: nft.space || '', + url: nft.url || '', + approved: nft.approved || false, + rejected: nft.rejected || false, + properties: nft.properties as unknown as PropStats, + stats: nft.stats as unknown as PropStats, + placeholderNft: nft.placeholderNft || false, + locked: nft.locked, + lockedBy: nft.lockedBy, + sold: nft.sold, + mintingData: { + address: nft.mintingData_address, + network: convertEnum(nft.mintingData_network, PgNetwork, Network), + mintedOn: pgDateToTimestamp(nft.mintingData_mintedOn), + mintedBy: nft.mintingData_mintedBy, + blockId: nft.mintingData_blockId, + nftId: nft.mintingData_nftId, + storageDeposit: nft.mintingData_storageDeposit, + aliasBlockId: nft.mintingData_aliasBlockId, + aliasId: nft.mintingData_aliasId, + aliasStorageDeposit: nft.mintingData_aliasStorageDeposit, + mintingOrderId: nft.mintingData_mintingOrderId, + nftsToMint: nft.mintingData_nftsToMint, + nftMediaToUpload: nft.mintingData_nftMediaToUpload, + nftMediaToPrepare: nft.mintingData_nftMediaToPrepare, + unsoldMintingOptions: convertEnum( + nft.mintingData_unsoldMintingOptions, + PgUnsoldMintingOptions, + UnsoldMintingOptions, + ), + newPrice: nft.mintingData_newPrice, + nftsStorageDeposit: nft.mintingData_nftsStorageDeposit, + }, + depositData: nft.depositData_address + ? { + address: nft.depositData_address, + network: convertEnum(nft.depositData_network, PgNetwork, Network), + mintedOn: pgDateToTimestamp(nft.depositData_mintedOn), + mintedBy: nft.depositData_mintedBy, + blockId: nft.depositData_blockId, + nftId: nft.depositData_nftId, + storageDeposit: nft.depositData_storageDeposit, + aliasBlockId: nft.depositData_aliasBlockId, + aliasId: nft.depositData_aliasId, + aliasStorageDeposit: nft.depositData_aliasStorageDeposit, + mintingOrderId: nft.depositData_mintingOrderId, + nftsToMint: nft.depositData_nftsToMint, + nftMediaToUpload: nft.depositData_nftMediaToUpload, + nftMediaToPrepare: nft.depositData_nftMediaToPrepare, + unsoldMintingOptions: convertEnum( + nft.depositData_unsoldMintingOptions, + PgUnsoldMintingOptions, + UnsoldMintingOptions, + ), + newPrice: nft.depositData_newPrice, + nftsStorageDeposit: nft.depositData_nftsStorageDeposit, + } + : undefined, + status: convertEnum(nft.status, PgNftStatus, NftStatus), + mediaStatus: convertEnum(nft.mediaStatus, PgMediaStatus, MediaStatus), + mediaUploadErrorCount: nft.mediaUploadErrorCount, + soldOn: pgDateToTimestamp(nft.soldOn), + setAsAvatar: nft.setAsAvatar, + auction: nft.auction, + position: nft.position!, + hidden: nft.hidden, + }); +} diff --git a/packages/database/src/pg/impl/tables/nft_stake.ts b/packages/database/src/pg/impl/tables/nft_stake.ts new file mode 100644 index 0000000000..61c76ba60b --- /dev/null +++ b/packages/database/src/pg/impl/tables/nft_stake.ts @@ -0,0 +1,41 @@ +import { NftStake, StakeType } from '@build-5/interfaces'; +import { Converter } from '../../interfaces'; +import { PgNftStake } from '../../models'; +import { PgStakeType } from '../../models/enums'; +import { convertEnum, removeNulls } from '../common'; +import { pgDateToTimestamp } from '../postgres'; + +export class NftStakeConverter implements Converter { + toPg = (nftStake: NftStake): PgNftStake => ({ + uid: nftStake.uid, + project: nftStake.project, + createdOn: nftStake.createdOn?.toDate(), + updatedOn: nftStake.updatedOn?.toDate(), + createdBy: nftStake.createdBy, + member: nftStake.member, + space: nftStake.space, + collection: nftStake.collection, + nft: nftStake.nft, + weeks: nftStake.weeks, + expiresAt: nftStake.expiresAt?.toDate(), + expirationProcessed: nftStake.expirationProcessed, + type: convertEnum(nftStake.type, StakeType, PgStakeType), + }); + + fromPg = (nftStake: PgNftStake): NftStake => + removeNulls({ + uid: nftStake.uid, + project: nftStake.project, + createdOn: pgDateToTimestamp(nftStake.createdOn), + updatedOn: pgDateToTimestamp(nftStake.updatedOn), + createdBy: nftStake.createdBy || '', + member: nftStake.member || '', + space: nftStake.space || '', + nft: nftStake.nft || '', + collection: nftStake.collection || '', + weeks: nftStake.weeks || 0, + expiresAt: pgDateToTimestamp(nftStake.expiresAt)!, + expirationProcessed: nftStake.expirationProcessed!, + type: convertEnum(nftStake.type, PgStakeType, StakeType) as StakeType, + }); +} diff --git a/packages/database/src/pg/impl/tables/notification.ts b/packages/database/src/pg/impl/tables/notification.ts new file mode 100644 index 0000000000..b6d62785ea --- /dev/null +++ b/packages/database/src/pg/impl/tables/notification.ts @@ -0,0 +1,43 @@ +import { + Notification, + NotificationBidParams, + NotificationLostBidParams, + NotificationType, + NotificationWinBidParams, +} from '@build-5/interfaces'; +import { Converter } from '../../interfaces'; +import { PgNotification } from '../../models'; +import { PgNotificationType } from '../../models/enums'; +import { convertEnum, removeNulls } from '../common'; +import { pgDateToTimestamp } from '../postgres'; + +export class NotificationConverter implements Converter { + toPg = (notification: Notification): PgNotification => ({ + uid: notification.uid, + project: notification.project, + createdOn: notification.createdOn?.toDate(), + updatedOn: notification.updatedOn?.toDate(), + createdBy: notification.createdBy, + space: notification.space, + member: notification.member, + type: convertEnum(notification.type, NotificationType, PgNotificationType), + params: JSON.stringify(notification.params || {}) as any, + }); + + fromPg = (pg: PgNotification): Notification => + removeNulls({ + uid: pg.uid, + project: pg.project, + createdOn: pgDateToTimestamp(pg.createdOn), + updatedOn: pgDateToTimestamp(pg.updatedOn), + createdBy: pg.createdBy || '', + + space: pg.space, + member: pg.member, + type: convertEnum(pg.type, PgNotificationType, NotificationType)!, + params: pg.params as unknown as + | NotificationBidParams + | NotificationWinBidParams + | NotificationLostBidParams, + }); +} diff --git a/packages/database/src/pg/impl/tables/project.ts b/packages/database/src/pg/impl/tables/project.ts new file mode 100644 index 0000000000..4b547b9715 --- /dev/null +++ b/packages/database/src/pg/impl/tables/project.ts @@ -0,0 +1,43 @@ +import { Project, ProjectBilling, ProjectOtr } from '@build-5/interfaces'; +import { Converter } from '../../interfaces'; +import { PgProject } from '../../models'; +import { PgProjectBilling } from '../../models/enums'; +import { removeNulls } from '../common'; +import { pgDateToTimestamp } from '../postgres'; + +export class ProjectConverter implements Converter { + toPg = (project: Project): PgProject => ({ + uid: project.uid, + createdOn: project.createdOn?.toDate(), + updatedOn: project.updatedOn?.toDate(), + createdBy: project.createdBy, + name: project.name, + contactEmail: project.contactEmail, + deactivated: project.deactivated, + config_billing: project.config?.billing as unknown as PgProjectBilling, + config_tiers: project.config?.tiers, + config_tokenTradingFeeDiscountPercentage: project.config?.tokenTradingFeeDiscountPercentage, + config_nativeTokenSymbol: project.config?.nativeTokenSymbol, + config_nativeTokenUid: project.config?.nativeTokenUid, + otr: JSON.stringify(project.otr || {}) as any, + }); + + fromPg = (project: PgProject): Project => + removeNulls({ + uid: project.uid, + createdOn: pgDateToTimestamp(project.createdOn), + updatedOn: pgDateToTimestamp(project.updatedOn), + createdBy: project.createdBy, + name: project.name || '', + contactEmail: project.contactEmail, + deactivated: project.deactivated, + config: { + billing: project.config_billing! as unknown as ProjectBilling, + tiers: project.config_tiers, + tokenTradingFeeDiscountPercentage: project.config_tokenTradingFeeDiscountPercentage, + nativeTokenSymbol: project.config_nativeTokenSymbol, + nativeTokenUid: project.config_nativeTokenUid, + }, + otr: project.otr as unknown as { [key: string]: ProjectOtr }, + }); +} diff --git a/packages/database/src/pg/impl/tables/project_admin.ts b/packages/database/src/pg/impl/tables/project_admin.ts new file mode 100644 index 0000000000..055423a6f2 --- /dev/null +++ b/packages/database/src/pg/impl/tables/project_admin.ts @@ -0,0 +1,23 @@ +import { COL, ProjectAdmin } from '@build-5/interfaces'; +import { Converter } from '../../interfaces'; +import { PgProjectAdmins } from '../../models'; +import { removeNulls } from '../common'; +import { pgDateToTimestamp } from '../postgres'; + +export class ProjectAdminConverter implements Converter { + toPg = (projectAdmin: ProjectAdmin): PgProjectAdmins => ({ + uid: projectAdmin.uid, + project: projectAdmin.project, + createdOn: projectAdmin.createdOn?.toDate(), + parentId: projectAdmin.parentId, + }); + + fromPg = (pg: PgProjectAdmins): ProjectAdmin => + removeNulls({ + uid: pg.uid, + project: pg.project, + parentId: pg.parentId, + parentCol: COL.PROJECT, + createdOn: pgDateToTimestamp(pg.createdOn)!, + }); +} diff --git a/packages/database/src/pg/impl/tables/project_api_key.ts b/packages/database/src/pg/impl/tables/project_api_key.ts new file mode 100644 index 0000000000..872d5a18db --- /dev/null +++ b/packages/database/src/pg/impl/tables/project_api_key.ts @@ -0,0 +1,25 @@ +import { COL, ProjectApiKey } from '@build-5/interfaces'; +import { Converter } from '../../interfaces'; +import { PgProjectApiKey } from '../../models'; +import { removeNulls } from '../common'; +import { pgDateToTimestamp } from '../postgres'; + +export class ProjectApiKeyConverter implements Converter { + toPg = (pk: ProjectApiKey): PgProjectApiKey => ({ + uid: pk.uid, + project: pk.project, + createdOn: pk.createdOn?.toDate(), + parentId: pk.parentId, + token: pk.token, + }); + + fromPg = (pg: PgProjectApiKey): ProjectApiKey => + removeNulls({ + uid: pg.uid, + project: pg.project, + parentId: pg.parentId, + parentCol: COL.PROJECT, + createdOn: pgDateToTimestamp(pg.createdOn)!, + token: pg.token!, + }); +} diff --git a/packages/database/src/pg/impl/tables/proposal.ts b/packages/database/src/pg/impl/tables/proposal.ts new file mode 100644 index 0000000000..68d7f37fe0 --- /dev/null +++ b/packages/database/src/pg/impl/tables/proposal.ts @@ -0,0 +1,80 @@ +import { Proposal, ProposalMember, ProposalQuestion, ProposalType } from '@build-5/interfaces'; +import { Converter } from '../../interfaces'; +import { PgProposal } from '../../models'; +import { PgProposalType } from '../../models/enums'; +import { convertEnum, removeNulls } from '../common'; +import { pgDateToTimestamp } from '../postgres'; + +export class ProposalConverter implements Converter { + toPg = (proposal: Proposal) => ({ + uid: proposal.uid, + project: proposal.project, + createdOn: proposal.createdOn?.toDate(), + updatedOn: proposal.updatedOn?.toDate(), + createdBy: proposal.createdBy, + + space: proposal.space, + name: proposal.name, + description: proposal.description, + additionalInfo: proposal.additionalInfo, + type: convertEnum(proposal.type, ProposalType, PgProposalType), + approved: proposal.approved, + rejected: proposal.rejected, + approvedBy: proposal.approvedBy, + rejectedBy: proposal.rejectedBy, + eventId: proposal.eventId, + totalWeight: proposal.totalWeight, + token: proposal.token, + completed: proposal.completed, + rank: proposal.rank, + settings_startDate: proposal.settings.startDate?.toDate(), + settings_endDate: proposal.settings?.endDate?.toDate(), + settings_guardiansOnly: proposal.settings?.guardiansOnly, + settings_addRemoveGuardian: proposal.settings?.addRemoveGuardian, + settings_spaceUpdateData: JSON.stringify(proposal.settings?.spaceUpdateData) as any, + settings_onlyGuardians: proposal.settings?.onlyGuardians, + settings_stakeRewardIds: proposal.settings?.stakeRewardIds, + settings_awards: proposal.settings?.awards, + questions: JSON.stringify(proposal.questions) as any, + members: JSON.stringify(proposal.members) as any, + + results: proposal.results, + }); + + fromPg = (pg: PgProposal): Proposal => + removeNulls({ + uid: pg.uid, + project: pg.project, + createdOn: pgDateToTimestamp(pg.createdOn), + updatedOn: pgDateToTimestamp(pg.updatedOn), + createdBy: pg.createdBy || '', + + name: pg.name!, + additionalInfo: pg.additionalInfo, + space: pg.space!, + members: pg.members as unknown as { [propName: string]: ProposalMember } | undefined, + description: pg.description!, + type: convertEnum(pg.type, PgProposalType, ProposalType)! as ProposalType, + approved: pg.approved!, + approvedBy: pg.approvedBy, + rejected: pg.rejected, + rejectedBy: pg.rejectedBy, + eventId: pg.eventId, + settings: { + startDate: pgDateToTimestamp(pg.settings_startDate)!, + endDate: pgDateToTimestamp(pg.settings_endDate)!, + guardiansOnly: pg.settings_guardiansOnly, + addRemoveGuardian: pg.settings_addRemoveGuardian, + spaceUpdateData: pg.settings_spaceUpdateData as unknown as any, + onlyGuardians: pg.settings_onlyGuardians, + stakeRewardIds: pg.settings_stakeRewardIds, + awards: pg.settings_awards, + }, + totalWeight: pg.totalWeight, + questions: pg.questions as unknown as ProposalQuestion[], + results: pg.results, + token: pg.token, + completed: pg.completed || false, + rank: pg.rank, + }); +} diff --git a/packages/database/src/pg/impl/tables/proposal_member.ts b/packages/database/src/pg/impl/tables/proposal_member.ts new file mode 100644 index 0000000000..172b9d61e5 --- /dev/null +++ b/packages/database/src/pg/impl/tables/proposal_member.ts @@ -0,0 +1,49 @@ +import { COL, ProposalMember } from '@build-5/interfaces'; +import { get } from 'lodash'; +import { Converter } from '../../interfaces'; +import { PgProposalMembers } from '../../models'; +import { removeNulls } from '../common'; +import { pgDateToTimestamp } from '../postgres'; + +export class ProposalMemberConverter implements Converter { + toPg = (pm: ProposalMember): PgProposalMembers => ({ + uid: pm.uid, + project: pm.project, + createdOn: pm.createdOn?.toDate(), + parentId: pm.parentId, + voted: pm.voted, + weight: pm.weight, + tranId: pm.tranId, + values: (pm.values || []).reduce((acc, act) => { + const value = Object.keys(act).filter((k) => k !== 'voteTransaction')[0]; + const voteTranId = get(act, 'voteTransaction', ''); + return { ...acc, [voteTranId]: { value, weight: get(act, value, 0) } }; + }, {}), + }); + + fromPg = (pg: PgProposalMembers): ProposalMember => + removeNulls({ + uid: pg.uid, + project: pg.project, + parentId: pg.parentId, + parentCol: COL.PROPOSAL, + createdOn: pgDateToTimestamp(pg.createdOn)!, + voted: pg.voted, + weight: pg.weight, + weightPerAnswer: Object.values(pg.values || {}).reduce( + (acc: { [key: number]: number }, act: any) => { + const value = Number(act.value); + const weight = act.weight; + return { ...acc, [value]: (acc[value] || 0) + weight }; + }, + {} as { [key: number]: number }, + ), + tranId: pg.tranId, + values: Object.entries(pg.values || {}).map(([key, value]) => { + return { + [Number(get(value, 'value'))]: get(value, 'weight', 0), + voteTransaction: key, + }; + }), + }); +} diff --git a/packages/database/src/pg/impl/tables/proposal_owner.ts b/packages/database/src/pg/impl/tables/proposal_owner.ts new file mode 100644 index 0000000000..aeb2d9541e --- /dev/null +++ b/packages/database/src/pg/impl/tables/proposal_owner.ts @@ -0,0 +1,23 @@ +import { COL, ProposalMember } from '@build-5/interfaces'; +import { Converter } from '../../interfaces'; +import { PgProposalMembers, PgProposalOwners } from '../../models'; +import { removeNulls } from '../common'; +import { pgDateToTimestamp } from '../postgres'; + +export class ProposalOwnerConverter implements Converter { + toPg = (proposalOwner: ProposalMember): PgProposalOwners => ({ + uid: proposalOwner.uid, + project: proposalOwner.project, + createdOn: proposalOwner.createdOn?.toDate(), + parentId: proposalOwner.parentId, + }); + + fromPg = (pg: PgProposalOwners): ProposalMember => + removeNulls({ + uid: pg.uid, + project: pg.project, + parentId: pg.parentId, + parentCol: COL.PROPOSAL, + createdOn: pgDateToTimestamp(pg.createdOn)!, + }); +} diff --git a/packages/database/src/pg/impl/tables/soon_snapshot.ts b/packages/database/src/pg/impl/tables/soon_snapshot.ts new file mode 100644 index 0000000000..b8a124ad5a --- /dev/null +++ b/packages/database/src/pg/impl/tables/soon_snapshot.ts @@ -0,0 +1,36 @@ +import { SoonSnap } from '@build-5/interfaces'; +import { Converter } from '../../interfaces'; +import { PgSoonSnapshot } from '../../models'; +import { removeNulls } from '../common'; +import { pgDateToTimestamp } from '../postgres'; + +export class SoonSnapshotConverter implements Converter { + toPg = (snapshot: SoonSnap): PgSoonSnapshot => ({ + uid: snapshot.uid, + project: snapshot.project, + createdOn: snapshot.createdOn?.toDate(), + updatedOn: snapshot.updatedOn?.toDate(), + createdBy: snapshot.createdBy, + + count: snapshot.count, + paidOut: snapshot.paidOut, + lastPaidOutOn: snapshot.lastPaidOutOn?.toDate(), + ethAddress: snapshot.ethAddress, + ethAddressVerified: snapshot.ethAddressVerified, + }); + + fromPg = (pg: PgSoonSnapshot): SoonSnap => + removeNulls({ + uid: pg.uid, + project: pg.project, + createdOn: pgDateToTimestamp(pg.createdOn), + updatedOn: pgDateToTimestamp(pg.updatedOn), + createdBy: pg.createdBy || '', + + count: pg.count, + paidOut: pg.paidOut, + lastPaidOutOn: pgDateToTimestamp(pg.lastPaidOutOn), + ethAddress: pg.ethAddress, + ethAddressVerified: pg.ethAddressVerified, + }); +} diff --git a/packages/database/src/pg/impl/tables/space.ts b/packages/database/src/pg/impl/tables/space.ts new file mode 100644 index 0000000000..c2b916a715 --- /dev/null +++ b/packages/database/src/pg/impl/tables/space.ts @@ -0,0 +1,93 @@ +import { MediaStatus, Network, Space } from '@build-5/interfaces'; +import { Converter } from '../../interfaces'; +import { PgSpace } from '../../models'; +import { PgMediaStatus } from '../../models/enums'; +import { convertEnum, removeNulls } from '../common'; +import { pgDateToTimestamp } from '../postgres'; + +export class SpaceConverter implements Converter { + toPg = (space: Space): PgSpace => ({ + uid: space.uid, + project: space.project, + createdOn: space.createdOn?.toDate(), + updatedOn: space.updatedOn?.toDate(), + createdBy: space.createdBy, + name: space.name, + about: space.about, + open: space.open, + tokenBased: space.tokenBased, + minStakedValue: space.minStakedValue, + github: space.github, + twitter: space.twitter, + discord: space.discord, + avatarUrl: space.avatarUrl, + bannerUrl: space.bannerUrl, + totalGuardians: space.totalGuardians, + totalMembers: space.totalMembers, + totalPendingMembers: space.totalPendingMembers, + smrAddress: (space.validatedAddress || {})[Network.SMR], + rmsAddress: (space.validatedAddress || {})[Network.RMS], + iotaAddress: (space.validatedAddress || {})[Network.IOTA], + atoiAddress: (space.validatedAddress || {})[Network.ATOI], + prevValidatedAddresses: space.prevValidatedAddresses, + vaultAddress: space.vaultAddress, + collectionId: space.collectionId, + claimed: space.claimed, + ipfsMedia: space.ipfsMedia, + ipfsMetadata: space.ipfsMetadata, + ipfsRoot: space.ipfsRoot, + mediaStatus: convertEnum(space.mediaStatus, MediaStatus, PgMediaStatus), + mediaUploadErrorCount: space.mediaUploadErrorCount, + alias_address: space.alias?.address, + alias_aliasId: space.alias?.aliasId, + alias_blockId: space.alias?.blockId, + alias_mintedOn: space.alias?.mintedOn.toDate(), + alias_mintedBy: space.alias?.mintedBy, + }); + + fromPg = (pg: PgSpace): Space => + removeNulls({ + uid: pg.uid, + project: pg.project, + createdOn: pgDateToTimestamp(pg.createdOn), + updatedOn: pgDateToTimestamp(pg.updatedOn), + createdBy: pg.createdBy || '', + name: pg.name, + about: pg.about, + open: pg.open, + tokenBased: pg.tokenBased, + minStakedValue: pg.minStakedValue, + github: pg.github, + twitter: pg.twitter, + discord: pg.discord, + avatarUrl: pg.avatarUrl, + bannerUrl: pg.bannerUrl, + totalGuardians: pg.totalGuardians || 0, + totalMembers: pg.totalMembers || 0, + totalPendingMembers: pg.totalPendingMembers || 0, + validatedAddress: { + [Network.SMR]: pg.smrAddress || '', + [Network.RMS]: pg.rmsAddress || '', + [Network.IOTA]: pg.iotaAddress || '', + [Network.ATOI]: pg.atoiAddress || '', + }, + prevValidatedAddresses: pg.prevValidatedAddresses, + vaultAddress: pg.vaultAddress, + collectionId: pg.collectionId, + claimed: pg.claimed, + ipfsMedia: pg.ipfsMedia, + ipfsMetadata: pg.ipfsMetadata, + ipfsRoot: pg.ipfsRoot, + mediaStatus: convertEnum(pg.mediaStatus, PgMediaStatus, MediaStatus), + mediaUploadErrorCount: pg.mediaUploadErrorCount, + members: {}, + guardians: {}, + alias: { + address: pg.alias_address || '', + aliasId: pg.alias_aliasId || '', + blockId: pg.alias_blockId || '', + mintedOn: pgDateToTimestamp(pg.alias_mintedOn)!, + mintedBy: pg.alias_mintedBy || '', + }, + }); +} diff --git a/packages/database/src/pg/impl/tables/space_guardians.ts b/packages/database/src/pg/impl/tables/space_guardians.ts new file mode 100644 index 0000000000..67228fde2f --- /dev/null +++ b/packages/database/src/pg/impl/tables/space_guardians.ts @@ -0,0 +1,23 @@ +import { COL, SpaceGuardian } from '@build-5/interfaces'; +import { Converter } from '../../interfaces'; +import { PgSpaceGuardians } from '../../models'; +import { removeNulls } from '../common'; +import { pgDateToTimestamp } from '../postgres'; + +export class SpaceGuardianConverter implements Converter { + toPg = (spaceGuardian: SpaceGuardian): PgSpaceGuardians => ({ + uid: spaceGuardian.uid, + project: spaceGuardian.project, + createdOn: spaceGuardian.createdOn?.toDate(), + parentId: spaceGuardian.parentId, + }); + + fromPg = (pg: PgSpaceGuardians): SpaceGuardian => + removeNulls({ + project: pg.project, + parentId: pg.parentId, + parentCol: COL.PROPOSAL, + uid: pg.uid, + createdOn: pgDateToTimestamp(pg.createdOn)!, + }); +} diff --git a/packages/database/src/pg/impl/tables/space_member.ts b/packages/database/src/pg/impl/tables/space_member.ts new file mode 100644 index 0000000000..94431c4799 --- /dev/null +++ b/packages/database/src/pg/impl/tables/space_member.ts @@ -0,0 +1,23 @@ +import { COL, SpaceMember } from '@build-5/interfaces'; +import { Converter } from '../../interfaces'; +import { PgSpaceMembers } from '../../models'; +import { removeNulls } from '../common'; +import { pgDateToTimestamp } from '../postgres'; + +export class SpaceMemberConverter implements Converter { + toPg = (spaceMember: SpaceMember): PgSpaceMembers => ({ + uid: spaceMember.uid, + project: spaceMember.project, + createdOn: spaceMember.createdOn?.toDate(), + parentId: spaceMember.parentId, + }); + + fromPg = (pg: PgSpaceMembers): SpaceMember => + removeNulls({ + project: pg.project, + parentId: pg.parentId, + parentCol: COL.SPACE, + uid: pg.uid, + createdOn: pgDateToTimestamp(pg.createdOn)!, + }); +} diff --git a/packages/database/src/pg/impl/tables/stake.ts b/packages/database/src/pg/impl/tables/stake.ts new file mode 100644 index 0000000000..0ffe02034e --- /dev/null +++ b/packages/database/src/pg/impl/tables/stake.ts @@ -0,0 +1,68 @@ +import { Stake, StakeReward, StakeType } from '@build-5/interfaces'; +import { Converter, ICollection } from '../../interfaces'; +import { PgStake } from '../../models'; +import { PgStakeType } from '../../models/enums'; +import { PgStakeUpdate } from '../../models/stake_update'; +import { convertEnum, removeNulls } from '../common'; +import { pgDateToTimestamp } from '../postgres'; + +export class PgStakeCollection extends ICollection { + getStakeSumPerMember = async (stakeReward: StakeReward): Promise<{ [key: string]: number }> => { + const result = await this.con(this.col) + .select('member') + .select(this.con.raw('SUM(value)::integer as value')) + .where({ token: stakeReward.token }) + .where({ type: PgStakeType.DYNAMIC }) + .where('expiresAt', '>=', stakeReward.startDate.toDate()) + .where('createdOn', '<=', stakeReward.endDate.toDate()) + .groupBy('member'); + return (result as { member: string; value: number }[]).reduce( + (acc, act) => ({ ...acc, [act.member]: act.value }), + {} as { [key: string]: number }, + ); + }; +} + +export class StakeConverter implements Converter { + toPg = (stake: Stake): PgStake => ({ + uid: stake.uid, + project: stake.project, + createdOn: stake.createdOn?.toDate(), + updatedOn: stake.updatedOn?.toDate(), + createdBy: stake.createdBy, + + member: stake.member, + space: stake.space, + token: stake.token, + amount: stake.amount, + value: stake.value, + weeks: stake.weeks, + expiresAt: stake.expiresAt?.toDate(), + expirationProcessed: stake.expirationProcessed, + orderId: stake.orderId, + billPaymentId: stake.billPaymentId, + type: convertEnum(stake.type, StakeType, PgStakeType), + customMetadata: JSON.stringify(stake.customMetadata) as any, + }); + + fromPg = (pg: PgStake): Stake => + removeNulls({ + uid: pg.uid, + project: pg.project, + createdOn: pgDateToTimestamp(pg.createdOn), + updatedOn: pgDateToTimestamp(pg.updatedOn), + createdBy: pg.createdBy || '', + member: pg.member!, + space: pg.space!, + token: pg.token!, + amount: pg.amount!, + value: pg.value!, + weeks: pg.weeks!, + expiresAt: pgDateToTimestamp(pg.expiresAt)!, + expirationProcessed: pg.expirationProcessed!, + orderId: pg.orderId!, + billPaymentId: pg.billPaymentId!, + type: convertEnum(pg.type, PgStakeType, StakeType)!, + customMetadata: pg.customMetadata as { [key: string]: string } | undefined, + }); +} diff --git a/packages/database/src/pg/impl/tables/stake_reward.ts b/packages/database/src/pg/impl/tables/stake_reward.ts new file mode 100644 index 0000000000..e6e8a5d3f1 --- /dev/null +++ b/packages/database/src/pg/impl/tables/stake_reward.ts @@ -0,0 +1,42 @@ +import { StakeReward, StakeRewardStatus } from '@build-5/interfaces'; +import { Converter } from '../../interfaces'; +import { PgStakeReward } from '../../models'; +import { PgStakeRewardStatus } from '../../models/enums'; +import { convertEnum, removeNulls } from '../common'; +import { pgDateToTimestamp } from '../postgres'; + +export class StakeRewardConverter implements Converter { + toPg = (sr: StakeReward): PgStakeReward => ({ + uid: sr.uid, + project: sr.project, + createdOn: sr.createdOn?.toDate(), + updatedOn: sr.updatedOn?.toDate(), + createdBy: sr.createdBy, + + startDate: sr.startDate.toDate(), + endDate: sr.endDate.toDate(), + tokenVestingDate: sr.tokenVestingDate.toDate(), + tokensToDistribute: sr.tokensToDistribute, + token: sr.token, + totalStaked: sr.totalStaked, + totalAirdropped: sr.totalAirdropped, + status: convertEnum(sr.status, StakeRewardStatus, PgStakeRewardStatus), + }); + + fromPg = (pg: PgStakeReward): StakeReward => + removeNulls({ + uid: pg.uid, + project: pg.project, + createdOn: pgDateToTimestamp(pg.createdOn), + updatedOn: pgDateToTimestamp(pg.updatedOn), + createdBy: pg.createdBy || '', + startDate: pgDateToTimestamp(pg.startDate)!, + endDate: pgDateToTimestamp(pg.endDate)!, + tokenVestingDate: pgDateToTimestamp(pg.tokenVestingDate)!, + tokensToDistribute: pg.tokensToDistribute!, + token: pg.token!, + status: convertEnum(pg.status, PgStakeRewardStatus, StakeRewardStatus)!, + totalStaked: pg.totalStaked, + totalAirdropped: pg.totalAirdropped, + }); +} diff --git a/packages/database/src/pg/impl/tables/stamp.ts b/packages/database/src/pg/impl/tables/stamp.ts new file mode 100644 index 0000000000..c78fec83a3 --- /dev/null +++ b/packages/database/src/pg/impl/tables/stamp.ts @@ -0,0 +1,63 @@ +import { MediaStatus, Network, Stamp } from '@build-5/interfaces'; +import { Converter } from '../../interfaces'; +import { PgStamp } from '../../models'; +import { PgMediaStatus, PgNetwork } from '../../models/enums'; +import { convertEnum, removeNulls } from '../common'; +import { pgDateToTimestamp } from '../postgres'; + +export class StampConverter implements Converter { + toPg = (stamp: Stamp): PgStamp => ({ + uid: stamp.uid, + project: stamp.project, + createdOn: stamp.createdOn?.toDate(), + updatedOn: stamp.updatedOn?.toDate(), + createdBy: stamp.createdBy, + + space: stamp.space, + build5Url: stamp.build5Url, + originUri: stamp.originUri, + checksum: stamp.checksum, + extension: stamp.extension, + bytes: stamp.bytes, + costPerMb: stamp.costPerMb, + network: convertEnum(stamp.network, Network, PgNetwork), + ipfsMedia: stamp.ipfsMedia, + ipfsRoot: stamp.ipfsRoot, + expiresAt: stamp.expiresAt.toDate(), + order: stamp.order, + funded: stamp.funded, + expired: stamp.expired, + mediaStatus: convertEnum(stamp.mediaStatus, MediaStatus, PgMediaStatus), + mediaUploadErrorCount: stamp.mediaUploadErrorCount, + nftId: stamp.nftId, + aliasId: stamp.aliasId, + }); + + fromPg = (pg: PgStamp): Stamp => + removeNulls({ + uid: pg.uid, + project: pg.project, + createdOn: pgDateToTimestamp(pg.createdOn), + updatedOn: pgDateToTimestamp(pg.updatedOn), + createdBy: pg.createdBy || '', + + space: pg.space!, + build5Url: pg.build5Url!, + originUri: pg.originUri!, + checksum: pg.checksum!, + extension: pg.extension!, + bytes: pg.bytes!, + costPerMb: pg.costPerMb!, + network: convertEnum(pg.network, PgNetwork, Network)!, + ipfsMedia: pg.ipfsMedia, + ipfsRoot: pg.ipfsRoot, + expiresAt: pgDateToTimestamp(pg.expiresAt)!, + order: pg.order!, + funded: pg.funded!, + expired: pg.expired!, + mediaStatus: convertEnum(pg.mediaStatus, PgMediaStatus, MediaStatus), + mediaUploadErrorCount: pg.mediaUploadErrorCount, + aliasId: pg.aliasId, + nftId: pg.nftId, + }); +} diff --git a/packages/database/src/pg/impl/tables/swap.ts b/packages/database/src/pg/impl/tables/swap.ts new file mode 100644 index 0000000000..f260dfa43e --- /dev/null +++ b/packages/database/src/pg/impl/tables/swap.ts @@ -0,0 +1,47 @@ +import { NativeToken, Network, Swap, SwapOutput, SwapStatus } from '@build-5/interfaces'; +import { Converter } from '../../interfaces'; +import { PgSwap } from '../../models'; +import { PgNetwork, PgSwapStatus } from '../../models/enums'; +import { convertEnum, removeNulls } from '../common'; +import { pgDateToTimestamp } from '../postgres'; + +export class SwapConverter implements Converter { + toPg = (swap: Swap): PgSwap => ({ + uid: swap.uid, + project: swap.project, + createdOn: swap.createdOn?.toDate(), + updatedOn: swap.updatedOn?.toDate(), + createdBy: swap.createdBy, + + recipient: swap.recipient, + network: convertEnum(swap.network, Network, PgNetwork), + address: swap.address, + orderId: swap.orderId, + nftIdsAsk: swap.nftIdsAsk, + baseTokenAmountAsk: swap.baseTokenAmountAsk, + nativeTokensAsk: JSON.stringify(swap.nativeTokensAsk) as any, + status: convertEnum(swap.status, SwapStatus, PgSwapStatus), + bidOutputs: JSON.stringify(swap.bidOutputs) as any, + askOutputs: JSON.stringify(swap.askOutputs) as any, + }); + + fromPg = (pg: PgSwap): Swap => + removeNulls({ + uid: pg.uid, + project: pg.project, + createdOn: pgDateToTimestamp(pg.createdOn), + updatedOn: pgDateToTimestamp(pg.updatedOn), + createdBy: pg.createdBy || '', + + recipient: pg.recipient!, + network: convertEnum(pg.network!, PgNetwork, Network)!, + address: pg.address!, + orderId: pg.orderId!, + bidOutputs: pg.bidOutputs as unknown as SwapOutput[], + nftIdsAsk: pg.nftIdsAsk!, + baseTokenAmountAsk: pg.baseTokenAmountAsk!, + nativeTokensAsk: pg.nativeTokensAsk as unknown as NativeToken[], + askOutputs: pg.askOutputs as unknown as SwapOutput[], + status: convertEnum(pg.status, PgSwapStatus, SwapStatus)!, + }); +} diff --git a/packages/database/src/pg/impl/tables/system.ts b/packages/database/src/pg/impl/tables/system.ts new file mode 100644 index 0000000000..c38cb56fd2 --- /dev/null +++ b/packages/database/src/pg/impl/tables/system.ts @@ -0,0 +1,19 @@ +import { SystemConfig } from '@build-5/interfaces'; +import { Converter } from '../../interfaces'; +import { PgSystem } from '../../models'; +import { removeNulls } from '../common'; + +export class SystemConverter implements Converter { + toPg = (system: SystemConfig): PgSystem => ({ + uid: system.uid, + tokenTradingFeePercentage: system.tokenTradingFeePercentage, + tokenPurchaseFeePercentage: system.tokenPurchaseFeePercentage, + }); + + fromPg = (pg: PgSystem): SystemConfig => + removeNulls({ + uid: pg.uid, + tokenTradingFeePercentage: pg.tokenTradingFeePercentage, + tokenPurchaseFeePercentage: pg.tokenPurchaseFeePercentage, + }); +} diff --git a/packages/database/src/pg/impl/tables/ticker.ts b/packages/database/src/pg/impl/tables/ticker.ts new file mode 100644 index 0000000000..7a012e1eb3 --- /dev/null +++ b/packages/database/src/pg/impl/tables/ticker.ts @@ -0,0 +1,18 @@ +import { Ticker } from '@build-5/interfaces'; +import { Converter } from '../../interfaces'; +import { PgTicker } from '../../models'; + +export class TickerConverter implements Converter { + toPg = (ticker: Ticker): PgTicker => ({ + uid: ticker.uid, + createdOn: ticker.createdOn?.toDate(), + updatedOn: ticker.updatedOn?.toDate(), + createdBy: ticker.createdBy, + price: ticker.price, + }); + + fromPg = (ticker: PgTicker): Ticker => ({ + uid: ticker.uid, + price: ticker.price || 0, + }); +} diff --git a/packages/database/src/pg/impl/tables/token.ts b/packages/database/src/pg/impl/tables/token.ts new file mode 100644 index 0000000000..e9ba9d128a --- /dev/null +++ b/packages/database/src/pg/impl/tables/token.ts @@ -0,0 +1,152 @@ +import { + Access, + MediaStatus, + Network, + Token, + TokenAllocation, + TokenStatus, +} from '@build-5/interfaces'; +import { Converter } from '../../interfaces'; +import { PgToken } from '../../models'; +import { PgAccess, PgMediaStatus, PgNetwork, PgTokenStatus } from '../../models/enums'; +import { convertEnum, removeNulls } from '../common'; +import { pgDateToTimestamp } from '../postgres'; + +export class TokenConverter implements Converter { + toPg = (token: Token): PgToken => ({ + uid: token.uid, + project: token.project, + createdOn: token.createdOn?.toDate(), + updatedOn: token.updatedOn?.toDate(), + createdBy: token.createdBy, + + name: token.name, + symbol: token.symbol, + title: token.title, + description: token.description, + shortDescriptionTitle: token.shortDescriptionTitle, + shortDescription: token.shortDescription, + space: token.space, + pricePerToken: token.pricePerToken, + totalSupply: token.totalSupply, + allocations: JSON.stringify(token.allocations) as any, + saleStartDate: token.saleStartDate?.toDate(), + saleLength: token.saleLength, + coolDownEnd: token.coolDownEnd?.toDate(), + autoProcessAt100Percent: token.autoProcessAt100Percent, + approved: token.approved, + rejected: token.rejected, + public: token.public, + links: token.links?.map((u) => u.toString()), + icon: token.icon, + overviewGraphics: token.overviewGraphics, + status: convertEnum(token.status, TokenStatus, PgTokenStatus), + totalDeposit: token.totalDeposit, + tokensOrdered: token.tokensOrdered, + totalAirdropped: token.totalAirdropped, + termsAndConditions: token.termsAndConditions, + access: convertEnum(token.access, Access, PgAccess), + accessAwards: token.accessAwards, + accessCollections: token.accessCollections, + ipfsMedia: token.ipfsMedia, + ipfsMetadata: token.ipfsMetadata, + ipfsRoot: token.ipfsRoot, + mintingData_mintedBy: token.mintingData?.mintedBy, + mintingData_mintedOn: token.mintingData?.mintedOn?.toDate(), + mintingData_aliasBlockId: token.mintingData?.aliasBlockId, + mintingData_aliasId: token.mintingData?.aliasId, + mintingData_aliasStorageDeposit: token.mintingData?.aliasStorageDeposit, + mintingData_tokenId: token.mintingData?.tokenId, + mintingData_blockId: token.mintingData?.blockId, + mintingData_foundryStorageDeposit: token.mintingData?.foundryStorageDeposit, + mintingData_network: convertEnum(token.mintingData?.network, Network, PgNetwork), + mintingData_networkFormat: token.mintingData?.networkFormat, + mintingData_vaultAddress: token.mintingData?.vaultAddress, + mintingData_tokensInVault: token.mintingData?.tokensInVault, + mintingData_vaultStorageDeposit: token.mintingData?.vaultStorageDeposit, + mintingData_guardianStorageDeposit: token.mintingData?.guardianStorageDeposit, + mintingData_meltedTokens: token.mintingData?.meltedTokens, + mintingData_circulatingSupply: token.mintingData?.circulatingSupply, + rankCount: token.rankCount, + rankSum: token.rankSum, + rankAvg: token.rankAvg, + mediaStatus: convertEnum(token.mediaStatus, MediaStatus, PgMediaStatus), + mediaUploadErrorCount: token.mediaUploadErrorCount, + tradingDisabled: token.tradingDisabled, + decimals: token.decimals, + votes_upvotes: token.votes?.upvotes, + votes_downvotes: token.votes?.downvotes, + votes_voteDiff: token.votes?.voteDiff, + }); + + fromPg = (pg: PgToken): Token => + removeNulls({ + uid: pg.uid, + project: pg.project, + createdOn: pgDateToTimestamp(pg.createdOn), + updatedOn: pgDateToTimestamp(pg.updatedOn), + createdBy: pg.createdBy || '', + + name: pg.name || '', + symbol: pg.symbol || '', + title: pg.title, + description: pg.description, + shortDescriptionTitle: pg.shortDescriptionTitle, + shortDescription: pg.shortDescription, + space: pg.space, + pricePerToken: pg.pricePerToken || 0, + totalSupply: pg.totalSupply || 0, + allocations: pg.allocations as unknown as TokenAllocation[], + saleStartDate: pgDateToTimestamp(pg.saleStartDate), + saleLength: pg.saleLength, + coolDownEnd: pgDateToTimestamp(pg.coolDownEnd), + autoProcessAt100Percent: pg.autoProcessAt100Percent, + approved: pg.approved || false, + rejected: pg.rejected || false, + public: pg.public, + links: (pg.links || []).map((l) => new URL(l)), + icon: pg.icon, + overviewGraphics: pg.overviewGraphics, + status: convertEnum(pg.status, PgTokenStatus, TokenStatus)!, + totalDeposit: pg.totalDeposit || 0, + tokensOrdered: pg.tokensOrdered, + totalAirdropped: pg.totalAirdropped || 0, + termsAndConditions: pg.termsAndConditions || '', + access: convertEnum(pg.access, PgAccess, Access) as Access, + accessAwards: pg.accessAwards, + accessCollections: pg.accessCollections, + ipfsMedia: pg.ipfsMedia, + ipfsMetadata: pg.ipfsMetadata, + ipfsRoot: pg.ipfsRoot, + mintingData: { + mintedBy: pg.mintingData_mintedBy, + mintedOn: pgDateToTimestamp(pg.mintingData_mintedOn), + aliasBlockId: pg.mintingData_aliasBlockId, + aliasId: pg.mintingData_aliasId, + aliasStorageDeposit: pg.mintingData_aliasStorageDeposit, + tokenId: pg.mintingData_tokenId, + blockId: pg.mintingData_blockId, + foundryStorageDeposit: pg.mintingData_foundryStorageDeposit, + network: convertEnum(pg.mintingData_network, PgNetwork, Network), + networkFormat: convertEnum(pg.mintingData_networkFormat, PgNetwork, Network), + vaultAddress: pg.mintingData_vaultAddress, + tokensInVault: pg.mintingData_tokensInVault, + vaultStorageDeposit: pg.mintingData_vaultStorageDeposit, + guardianStorageDeposit: pg.mintingData_guardianStorageDeposit, + meltedTokens: pg.mintingData_meltedTokens, + circulatingSupply: pg.mintingData_circulatingSupply, + }, + rankCount: pg.rankCount, + rankSum: pg.rankSum, + rankAvg: pg.rankAvg, + mediaStatus: convertEnum(pg.mediaStatus, PgMediaStatus, MediaStatus), + mediaUploadErrorCount: pg.mediaUploadErrorCount, + tradingDisabled: pg.tradingDisabled, + votes: { + upvotes: pg.votes_upvotes || 0, + downvotes: pg.votes_downvotes || 0, + voteDiff: pg.votes_voteDiff || 0, + }, + decimals: pg.decimals || 0, + }); +} diff --git a/packages/database/src/pg/impl/tables/token_distribution.ts b/packages/database/src/pg/impl/tables/token_distribution.ts new file mode 100644 index 0000000000..53c7360928 --- /dev/null +++ b/packages/database/src/pg/impl/tables/token_distribution.ts @@ -0,0 +1,108 @@ +import { COL, StakeType, TokenDistribution } from '@build-5/interfaces'; +import { head } from 'lodash'; +import { Converter, ISubCollection } from '../../interfaces'; +import { PgTokenDistribution } from '../../models'; +import { PgTokenDistributionUpdate } from '../../models/token_update'; +import { removeNulls } from '../common'; +import { pgDateToTimestamp } from '../postgres'; + +export class PgTokenDistributionCollection extends ISubCollection< + TokenDistribution, + PgTokenDistribution, + PgTokenDistributionUpdate +> { + getTotalOwned = async () => { + const snap = await this.con(this.table) + .select(this.con.raw('SUM("tokenOwned")::integer as "tokenOwned"')) + .where({ parentId: this.colId }); + return Number(head(snap).tokenOwned || 0); + }; +} + +export class TokenDistributionConverter + implements Converter +{ + toPg = (td: TokenDistribution) => ({ + uid: td.uid!, + project: td.project, + createdOn: td.createdOn?.toDate(), + parentId: td.parentId, + + totalDeposit: td.totalDeposit, + totalPaid: td.totalPaid, + refundedAmount: td.refundedAmount, + totalBought: td.totalBought, + reconciled: td.reconciled, + billPaymentId: td.billPaymentId, + creditPaymentId: td.creditPaymentId, + royaltyBillPaymentId: td.royaltyBillPaymentId, + tokenClaimed: td.tokenClaimed, + lockedForSale: td.lockedForSale, + sold: td.sold, + totalPurchased: td.totalPurchased, + tokenOwned: td.tokenOwned, + mintedClaimedOn: td.mintedClaimedOn?.toDate(), + mintingTransactions: td.mintingTransactions, + stakeRewards: td.stakeRewards, + extraStakeRewards: td.extraStakeRewards, + totalUnclaimedAirdrop: td.totalUnclaimedAirdrop, + stakeVoteTransactionId: td.stakeVoteTransactionId, + + stakes_static_amount: td.stakes?.[StakeType.STATIC]?.amount || 0, + stakes_static_totalAmount: td.stakes?.[StakeType.STATIC]?.totalAmount || 0, + stakes_static_value: td.stakes?.[StakeType.STATIC]?.value || 0, + stakes_static_totalValue: td.stakes?.[StakeType.STATIC]?.totalValue || 0, + stakes_static_stakingMembersCount: td.stakes?.[StakeType.STATIC]?.stakingMembersCount || 0, + stakes_dynamic_amount: td.stakes?.[StakeType.DYNAMIC]?.amount || 0, + stakes_dynamic_totalAmount: td.stakes?.[StakeType.DYNAMIC]?.totalAmount || 0, + stakes_dynamic_value: td.stakes?.[StakeType.DYNAMIC]?.value || 0, + stakes_dynamic_totalValue: td.stakes?.[StakeType.DYNAMIC]?.totalValue || 0, + stakes_dynamic_stakingMembersCount: td.stakes?.[StakeType.DYNAMIC]?.stakingMembersCount || 0, + stakeExpiry: td.stakeExpiry, + }); + + fromPg = (pg: PgTokenDistribution): TokenDistribution => + removeNulls({ + uid: pg.uid, + project: pg.project, + parentId: pg.parentId, + parentCol: COL.TOKEN, + totalDeposit: pg.totalDeposit, + totalPaid: pg.totalPaid, + refundedAmount: pg.refundedAmount, + totalBought: pg.totalBought, + reconciled: pg.reconciled, + billPaymentId: pg.billPaymentId, + creditPaymentId: pg.creditPaymentId, + royaltyBillPaymentId: pg.royaltyBillPaymentId, + tokenClaimed: pg.tokenClaimed, + lockedForSale: pg.lockedForSale, + sold: pg.sold, + totalPurchased: pg.totalPurchased, + tokenOwned: pg.tokenOwned, + createdOn: pgDateToTimestamp(pg.createdOn), + mintedClaimedOn: pgDateToTimestamp(pg.mintedClaimedOn), + mintingTransactions: pg.mintingTransactions, + stakes: { + [StakeType.STATIC]: { + amount: pg.stakes_static_amount, + totalAmount: pg.stakes_static_totalAmount, + value: pg.stakes_static_value, + totalValue: pg.stakes_static_totalValue, + stakingMembersCount: pg.stakes_static_stakingMembersCount, + }, + [StakeType.DYNAMIC]: { + amount: pg.stakes_dynamic_amount, + totalAmount: pg.stakes_dynamic_totalAmount, + value: pg.stakes_dynamic_value, + totalValue: pg.stakes_dynamic_totalValue, + stakingMembersCount: pg.stakes_dynamic_stakingMembersCount, + }, + }, + stakeExpiry: pg.stakeExpiry as { [key: string]: { [key: number]: number } }, + stakeRewards: pg.stakeRewards, + extraStakeRewards: pg.extraStakeRewards, + totalUnclaimedAirdrop: pg.totalUnclaimedAirdrop, + stakeVoteTransactionId: pg.stakeVoteTransactionId, + }); +} diff --git a/packages/database/src/pg/impl/tables/token_market.ts b/packages/database/src/pg/impl/tables/token_market.ts new file mode 100644 index 0000000000..0573690d08 --- /dev/null +++ b/packages/database/src/pg/impl/tables/token_market.ts @@ -0,0 +1,74 @@ +import { + Network, + TokenStatus, + TokenTradeOrder, + TokenTradeOrderStatus, + TokenTradeOrderType, +} from '@build-5/interfaces'; +import { Converter } from '../../interfaces'; +import { PgTokenMarket } from '../../models'; +import { + PgNetwork, + PgTokenStatus, + PgTokenTradeOrderStatus, + PgTokenTradeOrderType, +} from '../../models/enums'; +import { convertEnum, removeNulls } from '../common'; +import { pgDateToTimestamp } from '../postgres'; + +export class TokenTradeOrderConverter implements Converter { + toPg = (to: TokenTradeOrder): PgTokenMarket => ({ + uid: to.uid, + project: to.project, + createdOn: to.createdOn?.toDate(), + updatedOn: to.updatedOn?.toDate(), + createdBy: to.createdBy, + + owner: to.owner, + token: to.token, + tokenStatus: convertEnum(to.tokenStatus, TokenStatus, PgTokenStatus), + type: convertEnum(to.type, TokenTradeOrderType, PgTokenTradeOrderType), + count: to.count, + price: to.price, + totalDeposit: to.totalDeposit, + balance: to.balance, + fulfilled: to.fulfilled, + status: convertEnum(to.status, TokenTradeOrderStatus, PgTokenTradeOrderStatus), + orderTransactionId: to.orderTransactionId, + paymentTransactionId: to.paymentTransactionId, + creditTransactionId: to.creditTransactionId, + expiresAt: to.expiresAt?.toDate(), + shouldRetry: to.shouldRetry, + sourceNetwork: convertEnum(to.sourceNetwork, Network, PgNetwork), + targetNetwork: convertEnum(to.targetNetwork, Network, PgNetwork), + targetAddress: to.targetAddress, + }); + + fromPg = (pg: PgTokenMarket): TokenTradeOrder => + removeNulls({ + uid: pg.uid, + project: pg.project, + createdOn: pgDateToTimestamp(pg.createdOn), + updatedOn: pgDateToTimestamp(pg.updatedOn), + createdBy: pg.createdBy || '', + + owner: pg.owner!, + token: pg.token!, + tokenStatus: convertEnum(pg.tokenStatus, PgTokenStatus, TokenStatus)!, + type: convertEnum(pg.type, PgTokenTradeOrderType, TokenTradeOrderType)!, + count: pg.count!, + price: pg.price!, + totalDeposit: pg.totalDeposit!, + balance: pg.balance!, + fulfilled: pg.fulfilled!, + status: convertEnum(pg.status, PgTokenTradeOrderStatus, TokenTradeOrderStatus)!, + orderTransactionId: pg.orderTransactionId, + paymentTransactionId: pg.paymentTransactionId, + creditTransactionId: pg.creditTransactionId, + expiresAt: pgDateToTimestamp(pg.expiresAt)!, + shouldRetry: pg.shouldRetry, + sourceNetwork: convertEnum(pg.sourceNetwork, PgNetwork, Network), + targetNetwork: convertEnum(pg.targetNetwork, PgNetwork, Network), + targetAddress: pg.targetAddress, + }); +} diff --git a/packages/database/src/pg/impl/tables/token_purchase.ts b/packages/database/src/pg/impl/tables/token_purchase.ts new file mode 100644 index 0000000000..227f3708b4 --- /dev/null +++ b/packages/database/src/pg/impl/tables/token_purchase.ts @@ -0,0 +1,68 @@ +import { + Network, + TokenPurchase, + TokenPurchaseAge, + TokenStatus, + TokenTradeOrderType, +} from '@build-5/interfaces'; +import { Converter } from '../../interfaces'; +import { PgTokenPurchase } from '../../models'; +import { PgNetwork, PgTokenStatus, PgTokenTradeOrderType } from '../../models/enums'; +import { convertEnum, removeNulls } from '../common'; +import { pgDateToTimestamp } from '../postgres'; + +export class TokenPurchaseConverter implements Converter { + toPg = (tp: TokenPurchase): PgTokenPurchase => ({ + uid: tp.uid, + project: tp.project, + createdOn: tp.createdOn?.toDate(), + updatedOn: tp.updatedOn?.toDate(), + createdBy: tp.createdBy, + + token: tp.token, + tokenStatus: convertEnum(tp.tokenStatus, TokenStatus, PgTokenStatus), + sell: tp.sell, + buy: tp.buy, + count: tp.count, + price: tp.price, + triggeredBy: convertEnum(tp.triggeredBy, TokenTradeOrderType, PgTokenTradeOrderType), + billPaymentId: tp.billPaymentId, + buyerBillPaymentId: tp.buyerBillPaymentId, + royaltyBillPayments: tp.royaltyBillPayments, + sourceNetwork: convertEnum(tp.sourceNetwork, Network, PgNetwork), + targetNetwork: convertEnum(tp.targetNetwork, Network, PgNetwork), + sellerTokenTradingFeePercentage: tp.sellerTokenTradingFeePercentage, + sellerTier: tp.sellerTier, + in24h: tp.age.includes(TokenPurchaseAge.IN_24_H), + in48h: tp.age.includes(TokenPurchaseAge.IN_48_H), + in7d: tp.age.includes(TokenPurchaseAge.IN_7_D), + }); + + fromPg = (pg: PgTokenPurchase): TokenPurchase => + removeNulls({ + uid: pg.uid, + project: pg.project, + createdOn: pgDateToTimestamp(pg.createdOn), + updatedOn: pgDateToTimestamp(pg.updatedOn), + createdBy: pg.createdBy || '', + + token: pg.token!, + tokenStatus: convertEnum(pg.tokenStatus, PgTokenStatus, TokenStatus)!, + sell: pg.sell!, + buy: pg.buy!, + count: pg.count!, + price: pg.price!, + triggeredBy: convertEnum(pg.triggeredBy, PgTokenTradeOrderType, TokenTradeOrderType)!, + billPaymentId: pg.billPaymentId, + buyerBillPaymentId: pg.buyerBillPaymentId, + royaltyBillPayments: pg.royaltyBillPayments, + sourceNetwork: convertEnum(pg.sourceNetwork, PgNetwork, Network), + targetNetwork: convertEnum(pg.targetNetwork, PgNetwork, Network), + sellerTokenTradingFeePercentage: pg.sellerTokenTradingFeePercentage, + sellerTier: pg.sellerTier, + age: Object.values(TokenPurchaseAge).reduce( + (acc, act) => (pg[act] ? [...acc, act] : acc), + [] as TokenPurchaseAge[], + ), + }); +} diff --git a/packages/database/src/pg/impl/tables/token_rank.ts b/packages/database/src/pg/impl/tables/token_rank.ts new file mode 100644 index 0000000000..9cd4b95b46 --- /dev/null +++ b/packages/database/src/pg/impl/tables/token_rank.ts @@ -0,0 +1,22 @@ +import { COL, Rank } from '@build-5/interfaces'; +import { Converter } from '../../interfaces'; +import { PgTokenRanks } from '../../models'; +import { removeNulls } from '../common'; + +export class TokenRankConverter implements Converter { + toPg = (r: Rank): PgTokenRanks => ({ + uid: r.uid!, + project: r.project, + parentId: r.parentId, + rank: r.rank, + }); + + fromPg = (pg: PgTokenRanks): Rank => + removeNulls({ + uid: pg.uid, + project: pg.project, + parentId: pg.parentId, + parentCol: COL.TOKEN, + rank: pg.rank!, + }); +} diff --git a/packages/database/src/pg/impl/tables/token_stats.ts b/packages/database/src/pg/impl/tables/token_stats.ts new file mode 100644 index 0000000000..89f2bbccfd --- /dev/null +++ b/packages/database/src/pg/impl/tables/token_stats.ts @@ -0,0 +1,74 @@ +import { COL, StakeType, TokenPurchaseAge, TokenStats } from '@build-5/interfaces'; +import { Converter } from '../../interfaces'; +import { PgTokenStats } from '../../models'; +import { removeNulls } from '../common'; + +export class TokenStatsConverter implements Converter { + toPg = (ts: TokenStats): PgTokenStats => ({ + uid: ts.parentId, + project: ts.project, + parentId: ts.parentId, + + votes_upvotes: ts.votes?.upvotes, + votes_downvotes: ts.votes?.downvotes, + votes_voteDiff: ts.votes?.voteDiff, + ranks_count: ts.ranks?.count, + ranks_sum: ts.ranks?.sum, + ranks_avg: ts.ranks?.avg, + volumeTotal: ts.volumeTotal, + volume_in24h: ts.volume[TokenPurchaseAge.IN_24_H], + volume_in48h: ts.volume[TokenPurchaseAge.IN_48_H], + volume_in7d: ts.volume[TokenPurchaseAge.IN_7_D], + stakes_static_amount: ts.stakes?.[StakeType.STATIC]?.amount, + stakes_static_totalAmount: ts.stakes?.[StakeType.STATIC]?.totalAmount, + stakes_static_value: ts.stakes?.[StakeType.STATIC]?.value, + stakes_static_totalValue: ts.stakes?.[StakeType.STATIC]?.totalValue, + stakes_static_stakingMembersCount: ts.stakes?.[StakeType.STATIC]?.stakingMembersCount, + stakes_dynamic_amount: ts.stakes?.[StakeType.DYNAMIC]?.amount, + stakes_dynamic_totalAmount: ts.stakes?.[StakeType.DYNAMIC]?.totalAmount, + stakes_dynamic_value: ts.stakes?.[StakeType.DYNAMIC]?.value, + stakes_dynamic_totalValue: ts.stakes?.[StakeType.DYNAMIC]?.totalValue, + stakes_dynamic_stakingMembersCount: ts.stakes?.[StakeType.DYNAMIC]?.stakingMembersCount, + stakeExpiry: ts.stakeExpiry, + }); + + fromPg = (pg: PgTokenStats): TokenStats => + removeNulls({ + project: pg.project, + parentId: pg.parentId, + parentCol: COL.TOKEN, + volumeTotal: pg.volumeTotal || 0, + volume: { + [TokenPurchaseAge.IN_24_H]: pg.volume_in24h || 0, + [TokenPurchaseAge.IN_48_H]: pg.volume_in48h || 0, + [TokenPurchaseAge.IN_7_D]: pg.volume_in7d || 0, + }, + stakes: { + [StakeType.STATIC]: { + amount: pg.stakes_static_amount || 0, + totalAmount: pg.stakes_static_totalAmount || 0, + value: pg.stakes_static_value || 0, + totalValue: pg.stakes_static_totalValue || 0, + stakingMembersCount: pg.stakes_static_stakingMembersCount || 0, + }, + [StakeType.DYNAMIC]: { + amount: pg.stakes_dynamic_amount || 0, + totalAmount: pg.stakes_dynamic_totalAmount || 0, + value: pg.stakes_dynamic_value || 0, + totalValue: pg.stakes_dynamic_totalValue || 0, + stakingMembersCount: pg.stakes_dynamic_stakingMembersCount || 0, + }, + }, + votes: { + upvotes: pg.votes_upvotes || 0, + downvotes: pg.votes_downvotes || 0, + voteDiff: pg.votes_voteDiff || 0, + }, + ranks: { + sum: pg.ranks_sum || 0, + avg: pg.ranks_avg || 0, + count: pg.ranks_count || 0, + }, + stakeExpiry: pg.stakeExpiry as { [key: string]: { [key: number]: number } }, + }); +} diff --git a/packages/database/src/pg/impl/tables/token_vote.ts b/packages/database/src/pg/impl/tables/token_vote.ts new file mode 100644 index 0000000000..3c19972fc1 --- /dev/null +++ b/packages/database/src/pg/impl/tables/token_vote.ts @@ -0,0 +1,22 @@ +import { COL, Vote } from '@build-5/interfaces'; +import { Converter } from '../../interfaces'; +import { PgTokenVotes } from '../../models'; +import { removeNulls } from '../common'; + +export class TokenVotesConverter implements Converter { + toPg = (r: Vote): PgTokenVotes => ({ + uid: r.uid!, + project: r.project, + parentId: r.parentId, + direction: r.direction, + }); + + fromPg = (pg: PgTokenVotes): Vote => + removeNulls({ + uid: pg.uid, + project: pg.project, + parentId: pg.parentId, + parentCol: COL.TOKEN, + direction: pg.direction! as 1 | -1, + }); +} diff --git a/packages/database/src/pg/impl/tables/transaction.ts b/packages/database/src/pg/impl/tables/transaction.ts new file mode 100644 index 0000000000..8798ece3ee --- /dev/null +++ b/packages/database/src/pg/impl/tables/transaction.ts @@ -0,0 +1,325 @@ +import { + CreditPaymentReason, + Entity, + IgnoreWalletReason, + NativeToken, + Network, + NftBulkOrder, + SendToManyTargets, + StakeType, + StorageReturn, + Transaction, + TransactionPayloadType, + TransactionType, + TransactionValidationType, + UnsoldMintingOptions, +} from '@build-5/interfaces'; +import { Converter } from '../../interfaces'; +import { PgTransaction } from '../../models'; +import { + PgCreditPaymentReason, + PgEntity, + PgIgnoreWalletReason, + PgNetwork, + PgStakeType, + PgTransactionPayloadType, + PgTransactionType, + PgTransactionValidationType, + PgUnsoldMintingOptions, +} from '../../models/enums'; +import { convertEnum, removeNulls } from '../common'; +import { pgDateToTimestamp } from '../postgres'; + +export class TransactionConverter implements Converter { + toPg = (trx: Transaction): PgTransaction => ({ + uid: trx.uid, + project: trx.project, + createdOn: trx.createdOn?.toDate(), + updatedOn: trx.updatedOn?.toDate(), + createdBy: trx.createdBy, + + network: convertEnum(trx.network, Network, PgNetwork), + type: convertEnum(trx.type, TransactionType, PgTransactionType), + isOrderType: trx.isOrderType, + member: trx.member, + space: trx.space, + shouldRetry: trx.shouldRetry, + ignoreWallet: trx.ignoreWallet, + linkedTransactions: trx.linkedTransactions, + ignoreWalletReason: convertEnum( + trx.ignoreWalletReason, + IgnoreWalletReason, + PgIgnoreWalletReason, + ), + payload_type: convertEnum(trx.payload.type, TransactionPayloadType, PgTransactionPayloadType), + payload_amount: trx.payload.amount || 0, + payload_sourceAddress: trx.payload.sourceAddress || '', + payload_targetAddress: trx.payload.targetAddress || '', + payload_targetAddresses: JSON.stringify(trx.payload.targetAddresses) as any, + payload_sourceTransaction: trx.payload.sourceTransaction || [], + payload_validationType: convertEnum( + trx.payload.validationType, + TransactionValidationType, + PgTransactionValidationType, + ), + payload_expiresOn: trx.payload.expiresOn?.toDate(), + payload_reconciled: trx.payload.reconciled, + payload_void: trx.payload.void, + payload_collection: trx.payload.collection || undefined, + payload_unsoldMintingOptions: convertEnum( + trx.payload.unsoldMintingOptions, + UnsoldMintingOptions, + PgUnsoldMintingOptions, + ), + payload_newPrice: trx.payload.newPrice, + payload_collectionStorageDeposit: trx.payload.collectionStorageDeposit, + payload_nftsStorageDeposit: trx.payload.nftsStorageDeposit, + payload_aliasStorageDeposit: trx.payload.aliasStorageDeposit, + payload_nftsToMint: trx.payload.nftsToMint, + payload_transaction: trx.payload.transaction, + payload_unlockedBy: trx.payload.unlockedBy, + payload_beneficiary: convertEnum(trx.payload.beneficiary, Entity, PgEntity), + payload_beneficiaryUid: trx.payload.beneficiaryUid, + payload_beneficiaryAddress: trx.payload.beneficiaryAddress, + payload_royaltiesFee: trx.payload.royaltiesFee, + payload_royaltiesSpace: trx.payload.royaltiesSpace, + payload_royaltiesSpaceAddress: trx.payload.royaltiesSpaceAddress, + payload_chainReference: trx.payload.chainReference || undefined, + payload_nft: trx.payload.nft || undefined, + payload_restrictions: JSON.stringify(trx.payload.restrictions) as any, + payload_token: trx.payload.token, + payload_quantity: trx.payload.quantity, + payload_tokenSymbol: trx.payload.tokenSymbol, + payload_unclaimedAirdrops: trx.payload.unclaimedAirdrops, + payload_totalAirdropCount: trx.payload.totalAirdropCount, + payload_tokenId: trx.payload.tokenId, + payload_foundryStorageDeposit: trx.payload.foundryStorageDeposit, + payload_vaultStorageDeposit: trx.payload.vaultStorageDeposit, + payload_guardianStorageDeposit: trx.payload.guardianStorageDeposit, + payload_tokensInVault: trx.payload.tokensInVault, + payload_orderId: trx.payload.orderId, + payload_collectionOutputAmount: trx.payload.collectionOutputAmount, + payload_aliasOutputAmount: trx.payload.aliasOutputAmount, + payload_nftOutputAmount: trx.payload.nftOutputAmount, + payload_aliasId: trx.payload.aliasId, + payload_aliasBlockId: trx.payload.aliasBlockId, + payload_aliasGovAddress: trx.payload.aliasGovAddress, + payload_collectionId: trx.payload.collectionId || undefined, + payload_nftId: trx.payload.nftId || undefined, + payload_nativeTokens: JSON.stringify( + trx.payload.nativeTokens?.map((nt) => ({ ...nt, amount: Number(nt.amount) })), + ) as any, + payload_previousOwnerEntity: convertEnum(trx.payload.previousOwnerEntity, Entity, PgEntity), + payload_previousOwner: trx.payload.previousOwner, + payload_ownerEntity: convertEnum(trx.payload.ownerEntity, Entity, PgEntity), + payload_owner: trx.payload.owner, + payload_royalty: trx.payload.royalty, + payload_vestingAt: trx.payload.vestingAt?.toDate(), + payload_customMetadata: JSON.stringify(trx.payload.customMetadata) as any, + payload_stake: trx.payload.stake, + payload_award: trx.payload.award || undefined, + payload_legacyAwardFundRequestId: trx.payload.legacyAwardFundRequestId, + payload_legacyAwardsBeeingFunded: trx.payload.legacyAwardsBeeingFunded, + payload_weeks: trx.payload.weeks, + payload_stakeType: convertEnum(trx.payload.stakeType, StakeType, PgStakeType), + payload_count: trx.payload.count, + payload_price: trx.payload.price, + payload_tokenReward: trx.payload.tokenReward, + payload_edition: trx.payload.edition, + payload_participatedOn: trx.payload.participatedOn?.toDate(), + payload_proposalId: trx.payload.proposalId, + payload_voteValues: trx.payload.voteValues, + payload_storageDepositSourceAddress: trx.payload.storageDepositSourceAddress, + payload_storageReturn: JSON.stringify(trx.payload.storageReturn) as any, + payload_airdropId: trx.payload.airdropId, + payload_nfts: trx.payload.nfts, + payload_tag: trx.payload.tag, + payload_metadata: JSON.stringify(trx.payload.metadata) as any, + payload_response: JSON.stringify(trx.payload.response) as any, + payload_reason: convertEnum(trx.payload.reason, CreditPaymentReason, PgCreditPaymentReason), + payload_invalidPayment: trx.payload.invalidPayment, + payload_outputToConsume: trx.payload.outputToConsume, + payload_dependsOnBillPayment: trx.payload.dependsOnBillPayment, + payload_milestoneTransactionPath: trx.payload.milestoneTransactionPath, + payload_tokenAmount: trx.payload.tokenAmount, + payload_weight: trx.payload.weight, + payload_weightMultiplier: trx.payload.weightMultiplier, + payload_votes: trx.payload.votes, + payload_creditId: trx.payload.creditId, + payload_outputConsumed: trx.payload.outputConsumed, + payload_outputConsumedOn: trx.payload.outputConsumedOn?.toDate(), + payload_stakes: trx.payload.stakes, + payload_stakeReward: trx.payload.stakeReward, + payload_tanglePuchase: trx.payload.tanglePuchase, + payload_disableWithdraw: trx.payload.disableWithdraw, + payload_lockCollectionNft: trx.payload.lockCollectionNft, + payload_stamp: trx.payload.stamp, + payload_tokenTradeOderTargetAddress: trx.payload.tokenTradeOderTargetAddress, + payload_auction: trx.payload.auction, + payload_days: trx.payload.days, + payload_dailyCost: trx.payload.dailyCost, + payload_nftOrders: JSON.stringify(trx.payload.nftOrders) as any, + payload_swap: trx.payload.swap, + payload_outputId: trx.payload.outputId, + payload_walletReference_createdOn: trx.payload.walletReference?.createdOn?.toDate(), + payload_walletReference_processedOn: trx.payload.walletReference?.processedOn?.toDate(), + payload_walletReference_chainReference: + trx.payload.walletReference?.chainReference || undefined, + payload_walletReference_chainReferences: trx.payload.walletReference?.chainReferences, + payload_walletReference_error: trx.payload.walletReference?.error as string, + payload_walletReference_confirmed: trx.payload.walletReference?.confirmed, + payload_walletReference_confirmedOn: trx.payload.walletReference?.confirmedOn?.toDate(), + payload_walletReference_milestoneTransactionPath: + trx.payload.walletReference?.milestoneTransactionPath, + payload_walletReference_count: trx.payload.walletReference?.count, + payload_walletReference_inProgress: trx.payload.walletReference?.inProgress, + payload_walletReference_nodeIndex: trx.payload.walletReference?.nodeIndex, + payload_values: trx.payload.values, + }); + + fromPg = (pg: PgTransaction): Transaction => + removeNulls({ + uid: pg.uid, + project: pg.project, + createdOn: pgDateToTimestamp(pg.createdOn), + updatedOn: pgDateToTimestamp(pg.updatedOn), + createdBy: pg.createdBy || '', + network: convertEnum(pg.network, PgNetwork, Network)!, + type: convertEnum(pg.type, PgTransactionType, TransactionType)!, + isOrderType: pg.isOrderType, + member: pg.member, + space: pg.space, + shouldRetry: pg.shouldRetry, + ignoreWallet: pg.ignoreWallet, + linkedTransactions: pg.linkedTransactions, + ignoreWalletReason: convertEnum( + pg.ignoreWalletReason, + PgIgnoreWalletReason, + IgnoreWalletReason, + ), + payload: { + type: convertEnum(pg.payload_type, PgTransactionPayloadType, TransactionPayloadType), + amount: pg.payload_amount, + sourceAddress: pg.payload_sourceAddress, + targetAddress: pg.payload_targetAddress, + targetAddresses: pg.payload_targetAddresses as SendToManyTargets[] | undefined, + sourceTransaction: pg.payload_sourceTransaction, + validationType: convertEnum( + pg.payload_validationType, + PgTransactionValidationType, + TransactionValidationType, + ) as TransactionValidationType, + expiresOn: pgDateToTimestamp(pg.payload_expiresOn), + reconciled: pg.payload_reconciled, + void: pg.payload_void, + collection: pg.payload_collection, + unsoldMintingOptions: convertEnum( + pg.payload_unsoldMintingOptions, + PgUnsoldMintingOptions, + UnsoldMintingOptions, + ) as UnsoldMintingOptions, + newPrice: pg.payload_newPrice, + collectionStorageDeposit: pg.payload_collectionStorageDeposit, + nftsStorageDeposit: pg.payload_nftsStorageDeposit, + aliasStorageDeposit: pg.payload_aliasStorageDeposit, + nftsToMint: pg.payload_nftsToMint, + transaction: pg.payload_transaction, + unlockedBy: pg.payload_unlockedBy, + beneficiary: convertEnum(pg.payload_beneficiary, PgEntity, Entity), + beneficiaryUid: pg.payload_beneficiaryUid, + beneficiaryAddress: pg.payload_beneficiaryAddress, + royaltiesFee: pg.payload_royaltiesFee, + royaltiesSpace: pg.payload_royaltiesSpace, + royaltiesSpaceAddress: pg.payload_royaltiesSpaceAddress, + chainReference: pg.payload_chainReference, + nft: pg.payload_nft, + restrictions: pg.payload_restrictions as any, + token: pg.payload_token, + quantity: pg.payload_quantity, + tokenSymbol: pg.payload_tokenSymbol, + unclaimedAirdrops: pg.payload_unclaimedAirdrops, + totalAirdropCount: pg.payload_totalAirdropCount, + tokenId: pg.payload_tokenId, + foundryStorageDeposit: pg.payload_foundryStorageDeposit, + vaultStorageDeposit: pg.payload_vaultStorageDeposit, + guardianStorageDeposit: pg.payload_guardianStorageDeposit, + tokensInVault: pg.payload_tokensInVault, + orderId: pg.payload_orderId, + collectionOutputAmount: pg.payload_collectionOutputAmount, + aliasOutputAmount: pg.payload_aliasOutputAmount, + nftOutputAmount: pg.payload_nftOutputAmount, + aliasId: pg.payload_aliasId, + aliasBlockId: pg.payload_aliasBlockId, + aliasGovAddress: pg.payload_aliasGovAddress, + collectionId: pg.payload_collectionId, + nftId: pg.payload_nftId, + nativeTokens: pg.payload_nativeTokens as NativeToken[] | undefined, + previousOwnerEntity: convertEnum(pg.payload_previousOwnerEntity, PgEntity, Entity), + previousOwner: pg.payload_previousOwner, + ownerEntity: convertEnum(pg.payload_ownerEntity, PgEntity, Entity), + owner: pg.payload_owner, + royalty: pg.payload_royalty, + vestingAt: pgDateToTimestamp(pg.payload_vestingAt), + customMetadata: pg.payload_customMetadata as { [key: string]: string } | undefined, + stake: pg.payload_stake, + award: pg.payload_award, + legacyAwardFundRequestId: pg.payload_legacyAwardFundRequestId, + legacyAwardsBeeingFunded: pg.payload_legacyAwardsBeeingFunded, + weeks: pg.payload_weeks, + stakeType: convertEnum(pg.payload_stakeType, PgStakeType, StakeType), + count: pg.payload_count, + price: pg.payload_price, + tokenReward: pg.payload_tokenReward, + edition: pg.payload_edition, + participatedOn: pgDateToTimestamp(pg.payload_participatedOn), + proposalId: pg.payload_proposalId, + voteValues: pg.payload_voteValues, + storageDepositSourceAddress: pg.payload_storageDepositSourceAddress, + storageReturn: pg.payload_storageReturn as StorageReturn | undefined, + airdropId: pg.payload_airdropId, + outputId: pg.payload_outputId, + walletReference: { + createdOn: pgDateToTimestamp(pg.payload_walletReference_createdOn)!, + processedOn: pgDateToTimestamp(pg.payload_walletReference_processedOn)!, + chainReference: pg.payload_walletReference_chainReference, + chainReferences: pg.payload_walletReference_chainReferences, + error: pg.payload_walletReference_error, + confirmed: pg.payload_walletReference_confirmed || false, + confirmedOn: pgDateToTimestamp(pg.payload_walletReference_confirmedOn), + milestoneTransactionPath: pg.payload_walletReference_milestoneTransactionPath, + count: pg.payload_walletReference_count || 0, + inProgress: pg.payload_walletReference_inProgress, + nodeIndex: pg.payload_walletReference_nodeIndex, + }, + nfts: pg.payload_nfts, + tag: pg.payload_tag, + metadata: pg.payload_metadata as any, + response: pg.payload_response as any, + reason: convertEnum(pg.payload_reason, PgCreditPaymentReason, CreditPaymentReason), + invalidPayment: pg.payload_invalidPayment, + outputToConsume: pg.payload_outputToConsume, + dependsOnBillPayment: pg.payload_dependsOnBillPayment, + milestoneTransactionPath: pg.payload_milestoneTransactionPath, + values: pg.payload_values, + tokenAmount: pg.payload_tokenAmount, + weight: pg.payload_weight, + weightMultiplier: pg.payload_weightMultiplier, + votes: pg.payload_votes, + creditId: pg.payload_creditId, + outputConsumed: pg.payload_outputConsumed, + outputConsumedOn: pgDateToTimestamp(pg.payload_outputConsumedOn), + stakes: pg.payload_stakes, + stakeReward: pg.payload_stakeReward, + tanglePuchase: pg.payload_tanglePuchase, + disableWithdraw: pg.payload_disableWithdraw, + lockCollectionNft: pg.payload_lockCollectionNft, + stamp: pg.payload_stamp, + tokenTradeOderTargetAddress: pg.payload_tokenTradeOderTargetAddress, + auction: pg.payload_auction, + days: pg.payload_days, + dailyCost: pg.payload_dailyCost, + nftOrders: pg.payload_nftOrders as NftBulkOrder[] | undefined, + swap: pg.payload_swap, + }, + }); +} diff --git a/packages/database/src/pg/index.ts b/packages/database/src/pg/index.ts new file mode 100644 index 0000000000..0f92f8f1bd --- /dev/null +++ b/packages/database/src/pg/index.ts @@ -0,0 +1,8 @@ +export * from './impl/common'; +export * from './impl/instance'; +export { MilestoneTransactions } from './impl/tables/milestone_transactions'; +export * from './interfaces'; +export * from './models'; +export * from './models/common'; +export * from './models/common_update'; +export * from './models/enums'; diff --git a/packages/database/src/pg/interfaces.ts b/packages/database/src/pg/interfaces.ts new file mode 100644 index 0000000000..86dedfc23f --- /dev/null +++ b/packages/database/src/pg/interfaces.ts @@ -0,0 +1,486 @@ +import { COL, SUB_COL } from '@build-5/interfaces'; +import { Message, Subscription } from '@google-cloud/pubsub'; +import { Knex } from 'knex'; +import { get, head, isArray, isDate, isObject, isUndefined, uniq, unset } from 'lodash'; +import { undefinedToNull } from './impl/common'; +import { IColType, IDocType } from './impl/postgres'; +import { getSubscription } from './impl/pubsub'; +import { BaseRecord } from './models/common'; +import { Update } from './models/common_update'; + +export interface IDatabase { + collection: ( + col: C, + colId?: string, + subCol?: S, + ) => IColType; + + doc: ( + col: C, + colId: string, + subCol?: S, + subColId?: string, + ) => IDocType; + + batch: () => IBatch; + runTransaction: (func: (transaction: ITransaction) => Promise) => Promise; + + inc: (value: number) => Increment; + arrayUnion: (value: T) => ArrayUnion; + arrayRemove: (value: T) => ArrayRemove; + + destroy: () => Promise; + + getCon: () => Knex; +} + +export class ICollection { + protected table: string = ''; + + constructor( + protected con: Knex, + protected col: COL, + protected converter: Converter, + ) { + this.table = getTableName(col); + } + + protected createQuery = () => new IQuery(this.con, this.col, this.converter); + + doc = (colId: string) => new IDocument(this.con, this.col, colId, this.converter); + + get = () => this.createQuery().get(); + + where = ( + fieldPath: F, + operator: WhereFilterOp, + value: Q[F] | undefined | null, + ) => this.createQuery().where(fieldPath, operator, value); + + update = async (data: U, where: Record) => { + await this.con(this.table).update(undefinedToNull(data)).where(where); + }; + + delete = async (where: Record) => + await this.con(this.table).delete().where(where); + + count = async () => { + const result = await this.con(this.table).count(); + return Number(head(result)?.count || 0); + }; + + limit = (limit: number) => this.createQuery().limit(limit); + + orderBy = (fieldPath: F, dir?: 'asc' | 'desc') => + this.createQuery().orderBy(fieldPath, dir); +} + +export class ISubCollection extends ICollection< + T, + Q, + U +> { + constructor( + con: Knex, + col: COL, + protected colId: string, + protected subCol: SUB_COL, + protected converter: Converter, + ) { + super(con, col, converter); + this.table = getTableName(col, subCol); + } + + protected createQuery = () => + new ISubColQuery(this.con, this.col, this.colId, this.subCol, this.converter); + + doc = (subColId: string) => + new ISubDocument(this.con, this.col, this.colId, this.subCol, subColId, this.converter); + + count = async () => { + const result = await this.con(this.table).where({ parentId: this.colId }).count(); + return Number(head(result)?.count || 0); + }; +} + +interface PKey { + uid: string; + parentId?: string; +} + +export interface Converter { + toPg: (data: C) => B; + fromPg: (data: B) => C; +} + +export class IDocument { + protected pKey: PKey = { uid: '' }; + protected isOuterTransaction = false; + protected table: string; + + constructor( + protected con: Knex | Knex.Transaction, + protected col: COL, + protected colId: string, + public converter: Converter, + ) { + this.table = getTableName(col); + this.pKey.uid = colId; + } + + create = async (data: C): Promise => { + const pgData = this.converter.toPg({ ...data, ...this.pKey }); + await this.con(this.table).insert(pgData); + }; + + private rawQuery = () => { + let query = this.con(this.table).first().where(this.pKey); + if (this.con.isTransaction) { + query = query.forUpdate().noWait(); + } + return query; + }; + + get = async (): Promise => { + const snap = await this.rawQuery(); + return snap ? this.converter.fromPg(snap) : undefined; + }; + + onSnapshot = ( + callback: (data: C | undefined) => Promise | void, + _error?: (err: any) => void, + ) => { + const onMemssage = (message: Message) => { + message.ack(); + const data = JSON.parse(message.data.toString()); + if (data.uid === this.pKey.uid && data.parentId === this.pKey.parentId) { + callback(this.converter.fromPg(data)); + } + }; + let subscription: Subscription | undefined = undefined; + + this.rawQuery().then(async (raw) => { + callback(this.converter.fromPg(raw)); + subscription = await getSubscription(this.table); + subscription.on('message', onMemssage); + }); + + return () => { + subscription?.removeListener('message', onMemssage); + }; + }; + + update = async (data: U) => { + unset(data, 'parentCol'); + const update = toRaw(this.con, data); + await this.con(this.table).update(update).where(this.pKey); + }; + + upsert = async (data: U) => { + unset(data, 'parentCol'); + const update = toRaw(this.con, data); + const trx = await this.getTransaction(); + await trx(this.table).insert(this.pKey).onConflict(Object.keys(this.pKey)).ignore(); + await trx(this.table).update(update).where(this.pKey); + await this.commit(trx); + }; + + delete = async () => { + await this.con(this.table).delete().where(this.pKey); + }; + + useTransaction = async ( + trx: Knex.Transaction, + func: (doc: IDocument) => Promise, + ): Promise => { + const con = this.con; + try { + this.con = trx; + this.isOuterTransaction = true; + return await func(this); + } finally { + this.con = con; + this.isOuterTransaction = false; + } + }; + + protected getTransaction = async (): Promise => + this.isOuterTransaction ? (this.con as Knex.Transaction) : await this.con.transaction(); + + protected commit = async (trx: Knex.Transaction) => { + if (this.isOuterTransaction) { + return; + } + try { + await trx.commit(); + } catch (err) { + await trx.rollback(); + throw err; + } + }; +} + +const toRaw = (knex: Knex, data: any) => + Object.entries(data).reduce((acc, [key, value]) => { + if (value instanceof Increment) { + return { + ...acc, + [key]: knex.raw(`COALESCE("${key}", 0) + ?`, [value.value]), + }; + } + if (value instanceof ArrayUnion) { + return { + ...acc, + [key]: knex.raw(`array_cat("${key}", ?)`, [[value.value]]), + }; + } + if (value instanceof ArrayRemove) { + return { + ...acc, + [key]: knex.raw(`array_remove("${key}", ?)`, [value.value]), + }; + } + + if (isObject(value) && !isArray(value) && !isDate(value)) { + return { ...acc, [key]: knex.raw(objectToJsonRaw(`"${key}"`, value)) }; + } + + return { ...acc, [key]: isUndefined(value) ? null : value }; + }, {}); + +const objectToJsonRaw = (column: string, data: any, keys: string[] = [], acc = column) => { + let actAcc = acc; + Object.entries(data).forEach(([key, value]) => { + const setPath = [...keys, key].join(', '); + const fullPath = `${column}->${[...keys, key].map((k) => `'${k}'`).join('->')}`; + if (!value) { + actAcc = `jsonb_strip_nulls(jsonb_set(${actAcc}, '{${setPath}}', '${value}'))`; + return; + } + if (value instanceof Increment) { + actAcc = + `jsonb_set(${actAcc}, '{${setPath}}', ` + + `to_jsonb(COALESCE((${fullPath})::numeric, 0) + ${value.value})::jsonb` + + ')'; + return; + } + if (value instanceof ArrayUnion) { + actAcc = + `jsonb_set(${actAcc}, '{${setPath}}', ` + + `COALESCE((${fullPath}), '[]'::jsonb) || '${JSON.stringify(value.value)}'::jsonb)`; + return; + } + if (typeof value === 'object') { + actAcc = `jsonb_set(${actAcc}, '{${setPath}}', COALESCE(${fullPath} ,'{}'::jsonb))`; + actAcc = objectToJsonRaw(column, value, [...keys, key], actAcc); + return; + } + if (typeof value === 'string') { + actAcc = `jsonb_set(${actAcc}, '{${setPath}}', '"${value}"')`; + return; + } + actAcc = `jsonb_set(${actAcc}, '{${setPath}}', '${value}')`; + }); + return actAcc; +}; + +export class ISubDocument extends IDocument { + constructor( + con: Knex | Knex.Transaction, + col: COL, + colId: string, + protected subCol: SUB_COL, + protected subColId: string, + converter: Converter, + ) { + super(con, col, colId, converter); + this.pKey.uid = subColId; + this.pKey.parentId = this.colId; + this.table = getTableName(col, subCol); + } +} + +export interface IBatch { + create: (docRef: IDocument, data: C) => void; + update: (docRef: IDocument, data: U) => void; + upsert: (docRef: IDocument, data: U) => void; + delete: (docRef: IDocument) => void; + commit: () => Promise; +} + +export interface ITransaction { + get: ( + docRef: IDocument, + ) => Promise; + getAll: ( + ...docRefs: IDocument[] + ) => Promise<(C | undefined)[]>; + + create: ( + docRef: IDocument, + data: C, + ) => Promise; + update: ( + docRef: IDocument, + data: U, + ) => Promise; + upsert: ( + docRef: IDocument, + data: U, + ) => Promise; + delete: (docRef: IDocument) => Promise; +} + +export class IQuery { + protected query: Knex.QueryBuilder; + protected table: string; + protected startAfterData: C | undefined = undefined; + protected orderBys: string[] = []; + + constructor( + protected con: Knex, + protected col: COL, + protected converter: Converter, + ) { + this.table = getTableName(col); + this.query = con(this.table).select('*'); + } + + private rawQuery = () => { + let q = this.query; + + if (this.startAfterData) { + const orderBy = uniq([...this.orderBys, 'uid']); + q = q.whereRaw( + `(${orderBy.join(', ')}) > (${orderBy.map(() => '?').join(', ')})`, + orderBy.map((o) => get(this.startAfterData, o, null)), + ); + } + + if (!this.orderBys.includes('uid')) { + q = q.orderBy('uid'); + } + + return q; + }; + + get = async (): Promise => { + const snap = await this.rawQuery(); + return snap.map(this.converter.fromPg); + }; + + onSnapshot = (callback: (data: C[]) => Promise | void, _error?: (err: any) => void) => { + let pgData: Q[] = []; + let data: C[] = []; + let keys: { [key: string]: number } = {}; + + const onMemssage = (message: Message) => { + message.ack(); + const data = JSON.parse(message.data.toString()); + const key = `${data.uid}_${get(data, 'parentId', '')}`; + const index = keys[key]; + if (index !== undefined) { + data[index] = data; + callback(data); + } + }; + + let subscription: Subscription | undefined = undefined; + + this.rawQuery().then(async (raw: Q[]) => { + pgData = raw; + data = pgData.map(this.converter.fromPg); + keys = pgData.reduce( + (acc, act, i) => { + const key = `${act.uid}_${get(act, 'parentId', '')}`; + return { ...acc, [key]: i }; + }, + {} as { [key: string]: number }, + ); + + callback(data); + + subscription = await getSubscription(this.table); + subscription.on('message', onMemssage); + }); + + return () => { + subscription?.removeListener('message', onMemssage); + }; + }; + + whereOr = (filters: Record) => { + this.query.andWhere((builder) => { + Object.entries(filters).forEach(([key, value]) => { + builder.orWhere(key, value as any); + }); + }); + return this; + }; + + where = ( + fieldPath: F, + operator: WhereFilterOp, + value: Q[F] | undefined | null, + ): IQuery => { + if (operator === 'array-contains') { + this.query.andWhere(fieldPath as string, '@>', `{${value}}`); + } else { + const opr = operator === '==' ? '=' : operator; + this.query.andWhere(fieldPath as any, opr, value as any); + } + return this; + }; + + whereIn = (fieldPath: F, value: Q[F][]): IQuery => { + this.query.whereIn(fieldPath as any, value as any); + return this; + }; + + startAfter = (data: C) => { + this.startAfterData = data; + return this; + }; + + limit = (value: number): IQuery => { + this.query.limit(value); + return this; + }; + + orderBy = (fieldPath: F, dir?: 'asc' | 'desc') => { + this.query.orderBy(fieldPath, dir); + this.orderBys.push(fieldPath as string); + return this; + }; +} + +export class ISubColQuery extends IQuery { + constructor( + protected con: Knex, + protected col: COL, + protected colId: string, + protected subCol: SUB_COL, + converter: Converter, + ) { + super(con, col, converter); + this.table = getTableName(col, subCol); + this.query = con(this.table).select('*').where({ parentId: colId }); + } +} + +export class Increment { + constructor(public value: number) {} +} + +export class ArrayUnion { + constructor(public value: T) {} +} + +export class ArrayRemove { + constructor(public value: T) {} +} + +export type WhereFilterOp = '<' | '<=' | '==' | '!=' | '>=' | '>' | 'array-contains'; + +const getTableName = (col: COL, subCol?: SUB_COL) => + (col + (subCol ? '_' + subCol : '')).toLowerCase(); diff --git a/packages/database/src/pg/models/airdrop.ts b/packages/database/src/pg/models/airdrop.ts new file mode 100644 index 0000000000..304eef6ae2 --- /dev/null +++ b/packages/database/src/pg/models/airdrop.ts @@ -0,0 +1,21 @@ +/** + * This file was automatically generated by knex + * Do not modify this file manually + */ +import * as commons from './common'; +import * as enums from './enums'; + +export interface PgAirdrop extends commons.BaseRecord { + member?: string; + token?: string; + award?: string; + vestingAt?: Date; + count?: number; + status?: enums.PgTokenDropStatus; + orderId?: string; + billPaymentId?: string; + sourceAddress?: string; + stakeRewardId?: string; + stakeType?: enums.PgStakeType; + isBaseToken?: boolean; +} diff --git a/packages/database/src/pg/models/airdrop_update.ts b/packages/database/src/pg/models/airdrop_update.ts new file mode 100644 index 0000000000..84d5f66883 --- /dev/null +++ b/packages/database/src/pg/models/airdrop_update.ts @@ -0,0 +1,22 @@ +/** + * This file was automatically generated by knex + * Do not modify this file manually + */ +import { Increment } from '../interfaces'; +import * as commons from './common_update'; +import * as enums from './enums'; + +export interface PgAirdropUpdate extends commons.BaseRecordUpdate { + member?: string | null; + token?: string | null; + award?: string | null; + vestingAt?: Date | null; + count?: number | null | Increment; + status?: enums.PgTokenDropStatus | null; + orderId?: string | null; + billPaymentId?: string | null; + sourceAddress?: string | null; + stakeRewardId?: string | null; + stakeType?: enums.PgStakeType | null; + isBaseToken?: boolean | null; +} diff --git a/packages/database/src/pg/models/auction.ts b/packages/database/src/pg/models/auction.ts new file mode 100644 index 0000000000..c63ccbe862 --- /dev/null +++ b/packages/database/src/pg/models/auction.ts @@ -0,0 +1,28 @@ +/** + * This file was automatically generated by knex + * Do not modify this file manually + */ +import * as commons from './common'; +import * as enums from './enums'; + +export interface PgAuction extends commons.BaseRecord { + space?: string; + auctionFrom?: Date; + auctionTo?: Date; + auctionLength?: number; + extendedAuctionTo?: Date; + extendedAuctionLength?: number; + extendAuctionWithin?: number; + auctionFloorPrice?: number; + minimalBidIncrement?: number; + auctionHighestBidder?: string; + auctionHighestBid?: number; + maxBids?: number; + type?: enums.PgAuctionType; + network?: enums.PgNetwork; + nftId?: string; + targetAddress?: string; + active?: boolean; + topUpBased?: boolean; + bids?: Record[]; +} diff --git a/packages/database/src/pg/models/auction_update.ts b/packages/database/src/pg/models/auction_update.ts new file mode 100644 index 0000000000..3577632c61 --- /dev/null +++ b/packages/database/src/pg/models/auction_update.ts @@ -0,0 +1,29 @@ +/** + * This file was automatically generated by knex + * Do not modify this file manually + */ +import { Increment } from '../interfaces'; +import * as commons from './common_update'; +import * as enums from './enums'; + +export interface PgAuctionUpdate extends commons.BaseRecordUpdate { + space?: string | null; + auctionFrom?: Date | null; + auctionTo?: Date | null; + auctionLength?: number | null | Increment; + extendedAuctionTo?: Date | null; + extendedAuctionLength?: number | null | Increment; + extendAuctionWithin?: number | null | Increment; + auctionFloorPrice?: number | null | Increment; + minimalBidIncrement?: number | null | Increment; + auctionHighestBidder?: string | null; + auctionHighestBid?: number | null | Increment; + maxBids?: number | null | Increment; + type?: enums.PgAuctionType | null; + network?: enums.PgNetwork | null; + nftId?: string | null; + targetAddress?: string | null; + active?: boolean | null; + topUpBased?: boolean | null; + bids?: string | null; +} diff --git a/packages/database/src/pg/models/award.ts b/packages/database/src/pg/models/award.ts new file mode 100644 index 0000000000..7ca5ec32ca --- /dev/null +++ b/packages/database/src/pg/models/award.ts @@ -0,0 +1,57 @@ +/** + * This file was automatically generated by knex + * Do not modify this file manually + */ +import * as commons from './common'; +import * as enums from './enums'; + +export interface PgAwardParticipants extends commons.BaseSubRecord { + comment?: string; + completed?: boolean; + count?: number; + tokenReward?: number; +} + +export interface PgAwardOwners extends commons.BaseSubRecord {} + +export interface PgAward extends commons.BaseRecord { + name?: string; + description?: string; + space?: string; + endDate?: Date; + issued?: number; + badgesMinted?: number; + approved?: boolean; + rejected?: boolean; + completed?: boolean; + network?: enums.PgNetwork; + aliasStorageDeposit?: number; + collectionStorageDeposit?: number; + nttStorageDeposit?: number; + nativeTokenStorageDeposit?: number; + funded?: boolean; + fundingAddress?: string; + fundedBy?: string; + address?: string; + airdropClaimed?: number; + aliasBlockId?: string; + aliasId?: string; + collectionBlockId?: string; + collectionId?: string; + mediaStatus?: enums.PgMediaStatus; + mediaUploadErrorCount?: number; + isLegacy?: boolean; + badge_name?: string; + badge_description?: string; + badge_total?: number; + badge_type?: enums.PgAwardBadgeType; + badge_tokenReward?: number; + badge_tokenUid?: string; + badge_tokenId?: string; + badge_tokenSymbol?: string; + badge_image?: string; + badge_ipfsMedia?: string; + badge_ipfsMetadata?: string; + badge_ipfsRoot?: string; + badge_lockTime?: number; +} diff --git a/packages/database/src/pg/models/award_update.ts b/packages/database/src/pg/models/award_update.ts new file mode 100644 index 0000000000..08b3405d5b --- /dev/null +++ b/packages/database/src/pg/models/award_update.ts @@ -0,0 +1,58 @@ +/** + * This file was automatically generated by knex + * Do not modify this file manually + */ +import { Increment } from '../interfaces'; +import * as commons from './common_update'; +import * as enums from './enums'; + +export interface PgAwardParticipantsUpdate extends commons.BaseSubRecordUpdate { + comment?: string | null; + completed?: boolean | null; + count?: number | null | Increment; + tokenReward?: number | null | Increment; +} + +export interface PgAwardOwnersUpdate extends commons.BaseSubRecordUpdate {} + +export interface PgAwardUpdate extends commons.BaseRecordUpdate { + name?: string | null; + description?: string | null; + space?: string | null; + endDate?: Date | null; + issued?: number | null | Increment; + badgesMinted?: number | null | Increment; + approved?: boolean | null; + rejected?: boolean | null; + completed?: boolean | null; + network?: enums.PgNetwork | null; + aliasStorageDeposit?: number | null | Increment; + collectionStorageDeposit?: number | null | Increment; + nttStorageDeposit?: number | null | Increment; + nativeTokenStorageDeposit?: number | null | Increment; + funded?: boolean | null; + fundingAddress?: string | null; + fundedBy?: string | null; + address?: string | null; + airdropClaimed?: number | null | Increment; + aliasBlockId?: string | null; + aliasId?: string | null; + collectionBlockId?: string | null; + collectionId?: string | null; + mediaStatus?: enums.PgMediaStatus | null; + mediaUploadErrorCount?: number | null | Increment; + isLegacy?: boolean | null; + badge_name?: string | null; + badge_description?: string | null; + badge_total?: number | null | Increment; + badge_type?: enums.PgAwardBadgeType | null; + badge_tokenReward?: number | null | Increment; + badge_tokenUid?: string | null; + badge_tokenId?: string | null; + badge_tokenSymbol?: string | null; + badge_image?: string | null; + badge_ipfsMedia?: string | null; + badge_ipfsMetadata?: string | null; + badge_ipfsRoot?: string | null; + badge_lockTime?: number | null | Increment; +} diff --git a/packages/database/src/pg/models/changes.ts b/packages/database/src/pg/models/changes.ts new file mode 100644 index 0000000000..94f0f69842 --- /dev/null +++ b/packages/database/src/pg/models/changes.ts @@ -0,0 +1,9 @@ +/** + * This file was automatically generated by knex + * Do not modify this file manually + */ +import * as commons from './common'; + +export interface PgChanges extends commons.BaseRecord { + change?: Record; +} diff --git a/packages/database/src/pg/models/changes_update.ts b/packages/database/src/pg/models/changes_update.ts new file mode 100644 index 0000000000..6488048de9 --- /dev/null +++ b/packages/database/src/pg/models/changes_update.ts @@ -0,0 +1,9 @@ +/** + * This file was automatically generated by knex + * Do not modify this file manually + */ +import * as commons from './common_update'; + +export interface PgChangesUpdate extends commons.BaseRecordUpdate { + change?: string | any | null; +} diff --git a/packages/database/src/pg/models/collection.ts b/packages/database/src/pg/models/collection.ts new file mode 100644 index 0000000000..d257c5d631 --- /dev/null +++ b/packages/database/src/pg/models/collection.ts @@ -0,0 +1,88 @@ +/** + * This file was automatically generated by knex + * Do not modify this file manually + */ +import * as commons from './common'; +import * as enums from './enums'; + +export interface PgCollectionVotes extends commons.BaseSubRecord { + direction?: number; +} + +export interface PgCollectionStats extends commons.BaseSubRecord { + votes_upvotes?: number; + votes_downvotes?: number; + votes_voteDiff?: number; + ranks_count?: number; + ranks_sum?: number; + ranks_avg?: number; +} + +export interface PgCollectionRanks extends commons.BaseSubRecord { + rank?: number; +} + +export interface PgCollection extends commons.BaseRecord { + name?: string; + description?: string; + bannerUrl?: string; + royaltiesFee?: number; + royaltiesSpace?: string; + total?: number; + totalTrades?: number; + lastTradedOn?: Date; + sold?: number; + discord?: string; + url?: string; + twitter?: string; + approved?: boolean; + rejected?: boolean; + limitedEdition?: boolean; + ipfsMedia?: string; + ipfsMetadata?: string; + ipfsRoot?: string; + category?: enums.PgCategories; + type?: enums.PgCollectionType; + access?: enums.PgAccess; + accessAwards?: string[]; + accessCollections?: string[]; + space?: string; + availableFrom?: Date; + price?: number; + availablePrice?: number; + onePerMemberOnly?: boolean; + placeholderNft?: string; + placeholderUrl?: string; + status?: enums.PgCollectionStatus; + mintingData_address?: string; + mintingData_network?: enums.PgNetwork; + mintingData_mintedOn?: Date; + mintingData_mintedBy?: string; + mintingData_blockId?: string; + mintingData_nftId?: string; + mintingData_storageDeposit?: number; + mintingData_aliasBlockId?: string; + mintingData_aliasId?: string; + mintingData_aliasStorageDeposit?: number; + mintingData_mintingOrderId?: string; + mintingData_nftsToMint?: number; + mintingData_nftMediaToUpload?: number; + mintingData_nftMediaToPrepare?: number; + mintingData_unsoldMintingOptions?: enums.PgUnsoldMintingOptions; + mintingData_newPrice?: number; + mintingData_nftsStorageDeposit?: number; + rankCount?: number; + rankSum?: number; + rankAvg?: number; + mediaStatus?: enums.PgMediaStatus; + mediaUploadErrorCount?: number; + stakedNft?: number; + nftsOnSale?: number; + nftsOnAuction?: number; + availableNfts?: number; + floorPrice?: number; + votes_upvotes?: number; + votes_downvotes?: number; + votes_voteDiff?: number; + discounts?: Record[]; +} diff --git a/packages/database/src/pg/models/collection_update.ts b/packages/database/src/pg/models/collection_update.ts new file mode 100644 index 0000000000..48ba6f5ec5 --- /dev/null +++ b/packages/database/src/pg/models/collection_update.ts @@ -0,0 +1,89 @@ +/** + * This file was automatically generated by knex + * Do not modify this file manually + */ +import { ArrayRemove, ArrayUnion, Increment } from '../interfaces'; +import * as commons from './common_update'; +import * as enums from './enums'; + +export interface PgCollectionVotesUpdate extends commons.BaseSubRecordUpdate { + direction?: number | null | Increment; +} + +export interface PgCollectionStatsUpdate extends commons.BaseSubRecordUpdate { + votes_upvotes?: number | null | Increment; + votes_downvotes?: number | null | Increment; + votes_voteDiff?: number | null | Increment; + ranks_count?: number | null | Increment; + ranks_sum?: number | null | Increment; + ranks_avg?: number | null | Increment; +} + +export interface PgCollectionRanksUpdate extends commons.BaseSubRecordUpdate { + rank?: number | null | Increment; +} + +export interface PgCollectionUpdate extends commons.BaseRecordUpdate { + name?: string | null; + description?: string | null; + bannerUrl?: string | null; + royaltiesFee?: number | null | Increment; + royaltiesSpace?: string | null; + total?: number | null | Increment; + totalTrades?: number | null | Increment; + lastTradedOn?: Date | null; + sold?: number | null | Increment; + discord?: string | null; + url?: string | null; + twitter?: string | null; + approved?: boolean | null; + rejected?: boolean | null; + limitedEdition?: boolean | null; + ipfsMedia?: string | null; + ipfsMetadata?: string | null; + ipfsRoot?: string | null; + category?: enums.PgCategories | null; + type?: enums.PgCollectionType | null; + access?: enums.PgAccess | null; + accessAwards?: string[] | null | ArrayUnion | ArrayRemove; + accessCollections?: string[] | null | ArrayUnion | ArrayRemove; + space?: string | null; + availableFrom?: Date | null; + price?: number | null | Increment; + availablePrice?: number | null | Increment; + onePerMemberOnly?: boolean | null; + placeholderNft?: string | null; + placeholderUrl?: string | null; + status?: enums.PgCollectionStatus | null; + mintingData_address?: string | null; + mintingData_network?: enums.PgNetwork | null; + mintingData_mintedOn?: Date | null; + mintingData_mintedBy?: string | null; + mintingData_blockId?: string | null; + mintingData_nftId?: string | null; + mintingData_storageDeposit?: number | null | Increment; + mintingData_aliasBlockId?: string | null; + mintingData_aliasId?: string | null; + mintingData_aliasStorageDeposit?: number | null | Increment; + mintingData_mintingOrderId?: string | null; + mintingData_nftsToMint?: number | null | Increment; + mintingData_nftMediaToUpload?: number | null | Increment; + mintingData_nftMediaToPrepare?: number | null | Increment; + mintingData_unsoldMintingOptions?: enums.PgUnsoldMintingOptions | null; + mintingData_newPrice?: number | null | Increment; + mintingData_nftsStorageDeposit?: number | null | Increment; + rankCount?: number | null | Increment; + rankSum?: number | null | Increment; + rankAvg?: number | null | Increment; + mediaStatus?: enums.PgMediaStatus | null; + mediaUploadErrorCount?: number | null | Increment; + stakedNft?: number | null | Increment; + nftsOnSale?: number | null | Increment; + nftsOnAuction?: number | null | Increment; + availableNfts?: number | null | Increment; + floorPrice?: number | null | Increment; + votes_upvotes?: number | null | Increment; + votes_downvotes?: number | null | Increment; + votes_voteDiff?: number | null | Increment; + discounts?: string | null; +} diff --git a/packages/database/src/pg/models/common.ts b/packages/database/src/pg/models/common.ts new file mode 100644 index 0000000000..25242cb6a6 --- /dev/null +++ b/packages/database/src/pg/models/common.ts @@ -0,0 +1,14 @@ +/** + * This file was automatically generated by knex + * Do not modify this file manually + */ +export interface BaseRecord { + uid: string; + project?: string; + createdOn?: Date; + updatedOn?: Date; + createdBy?: string; +} +export interface BaseSubRecord extends BaseRecord { + parentId: string; +} diff --git a/packages/database/src/pg/models/common_update.ts b/packages/database/src/pg/models/common_update.ts new file mode 100644 index 0000000000..4b9268a994 --- /dev/null +++ b/packages/database/src/pg/models/common_update.ts @@ -0,0 +1,14 @@ +/** + * This file was automatically generated by knex + * Do not modify this file manually + */ +export interface Update {} +export interface BaseRecordUpdate extends Update { + project?: string; + createdOn?: Date; + updatedOn?: Date; + createdBy?: string; +} +export interface BaseSubRecordUpdate extends Update, BaseRecordUpdate { + parentId?: string; +} diff --git a/packages/database/src/pg/models/enums.ts b/packages/database/src/pg/models/enums.ts new file mode 100644 index 0000000000..ec2eb4780f --- /dev/null +++ b/packages/database/src/pg/models/enums.ts @@ -0,0 +1,274 @@ +/** + * This file was automatically generated by knex + * Do not modify this file manually + */ + +export enum PgAccess { + OPEN = 'open', + MEMBERS_ONLY = 'members_only', + GUARDIANS_ONLY = 'guardians_only', + MEMBERS_WITH_BADGE = 'members_with_badge', + MEMBERS_WITH_NFT_FROM_COLLECTION = 'members_with_nft_from_collection', +} + +export enum PgAuctionType { + OPEN = 'open', + NFT = 'nft', +} + +export enum PgAwardBadgeType { + NATIVE = 'native', + BASE = 'base', +} + +export enum PgCategories { + COLLECTIBLE = 'collectible', + PFP = 'pfp', + PHOTOGRAPHY = 'photography', + ANIMATION = 'animation', + THREE_D = '3d', + GENERATIVE = 'generative', + SINGLE = 'single', + INTERACTIVE = 'interactive', + ABSTRACT = 'abstract', + PIXELART = 'pixelart', + GAME = 'game', + ART = 'art', +} + +export enum PgCollectionStatus { + PRE_MINTED = 'pre_minted', + MINTING = 'minting', + MINTED = 'minted', +} + +export enum PgCollectionType { + CLASSIC = 'classic', + GENERATED = 'generated', + SFT = 'sft', + METADATA = 'metadata', +} + +export enum PgCreditPaymentReason { + TRADE_CANCELLED = 'trade_cancelled', +} + +export enum PgEntity { + SPACE = 'space', + MEMBER = 'member', +} + +export enum PgIgnoreWalletReason { + NONE = '', + UNREFUNDABLE_DUE_UNLOCK_CONDITIONS = 'unrefundable_due_unlock_conditions', + UNREFUNDABLE_DUE_TIMELOCK_CONDITION = 'unrefundable_due_timelock_condition', + UNREFUNDABLE_DUE_STORAGE_DEPOSIT_CONDITION = 'unrefundable_due_storage_deposit_condition', + PRE_MINTED_AIRDROP_CLAIM = 'pre_minted_airdrop_claim', + EXTRA_STAKE_REWARD = 'extra_stake_reward', + MISSING_TARGET_ADDRESS = 'missing_target_address', +} + +export enum PgMediaStatus { + UPLOADED = 'uploaded', + PENDING_UPLOAD = 'pending_upload', + ERROR = 'error', + PREPARE_IPFS = 'prepare_ipfs', +} + +export enum PgNetwork { + SMR = 'smr', + RMS = 'rms', + IOTA = 'iota', + ATOI = 'atoi', +} + +export enum PgNftAccess { + OPEN = 'open', + MEMBERS = 'members', +} + +export enum PgNftAvailable { + UNAVAILABLE = 'unavailable', + SALE = 'sale', + AUCTION = 'auction', + AUCTION_AND_SALE = 'auction_and_sale', +} + +export enum PgNftStatus { + PRE_MINTED = 'pre_minted', + MINTED = 'minted', + WITHDRAWN = 'withdrawn', + STAKED = 'staked', +} + +export enum PgNotificationType { + NEW_BID = 'new_bid', + LOST_BID = 'lost_bid', + WIN_BID = 'win_bid', +} + +export enum PgProjectBilling { + TOKEN_BASED = 'token_based', + VOLUME_BASED = 'volume_based', +} + +export enum PgProposalType { + NATIVE = 'native', + MEMBERS = 'members', + ADD_GUARDIAN = 'add_guardian', + REMOVE_GUARDIAN = 'remove_guardian', + EDIT_SPACE = 'edit_space', + REMOVE_STAKE_REWARD = 'remove_stake_reward', +} + +export enum PgStakeRewardStatus { + UNPROCESSED = 'unprocessed', + PROCESSED = 'processed', + PROCESSED_NO_STAKES = 'processed_no_stakes', + ERROR = 'error', + DELETED = 'deleted', +} + +export enum PgStakeType { + STATIC = 'static', + DYNAMIC = 'dynamic', +} + +export enum PgSwapStatus { + DRAFT = 'draft', + FUNDED = 'funded', + FULFILLED = 'fulfilled', + REJECTED = 'rejected', +} + +export enum PgTokenDropStatus { + DEPOSIT_NEEDED = 'deposit_needed', + UNCLAIMED = 'unclaimed', + CLAIMED = 'claimed', +} + +export enum PgTokenPurchaseAge { + IN_24_H = 'in24h', + IN_48_H = 'in48h', + IN_7_D = 'in7d', +} + +export enum PgTokenStatus { + AVAILABLE = 'available', + CANCEL_SALE = 'cancel_sale', + PROCESSING = 'processing', + PRE_MINTED = 'pre_minted', + ERROR = 'error', + MINTING = 'minting', + MINTED = 'minted', + MINTING_ERROR = 'minting_error', + BASE = 'base', +} + +export enum PgTokenTradeOrderStatus { + ACTIVE = 'active', + SETTLED = 'settled', + CANCELLED = 'cancelled', + PARTIALLY_SETTLED_AND_CANCELLED = 'partially_settled_and_cancelled', + EXPIRED = 'expired', + CANCELLED_UNFULFILLABLE = 'cancelled_unfulfillable', + CANCELLED_MINTING_TOKEN = 'cancelled_minting_token', +} + +export enum PgTokenTradeOrderType { + BUY = 'buy', + SELL = 'sell', +} + +export enum PgTransactionPayloadType { + NFT_PURCHASE = 'nft_purchase', + NFT_PURCHASE_BULK = 'nft_purchase_bulk', + NFT_BID = 'nft_bid', + AUCTION_BID = 'auction_bid', + SPACE_ADDRESS_VALIDATION = 'space_address_validation', + MEMBER_ADDRESS_VALIDATION = 'member_address_validation', + TOKEN_PURCHASE = 'token_purchase', + TOKEN_AIRDROP = 'token_airdrop', + MINT_TOKEN = 'mint_token', + CLAIM_MINTED_TOKEN = 'claim_minted_token', + CLAIM_BASE_TOKEN = 'claim_base_token', + SELL_TOKEN = 'sell_token', + BUY_TOKEN = 'buy_token', + MINT_COLLECTION = 'mint_collection', + DEPOSIT_NFT = 'deposit_nft', + AIRDROP_MINTED_TOKEN = 'airdrop_minted_token', + CREDIT_LOCKED_FUNDS = 'credit_locked_funds', + STAKE = 'stake', + TANGLE_REQUEST = 'tangle_request', + PROPOSAL_VOTE = 'proposal_vote', + CLAIM_SPACE = 'claim_space', + STAKE_NFT = 'stake_nft', + FUND_AWARD = 'fund_award', + IMPORT_TOKEN = 'import_token', + MINT_METADATA_NFT = 'mint_metadata_nft', + MINT_ALIAS = 'mint_alias', + BADGE = 'badge', + BURN_ALIAS = 'burn_alias', + NONE = '', + TOKEN_BUY = 'token_buy', + AWARD_COMPLETED = 'award_completed', + TOKEN_VAULT_EMPTIED = 'token_vault_emptied', + TOKEN_TRADE_FULLFILLMENT = 'token_trade_fullfillment', + ADDRESS_VALIDATION = 'address_validation', + TRANSACTION_ALREADY_UNLOCKED = 'transaction_already_unlocked', + INVALID_AMOUNT = 'invalid_amount', + INVALID_PAYMENT = 'invalid_payment', + TOKEN_VOTE = 'token_vote', + DATA_NO_LONGER_VALID = 'data_no_longer_valid', + SPACE_CALIMED = 'space_calimed', + PRE_MINTED_CLAIM = 'pre_minted_claim', + UNLOCK_FUNDS = 'unlock_funds', + UNLOCK_NFT = 'unlock_nft', + TANGLE_TRANSFER = 'tangle_transfer', + TANGLE_TRANSFER_MANY = 'tangle_transfer_many', + MINT_NFT = 'mint_nft', + UPDATE_MINTED_NFT = 'update_minted_nft', + MINT_NFTS = 'mint_nfts', + LOCK_COLLECTION = 'lock_collection', + SEND_ALIAS_TO_GUARDIAN = 'send_alias_to_guardian', + MINT_FOUNDRY = 'mint_foundry', + MINTED_AIRDROP_CLAIM = 'minted_airdrop_claim', + PRE_MINTED_AIRDROP_CLAIM = 'pre_minted_airdrop_claim', + PRE_MINTED_TOKEN_TRADE = 'pre_minted_token_trade', + MINTED_TOKEN_TRADE = 'minted_token_trade', + BASE_TOKEN_TRADE = 'base_token_trade', + BASE_AIRDROP_CLAIM = 'base_airdrop_claim', + STAMP = 'stamp', + SWAP = 'swap', +} + +export enum PgTransactionType { + VOTE = 'vote', + ORDER = 'order', + PAYMENT = 'payment', + BILL_PAYMENT = 'bill_payment', + CREDIT = 'credit', + CREDIT_TANGLE_REQUEST = 'credit_tangle_request', + CREDIT_STORAGE_DEPOSIT_LOCKED = 'credit_storage_deposit_locked', + MINT_COLLECTION = 'mint_collection', + CREDIT_NFT = 'credit_nft', + WITHDRAW_NFT = 'withdraw_nft', + MINT_TOKEN = 'mint_token', + AWARD = 'award', + UNLOCK = 'unlock', + METADATA_NFT = 'metadata_nft', + STAMP = 'stamp', + NFT_TRANSFER = 'nft_transfer', +} + +export enum PgTransactionValidationType { + ADDRESS = 'address', + ADDRESS_AND_AMOUNT = 'address_and_amount', +} + +export enum PgUnsoldMintingOptions { + BURN_UNSOLD = 'burn_unsold', + SET_NEW_PRICE = 'set_new_price', + KEEP_PRICE = 'keep_price', + TAKE_OWNERSHIP = 'take_ownership', +} diff --git a/packages/database/src/pg/models/index.ts b/packages/database/src/pg/models/index.ts new file mode 100644 index 0000000000..e563ada6ee --- /dev/null +++ b/packages/database/src/pg/models/index.ts @@ -0,0 +1,42 @@ +export * from './airdrop'; +export * from './airdrop_update'; +export * from './auction'; +export * from './auction_update'; +export * from './award'; +export * from './award_update'; +export * from './changes'; +export * from './changes_update'; +export * from './collection'; +export * from './collection_update'; +export * from './member'; +export * from './member_update'; +export * from './milestone'; +export * from './milestone_update'; +export * from './mnemonic'; +export * from './mnemonic_update'; +export * from './nft'; +export * from './nft_update'; +export * from './notification'; +export * from './notification_update'; +export * from './project'; +export * from './project_update'; +export * from './proposal'; +export * from './proposal_update'; +export * from './soon'; +export * from './soon_update'; +export * from './space'; +export * from './space_update'; +export * from './stake'; +export * from './stake_update'; +export * from './stamp'; +export * from './stamp_update'; +export * from './swap'; +export * from './swap_update'; +export * from './system'; +export * from './system_update'; +export * from './ticker'; +export * from './ticker_update'; +export * from './token'; +export * from './token_update'; +export * from './transaction'; +export * from './transaction_update'; diff --git a/packages/database/src/pg/models/member.ts b/packages/database/src/pg/models/member.ts new file mode 100644 index 0000000000..490b1b3383 --- /dev/null +++ b/packages/database/src/pg/models/member.ts @@ -0,0 +1,25 @@ +/** + * This file was automatically generated by knex + * Do not modify this file manually + */ +import * as commons from './common'; + +export interface PgMember extends commons.BaseRecord { + nonce?: string; + name?: string; + about?: string; + avatarNft?: string; + avatar?: string; + discord?: string; + twitter?: string; + github?: string; + smrAddress?: string; + rmsAddress?: string; + iotaAddress?: string; + atoiAddress?: string; + prevValidatedAddresses?: string[]; + tokenTradingFeePercentage?: number; + tokenPurchaseFeePercentage?: number; + awardsCompleted?: number; + spaces?: Record; +} diff --git a/packages/database/src/pg/models/member_update.ts b/packages/database/src/pg/models/member_update.ts new file mode 100644 index 0000000000..c471ba9323 --- /dev/null +++ b/packages/database/src/pg/models/member_update.ts @@ -0,0 +1,26 @@ +/** + * This file was automatically generated by knex + * Do not modify this file manually + */ +import { ArrayRemove, ArrayUnion, Increment } from '../interfaces'; +import * as commons from './common_update'; + +export interface PgMemberUpdate extends commons.BaseRecordUpdate { + nonce?: string | null; + name?: string | null; + about?: string | null; + avatarNft?: string | null; + avatar?: string | null; + discord?: string | null; + twitter?: string | null; + github?: string | null; + smrAddress?: string | null; + rmsAddress?: string | null; + iotaAddress?: string | null; + atoiAddress?: string | null; + prevValidatedAddresses?: string[] | null | ArrayUnion | ArrayRemove; + tokenTradingFeePercentage?: number | null | Increment; + tokenPurchaseFeePercentage?: number | null | Increment; + awardsCompleted?: number | null | Increment; + spaces?: string | any | null; +} diff --git a/packages/database/src/pg/models/milestone.ts b/packages/database/src/pg/models/milestone.ts new file mode 100644 index 0000000000..23bf82f0eb --- /dev/null +++ b/packages/database/src/pg/models/milestone.ts @@ -0,0 +1,65 @@ +/** + * This file was automatically generated by knex + * Do not modify this file manually + */ +import * as commons from './common'; + +export interface PgMilestoneTransactions extends commons.BaseSubRecord { + PayloadSize?: number; + blockId?: string; + milestone?: number; + payload?: Record; + processed?: boolean; + processedOn?: Date; +} + +export interface PgMilestoneSmrTransactions extends commons.BaseSubRecord { + PayloadSize?: number; + blockId?: string; + milestone?: number; + payload?: Record; + processed?: boolean; + processedOn?: Date; +} + +export interface PgMilestoneSmr extends commons.BaseRecord { + completed?: boolean; + completedOn?: Date; + listenerNodeId?: string; + milestone?: number; + milestoneTimestamp?: Date; + trxConflictCount?: number; + trxFailedCount?: number; + trxValidCount?: number; +} + +export interface PgMilestoneRmsT2Transactions extends commons.BaseSubRecord { + PayloadSize?: number; + blockId?: string; + milestone?: number; + payload?: Record; + processed?: boolean; + processedOn?: Date; +} + +export interface PgMilestoneRmsT2 extends commons.BaseRecord { + completed?: boolean; + completedOn?: Date; + listenerNodeId?: string; + milestone?: number; + milestoneTimestamp?: Date; + trxConflictCount?: number; + trxFailedCount?: number; + trxValidCount?: number; +} + +export interface PgMilestone extends commons.BaseRecord { + completed?: boolean; + completedOn?: Date; + listenerNodeId?: string; + milestone?: number; + milestoneTimestamp?: Date; + trxConflictCount?: number; + trxFailedCount?: number; + trxValidCount?: number; +} diff --git a/packages/database/src/pg/models/milestone_update.ts b/packages/database/src/pg/models/milestone_update.ts new file mode 100644 index 0000000000..4e70191118 --- /dev/null +++ b/packages/database/src/pg/models/milestone_update.ts @@ -0,0 +1,66 @@ +/** + * This file was automatically generated by knex + * Do not modify this file manually + */ +import { Increment } from '../interfaces'; +import * as commons from './common_update'; + +export interface PgMilestoneTransactionsUpdate extends commons.BaseSubRecordUpdate { + PayloadSize?: number | null | Increment; + blockId?: string | null; + milestone?: number | null | Increment; + payload?: string | any | null; + processed?: boolean | null; + processedOn?: Date | null; +} + +export interface PgMilestoneSmrTransactionsUpdate extends commons.BaseSubRecordUpdate { + PayloadSize?: number | null | Increment; + blockId?: string | null; + milestone?: number | null | Increment; + payload?: string | any | null; + processed?: boolean | null; + processedOn?: Date | null; +} + +export interface PgMilestoneSmrUpdate extends commons.BaseRecordUpdate { + completed?: boolean | null; + completedOn?: Date | null; + listenerNodeId?: string | null; + milestone?: number | null | Increment; + milestoneTimestamp?: Date | null; + trxConflictCount?: number | null | Increment; + trxFailedCount?: number | null | Increment; + trxValidCount?: number | null | Increment; +} + +export interface PgMilestoneRmsT2TransactionsUpdate extends commons.BaseSubRecordUpdate { + PayloadSize?: number | null | Increment; + blockId?: string | null; + milestone?: number | null | Increment; + payload?: string | any | null; + processed?: boolean | null; + processedOn?: Date | null; +} + +export interface PgMilestoneRmsT2Update extends commons.BaseRecordUpdate { + completed?: boolean | null; + completedOn?: Date | null; + listenerNodeId?: string | null; + milestone?: number | null | Increment; + milestoneTimestamp?: Date | null; + trxConflictCount?: number | null | Increment; + trxFailedCount?: number | null | Increment; + trxValidCount?: number | null | Increment; +} + +export interface PgMilestoneUpdate extends commons.BaseRecordUpdate { + completed?: boolean | null; + completedOn?: Date | null; + listenerNodeId?: string | null; + milestone?: number | null | Increment; + milestoneTimestamp?: Date | null; + trxConflictCount?: number | null | Increment; + trxFailedCount?: number | null | Increment; + trxValidCount?: number | null | Increment; +} diff --git a/packages/database/src/pg/models/mnemonic.ts b/packages/database/src/pg/models/mnemonic.ts new file mode 100644 index 0000000000..0a5830dd9e --- /dev/null +++ b/packages/database/src/pg/models/mnemonic.ts @@ -0,0 +1,15 @@ +/** + * This file was automatically generated by knex + * Do not modify this file manually + */ +import * as commons from './common'; +import * as enums from './enums'; + +export interface PgMnemonic extends commons.BaseRecord { + mnemonic?: string; + network?: enums.PgNetwork; + lockedBy?: string; + consumedOutputIds?: string[]; + consumedNftOutputIds?: string[]; + consumedAliasOutputIds?: string[]; +} diff --git a/packages/database/src/pg/models/mnemonic_update.ts b/packages/database/src/pg/models/mnemonic_update.ts new file mode 100644 index 0000000000..61eea52efc --- /dev/null +++ b/packages/database/src/pg/models/mnemonic_update.ts @@ -0,0 +1,16 @@ +/** + * This file was automatically generated by knex + * Do not modify this file manually + */ +import { ArrayRemove, ArrayUnion } from '../interfaces'; +import * as commons from './common_update'; +import * as enums from './enums'; + +export interface PgMnemonicUpdate extends commons.BaseRecordUpdate { + mnemonic?: string | null; + network?: enums.PgNetwork | null; + lockedBy?: string | null; + consumedOutputIds?: string[] | null | ArrayUnion | ArrayRemove; + consumedNftOutputIds?: string[] | null | ArrayUnion | ArrayRemove; + consumedAliasOutputIds?: string[] | null | ArrayUnion | ArrayRemove; +} diff --git a/packages/database/src/pg/models/nft.ts b/packages/database/src/pg/models/nft.ts new file mode 100644 index 0000000000..a12ba2726e --- /dev/null +++ b/packages/database/src/pg/models/nft.ts @@ -0,0 +1,99 @@ +/** + * This file was automatically generated by knex + * Do not modify this file manually + */ +import * as commons from './common'; +import * as enums from './enums'; + +export interface PgNftStake extends commons.BaseRecord { + member?: string; + space?: string; + collection?: string; + nft?: string; + weeks?: number; + expiresAt?: Date; + expirationProcessed?: boolean; + type?: enums.PgStakeType; +} + +export interface PgNft extends commons.BaseRecord { + name?: string; + description?: string; + collection?: string; + owner?: string; + isOwned?: boolean; + media?: string; + ipfsMedia?: string; + ipfsMetadata?: string; + ipfsRoot?: string; + saleAccess?: enums.PgNftAccess; + saleAccessMembers?: string[]; + available?: enums.PgNftAvailable; + availableFrom?: Date; + auctionFrom?: Date; + auctionTo?: Date; + extendedAuctionTo?: Date; + auctionHighestBid?: number; + auctionHighestBidder?: string; + price?: number; + totalTrades?: number; + lastTradedOn?: Date; + availablePrice?: number; + auctionFloorPrice?: number; + auctionLength?: number; + extendedAuctionLength?: number; + extendAuctionWithin?: number; + type?: enums.PgCollectionType; + space?: string; + url?: string; + approved?: boolean; + rejected?: boolean; + properties?: Record; + stats?: Record; + placeholderNft?: boolean; + position?: number; + locked?: boolean; + lockedBy?: string; + sold?: boolean; + mintingData_address?: string; + mintingData_network?: enums.PgNetwork; + mintingData_mintedOn?: Date; + mintingData_mintedBy?: string; + mintingData_blockId?: string; + mintingData_nftId?: string; + mintingData_storageDeposit?: number; + mintingData_aliasBlockId?: string; + mintingData_aliasId?: string; + mintingData_aliasStorageDeposit?: number; + mintingData_mintingOrderId?: string; + mintingData_nftsToMint?: number; + mintingData_nftMediaToUpload?: number; + mintingData_nftMediaToPrepare?: number; + mintingData_unsoldMintingOptions?: enums.PgUnsoldMintingOptions; + mintingData_newPrice?: number; + mintingData_nftsStorageDeposit?: number; + depositData_address?: string; + depositData_network?: enums.PgNetwork; + depositData_mintedOn?: Date; + depositData_mintedBy?: string; + depositData_blockId?: string; + depositData_nftId?: string; + depositData_storageDeposit?: number; + depositData_aliasBlockId?: string; + depositData_aliasId?: string; + depositData_aliasStorageDeposit?: number; + depositData_mintingOrderId?: string; + depositData_nftsToMint?: number; + depositData_nftMediaToUpload?: number; + depositData_nftMediaToPrepare?: number; + depositData_unsoldMintingOptions?: enums.PgUnsoldMintingOptions; + depositData_newPrice?: number; + depositData_nftsStorageDeposit?: number; + status?: enums.PgNftStatus; + hidden?: boolean; + mediaStatus?: enums.PgMediaStatus; + mediaUploadErrorCount?: number; + soldOn?: Date; + setAsAvatar?: boolean; + auction?: string; +} diff --git a/packages/database/src/pg/models/nft_update.ts b/packages/database/src/pg/models/nft_update.ts new file mode 100644 index 0000000000..210c3252d4 --- /dev/null +++ b/packages/database/src/pg/models/nft_update.ts @@ -0,0 +1,100 @@ +/** + * This file was automatically generated by knex + * Do not modify this file manually + */ +import { ArrayRemove, ArrayUnion, Increment } from '../interfaces'; +import * as commons from './common_update'; +import * as enums from './enums'; + +export interface PgNftStakeUpdate extends commons.BaseRecordUpdate { + member?: string | null; + space?: string | null; + collection?: string | null; + nft?: string | null; + weeks?: number | null | Increment; + expiresAt?: Date | null; + expirationProcessed?: boolean | null; + type?: enums.PgStakeType | null; +} + +export interface PgNftUpdate extends commons.BaseRecordUpdate { + name?: string | null; + description?: string | null; + collection?: string | null; + owner?: string | null; + isOwned?: boolean | null; + media?: string | null; + ipfsMedia?: string | null; + ipfsMetadata?: string | null; + ipfsRoot?: string | null; + saleAccess?: enums.PgNftAccess | null; + saleAccessMembers?: string[] | null | ArrayUnion | ArrayRemove; + available?: enums.PgNftAvailable | null; + availableFrom?: Date | null; + auctionFrom?: Date | null; + auctionTo?: Date | null; + extendedAuctionTo?: Date | null; + auctionHighestBid?: number | null | Increment; + auctionHighestBidder?: string | null; + price?: number | null | Increment; + totalTrades?: number | null | Increment; + lastTradedOn?: Date | null; + availablePrice?: number | null | Increment; + auctionFloorPrice?: number | null | Increment; + auctionLength?: number | null | Increment; + extendedAuctionLength?: number | null | Increment; + extendAuctionWithin?: number | null | Increment; + type?: enums.PgCollectionType | null; + space?: string | null; + url?: string | null; + approved?: boolean | null; + rejected?: boolean | null; + properties?: string | any | null; + stats?: string | any | null; + placeholderNft?: boolean | null; + position?: number | null | Increment; + locked?: boolean | null; + lockedBy?: string | null; + sold?: boolean | null; + mintingData_address?: string | null; + mintingData_network?: enums.PgNetwork | null; + mintingData_mintedOn?: Date | null; + mintingData_mintedBy?: string | null; + mintingData_blockId?: string | null; + mintingData_nftId?: string | null; + mintingData_storageDeposit?: number | null | Increment; + mintingData_aliasBlockId?: string | null; + mintingData_aliasId?: string | null; + mintingData_aliasStorageDeposit?: number | null | Increment; + mintingData_mintingOrderId?: string | null; + mintingData_nftsToMint?: number | null | Increment; + mintingData_nftMediaToUpload?: number | null | Increment; + mintingData_nftMediaToPrepare?: number | null | Increment; + mintingData_unsoldMintingOptions?: enums.PgUnsoldMintingOptions | null; + mintingData_newPrice?: number | null | Increment; + mintingData_nftsStorageDeposit?: number | null | Increment; + depositData_address?: string | null; + depositData_network?: enums.PgNetwork | null; + depositData_mintedOn?: Date | null; + depositData_mintedBy?: string | null; + depositData_blockId?: string | null; + depositData_nftId?: string | null; + depositData_storageDeposit?: number | null | Increment; + depositData_aliasBlockId?: string | null; + depositData_aliasId?: string | null; + depositData_aliasStorageDeposit?: number | null | Increment; + depositData_mintingOrderId?: string | null; + depositData_nftsToMint?: number | null | Increment; + depositData_nftMediaToUpload?: number | null | Increment; + depositData_nftMediaToPrepare?: number | null | Increment; + depositData_unsoldMintingOptions?: enums.PgUnsoldMintingOptions | null; + depositData_newPrice?: number | null | Increment; + depositData_nftsStorageDeposit?: number | null | Increment; + status?: enums.PgNftStatus | null; + hidden?: boolean | null; + mediaStatus?: enums.PgMediaStatus | null; + mediaUploadErrorCount?: number | null | Increment; + soldOn?: Date | null; + setAsAvatar?: boolean | null; + auction?: string | null; +} diff --git a/packages/database/src/pg/models/notification.ts b/packages/database/src/pg/models/notification.ts new file mode 100644 index 0000000000..a7b2d27563 --- /dev/null +++ b/packages/database/src/pg/models/notification.ts @@ -0,0 +1,13 @@ +/** + * This file was automatically generated by knex + * Do not modify this file manually + */ +import * as commons from './common'; +import * as enums from './enums'; + +export interface PgNotification extends commons.BaseRecord { + space?: string; + member?: string; + type?: enums.PgNotificationType; + params?: Record; +} diff --git a/packages/database/src/pg/models/notification_update.ts b/packages/database/src/pg/models/notification_update.ts new file mode 100644 index 0000000000..0e30b3a2af --- /dev/null +++ b/packages/database/src/pg/models/notification_update.ts @@ -0,0 +1,13 @@ +/** + * This file was automatically generated by knex + * Do not modify this file manually + */ +import * as commons from './common_update'; +import * as enums from './enums'; + +export interface PgNotificationUpdate extends commons.BaseRecordUpdate { + space?: string | null; + member?: string | null; + type?: enums.PgNotificationType | null; + params?: string | any | null; +} diff --git a/packages/database/src/pg/models/project.ts b/packages/database/src/pg/models/project.ts new file mode 100644 index 0000000000..f579513d09 --- /dev/null +++ b/packages/database/src/pg/models/project.ts @@ -0,0 +1,24 @@ +/** + * This file was automatically generated by knex + * Do not modify this file manually + */ +import * as commons from './common'; +import * as enums from './enums'; + +export interface PgProjectAdmins extends commons.BaseSubRecord {} + +export interface PgProjectApiKey extends commons.BaseSubRecord { + token?: string; +} + +export interface PgProject extends commons.BaseRecord { + name?: string; + contactEmail?: string; + deactivated?: boolean; + config_billing?: enums.PgProjectBilling; + config_tiers?: number[]; + config_tokenTradingFeeDiscountPercentage?: number[]; + config_nativeTokenSymbol?: string; + config_nativeTokenUid?: string; + otr?: Record; +} diff --git a/packages/database/src/pg/models/project_update.ts b/packages/database/src/pg/models/project_update.ts new file mode 100644 index 0000000000..f33c58c867 --- /dev/null +++ b/packages/database/src/pg/models/project_update.ts @@ -0,0 +1,24 @@ +/** + * This file was automatically generated by knex + * Do not modify this file manually + */ +import * as commons from './common_update'; +import * as enums from './enums'; + +export interface PgProjectAdminsUpdate extends commons.BaseSubRecordUpdate {} + +export interface PgProjectApiKeyUpdate extends commons.BaseSubRecordUpdate { + token?: string | null; +} + +export interface PgProjectUpdate extends commons.BaseRecordUpdate { + name?: string | null; + contactEmail?: string | null; + deactivated?: boolean | null; + config_billing?: enums.PgProjectBilling | null; + config_tiers?: number[] | null; + config_tokenTradingFeeDiscountPercentage?: number[] | null; + config_nativeTokenSymbol?: string | null; + config_nativeTokenUid?: string | null; + otr?: string | any | null; +} diff --git a/packages/database/src/pg/models/proposal.ts b/packages/database/src/pg/models/proposal.ts new file mode 100644 index 0000000000..afe41e8150 --- /dev/null +++ b/packages/database/src/pg/models/proposal.ts @@ -0,0 +1,43 @@ +/** + * This file was automatically generated by knex + * Do not modify this file manually + */ +import * as commons from './common'; +import * as enums from './enums'; + +export interface PgProposalOwners extends commons.BaseSubRecord {} + +export interface PgProposalMembers extends commons.BaseSubRecord { + voted?: boolean; + weight?: number; + tranId?: string; + values?: Record; +} + +export interface PgProposal extends commons.BaseRecord { + space?: string; + name?: string; + description?: string; + additionalInfo?: string; + type?: enums.PgProposalType; + approved?: boolean; + rejected?: boolean; + approvedBy?: string; + rejectedBy?: string; + eventId?: string; + totalWeight?: number; + token?: string; + completed?: boolean; + rank?: number; + settings_startDate?: Date; + settings_endDate?: Date; + settings_guardiansOnly?: boolean; + settings_addRemoveGuardian?: string; + settings_spaceUpdateData?: Record; + settings_onlyGuardians?: boolean; + settings_stakeRewardIds?: string[]; + settings_awards?: string[]; + questions?: Record[]; + members?: Record[]; + results?: Record; +} diff --git a/packages/database/src/pg/models/proposal_update.ts b/packages/database/src/pg/models/proposal_update.ts new file mode 100644 index 0000000000..b21544d960 --- /dev/null +++ b/packages/database/src/pg/models/proposal_update.ts @@ -0,0 +1,44 @@ +/** + * This file was automatically generated by knex + * Do not modify this file manually + */ +import { ArrayRemove, ArrayUnion, Increment } from '../interfaces'; +import * as commons from './common_update'; +import * as enums from './enums'; + +export interface PgProposalOwnersUpdate extends commons.BaseSubRecordUpdate {} + +export interface PgProposalMembersUpdate extends commons.BaseSubRecordUpdate { + voted?: boolean | null; + weight?: number | null | Increment; + tranId?: string | null; + values?: string | any | null; +} + +export interface PgProposalUpdate extends commons.BaseRecordUpdate { + space?: string | null; + name?: string | null; + description?: string | null; + additionalInfo?: string | null; + type?: enums.PgProposalType | null; + approved?: boolean | null; + rejected?: boolean | null; + approvedBy?: string | null; + rejectedBy?: string | null; + eventId?: string | null; + totalWeight?: number | null | Increment; + token?: string | null; + completed?: boolean | null; + rank?: number | null | Increment; + settings_startDate?: Date | null; + settings_endDate?: Date | null; + settings_guardiansOnly?: boolean | null; + settings_addRemoveGuardian?: string | null; + settings_spaceUpdateData?: string | any | null; + settings_onlyGuardians?: boolean | null; + settings_stakeRewardIds?: string[] | null | ArrayUnion | ArrayRemove; + settings_awards?: string[] | null | ArrayUnion | ArrayRemove; + questions?: string | null; + members?: string | null; + results?: string | any | null; +} diff --git a/packages/database/src/pg/models/soon.ts b/packages/database/src/pg/models/soon.ts new file mode 100644 index 0000000000..9a0f114dfd --- /dev/null +++ b/packages/database/src/pg/models/soon.ts @@ -0,0 +1,13 @@ +/** + * This file was automatically generated by knex + * Do not modify this file manually + */ +import * as commons from './common'; + +export interface PgSoonSnapshot extends commons.BaseRecord { + count: number; + paidOut: number; + lastPaidOutOn?: Date; + ethAddress: string; + ethAddressVerified: boolean; +} diff --git a/packages/database/src/pg/models/soon_update.ts b/packages/database/src/pg/models/soon_update.ts new file mode 100644 index 0000000000..3b79220df4 --- /dev/null +++ b/packages/database/src/pg/models/soon_update.ts @@ -0,0 +1,14 @@ +/** + * This file was automatically generated by knex + * Do not modify this file manually + */ +import { Increment } from '../interfaces'; +import * as commons from './common_update'; + +export interface PgSoonSnapshotUpdate extends commons.BaseRecordUpdate { + count?: number | Increment; + paidOut?: number | Increment; + lastPaidOutOn?: Date | null; + ethAddress?: string; + ethAddressVerified?: boolean; +} diff --git a/packages/database/src/pg/models/space.ts b/packages/database/src/pg/models/space.ts new file mode 100644 index 0000000000..731c7117a0 --- /dev/null +++ b/packages/database/src/pg/models/space.ts @@ -0,0 +1,48 @@ +/** + * This file was automatically generated by knex + * Do not modify this file manually + */ +import * as commons from './common'; +import * as enums from './enums'; + +export interface PgSpaceMembers extends commons.BaseSubRecord {} + +export interface PgSpaceKnockingmembers extends commons.BaseSubRecord {} + +export interface PgSpaceGuardians extends commons.BaseSubRecord {} + +export interface PgSpaceBlockedmembers extends commons.BaseSubRecord {} + +export interface PgSpace extends commons.BaseRecord { + name?: string; + about?: string; + open?: boolean; + tokenBased?: boolean; + minStakedValue?: number; + github?: string; + twitter?: string; + discord?: string; + avatarUrl?: string; + bannerUrl?: string; + totalGuardians?: number; + totalMembers?: number; + totalPendingMembers?: number; + smrAddress?: string; + rmsAddress?: string; + iotaAddress?: string; + atoiAddress?: string; + prevValidatedAddresses?: string[]; + vaultAddress?: string; + collectionId?: string; + claimed?: boolean; + ipfsMedia?: string; + ipfsMetadata?: string; + ipfsRoot?: string; + mediaStatus?: enums.PgMediaStatus; + mediaUploadErrorCount?: number; + alias_address?: string; + alias_aliasId?: string; + alias_blockId?: string; + alias_mintedOn?: Date; + alias_mintedBy?: string; +} diff --git a/packages/database/src/pg/models/space_update.ts b/packages/database/src/pg/models/space_update.ts new file mode 100644 index 0000000000..af630084e3 --- /dev/null +++ b/packages/database/src/pg/models/space_update.ts @@ -0,0 +1,49 @@ +/** + * This file was automatically generated by knex + * Do not modify this file manually + */ +import { ArrayRemove, ArrayUnion, Increment } from '../interfaces'; +import * as commons from './common_update'; +import * as enums from './enums'; + +export interface PgSpaceMembersUpdate extends commons.BaseSubRecordUpdate {} + +export interface PgSpaceKnockingmembersUpdate extends commons.BaseSubRecordUpdate {} + +export interface PgSpaceGuardiansUpdate extends commons.BaseSubRecordUpdate {} + +export interface PgSpaceBlockedmembersUpdate extends commons.BaseSubRecordUpdate {} + +export interface PgSpaceUpdate extends commons.BaseRecordUpdate { + name?: string | null; + about?: string | null; + open?: boolean | null; + tokenBased?: boolean | null; + minStakedValue?: number | null | Increment; + github?: string | null; + twitter?: string | null; + discord?: string | null; + avatarUrl?: string | null; + bannerUrl?: string | null; + totalGuardians?: number | null | Increment; + totalMembers?: number | null | Increment; + totalPendingMembers?: number | null | Increment; + smrAddress?: string | null; + rmsAddress?: string | null; + iotaAddress?: string | null; + atoiAddress?: string | null; + prevValidatedAddresses?: string[] | null | ArrayUnion | ArrayRemove; + vaultAddress?: string | null; + collectionId?: string | null; + claimed?: boolean | null; + ipfsMedia?: string | null; + ipfsMetadata?: string | null; + ipfsRoot?: string | null; + mediaStatus?: enums.PgMediaStatus | null; + mediaUploadErrorCount?: number | null | Increment; + alias_address?: string | null; + alias_aliasId?: string | null; + alias_blockId?: string | null; + alias_mintedOn?: Date | null; + alias_mintedBy?: string | null; +} diff --git a/packages/database/src/pg/models/stake.ts b/packages/database/src/pg/models/stake.ts new file mode 100644 index 0000000000..0c8fea06de --- /dev/null +++ b/packages/database/src/pg/models/stake.ts @@ -0,0 +1,32 @@ +/** + * This file was automatically generated by knex + * Do not modify this file manually + */ +import * as commons from './common'; +import * as enums from './enums'; + +export interface PgStakeReward extends commons.BaseRecord { + startDate?: Date; + endDate?: Date; + tokenVestingDate?: Date; + tokensToDistribute?: number; + token?: string; + totalStaked?: number; + totalAirdropped?: number; + status?: enums.PgStakeRewardStatus; +} + +export interface PgStake extends commons.BaseRecord { + member?: string; + space?: string; + token?: string; + amount?: number; + value?: number; + weeks?: number; + expiresAt?: Date; + expirationProcessed?: boolean; + orderId?: string; + billPaymentId?: string; + type?: enums.PgStakeType; + customMetadata?: Record; +} diff --git a/packages/database/src/pg/models/stake_update.ts b/packages/database/src/pg/models/stake_update.ts new file mode 100644 index 0000000000..8ca93b9d94 --- /dev/null +++ b/packages/database/src/pg/models/stake_update.ts @@ -0,0 +1,33 @@ +/** + * This file was automatically generated by knex + * Do not modify this file manually + */ +import { Increment } from '../interfaces'; +import * as commons from './common_update'; +import * as enums from './enums'; + +export interface PgStakeRewardUpdate extends commons.BaseRecordUpdate { + startDate?: Date | null; + endDate?: Date | null; + tokenVestingDate?: Date | null; + tokensToDistribute?: number | null | Increment; + token?: string | null; + totalStaked?: number | null | Increment; + totalAirdropped?: number | null | Increment; + status?: enums.PgStakeRewardStatus | null; +} + +export interface PgStakeUpdate extends commons.BaseRecordUpdate { + member?: string | null; + space?: string | null; + token?: string | null; + amount?: number | null | Increment; + value?: number | null | Increment; + weeks?: number | null | Increment; + expiresAt?: Date | null; + expirationProcessed?: boolean | null; + orderId?: string | null; + billPaymentId?: string | null; + type?: enums.PgStakeType | null; + customMetadata?: string | any | null; +} diff --git a/packages/database/src/pg/models/stamp.ts b/packages/database/src/pg/models/stamp.ts new file mode 100644 index 0000000000..bec4794723 --- /dev/null +++ b/packages/database/src/pg/models/stamp.ts @@ -0,0 +1,27 @@ +/** + * This file was automatically generated by knex + * Do not modify this file manually + */ +import * as commons from './common'; +import * as enums from './enums'; + +export interface PgStamp extends commons.BaseRecord { + space?: string; + build5Url?: string; + originUri?: string; + checksum?: string; + extension?: string; + bytes?: number; + costPerMb?: number; + network?: enums.PgNetwork; + ipfsMedia?: string; + ipfsRoot?: string; + expiresAt?: Date; + order?: string; + funded?: boolean; + expired?: boolean; + mediaStatus?: enums.PgMediaStatus; + mediaUploadErrorCount?: number; + aliasId?: string; + nftId?: string; +} diff --git a/packages/database/src/pg/models/stamp_update.ts b/packages/database/src/pg/models/stamp_update.ts new file mode 100644 index 0000000000..901e142dab --- /dev/null +++ b/packages/database/src/pg/models/stamp_update.ts @@ -0,0 +1,28 @@ +/** + * This file was automatically generated by knex + * Do not modify this file manually + */ +import { Increment } from '../interfaces'; +import * as commons from './common_update'; +import * as enums from './enums'; + +export interface PgStampUpdate extends commons.BaseRecordUpdate { + space?: string | null; + build5Url?: string | null; + originUri?: string | null; + checksum?: string | null; + extension?: string | null; + bytes?: number | null | Increment; + costPerMb?: number | null | Increment; + network?: enums.PgNetwork | null; + ipfsMedia?: string | null; + ipfsRoot?: string | null; + expiresAt?: Date | null; + order?: string | null; + funded?: boolean | null; + expired?: boolean | null; + mediaStatus?: enums.PgMediaStatus | null; + mediaUploadErrorCount?: number | null | Increment; + aliasId?: string | null; + nftId?: string | null; +} diff --git a/packages/database/src/pg/models/swap.ts b/packages/database/src/pg/models/swap.ts new file mode 100644 index 0000000000..0e4c65528a --- /dev/null +++ b/packages/database/src/pg/models/swap.ts @@ -0,0 +1,19 @@ +/** + * This file was automatically generated by knex + * Do not modify this file manually + */ +import * as commons from './common'; +import * as enums from './enums'; + +export interface PgSwap extends commons.BaseRecord { + recipient?: string; + network?: enums.PgNetwork; + address?: string; + orderId?: string; + nftIdsAsk?: string[]; + baseTokenAmountAsk?: number; + nativeTokensAsk?: Record[]; + status?: enums.PgSwapStatus; + bidOutputs?: Record[]; + askOutputs?: Record[]; +} diff --git a/packages/database/src/pg/models/swap_update.ts b/packages/database/src/pg/models/swap_update.ts new file mode 100644 index 0000000000..7722ca2b5f --- /dev/null +++ b/packages/database/src/pg/models/swap_update.ts @@ -0,0 +1,20 @@ +/** + * This file was automatically generated by knex + * Do not modify this file manually + */ +import { ArrayRemove, ArrayUnion, Increment } from '../interfaces'; +import * as commons from './common_update'; +import * as enums from './enums'; + +export interface PgSwapUpdate extends commons.BaseRecordUpdate { + recipient?: string | null; + network?: enums.PgNetwork | null; + address?: string | null; + orderId?: string | null; + nftIdsAsk?: string[] | null | ArrayUnion | ArrayRemove; + baseTokenAmountAsk?: number | null | Increment; + nativeTokensAsk?: string | null; + status?: enums.PgSwapStatus | null; + bidOutputs?: string | null; + askOutputs?: string | null; +} diff --git a/packages/database/src/pg/models/system.ts b/packages/database/src/pg/models/system.ts new file mode 100644 index 0000000000..1d88900af2 --- /dev/null +++ b/packages/database/src/pg/models/system.ts @@ -0,0 +1,10 @@ +/** + * This file was automatically generated by knex + * Do not modify this file manually + */ +import * as commons from './common'; + +export interface PgSystem extends commons.BaseRecord { + tokenTradingFeePercentage?: number; + tokenPurchaseFeePercentage?: number; +} diff --git a/packages/database/src/pg/models/system_update.ts b/packages/database/src/pg/models/system_update.ts new file mode 100644 index 0000000000..b42f06f9da --- /dev/null +++ b/packages/database/src/pg/models/system_update.ts @@ -0,0 +1,11 @@ +/** + * This file was automatically generated by knex + * Do not modify this file manually + */ +import { Increment } from '../interfaces'; +import * as commons from './common_update'; + +export interface PgSystemUpdate extends commons.BaseRecordUpdate { + tokenTradingFeePercentage?: number | null | Increment; + tokenPurchaseFeePercentage?: number | null | Increment; +} diff --git a/packages/database/src/pg/models/ticker.ts b/packages/database/src/pg/models/ticker.ts new file mode 100644 index 0000000000..2f899f5093 --- /dev/null +++ b/packages/database/src/pg/models/ticker.ts @@ -0,0 +1,9 @@ +/** + * This file was automatically generated by knex + * Do not modify this file manually + */ +import * as commons from './common'; + +export interface PgTicker extends commons.BaseRecord { + price?: number; +} diff --git a/packages/database/src/pg/models/ticker_update.ts b/packages/database/src/pg/models/ticker_update.ts new file mode 100644 index 0000000000..05dd9d6b42 --- /dev/null +++ b/packages/database/src/pg/models/ticker_update.ts @@ -0,0 +1,10 @@ +/** + * This file was automatically generated by knex + * Do not modify this file manually + */ +import { Increment } from '../interfaces'; +import * as commons from './common_update'; + +export interface PgTickerUpdate extends commons.BaseRecordUpdate { + price?: number | null | Increment; +} diff --git a/packages/database/src/pg/models/token.ts b/packages/database/src/pg/models/token.ts new file mode 100644 index 0000000000..b8c6abc48e --- /dev/null +++ b/packages/database/src/pg/models/token.ts @@ -0,0 +1,172 @@ +/** + * This file was automatically generated by knex + * Do not modify this file manually + */ +import * as commons from './common'; +import * as enums from './enums'; + +export interface PgTokenVotes extends commons.BaseSubRecord { + direction?: number; +} + +export interface PgTokenStats extends commons.BaseSubRecord { + votes_upvotes?: number; + votes_downvotes?: number; + votes_voteDiff?: number; + ranks_count?: number; + ranks_sum?: number; + ranks_avg?: number; + volumeTotal?: number; + volume_in24h?: number; + volume_in48h?: number; + volume_in7d?: number; + stakes_static_amount?: number; + stakes_static_totalAmount?: number; + stakes_static_value?: number; + stakes_static_totalValue?: number; + stakes_static_stakingMembersCount?: number; + stakes_dynamic_amount?: number; + stakes_dynamic_totalAmount?: number; + stakes_dynamic_value?: number; + stakes_dynamic_totalValue?: number; + stakes_dynamic_stakingMembersCount?: number; + stakeExpiry?: Record; +} + +export interface PgTokenRanks extends commons.BaseSubRecord { + rank?: number; +} + +export interface PgTokenPurchase extends commons.BaseRecord { + token?: string; + tokenStatus?: enums.PgTokenStatus; + sell?: string; + buy?: string; + count?: number; + price?: number; + triggeredBy?: enums.PgTokenTradeOrderType; + billPaymentId?: string; + buyerBillPaymentId?: string; + royaltyBillPayments?: string[]; + sourceNetwork?: enums.PgNetwork; + targetNetwork?: enums.PgNetwork; + sellerTokenTradingFeePercentage?: number; + sellerTier?: number; + in24h?: boolean; + in48h?: boolean; + in7d?: boolean; +} + +export interface PgTokenMarket extends commons.BaseRecord { + owner?: string; + token?: string; + tokenStatus?: enums.PgTokenStatus; + type?: enums.PgTokenTradeOrderType; + count?: number; + price?: number; + totalDeposit?: number; + balance?: number; + fulfilled?: number; + status?: enums.PgTokenTradeOrderStatus; + orderTransactionId?: string; + paymentTransactionId?: string; + creditTransactionId?: string; + expiresAt?: Date; + shouldRetry?: boolean; + sourceNetwork?: enums.PgNetwork; + targetNetwork?: enums.PgNetwork; + targetAddress?: string; +} + +export interface PgTokenDistribution extends commons.BaseSubRecord { + totalDeposit?: number; + totalPaid?: number; + refundedAmount?: number; + totalBought?: number; + reconciled?: boolean; + billPaymentId?: string; + creditPaymentId?: string; + royaltyBillPaymentId?: string; + tokenClaimed?: number; + lockedForSale?: number; + sold?: number; + totalPurchased?: number; + tokenOwned?: number; + mintedClaimedOn?: Date; + mintingTransactions?: string[]; + stakeRewards?: number; + extraStakeRewards?: number; + totalUnclaimedAirdrop?: number; + stakeVoteTransactionId?: string; + stakes_static_amount?: number; + stakes_static_totalAmount?: number; + stakes_static_value?: number; + stakes_static_totalValue?: number; + stakes_static_stakingMembersCount?: number; + stakes_dynamic_amount?: number; + stakes_dynamic_totalAmount?: number; + stakes_dynamic_value?: number; + stakes_dynamic_totalValue?: number; + stakes_dynamic_stakingMembersCount?: number; + stakeExpiry?: Record; +} + +export interface PgToken extends commons.BaseRecord { + name?: string; + symbol?: string; + title?: string; + description?: string; + shortDescriptionTitle?: string; + shortDescription?: string; + space?: string; + pricePerToken?: number; + totalSupply?: number; + allocations?: Record[]; + saleStartDate?: Date; + saleLength?: number; + coolDownEnd?: Date; + autoProcessAt100Percent?: boolean; + approved?: boolean; + rejected?: boolean; + public?: boolean; + links?: string[]; + icon?: string; + overviewGraphics?: string; + status?: enums.PgTokenStatus; + totalDeposit?: number; + tokensOrdered?: number; + totalAirdropped?: number; + termsAndConditions?: string; + access?: enums.PgAccess; + accessAwards?: string[]; + accessCollections?: string[]; + ipfsMedia?: string; + ipfsMetadata?: string; + ipfsRoot?: string; + mintingData_mintedBy?: string; + mintingData_mintedOn?: Date; + mintingData_aliasBlockId?: string; + mintingData_aliasId?: string; + mintingData_aliasStorageDeposit?: number; + mintingData_tokenId?: string; + mintingData_blockId?: string; + mintingData_foundryStorageDeposit?: number; + mintingData_network?: enums.PgNetwork; + mintingData_networkFormat?: string; + mintingData_vaultAddress?: string; + mintingData_tokensInVault?: number; + mintingData_vaultStorageDeposit?: number; + mintingData_guardianStorageDeposit?: number; + mintingData_meltedTokens?: number; + mintingData_circulatingSupply?: number; + rankCount?: number; + rankSum?: number; + rankAvg?: number; + mediaStatus?: enums.PgMediaStatus; + mediaUploadErrorCount?: number; + tradingDisabled?: boolean; + decimals?: number; + votes_upvotes?: number; + votes_downvotes?: number; + votes_voteDiff?: number; +} diff --git a/packages/database/src/pg/models/token_update.ts b/packages/database/src/pg/models/token_update.ts new file mode 100644 index 0000000000..886e510398 --- /dev/null +++ b/packages/database/src/pg/models/token_update.ts @@ -0,0 +1,173 @@ +/** + * This file was automatically generated by knex + * Do not modify this file manually + */ +import { ArrayRemove, ArrayUnion, Increment } from '../interfaces'; +import * as commons from './common_update'; +import * as enums from './enums'; + +export interface PgTokenVotesUpdate extends commons.BaseSubRecordUpdate { + direction?: number | null | Increment; +} + +export interface PgTokenStatsUpdate extends commons.BaseSubRecordUpdate { + votes_upvotes?: number | null | Increment; + votes_downvotes?: number | null | Increment; + votes_voteDiff?: number | null | Increment; + ranks_count?: number | null | Increment; + ranks_sum?: number | null | Increment; + ranks_avg?: number | null | Increment; + volumeTotal?: number | null | Increment; + volume_in24h?: number | null | Increment; + volume_in48h?: number | null | Increment; + volume_in7d?: number | null | Increment; + stakes_static_amount?: number | null | Increment; + stakes_static_totalAmount?: number | null | Increment; + stakes_static_value?: number | null | Increment; + stakes_static_totalValue?: number | null | Increment; + stakes_static_stakingMembersCount?: number | null | Increment; + stakes_dynamic_amount?: number | null | Increment; + stakes_dynamic_totalAmount?: number | null | Increment; + stakes_dynamic_value?: number | null | Increment; + stakes_dynamic_totalValue?: number | null | Increment; + stakes_dynamic_stakingMembersCount?: number | null | Increment; + stakeExpiry?: string | any | null; +} + +export interface PgTokenRanksUpdate extends commons.BaseSubRecordUpdate { + rank?: number | null | Increment; +} + +export interface PgTokenPurchaseUpdate extends commons.BaseRecordUpdate { + token?: string | null; + tokenStatus?: enums.PgTokenStatus | null; + sell?: string | null; + buy?: string | null; + count?: number | null | Increment; + price?: number | null | Increment; + triggeredBy?: enums.PgTokenTradeOrderType | null; + billPaymentId?: string | null; + buyerBillPaymentId?: string | null; + royaltyBillPayments?: string[] | null | ArrayUnion | ArrayRemove; + sourceNetwork?: enums.PgNetwork | null; + targetNetwork?: enums.PgNetwork | null; + sellerTokenTradingFeePercentage?: number | null | Increment; + sellerTier?: number | null | Increment; + in24h?: boolean | null; + in48h?: boolean | null; + in7d?: boolean | null; +} + +export interface PgTokenMarketUpdate extends commons.BaseRecordUpdate { + owner?: string | null; + token?: string | null; + tokenStatus?: enums.PgTokenStatus | null; + type?: enums.PgTokenTradeOrderType | null; + count?: number | null | Increment; + price?: number | null | Increment; + totalDeposit?: number | null | Increment; + balance?: number | null | Increment; + fulfilled?: number | null | Increment; + status?: enums.PgTokenTradeOrderStatus | null; + orderTransactionId?: string | null; + paymentTransactionId?: string | null; + creditTransactionId?: string | null; + expiresAt?: Date | null; + shouldRetry?: boolean | null; + sourceNetwork?: enums.PgNetwork | null; + targetNetwork?: enums.PgNetwork | null; + targetAddress?: string | null; +} + +export interface PgTokenDistributionUpdate extends commons.BaseSubRecordUpdate { + totalDeposit?: number | null | Increment; + totalPaid?: number | null | Increment; + refundedAmount?: number | null | Increment; + totalBought?: number | null | Increment; + reconciled?: boolean | null; + billPaymentId?: string | null; + creditPaymentId?: string | null; + royaltyBillPaymentId?: string | null; + tokenClaimed?: number | null | Increment; + lockedForSale?: number | null | Increment; + sold?: number | null | Increment; + totalPurchased?: number | null | Increment; + tokenOwned?: number | null | Increment; + mintedClaimedOn?: Date | null; + mintingTransactions?: string[] | null | ArrayUnion | ArrayRemove; + stakeRewards?: number | null | Increment; + extraStakeRewards?: number | null | Increment; + totalUnclaimedAirdrop?: number | null | Increment; + stakeVoteTransactionId?: string | null; + stakes_static_amount?: number | null | Increment; + stakes_static_totalAmount?: number | null | Increment; + stakes_static_value?: number | null | Increment; + stakes_static_totalValue?: number | null | Increment; + stakes_static_stakingMembersCount?: number | null | Increment; + stakes_dynamic_amount?: number | null | Increment; + stakes_dynamic_totalAmount?: number | null | Increment; + stakes_dynamic_value?: number | null | Increment; + stakes_dynamic_totalValue?: number | null | Increment; + stakes_dynamic_stakingMembersCount?: number | null | Increment; + stakeExpiry?: string | any | null; +} + +export interface PgTokenUpdate extends commons.BaseRecordUpdate { + name?: string | null; + symbol?: string | null; + title?: string | null; + description?: string | null; + shortDescriptionTitle?: string | null; + shortDescription?: string | null; + space?: string | null; + pricePerToken?: number | null | Increment; + totalSupply?: number | null | Increment; + allocations?: string | null; + saleStartDate?: Date | null; + saleLength?: number | null | Increment; + coolDownEnd?: Date | null; + autoProcessAt100Percent?: boolean | null; + approved?: boolean | null; + rejected?: boolean | null; + public?: boolean | null; + links?: string[] | null | ArrayUnion | ArrayRemove; + icon?: string | null; + overviewGraphics?: string | null; + status?: enums.PgTokenStatus | null; + totalDeposit?: number | null | Increment; + tokensOrdered?: number | null | Increment; + totalAirdropped?: number | null | Increment; + termsAndConditions?: string | null; + access?: enums.PgAccess | null; + accessAwards?: string[] | null | ArrayUnion | ArrayRemove; + accessCollections?: string[] | null | ArrayUnion | ArrayRemove; + ipfsMedia?: string | null; + ipfsMetadata?: string | null; + ipfsRoot?: string | null; + mintingData_mintedBy?: string | null; + mintingData_mintedOn?: Date | null; + mintingData_aliasBlockId?: string | null; + mintingData_aliasId?: string | null; + mintingData_aliasStorageDeposit?: number | null | Increment; + mintingData_tokenId?: string | null; + mintingData_blockId?: string | null; + mintingData_foundryStorageDeposit?: number | null | Increment; + mintingData_network?: enums.PgNetwork | null; + mintingData_networkFormat?: string | null; + mintingData_vaultAddress?: string | null; + mintingData_tokensInVault?: number | null | Increment; + mintingData_vaultStorageDeposit?: number | null | Increment; + mintingData_guardianStorageDeposit?: number | null | Increment; + mintingData_meltedTokens?: number | null | Increment; + mintingData_circulatingSupply?: number | null | Increment; + rankCount?: number | null | Increment; + rankSum?: number | null | Increment; + rankAvg?: number | null | Increment; + mediaStatus?: enums.PgMediaStatus | null; + mediaUploadErrorCount?: number | null | Increment; + tradingDisabled?: boolean | null; + decimals?: number | null | Increment; + votes_upvotes?: number | null | Increment; + votes_downvotes?: number | null | Increment; + votes_voteDiff?: number | null | Increment; +} diff --git a/packages/database/src/pg/models/transaction.ts b/packages/database/src/pg/models/transaction.ts new file mode 100644 index 0000000000..a9369cd005 --- /dev/null +++ b/packages/database/src/pg/models/transaction.ts @@ -0,0 +1,130 @@ +/** + * This file was automatically generated by knex + * Do not modify this file manually + */ +import * as commons from './common'; +import * as enums from './enums'; + +export interface PgTransaction extends commons.BaseRecord { + network?: enums.PgNetwork; + type?: enums.PgTransactionType; + isOrderType?: boolean; + member?: string; + space?: string; + shouldRetry?: boolean; + ignoreWallet?: boolean; + linkedTransactions?: string[]; + ignoreWalletReason?: enums.PgIgnoreWalletReason; + payload_type?: enums.PgTransactionPayloadType; + payload_amount?: number; + payload_sourceAddress?: string; + payload_targetAddress?: string; + payload_targetAddresses?: Record[]; + payload_sourceTransaction?: string[]; + payload_validationType?: enums.PgTransactionValidationType; + payload_expiresOn?: Date; + payload_reconciled?: boolean; + payload_void?: boolean; + payload_collection?: string; + payload_unsoldMintingOptions?: enums.PgUnsoldMintingOptions; + payload_newPrice?: number; + payload_collectionStorageDeposit?: number; + payload_nftsStorageDeposit?: number; + payload_aliasStorageDeposit?: number; + payload_nftsToMint?: number; + payload_transaction?: string; + payload_unlockedBy?: string; + payload_beneficiary?: enums.PgEntity; + payload_beneficiaryUid?: string; + payload_beneficiaryAddress?: string; + payload_royaltiesFee?: number; + payload_royaltiesSpace?: string; + payload_royaltiesSpaceAddress?: string; + payload_chainReference?: string; + payload_nft?: string; + payload_restrictions?: Record; + payload_token?: string; + payload_quantity?: number; + payload_tokenSymbol?: string; + payload_unclaimedAirdrops?: number; + payload_totalAirdropCount?: number; + payload_tokenId?: string; + payload_foundryStorageDeposit?: number; + payload_vaultStorageDeposit?: number; + payload_guardianStorageDeposit?: number; + payload_tokensInVault?: number; + payload_orderId?: string; + payload_collectionOutputAmount?: number; + payload_aliasOutputAmount?: number; + payload_nftOutputAmount?: number; + payload_aliasId?: string; + payload_aliasBlockId?: string; + payload_aliasGovAddress?: string; + payload_collectionId?: string; + payload_nftId?: string; + payload_nativeTokens?: Record[]; + payload_previousOwnerEntity?: enums.PgEntity; + payload_previousOwner?: string; + payload_ownerEntity?: enums.PgEntity; + payload_owner?: string; + payload_royalty?: boolean; + payload_vestingAt?: Date; + payload_customMetadata?: Record; + payload_stake?: string; + payload_award?: string; + payload_legacyAwardFundRequestId?: string; + payload_legacyAwardsBeeingFunded?: number; + payload_weeks?: number; + payload_stakeType?: enums.PgStakeType; + payload_count?: number; + payload_price?: number; + payload_tokenReward?: number; + payload_edition?: number; + payload_participatedOn?: Date; + payload_proposalId?: string; + payload_voteValues?: number[]; + payload_storageDepositSourceAddress?: string; + payload_storageReturn?: Record; + payload_airdropId?: string; + payload_nfts?: string[]; + payload_tag?: string; + payload_metadata?: Record; + payload_response?: Record; + payload_reason?: enums.PgCreditPaymentReason; + payload_invalidPayment?: boolean; + payload_outputToConsume?: string; + payload_dependsOnBillPayment?: boolean; + payload_milestoneTransactionPath?: string; + payload_tokenAmount?: number; + payload_weight?: number; + payload_weightMultiplier?: number; + payload_votes?: number[]; + payload_values?: number[]; + payload_creditId?: string; + payload_outputConsumed?: boolean; + payload_outputConsumedOn?: Date; + payload_stakes?: string[]; + payload_stakeReward?: string; + payload_tanglePuchase?: boolean; + payload_disableWithdraw?: boolean; + payload_lockCollectionNft?: boolean; + payload_stamp?: string; + payload_tokenTradeOderTargetAddress?: string; + payload_auction?: string; + payload_days?: number; + payload_dailyCost?: number; + payload_nftOrders?: Record[]; + payload_swap?: string; + payload_walletReference_createdOn?: Date; + payload_walletReference_processedOn?: Date; + payload_walletReference_chainReference?: string; + payload_walletReference_chainReferences?: string[]; + payload_walletReference_error?: string; + payload_walletReference_confirmed?: boolean; + payload_walletReference_confirmedOn?: Date; + payload_walletReference_milestoneTransactionPath?: string; + payload_walletReference_count?: number; + payload_walletReference_inProgress?: boolean; + payload_walletReference_nodeIndex?: number; + payload_outputId?: string; +} diff --git a/packages/database/src/pg/models/transaction_update.ts b/packages/database/src/pg/models/transaction_update.ts new file mode 100644 index 0000000000..33dd03368c --- /dev/null +++ b/packages/database/src/pg/models/transaction_update.ts @@ -0,0 +1,135 @@ +/** + * This file was automatically generated by knex + * Do not modify this file manually + */ +import { ArrayRemove, ArrayUnion, Increment } from '../interfaces'; +import * as commons from './common_update'; +import * as enums from './enums'; + +export interface PgTransactionUpdate extends commons.BaseRecordUpdate { + network?: enums.PgNetwork | null; + type?: enums.PgTransactionType | null; + isOrderType?: boolean | null; + member?: string | null; + space?: string | null; + shouldRetry?: boolean | null; + ignoreWallet?: boolean | null; + linkedTransactions?: string[] | null | ArrayUnion | ArrayRemove; + ignoreWalletReason?: enums.PgIgnoreWalletReason | null; + payload_type?: enums.PgTransactionPayloadType | null; + payload_amount?: number | null | Increment; + payload_sourceAddress?: string | null; + payload_targetAddress?: string | null; + payload_targetAddresses?: string | null; + payload_sourceTransaction?: string[] | null | ArrayUnion | ArrayRemove; + payload_validationType?: enums.PgTransactionValidationType | null; + payload_expiresOn?: Date | null; + payload_reconciled?: boolean | null; + payload_void?: boolean | null; + payload_collection?: string | null; + payload_unsoldMintingOptions?: enums.PgUnsoldMintingOptions | null; + payload_newPrice?: number | null | Increment; + payload_collectionStorageDeposit?: number | null | Increment; + payload_nftsStorageDeposit?: number | null | Increment; + payload_aliasStorageDeposit?: number | null | Increment; + payload_nftsToMint?: number | null | Increment; + payload_transaction?: string | null; + payload_unlockedBy?: string | null; + payload_beneficiary?: enums.PgEntity | null; + payload_beneficiaryUid?: string | null; + payload_beneficiaryAddress?: string | null; + payload_royaltiesFee?: number | null | Increment; + payload_royaltiesSpace?: string | null; + payload_royaltiesSpaceAddress?: string | null; + payload_chainReference?: string | null; + payload_nft?: string | null; + payload_restrictions?: string | any | null; + payload_token?: string | null; + payload_quantity?: number | null | Increment; + payload_tokenSymbol?: string | null; + payload_unclaimedAirdrops?: number | null | Increment; + payload_totalAirdropCount?: number | null | Increment; + payload_tokenId?: string | null; + payload_foundryStorageDeposit?: number | null | Increment; + payload_vaultStorageDeposit?: number | null | Increment; + payload_guardianStorageDeposit?: number | null | Increment; + payload_tokensInVault?: number | null | Increment; + payload_orderId?: string | null; + payload_collectionOutputAmount?: number | null | Increment; + payload_aliasOutputAmount?: number | null | Increment; + payload_nftOutputAmount?: number | null | Increment; + payload_aliasId?: string | null; + payload_aliasBlockId?: string | null; + payload_aliasGovAddress?: string | null; + payload_collectionId?: string | null; + payload_nftId?: string | null; + payload_nativeTokens?: string | null; + payload_previousOwnerEntity?: enums.PgEntity | null; + payload_previousOwner?: string | null; + payload_ownerEntity?: enums.PgEntity | null; + payload_owner?: string | null; + payload_royalty?: boolean | null; + payload_vestingAt?: Date | null; + payload_customMetadata?: string | any | null; + payload_stake?: string | null; + payload_award?: string | null; + payload_legacyAwardFundRequestId?: string | null; + payload_legacyAwardsBeeingFunded?: number | null | Increment; + payload_weeks?: number | null | Increment; + payload_stakeType?: enums.PgStakeType | null; + payload_count?: number | null | Increment; + payload_price?: number | null | Increment; + payload_tokenReward?: number | null | Increment; + payload_edition?: number | null | Increment; + payload_participatedOn?: Date | null; + payload_proposalId?: string | null; + payload_voteValues?: number[] | null; + payload_storageDepositSourceAddress?: string | null; + payload_storageReturn?: string | any | null; + payload_airdropId?: string | null; + payload_nfts?: string[] | null | ArrayUnion | ArrayRemove; + payload_tag?: string | null; + payload_metadata?: string | any | null; + payload_response?: string | any | null; + payload_reason?: enums.PgCreditPaymentReason | null; + payload_invalidPayment?: boolean | null; + payload_outputToConsume?: string | null; + payload_dependsOnBillPayment?: boolean | null; + payload_milestoneTransactionPath?: string | null; + payload_tokenAmount?: number | null | Increment; + payload_weight?: number | null | Increment; + payload_weightMultiplier?: number | null | Increment; + payload_votes?: number[] | null; + payload_values?: number[] | null; + payload_creditId?: string | null; + payload_outputConsumed?: boolean | null; + payload_outputConsumedOn?: Date | null; + payload_stakes?: string[] | null | ArrayUnion | ArrayRemove; + payload_stakeReward?: string | null; + payload_tanglePuchase?: boolean | null; + payload_disableWithdraw?: boolean | null; + payload_lockCollectionNft?: boolean | null; + payload_stamp?: string | null; + payload_tokenTradeOderTargetAddress?: string | null; + payload_auction?: string | null; + payload_days?: number | null | Increment; + payload_dailyCost?: number | null | Increment; + payload_nftOrders?: string | null; + payload_swap?: string | null; + payload_walletReference_createdOn?: Date | null; + payload_walletReference_processedOn?: Date | null; + payload_walletReference_chainReference?: string | null; + payload_walletReference_chainReferences?: + | string[] + | null + | ArrayUnion + | ArrayRemove; + payload_walletReference_error?: string | null; + payload_walletReference_confirmed?: boolean | null; + payload_walletReference_confirmedOn?: Date | null; + payload_walletReference_milestoneTransactionPath?: string | null; + payload_walletReference_count?: number | null | Increment; + payload_walletReference_inProgress?: boolean | null; + payload_walletReference_nodeIndex?: number | null | Increment; + payload_outputId?: string | null; +} diff --git a/packages/database/src/storage/build5Storage.ts b/packages/database/src/storage/build5Storage.ts index 01b7c2d600..0d05201814 100644 --- a/packages/database/src/storage/build5Storage.ts +++ b/packages/database/src/storage/build5Storage.ts @@ -1,5 +1,4 @@ -import { build5App } from '../app/build5App'; import { IStorage } from './interfaces'; import { FirebaseStorage } from './storage'; -export const build5Storage = (): IStorage => new FirebaseStorage(build5App); +export const build5Storage = (): IStorage => new FirebaseStorage(); diff --git a/packages/database/src/storage/storage.ts b/packages/database/src/storage/storage.ts index b649dfdaca..2fca44e5db 100644 --- a/packages/database/src/storage/storage.ts +++ b/packages/database/src/storage/storage.ts @@ -1,16 +1,11 @@ import { Bucket } from '@build-5/interfaces'; -import { Bucket as FBucket } from '@google-cloud/storage'; -import { Storage } from 'firebase-admin/storage'; -import { get } from 'lodash'; -import { FirebaseApp } from '../app/app'; +import { Bucket as FBucket, Storage } from '@google-cloud/storage'; import { IBucket, IStorage } from './interfaces'; export class FirebaseStorage implements IStorage { - private readonly storage: Storage; + private readonly storage = new Storage(); - constructor(private readonly app: FirebaseApp) { - this.storage = this.app.getInstance().storage(); - } + constructor() {} public bucket = (name: string) => new FirebaseBucket(this.storage, name as Bucket); } @@ -29,7 +24,8 @@ export class FirebaseBucket implements IBucket { public upload = async (path: string, destination: string, metadata: Record) => { const response = await this.bucket.upload(path, { destination, metadata }); - return get(response[1], 'mediaLink', ''); + const responseMetadata = response[0].metadata; + return responseMetadata.mediaLink!.replace(`generation=${responseMetadata.generation}&`, ''); }; public download = async (fileName: string, destination: string) => { diff --git a/packages/functions/.env b/packages/functions/.env index 18e81e3968..bda0691bce 100644 --- a/packages/functions/.env +++ b/packages/functions/.env @@ -1,11 +1,19 @@ -ENVIRONMENT=test -WEB3_TOKEN=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJkaWQ6ZXRocjoweEZCOTFiNTdEN2YzNmVhNjQ4NjQ3ODIyQjJGNGVEOEEyMDZCNERhNjQiLCJpc3MiOiJ3ZWIzLXN0b3JhZ2UiLCJpYXQiOjE2Njc0MDYzNzE3NDksIm5hbWUiOiJ0ZXN0IGRldiJ9.88vd8ZmeEle2Xqyc8uEMBOXJqDrFcxxF8gyHuXIjXgk +FUNCTIONS_EMULATOR_TIMEOUT_SECONDS="540s" +ENVIRONMENT="emulator" +WEB3_TOKEN="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJkaWQ6ZXRocjoweEVFMjA3Qzk5YzA2NzkxMDg0QjU5NmU4NkEyMzVGNzFiNTc0NWNkMTIiLCJpc3MiOiJ3ZWIzLXN0b3JhZ2UiLCJpYXQiOjE2Njg0Njc4MDQ3NDAsIm5hbWUiOiJERVZfVE9LRU4ifQ.TB2AbWZDMk4WhWIeWKsdEKUReXUh0WUgcHAU5ccb4FA" NFT_STORAGE_TOKEN=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJkaWQ6ZXRocjoweDhiYjBGMDk4NzIzYTY5ODg1NTg3NTJCYWM0ODRlMTJCNGJlMGYxMDIiLCJpc3MiOiJuZnQtc3RvcmFnZSIsImlhdCI6MTcwNTUwMjkyMTEwMiwibmFtZSI6InNhbmRib3gifQ.a4TfMHsghXJjKQUO9zC9O0Wu_NGXVffDkw1E6-jr3hI -JWT_SECRET="asdas#@#@xdas31sad" -ALGOLIA_APPID=6MPUETJRDB -ALGOLIA_KEY=a75153c20ebe86d31e1fe5874f55dbac -ENCRYPTION_SALT=c4kWxCtNVQ5c2m -IP_INFO_TOKEN='' -XPTOKEN_ID=0x08fe43472f5968c4ccfa7154599e3d9c8df3f2e0b6396cafc2b038f15ee1974e050100000000 -XPTOKEN_UID=0xe71439be7001d2311658ded364e4043a284d16f4 -XPTOKEN_GUARDIANID=0x551fd2c7c7bf356bac194587dab2fcd46420054b \ No newline at end of file +JWT_SECRET="mysecret" +ALGOLIA_APPID="UZXKW1YS76" +ALGOLIA_KEY="8bf460848691fae9111b6159867d6bc1" +ENCRYPTION_SALT="sa#asda!2sasd##asad" +IP_INFO_TOKEN="" +XPTOKEN_ID="0x08f800d9e15c1da60c36cb0b2d4a02366ea3e200a65fc071a9e25f09b7fb9e951f0100000000" +XPTOKEN_UID="0xcef8ddcea97a5b82921d1cadbc8ccddcd69341da" +XPTOKEN_GUARDIANID="0x45f8379c44a73fc0ee6ad56acf51bd0f69240af5" + +DB_USER="postgres" +DB_USER_PWD="postgres" +DB_NAME="build5db" +DB_HOST=localhost +DB_PORT=5432 + \ No newline at end of file diff --git a/packages/functions/.env.dev b/packages/functions/.env.dev deleted file mode 100644 index 2461f634e2..0000000000 --- a/packages/functions/.env.dev +++ /dev/null @@ -1,11 +0,0 @@ -ENVIRONMENT=dev -WEB3_TOKEN=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJkaWQ6ZXRocjoweEVFMjA3Qzk5YzA2NzkxMDg0QjU5NmU4NkEyMzVGNzFiNTc0NWNkMTIiLCJpc3MiOiJ3ZWIzLXN0b3JhZ2UiLCJpYXQiOjE2Njg0Njc4MDQ3NDAsIm5hbWUiOiJERVZfVE9LRU4ifQ.TB2AbWZDMk4WhWIeWKsdEKUReXUh0WUgcHAU5ccb4FA -NFT_STORAGE_TOKEN=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJkaWQ6ZXRocjoweDhiYjBGMDk4NzIzYTY5ODg1NTg3NTJCYWM0ODRlMTJCNGJlMGYxMDIiLCJpc3MiOiJuZnQtc3RvcmFnZSIsImlhdCI6MTcwNTUwMjkyMTEwMiwibmFtZSI6InNhbmRib3gifQ.a4TfMHsghXJjKQUO9zC9O0Wu_NGXVffDkw1E6-jr3hI -JWT_SECRET=mysecret -ALGOLIA_APPID=UZXKW1YS76 -ALGOLIA_KEY=8bf460848691fae9111b6159867d6bc1 -ENCRYPTION_SALT=sa#asda!2sasd##asad -IP_INFO_TOKEN='' -XPTOKEN_ID=0x08f800d9e15c1da60c36cb0b2d4a02366ea3e200a65fc071a9e25f09b7fb9e951f0100000000 -XPTOKEN_UID=0xcef8ddcea97a5b82921d1cadbc8ccddcd69341da -XPTOKEN_GUARDIANID=0x45f8379c44a73fc0ee6ad56acf51bd0f69240af5 \ No newline at end of file diff --git a/packages/functions/.env.local b/packages/functions/.env.local deleted file mode 100644 index b6a0ed52c3..0000000000 --- a/packages/functions/.env.local +++ /dev/null @@ -1,12 +0,0 @@ -FUNCTIONS_EMULATOR_TIMEOUT_SECONDS="540s" -ENVIRONMENT="emulator" -WEB3_TOKEN="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJkaWQ6ZXRocjoweEVFMjA3Qzk5YzA2NzkxMDg0QjU5NmU4NkEyMzVGNzFiNTc0NWNkMTIiLCJpc3MiOiJ3ZWIzLXN0b3JhZ2UiLCJpYXQiOjE2Njg0Njc4MDQ3NDAsIm5hbWUiOiJERVZfVE9LRU4ifQ.TB2AbWZDMk4WhWIeWKsdEKUReXUh0WUgcHAU5ccb4FA" -NFT_STORAGE_TOKEN=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJkaWQ6ZXRocjoweDhiYjBGMDk4NzIzYTY5ODg1NTg3NTJCYWM0ODRlMTJCNGJlMGYxMDIiLCJpc3MiOiJuZnQtc3RvcmFnZSIsImlhdCI6MTcwNTUwMjkyMTEwMiwibmFtZSI6InNhbmRib3gifQ.a4TfMHsghXJjKQUO9zC9O0Wu_NGXVffDkw1E6-jr3hI -JWT_SECRET="mysecret" -ALGOLIA_APPID="UZXKW1YS76" -ALGOLIA_KEY="8bf460848691fae9111b6159867d6bc1" -ENCRYPTION_SALT="sa#asda!2sasd##asad" -IP_INFO_TOKEN="" -XPTOKEN_ID="0x08f800d9e15c1da60c36cb0b2d4a02366ea3e200a65fc071a9e25f09b7fb9e951f0100000000" -XPTOKEN_UID="0xcef8ddcea97a5b82921d1cadbc8ccddcd69341da" -XPTOKEN_GUARDIANID="0x45f8379c44a73fc0ee6ad56acf51bd0f69240af5" \ No newline at end of file diff --git a/packages/functions/.eslintrc.js b/packages/functions/.eslintrc.js index 44802784fa..20c4d0d988 100644 --- a/packages/functions/.eslintrc.js +++ b/packages/functions/.eslintrc.js @@ -41,14 +41,6 @@ module.exports = { '@typescript-eslint/prefer-enum-initializers': 2, '@typescript-eslint/member-delimiter-style': 2, // Disabled for now. - 'require-jsdoc': 0, // ["error", { - // "require": { - // "FunctionDeclaration": true, - // "MethodDefinition": true, - // "ClassDeclaration": true, - // "ArrowFunctionExpression": true, - // "FunctionExpression": true - // } - // }] + 'require-jsdoc': 0, }, }; diff --git a/packages/functions/.runtimeconfig.json b/packages/functions/.runtimeconfig.json deleted file mode 100644 index b5eb4a1bb4..0000000000 --- a/packages/functions/.runtimeconfig.json +++ /dev/null @@ -1,33 +0,0 @@ -{ - "pinata": { - "key": "", - "secret": "" - }, - "nftstorage": { - "token": "" - }, - "encryption": { - "salt": "sa#asda!2sasd##asad" - }, - "environment": { - "type": "emulator" - }, - "ip_info": { - "token": "" - }, - "web3": { - "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJkaWQ6ZXRocjoweEVFMjA3Qzk5YzA2NzkxMDg0QjU5NmU4NkEyMzVGNzFiNTc0NWNkMTIiLCJpc3MiOiJ3ZWIzLXN0b3JhZ2UiLCJpYXQiOjE2Njg0Njc4MDQ3NDAsIm5hbWUiOiJERVZfVE9LRU4ifQ.TB2AbWZDMk4WhWIeWKsdEKUReXUh0WUgcHAU5ccb4FA" - }, - "jwt": { - "secret": "mysecret" - }, - "algolia": { - "appid": "UZXKW1YS76", - "key": "8bf460848691fae9111b6159867d6bc1" - }, - "xptoken": { - "id": "0x08f800d9e15c1da60c36cb0b2d4a02366ea3e200a65fc071a9e25f09b7fb9e951f0100000000", - "uid": "0xcef8ddcea97a5b82921d1cadbc8ccddcd69341da", - "guardianid": "0x45f8379c44a73fc0ee6ad56acf51bd0f69240af5" - } -} diff --git a/packages/functions/jest-setup.ts b/packages/functions/jest-setup.ts new file mode 100644 index 0000000000..03bc279cce --- /dev/null +++ b/packages/functions/jest-setup.ts @@ -0,0 +1,100 @@ +// eslint-disable-next-line @typescript-eslint/no-var-requires +require('dotenv').config({ path: __dirname + '/.env' }); +import { + PgAccess, + PgNetwork, + PgProjectAdmins, + PgProjectBilling, + PgProjectUpdate, + PgTokenStatus, + PgTokenUpdate, + build5Db, +} from '@build-5/database'; +import { COL, MIN_IOTA_AMOUNT, SOON_PROJECT_ID, SUB_COL } from '@build-5/interfaces'; +import { migrate as pgMigrate } from './migration/pg.migration'; + +const MEDIA = + 'https://images-wen.soonaverse.com/0x0275dfc7c2624c0111d441a0819dccfd5e947c89%2F6stvhnutvg%2Ftoken_introductionary'; +const SOON_PROJ_GUARDIAN = '0x3d5d0b3f40c9438871b1c43d6b70117eeff77ad8'; +const soonTokenId = '0xa381bfccaf121e38e31362d85b5ad30cd7fc0d06'; +const rmsTokenId = '0x52f27a34170900537acb61e5ff0fe94a2841ff52'; + +const setup = async () => { + await migrateSchema(); + + await build5Db() + .doc(COL.TOKEN, soonTokenId) + .upsert({ + project: SOON_PROJECT_ID, + uid: soonTokenId, + name: 'Soon token', + symbol: 'SOON', + } as PgTokenUpdate); + + await build5Db().doc(COL.TOKEN, rmsTokenId).upsert({ + project: SOON_PROJECT_ID, + symbol: 'RMS', + approved: true, + name: 'RMS token', + status: PgTokenStatus.BASE, + access: PgAccess.OPEN, + icon: MEDIA, + mintingData_network: PgNetwork.RMS, + }); + + const soonProject: PgProjectUpdate = { + name: 'Soonaverse', + createdBy: SOON_PROJ_GUARDIAN, + deactivated: false, + config_billing: PgProjectBilling.TOKEN_BASED, + config_tiers: [0, 0, 0, 0, 0].map((v) => v * MIN_IOTA_AMOUNT), + config_tokenTradingFeeDiscountPercentage: [0, 0, 0, 0, 0], + config_nativeTokenSymbol: 'SOON', + config_nativeTokenUid: soonTokenId, + otr: JSON.stringify({}), + }; + + const soonProjDocRef = build5Db().doc(COL.PROJECT, SOON_PROJECT_ID); + await soonProjDocRef.upsert(soonProject); + const adminDocRef = build5Db().doc( + COL.PROJECT, + SOON_PROJECT_ID, + SUB_COL.ADMINS, + SOON_PROJ_GUARDIAN, + ); + const admin: PgProjectAdmins = { + uid: SOON_PROJ_GUARDIAN, + project: SOON_PROJECT_ID, + parentId: SOON_PROJECT_ID, + }; + await adminDocRef.upsert(admin); + + await build5Db().destroy(); + console.log('Setup env'); +}; + +const migrateSchema = async () => { + const knex = build5Db().getCon(); + + await pgMigrate(); + + if (!(await knex.schema.hasTable('blocks'))) { + await knex.schema.createTable('blocks', (t) => { + t.timestamp('createdOn').defaultTo(knex.raw('CURRENT_TIMESTAMP')); + t.string('blockId').primary(); + }); + } + + await knex.raw(` + CREATE OR REPLACE FUNCTION block_func() RETURNS TRIGGER AS $$ + BEGIN + PERFORM pg_notify('blocks', NEW."blockId"); + RETURN NEW; + END; + $$ LANGUAGE plpgsql; + CREATE OR REPLACE TRIGGER block AFTER INSERT ON blocks + FOR EACH ROW EXECUTE FUNCTION block_func(); + `); +}; + +export default setup; diff --git a/packages/functions/jest.config.js b/packages/functions/jest.config.js index de54050089..73f2f312b9 100644 --- a/packages/functions/jest.config.js +++ b/packages/functions/jest.config.js @@ -2,8 +2,7 @@ module.exports = { preset: 'ts-jest', testEnvironment: 'node', testTimeout: 900000, - globalSetup: './test/set-up.ts', - globalTeardown: './test/teardown.ts', + globalSetup: './jest-setup.ts', reporters: ['default', 'github-actions'], setupFilesAfterEnv: ['./test/teardown.ts'], }; diff --git a/packages/functions/migration/index.ts b/packages/functions/migration/index.ts new file mode 100644 index 0000000000..1ee0b49480 --- /dev/null +++ b/packages/functions/migration/index.ts @@ -0,0 +1,8 @@ +import { migrate as pgMigrate } from './pg.migration'; +import { migrate as pubSubMigrate } from './pubsub.migration'; + +const migrate = async () => { + await Promise.all([pgMigrate(), pubSubMigrate()]); +}; + +migrate(); diff --git a/packages/functions/migration/pg.migration.ts b/packages/functions/migration/pg.migration.ts new file mode 100644 index 0000000000..2a8cff8115 --- /dev/null +++ b/packages/functions/migration/pg.migration.ts @@ -0,0 +1,80 @@ +import initKnex from 'knex'; +import path from 'path'; +import { flattenObject } from '../src/common'; +import * as triggers from '../src/runtime/trigger/index'; +import { TriggeredFunction, TriggeredFunctionType } from '../src/runtime/trigger/trigger'; +// eslint-disable-next-line @typescript-eslint/no-var-requires +require('dotenv').config({ path: path.join(__dirname + '/../.env') }); + +export const migrate = async () => { + const knex = initKnex({ + client: 'pg', + connection: { + user: process.env.DB_USER, + password: process.env.DB_USER_PWD, + database: process.env.DB_NAME, + host: process.env.DB_HOST, + port: Number(process.env.DB_PORT), + }, + migrations: { + directory: '../database/migrations', + extension: 'ts', + }, + pool: { min: 0, max: 3 }, + }); + + await knex.migrate.latest(); + + const promises = Object.entries(flattenObject(triggers)).map(async ([key, v]) => { + const trigger = v as TriggeredFunction; + const table = trigger.col + (trigger.subCol ? '_' + trigger.subCol : ''); + const opr = (type: TriggeredFunctionType) => { + switch (type) { + case TriggeredFunctionType.ON_CREATE: + return 'INSERT'; + case TriggeredFunctionType.ON_UPDATE: + return 'UPDATE'; + case TriggeredFunctionType.ON_WRITE: + return 'INSERT OR UPDATE '; + default: + throw Error('Invalid type: ' + type); + } + }; + + await knex.raw(` + CREATE OR REPLACE FUNCTION ${key}_func() RETURNS TRIGGER AS $$ + DECLARE + payload JSON; + subCol TEXT; + subColId TEXT; + generated_id INT; + BEGIN + subCol := '${trigger.subCol || null}'; + subColId := ${trigger.subCol ? 'NEW."parentId"' : null}; + + payload := json_build_object( + 'col', '${trigger.col}', + 'uid', NEW.uid, + 'subCol', subCol, + 'subColId', subColId, + 'prev', row_to_json(OLD), + 'curr', row_to_json(NEW) + ); + + INSERT INTO changes(change) + VALUES (payload) + RETURNING uid INTO generated_id; + + PERFORM pg_notify('trigger', '${key}' || ':' || generated_id::text); + RETURN NEW; + END; + $$ LANGUAGE plpgsql; + CREATE OR REPLACE TRIGGER ${key} AFTER ${opr(trigger.type)} ON ${table} + FOR EACH ROW EXECUTE FUNCTION ${key}_func(); + `); + }); + + await Promise.all(promises); + + await knex.destroy(); +}; diff --git a/packages/functions/migration/pubsub.migration.ts b/packages/functions/migration/pubsub.migration.ts new file mode 100644 index 0000000000..6cd2dfa977 --- /dev/null +++ b/packages/functions/migration/pubsub.migration.ts @@ -0,0 +1,20 @@ +import { PubSub } from '@google-cloud/pubsub'; +import { flattenObject } from '../src/common'; +import * as triggers from '../src/runtime/trigger/index'; + +export const migrate = async () => { + const pubSub = new PubSub(); + + const promises = Object.entries(flattenObject(triggers)).map(async ([key]) => { + if (!(await pubSub.topic(key).exists())) { + await pubSub.topic(key).create(); + } + }); + + await Promise.all(promises); + + const onUpsertTopic = 'onupsert'; + if (!(await pubSub.topic(onUpsertTopic).exists())) { + await pubSub.topic(onUpsertTopic).create(); + } +}; diff --git a/packages/functions/package.json b/packages/functions/package.json index b173ba7883..9cf761d1f0 100644 --- a/packages/functions/package.json +++ b/packages/functions/package.json @@ -17,18 +17,15 @@ "scripts": { "lint": "eslint --ext .js,.ts src", "build": "tsc && cp .env lib/.env", - "emulators": "tsc --watch & firebase -c ../../firebase.json emulators:start --only functions,firestore,storage,ui,auth", - "milestone-sync": "npx ts-node ./test/milestone.sync.ts", - "serve": "run-p \"milestone-sync\" \"emulators\" ", - "test": "export LOCAL_TEST=true && jest --runInBand", - "test-tangle": "export LOCAL_TEST=true && jest test-tangle/ --runInBand ", - "test:ci": "export LOCAL_TEST=true && jest test/ --runInBand --ci --config=jest.config.ci.js", - "test-tangle:ci": "export LOCAL_TEST=true && jest test-tangle/ --runInBand --ci --config=jest.config.ci.js", - "export-online-test-credentials": "export GOOGLE_APPLICATION_CREDENTIALS=\"./test-service-account-key.json\"", - "test-online:ci": "npm run export-online-test-credentials && jest test/ --runInBand --ci --config=jest.config.ci.js", - "test-tangle-online:ci": "npm run export-online-test-credentials && jest test-tangle/ --runInBand --ci --config=jest.config.ci.js" + "start": "export GOOGLE_APPLICATION_CREDENTIALS=\"./service-account-key.json\" && node lib/index.js", + "build-start": "npm run build && npm run start", + "notifier": "export GOOGLE_APPLICATION_CREDENTIALS=\"./service-account-key.json\" && npx ts-node ./test/notifier.ts", + "serve": "run-p \"build-start\" \"notifier\"", + "test": "export GOOGLE_APPLICATION_CREDENTIALS=\"./service-account-key.json\" && jest", + "migrate": "export GOOGLE_APPLICATION_CREDENTIALS=\"./service-account-key.json\" && ts-node ./migration/index.ts" }, "devDependencies": { + "@google-cloud/pubsub": "4.3.3", "@types/busboy": "1.5.3", "@types/chai": "4.3.11", "@types/chance": "1.1.6", @@ -55,10 +52,8 @@ "eslint-plugin-jsdoc": "48.1.0", "eslint-plugin-prefer-arrow": "1.2.3", "eslint-plugin-prettier": "5.1.3", - "firebase-functions-test": "3.1.1", "glob": "8.0.3", "jest": "29.7.0", - "jest-junit": "16.0.0", "prettier": "3.2.5", "prettier-eslint": "16.3.0", "ts-jest": "29.1.2", @@ -79,20 +74,18 @@ "@iota/util.js": "1.8.6", "@iota/util.js-next": "npm:@iota/util.js@2.0.0-rc.2", "@metamask/eth-sig-util": "7.0.1", + "@types/express": "4.17.21", "algoliasearch": "4.22.1", "axios": "1.6.7", "bip39": "3.1.0", "busboy": "1.6.0", "child-process-promise": "2.2.1", - "cloudevents": "8.0.0", "cors": "2.8.5", "crypto-js": "4.2.0", "dayjs": "1.11.10", "ethers": "6.11.1", + "express": "4.19.2", "files-from-path": "^1.0.4", - "firebase-admin": "12.0.0", - "firebase-functions": "4.7.0", - "interfaces": "0.0.3", "is-ipfs": "8.0.4", "joi": "17.12.1", "js-big-decimal": "2.0.7", @@ -101,8 +94,6 @@ "mime-types": "2.1.35", "nft.storage": "7.1.1", "node-ipinfo": "3.5.1", - "protobufjs": "7.2.6", - "rxjs": "7.8.1", "sharp": "0.33.2" } } diff --git a/packages/functions/scripts/db.upgrade.ts b/packages/functions/scripts/db.upgrade.ts index bd2fff49c6..3b0746b365 100644 --- a/packages/functions/scripts/db.upgrade.ts +++ b/packages/functions/scripts/db.upgrade.ts @@ -1,3 +1,4 @@ +import { FirebaseApp } from '@build-5/database'; import { COL } from '@build-5/interfaces'; import crypto from 'crypto'; import dotenv from 'dotenv'; @@ -5,7 +6,6 @@ import admin from 'firebase-admin'; import { getFirestore } from 'firebase-admin/firestore'; import fs from 'fs'; import { glob } from 'glob'; -import { FirebaseApp } from '@build-5/database'; import serviceAccount from './serviceAccountKey.json'; dotenv.config({ path: '../.env' }); diff --git a/packages/functions/scripts/dbUpgrades/2.1/soon.snapshot.ts b/packages/functions/scripts/dbUpgrades/2.1/soon.snapshot.ts deleted file mode 100644 index 34e15d6bd7..0000000000 --- a/packages/functions/scripts/dbUpgrades/2.1/soon.snapshot.ts +++ /dev/null @@ -1,235 +0,0 @@ -import { FirebaseApp } from '@build-5/database'; -import { COL, Network, SUB_COL, TokenDrop, TokenDropStatus } from '@build-5/interfaces'; -import { - Address, - AddressType, - AddressUnlockCondition, - AliasAddress, - AliasOutput, - BasicOutput, - Ed25519Address, - GovernorAddressUnlockCondition, - InputType, - NftAddress, - NftOutput, - OutputType, - RegularTransactionEssence, - StateControllerAddressUnlockCondition, - TransactionPayload, - UTXOInput, - UnlockConditionType, - Utils, -} from '@iota/sdk'; -import dayjs from 'dayjs'; -import admin from 'firebase-admin'; -import { chunk, flatMap, head, last } from 'lodash'; - -const consumedOutputs: Set = new Set(); - -const limit = 1000; - -let tokensPerAddress: { [key: string]: number } = {}; - -let SOON_TOKEN_ID = - '0x0884298fe9b82504d26ddb873dbd234a344c120da3a4317d8063dbcf96d356aa9d0100000000'; -let NETWORK: Network.SMR | Network.RMS = Network.SMR; -let MILESTONE_COL = COL.MILESTONE_SMR; -let MIN_MILESTONE = 125439; - -export const soonSnapshot = async ( - app: FirebaseApp, - tokenId?: string, - network?: Network.SMR | Network.RMS, -) => { - SOON_TOKEN_ID = tokenId === undefined ? SOON_TOKEN_ID : tokenId; - NETWORK = network === undefined ? NETWORK : network; - MILESTONE_COL = NETWORK === Network.SMR ? COL.MILESTONE_SMR : COL.MILESTONE_RMS; - tokensPerAddress = {}; - - const instance = app.getInstance() as admin.app.App; - const firestore = instance.firestore(); - - const tokensPerMember = await createSoonSnapshot(firestore); - - const chunks = chunk(Object.entries(tokensPerMember), 500); - for (const chunk of chunks) { - const batch = firestore.batch(); - - for (const [address, count] of chunk) { - const docRef = firestore.doc(`${COL.SOON_SNAP}/${address}`); - batch.set(docRef, { - uid: address, - createdOn: dayjs().toDate(), - - count, - paidOut: 0, - - ethAddress: address.startsWith('0x') ? address : '', - ethAddressVerified: false, - }); - } - - await batch.commit(); - } - - return tokensPerMember; -}; - -const createSoonSnapshot = async (db: admin.firestore.Firestore) => { - let lastDoc: any = undefined; - - do { - let query = db.collection(MILESTONE_COL).orderBy('createdOn', 'desc').limit(limit); - if (lastDoc) { - query = query.startAfter(lastDoc); - } - - const milestoneSnapshot = await query.get(); - lastDoc = last(milestoneSnapshot.docs); - - const milestones = milestoneSnapshot.docs.map((d) => d.id); - const transactions = await getTransactions(db, milestones); - - for (const transaction of transactions) { - const payload = transaction.payload as TransactionPayload; - const essence = payload.essence as RegularTransactionEssence; - - updateConsumedOutputs(essence); - await processTransactions(payload); - } - } while (lastDoc && Number(lastDoc.data().milestone) > MIN_MILESTONE); - - const promises = Object.entries(tokensPerAddress).map((act) => - addressToMember(db, act[0], act[1]), - ); - - return (await Promise.all(promises)).reduce( - (acc, act) => { - Object.entries(act).forEach(([key, value]) => { - acc[key] = (acc[key] || 0) + value; - }); - return acc; - }, - {} as { [key: string]: number }, - ); -}; - -const addressToMember = async (db: admin.firestore.Firestore, address: string, count: number) => { - const tokensPerMember: { [key: string]: number } = {}; - const airdropsSnap = await db - .collection(COL.AIRDROP) - .where('sourceAddress', '==', address) - .where('status', '==', TokenDropStatus.UNCLAIMED) - .get(); - - for (const doc of airdropsSnap.docs) { - const airdrop = doc.data() as TokenDrop; - - const memberSnap = await db - .collection(COL.MEMBER) - .where(`validatedAddress.${NETWORK}`, '==', airdrop.member) - .limit(1) - .get(); - const memberAddress = - head(memberSnap.docs)?.data().validatedAddress?.[NETWORK] || airdrop.member; - - tokensPerMember[memberAddress] = (tokensPerMember[memberAddress] || 0) + airdrop.count; - } - - if (airdropsSnap.size) { - return tokensPerMember; - } - - const memberSnap = await db - .collection(COL.MEMBER) - .where(`validatedAddress.${NETWORK}`, '==', address) - .get(); - const memberAddress = head(memberSnap.docs)?.data().validatedAddress?.[NETWORK] || address; - tokensPerMember[memberAddress] = (tokensPerMember[memberAddress] || 0) + count; - - return tokensPerMember; -}; - -const getTransactions = async (db: admin.firestore.Firestore, milestones: string[]) => { - const promises = milestones.map(async (milestone) => { - const snap = await db - .collection(MILESTONE_COL) - .doc(milestone) - .collection(SUB_COL.TRANSACTIONS) - .get(); - return snap.docs.map((d) => d.data()); - }); - return flatMap(await Promise.all(promises)); -}; - -const processTransactions = async (payload: TransactionPayload) => { - const essence = payload.essence as RegularTransactionEssence; - - const outputs = essence.outputs.filter( - (o, i) => - [OutputType.Alias, OutputType.Basic, OutputType.Nft].includes(o.type) && - !consumedOutputs.has(Utils.computeOutputId(Utils.transactionId(payload), i)), - ); - - for (const output of outputs) { - const result = getAddressAndSoons(output as AliasOutput | BasicOutput | NftOutput); - if (result.tokens) { - tokensPerAddress[result.address] = (tokensPerAddress[result.address] || 0) + result.tokens; - } - } -}; - -const updateConsumedOutputs = (essence: RegularTransactionEssence) => { - for (const input of essence.inputs) { - if (input.type === InputType.UTXO) { - const i = input as UTXOInput; - consumedOutputs.add(Utils.computeOutputId(i.transactionId, i.transactionOutputIndex)); - } - } -}; - -const getAddressAndSoons = (output: AliasOutput | BasicOutput | NftOutput) => { - const soonTokens = getSoonTokenCount(output); - if (!soonTokens) { - return { tokens: 0, address: '' }; - } - const address = bech32FromUnlockConditions(output, NETWORK); - return { tokens: soonTokens, address }; -}; - -const getSoonTokenCount = (output: BasicOutput | AliasOutput | NftOutput) => - (output.nativeTokens || []) - .filter((nt) => nt.id === SOON_TOKEN_ID) - .reduce((acc, act) => acc + Number(act.amount), 0); - -const bech32FromUnlockConditions = (output: BasicOutput, hrp: string) => - addressToBech32(getUnlockCondition(output)?.address, hrp); - -const getUnlockCondition = (output: AliasOutput | BasicOutput | NftOutput) => { - if (output.type === OutputType.Basic || output.type === OutputType.Nft) { - return output.unlockConditions.find( - (c) => c.type === UnlockConditionType.Address, - ) as AddressUnlockCondition; - } - - const condition = output.unlockConditions.find( - (c) => c.type === UnlockConditionType.GovernorAddress, - ) as GovernorAddressUnlockCondition; - return (condition || - output.unlockConditions.find( - (c) => c.type === UnlockConditionType.StateControllerAddress, - )) as StateControllerAddressUnlockCondition; -}; - -const addressToBech32 = (address: Address, hrp: string) => { - switch (address.type) { - case AddressType.Ed25519: - return Utils.hexToBech32((address as Ed25519Address).pubKeyHash, hrp); - case AddressType.Alias: - return Utils.aliasIdToBech32((address as AliasAddress).aliasId, hrp); - case AddressType.Nft: - return Utils.aliasIdToBech32((address as NftAddress).nftId, hrp); - } -}; - -export const roll = soonSnapshot; diff --git a/packages/functions/scripts/dummyTransfer.ts b/packages/functions/scripts/dummyTransfer.ts index 5479cb88e4..a532879c08 100644 --- a/packages/functions/scripts/dummyTransfer.ts +++ b/packages/functions/scripts/dummyTransfer.ts @@ -1,16 +1,16 @@ import { Bip32Path } from '@iota/crypto.js'; import { Bech32Helper, + ED25519_ADDRESS_TYPE, Ed25519Address, Ed25519Seed, - ED25519_ADDRESS_TYPE, IKeyPair, ISigLockedSingleOutput, IUTXOInput, - sendAdvanced, SIG_LOCKED_SINGLE_OUTPUT_TYPE, SingleNodeClient, UTXO_INPUT_TYPE, + sendAdvanced, } from '@iota/iota.js'; import { Converter } from '@iota/util.js'; import { generateMnemonic } from 'bip39'; diff --git a/packages/functions/scripts/duplicatePurchases.ts b/packages/functions/scripts/duplicatePurchases.ts index 7b953a1a7e..0d14cba798 100644 --- a/packages/functions/scripts/duplicatePurchases.ts +++ b/packages/functions/scripts/duplicatePurchases.ts @@ -10,7 +10,7 @@ const db = getFirestore(); const nfts: any = {}; db.collection('transaction') .where('type', '==', 'BILL_PAYMENT') - .where('payload.royalty', '==', false) + .where('payload_royalty', '==', false) .get() .then(async (ss) => { for (const t of ss.docs) { diff --git a/packages/functions/scripts/manualRefund.ts b/packages/functions/scripts/manualRefund.ts index 158ac5b67c..edcdcc851b 100644 --- a/packages/functions/scripts/manualRefund.ts +++ b/packages/functions/scripts/manualRefund.ts @@ -31,7 +31,7 @@ db.collection(COL.MEMBER) await db .collection(COL.TRANSACTION) .doc(tranId) - .set({ + .upsert({ project: SOON_PROJECT_ID, type: TransactionType.CREDIT, uid: tranId, diff --git a/packages/functions/scripts/nullPayments.ts b/packages/functions/scripts/nullPayments.ts index 8dff8e116e..144ba08843 100644 --- a/packages/functions/scripts/nullPayments.ts +++ b/packages/functions/scripts/nullPayments.ts @@ -9,8 +9,8 @@ initializeApp({ const db = getFirestore(); db.collection('transaction') - .where('payload.walletReference.chainReference', '==', null) - .where('payload.walletReference.error', '==', 'Error: You must specify some inputs') + .where('payload_walletReference.chainReference', '==', null) + .where('payload_walletReference.error', '==', 'Error: You must specify some inputs') .get() .then(async (ss) => { for (const t of ss.docs) { diff --git a/packages/functions/scripts/retryPayment.ts b/packages/functions/scripts/retryPayment.ts index 754d926f2f..fa6c0e3355 100644 --- a/packages/functions/scripts/retryPayment.ts +++ b/packages/functions/scripts/retryPayment.ts @@ -9,8 +9,8 @@ initializeApp({ const db = getFirestore(); db.collection('transaction') - .where('payload.walletReference.confirmed', '==', false) - .where('payload.walletReference.count', '<=', 4) + .where('payload_walletReference.confirmed', '==', false) + .where('payload_walletReference.count', '<=', 4) .orderBy('payload.walletReference.count', 'asc') .limit(10000) .get() diff --git a/packages/functions/test-service-account-key.json b/packages/functions/service-account-key.json similarity index 100% rename from packages/functions/test-service-account-key.json rename to packages/functions/service-account-key.json diff --git a/packages/functions/src/controls/address/address.control.ts b/packages/functions/src/controls/address/address.control.ts index ca55e5a18c..e505f46127 100644 --- a/packages/functions/src/controls/address/address.control.ts +++ b/packages/functions/src/controls/address/address.control.ts @@ -3,7 +3,6 @@ import { AddressValidationRequest, COL, DEFAULT_NETWORK, - Member, Network, Transaction, WenError, @@ -18,14 +17,15 @@ export const validateAddressControl = async ({ project, }: Context): Promise => { const network = (params.network as Network) || DEFAULT_NETWORK; - const member = await build5Db().doc(`${COL.MEMBER}/${owner}`).get(); + const memberDocRef = build5Db().doc(COL.MEMBER, owner); + const member = await memberDocRef.get(); if (!member) { throw invalidArgument(WenError.member_does_not_exists); } - const order = await createAddressValidationOrder(project, member.uid, network, params.space); - await build5Db().doc(`${COL.TRANSACTION}/${order.uid}`).create(order); + const order = await createAddressValidationOrder(project, owner, network, params.space); + await build5Db().doc(COL.TRANSACTION, order.uid).create(order); return order; }; diff --git a/packages/functions/src/controls/auction/auction.control.ts b/packages/functions/src/controls/auction/auction.control.ts index ef523e6992..a95dbdcc4f 100644 --- a/packages/functions/src/controls/auction/auction.control.ts +++ b/packages/functions/src/controls/auction/auction.control.ts @@ -10,7 +10,7 @@ export const auctionBidControl = async ({ params, project, }: Context): Promise => { - const memberDocRef = build5Db().doc(`${COL.MEMBER}/${owner}`); + const memberDocRef = build5Db().doc(COL.MEMBER, owner); const member = await memberDocRef.get(); if (!member) { throw invalidArgument(WenError.member_does_not_exists); @@ -18,8 +18,8 @@ export const auctionBidControl = async ({ const bidTransaction = await createBidOrder(project, owner, params.auction, ip); - const transactionDocRef = build5Db().doc(`${COL.TRANSACTION}/${bidTransaction.uid}`); + 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/auction/auction.create.control.ts b/packages/functions/src/controls/auction/auction.create.control.ts index 8341d08f29..254222d18d 100644 --- a/packages/functions/src/controls/auction/auction.create.control.ts +++ b/packages/functions/src/controls/auction/auction.create.control.ts @@ -1,5 +1,5 @@ import { build5Db } from '@build-5/database'; -import { Auction, AuctionCreateRequest, COL, Member, WenError } from '@build-5/interfaces'; +import { Auction, AuctionCreateRequest, COL, WenError } from '@build-5/interfaces'; import { getAuctionData } from '../../services/payment/tangle-service/auction/auction.create.service'; import { invalidArgument } from '../../utils/error.utils'; import { assertIsSpaceMember } from '../../utils/space.utils'; @@ -10,8 +10,8 @@ export const auctionCreateControl = async ({ project, params, }: Context) => { - const memberDocRef = build5Db().doc(`${COL.MEMBER}/${owner}`); - const member = await memberDocRef.get(); + const memberDocRef = build5Db().doc(COL.MEMBER, owner); + const member = await memberDocRef.get(); if (!member) { throw invalidArgument(WenError.member_does_not_exists); } @@ -19,7 +19,7 @@ export const auctionCreateControl = async ({ await assertIsSpaceMember(params.space, owner); const auction = getAuctionData(project, member, params); - const auctionDocRef = build5Db().doc(`${COL.AUCTION}/${auction.uid}`); + const auctionDocRef = build5Db().doc(COL.AUCTION, auction.uid); await auctionDocRef.create(auction); return await auctionDocRef.get(); diff --git a/packages/functions/src/controls/award/award.approve.participant.ts b/packages/functions/src/controls/award/award.approve.participant.ts index 748be5c0b7..e986ef5eb0 100644 --- a/packages/functions/src/controls/award/award.approve.participant.ts +++ b/packages/functions/src/controls/award/award.approve.participant.ts @@ -28,8 +28,8 @@ export const approveAwardParticipantControl = async ({ // eslint-disable-next-line @typescript-eslint/no-explicit-any } catch (error: any) { errors[member] = { - code: get(error, 'details.code', 0), - message: get(error, 'details.key', ''), + code: get(error, 'eCode', 0), + message: get(error, 'eKey', ''), }; } } diff --git a/packages/functions/src/controls/award/award.cancel.ts b/packages/functions/src/controls/award/award.cancel.ts index dd3832cdb4..6aa7c95b0e 100644 --- a/packages/functions/src/controls/award/award.cancel.ts +++ b/packages/functions/src/controls/award/award.cancel.ts @@ -10,8 +10,8 @@ export const cancelAwardControl = ({ params, }: Context): Promise => build5Db().runTransaction(async (transaction) => { - const awardDocRef = build5Db().doc(`${COL.AWARD}/${params.uid}`); - const award = await transaction.get(awardDocRef); + const awardDocRef = build5Db().doc(COL.AWARD, params.uid); + const award = await transaction.get(awardDocRef); if (!award) { throw invalidArgument(WenError.award_does_not_exists); @@ -26,7 +26,7 @@ export const cancelAwardControl = ({ await assertIsGuardian(award.space, owner); const data = { uid: award.uid, completed: true }; - transaction.update(awardDocRef, data); + await transaction.update(awardDocRef, data); return { ...award, ...data }; }); diff --git a/packages/functions/src/controls/award/award.create.ts b/packages/functions/src/controls/award/award.create.ts index 7a3291aff3..35df70cf96 100644 --- a/packages/functions/src/controls/award/award.create.ts +++ b/packages/functions/src/controls/award/award.create.ts @@ -1,5 +1,5 @@ import { build5Db } from '@build-5/database'; -import { Award, AwardCreateRequest, COL, SUB_COL } from '@build-5/interfaces'; +import { AwardCreateRequest, COL, SUB_COL } from '@build-5/interfaces'; import { createAward } from '../../services/payment/tangle-service/award/award.create.service'; import { Context } from '../common'; @@ -12,13 +12,13 @@ export const createAwardControl = async ({ const batch = build5Db().batch(); - const awardDocRef = build5Db().doc(`${COL.AWARD}/${award.uid}`); + const awardDocRef = build5Db().doc(COL.AWARD, award.uid); batch.create(awardDocRef, award); - const ownerDocRef = awardDocRef.collection(SUB_COL.OWNERS).doc(owner); + const ownerDocRef = build5Db().doc(COL.AWARD, award.uid, SUB_COL.OWNERS, owner); batch.create(ownerDocRef, awardOwner); await batch.commit(); - return await awardDocRef.get(); + return await awardDocRef.get(); }; diff --git a/packages/functions/src/controls/award/award.fund.ts b/packages/functions/src/controls/award/award.fund.ts index d770f23788..4d6c761ed4 100644 --- a/packages/functions/src/controls/award/award.fund.ts +++ b/packages/functions/src/controls/award/award.fund.ts @@ -14,7 +14,7 @@ export const fundAwardControl = async ({ const award = await getAwardForFunding(owner, params.uid); const order = await createAwardFundOrder(project, owner, award); - await build5Db().doc(`${COL.TRANSACTION}/${order.uid}`).create(order); + await build5Db().doc(COL.TRANSACTION, order.uid).create(order); return order; }; diff --git a/packages/functions/src/controls/award/award.owner.ts b/packages/functions/src/controls/award/award.owner.ts index d9bc2c5d73..5f70366daf 100644 --- a/packages/functions/src/controls/award/award.owner.ts +++ b/packages/functions/src/controls/award/award.owner.ts @@ -1,12 +1,5 @@ import { build5Db } from '@build-5/database'; -import { - Award, - AwardAddOwnerRequest, - AwardOwner, - COL, - SUB_COL, - WenError, -} from '@build-5/interfaces'; +import { AwardAddOwnerRequest, AwardOwner, COL, SUB_COL, WenError } from '@build-5/interfaces'; import dayjs from 'dayjs'; import { dateToTimestamp } from '../../utils/dateTime.utils'; import { invalidArgument } from '../../utils/error.utils'; @@ -17,18 +10,20 @@ export const addOwnerControl = async ({ params, project, }: Context): Promise => { - const awardDocRef = build5Db().doc(`${COL.AWARD}/${params.uid}`); - const award = await awardDocRef.get(); + const awardDocRef = build5Db().doc(COL.AWARD, params.uid); + const award = await awardDocRef.get(); if (!award) { throw invalidArgument(WenError.award_does_not_exists); } - const awardOwner = await awardDocRef.collection(SUB_COL.OWNERS).doc(owner).get(); + const awardOwner = await build5Db().doc(COL.AWARD, params.uid, SUB_COL.OWNERS, owner).get(); if (!awardOwner) { throw invalidArgument(WenError.you_are_not_owner_of_the_award); } - const awardMember = await awardDocRef.collection(SUB_COL.OWNERS).doc(params.member).get(); + const awardMember = await build5Db() + .doc(COL.AWARD, params.uid, SUB_COL.OWNERS, params.member) + .get(); if (awardMember) { throw invalidArgument(WenError.member_is_already_owner_of_space); } @@ -40,6 +35,6 @@ export const addOwnerControl = async ({ parentCol: COL.AWARD, createdOn: dateToTimestamp(dayjs()), }; - await awardDocRef.collection(SUB_COL.OWNERS).doc(params.member).create(newOwner); + await build5Db().doc(COL.AWARD, params.uid, SUB_COL.OWNERS, params.member).create(newOwner); return newOwner; }; diff --git a/packages/functions/src/controls/award/award.participate.ts b/packages/functions/src/controls/award/award.participate.ts index 659bc94910..965c6d1108 100644 --- a/packages/functions/src/controls/award/award.participate.ts +++ b/packages/functions/src/controls/award/award.participate.ts @@ -1,6 +1,5 @@ import { build5Db } from '@build-5/database'; import { - Award, AwardParticipant, AwardParticpateRequest, COL, @@ -17,8 +16,8 @@ export const awardParticipateControl = async ({ params, project, }: Context): Promise => { - const awardDocRef = build5Db().doc(`${COL.AWARD}/${params.uid}`); - const award = await awardDocRef.get(); + const awardDocRef = build5Db().doc(COL.AWARD, params.uid); + const award = await awardDocRef.get(); if (!award) { throw invalidArgument(WenError.award_does_not_exists); } @@ -35,7 +34,9 @@ export const awardParticipateControl = async ({ throw invalidArgument(WenError.award_is_no_longer_available); } - const awardParticipant = await awardDocRef.collection(SUB_COL.PARTICIPANTS).doc(owner).get(); + const awardParticipant = await build5Db() + .doc(COL.AWARD, params.uid, SUB_COL.PARTICIPANTS, owner) + .get(); if (awardParticipant) { throw invalidArgument(WenError.member_is_already_participant_of_space); } @@ -51,6 +52,6 @@ export const awardParticipateControl = async ({ tokenReward: 0, createdOn: dateToTimestamp(dayjs()), }; - await awardDocRef.collection(SUB_COL.PARTICIPANTS).doc(owner).create(participant); + await build5Db().doc(COL.AWARD, params.uid, SUB_COL.PARTICIPANTS, owner).create(participant); return participant; }; diff --git a/packages/functions/src/controls/award/award.reject.ts b/packages/functions/src/controls/award/award.reject.ts index f7b45bc3f7..8e6b834ea0 100644 --- a/packages/functions/src/controls/award/award.reject.ts +++ b/packages/functions/src/controls/award/award.reject.ts @@ -8,8 +8,8 @@ export const rejectAwardControl = async ({ owner, params, }: Context): Promise => { - const awardDocRef = build5Db().doc(`${COL.AWARD}/${params.uid}`); - const award = await awardDocRef.get(); + const awardDocRef = build5Db().doc(COL.AWARD, params.uid); + const award = await awardDocRef.get(); if (!award) { throw invalidArgument(WenError.award_does_not_exists); } diff --git a/packages/functions/src/controls/collection/collection-mint.control.ts b/packages/functions/src/controls/collection/collection-mint.control.ts index 95eefce147..5c753423d2 100644 --- a/packages/functions/src/controls/collection/collection-mint.control.ts +++ b/packages/functions/src/controls/collection/collection-mint.control.ts @@ -1,14 +1,11 @@ -import { build5Db, getSnapshot } from '@build-5/database'; +import { build5Db } from '@build-5/database'; import { COL, Collection, CollectionMintRequest, CollectionStatus, CollectionType, - Member, Network, - Nft, - Space, TRANSACTION_AUTO_EXPIRY_MS, Transaction, TransactionPayloadType, @@ -43,12 +40,12 @@ export const mintCollectionOrderControl = async ({ }: Context) => { const network = params.network as Network; - const member = await build5Db().doc(`${COL.MEMBER}/${owner}`).get(); + const member = await build5Db().doc(COL.MEMBER, owner).get(); assertMemberHasValidAddress(member, network); return await build5Db().runTransaction(async (transaction) => { - const collectionDocRef = build5Db().doc(`${COL.COLLECTION}/${params.collection}`); - const collection = await transaction.get(collectionDocRef); + const collectionDocRef = build5Db().doc(COL.COLLECTION, params.collection); + const collection = await transaction.get(collectionDocRef); if (!collection) { throw invalidArgument(WenError.collection_does_not_exists); @@ -74,13 +71,11 @@ export const mintCollectionOrderControl = async ({ await assertIsCollectionGuardian(collection, owner); - const space = await build5Db().doc(`${COL.SPACE}/${collection.space}`).get(); + const space = await build5Db().doc(COL.SPACE, collection.space!).get(); assertSpaceHasValidAddress(space, network); - if (collection.royaltiesFee) { - const royaltySpace = await build5Db() - .doc(`${COL.SPACE}/${collection.royaltiesSpace}`) - .get(); + if (collection.royaltiesSpace) { + const royaltySpace = await build5Db().doc(COL.SPACE, collection.royaltiesSpace).get(); assertSpaceHasValidAddress(royaltySpace, network); } @@ -128,8 +123,8 @@ export const mintCollectionOrderControl = async ({ nftsToMint, }, }; - const orderDocRef = build5Db().doc(`${COL.TRANSACTION}/${order.uid}`); - transaction.create(orderDocRef, order); + const orderDocRef = build5Db().doc(COL.TRANSACTION, order.uid); + await transaction.create(orderDocRef, order); return order; }); }; @@ -144,14 +139,14 @@ const getNftsTotalStorageDeposit = async ( let nftsToMint = 0; let lastUid = ''; do { - const lastDoc = await getSnapshot(COL.NFT, lastUid); const nfts = await build5Db() .collection(COL.NFT) .where('collection', '==', collection.uid) .where('placeholderNft', '==', false) + .where('uid', '>', lastUid) + .orderBy('uid') .limit(500) - .startAfter(lastDoc) - .get(); + .get(); lastUid = last(nfts)?.uid || ''; const promises = nfts.map(async (nft) => { @@ -159,9 +154,8 @@ const getNftsTotalStorageDeposit = async ( return 0; } const ownerAddress = new Ed25519Address(address.hex); - const metadata = JSON.stringify( - await nftToMetadata(nft, collection, address.bech32, EMPTY_NFT_ID), - ); + const nftMetadata = await nftToMetadata(nft, collection, address.bech32, EMPTY_NFT_ID); + const metadata = JSON.stringify(nftMetadata); const output = await createNftOutput(wallet, ownerAddress, ownerAddress, metadata); return Number(output.amount); }); diff --git a/packages/functions/src/controls/collection/collection.create.control.ts b/packages/functions/src/controls/collection/collection.create.control.ts index d37710a9a4..6f96419c44 100644 --- a/packages/functions/src/controls/collection/collection.create.control.ts +++ b/packages/functions/src/controls/collection/collection.create.control.ts @@ -7,12 +7,12 @@ import { CreateCollectionRequest, DEFAULT_NETWORK, DiscountLine, - Member, + Nft, NftStatus, - Space, SUB_COL, WenError, } from '@build-5/interfaces'; +import { set } from 'lodash'; import { hasStakedTokens } from '../../services/stake.service'; import { assertSpaceHasValidAddress } from '../../utils/address.utils'; import { dateToTimestamp, serverTime } from '../../utils/dateTime.utils'; @@ -33,31 +33,27 @@ export const createCollectionControl = async ({ const spaceUid = params.space || ''; if (spaceUid) { - const spaceDocRef = build5Db().doc(`${COL.SPACE}/${spaceUid}`); - const space = await spaceDocRef.get(); + const spaceDocRef = build5Db().doc(COL.SPACE, spaceUid); + const space = await spaceDocRef.get(); if (!space) { throw invalidArgument(WenError.space_does_not_exists); } assertSpaceHasValidAddress(space, DEFAULT_NETWORK); - const spaceMember = await spaceDocRef.collection(SUB_COL.MEMBERS).doc(owner).get(); + const spaceMember = await build5Db().doc(COL.SPACE, spaceUid, SUB_COL.MEMBERS, owner).get(); if (!spaceMember) { throw invalidArgument(WenError.you_are_not_part_of_space); } } - if (params.royaltiesFee) { - const royaltySpace = await build5Db().doc(`${COL.SPACE}/${params.royaltiesSpace}`).get(); + if (params.royaltiesSpace) { + const royaltySpace = await build5Db().doc(COL.SPACE, params.royaltiesSpace).get(); if (!royaltySpace) { throw invalidArgument(WenError.space_does_not_exists); } assertSpaceHasValidAddress(royaltySpace, DEFAULT_NETWORK); } - if (params.availableFrom) { - params.availableFrom = dateToTimestamp(params.availableFrom, true).toDate(); - } - const batch = build5Db().batch(); const discounts = (params.discounts || []); @@ -73,14 +69,17 @@ export const createCollectionControl = async ({ createdBy: owner, approved: false, rejected: false, - ipfsMedia: null, + ipfsMedia: undefined, limitedEdition: !!params.limitedEdition, onePerMemberOnly: !!params.onePerMemberOnly, - placeholderNft: placeholderNftId || null, + placeholderNft: placeholderNftId || '', status: CollectionStatus.PRE_MINTED, }; - const collectionDocRef = build5Db().doc(`${COL.COLLECTION}/${collection.uid}`); - batch.create(collectionDocRef, collection); + if (collection.availableFrom) { + set(collection, 'availableFrom', dateToTimestamp(params.availableFrom, true)); + } + const collectionDocRef = build5Db().doc(COL.COLLECTION, collection.uid); + batch.create(collectionDocRef, collection as unknown as Collection); if (placeholderNftId) { const placeholderNft = { @@ -90,7 +89,7 @@ export const createCollectionControl = async ({ description: params.description, locked: false, media: params.placeholderUrl || null, - availableFrom: params.availableFrom || null, + availableFrom: collection.availableFrom, price: params.price, availablePrice: params.price, collection: collection.uid, @@ -109,10 +108,10 @@ export const createCollectionControl = async ({ createdBy: owner, status: NftStatus.PRE_MINTED, }; - const placeholderNftDocRef = build5Db().doc(`${COL.NFT}/${placeholderNft.uid}`); - batch.create(placeholderNftDocRef, placeholderNft); + const placeholderNftDocRef = build5Db().doc(COL.NFT, placeholderNft.uid); + batch.create(placeholderNftDocRef, placeholderNft as unknown as Nft); } await batch.commit(); - return await collectionDocRef.get(); + return await collectionDocRef.get(); }; diff --git a/packages/functions/src/controls/collection/collection.reject.control.ts b/packages/functions/src/controls/collection/collection.reject.control.ts index 8c42ad2887..1c36d48b70 100644 --- a/packages/functions/src/controls/collection/collection.reject.control.ts +++ b/packages/functions/src/controls/collection/collection.reject.control.ts @@ -9,8 +9,8 @@ export const rejectCollectionControl = async ({ owner, params, }: Context): Promise => { - const collectionDocRef = build5Db().doc(`${COL.COLLECTION}/${params.uid}`); - const collection = await collectionDocRef.get(); + const collectionDocRef = build5Db().doc(COL.COLLECTION, params.uid); + const collection = await collectionDocRef.get(); if (!collection) { throw invalidArgument(WenError.collection_does_not_exists); } diff --git a/packages/functions/src/controls/collection/collection.update.control.ts b/packages/functions/src/controls/collection/collection.update.control.ts index 2f2949ac0d..d2ec232c6c 100644 --- a/packages/functions/src/controls/collection/collection.update.control.ts +++ b/packages/functions/src/controls/collection/collection.update.control.ts @@ -1,17 +1,14 @@ -import { build5Db, getSnapshot } from '@build-5/database'; +import { PgAccess, PgCollectionType, PgNftStatus, build5Db, convertEnum } from '@build-5/database'; import { + Access, COL, - Collection, CollectionStatus, - DiscountLine, - Member, - Nft, - NftStatus, + CollectionType, UpdateCollectionRequest, WenError, } from '@build-5/interfaces'; import dayjs from 'dayjs'; -import { isEmpty, last, set } from 'lodash'; +import { isEmpty, set } from 'lodash'; import { dateToTimestamp } from '../../utils/dateTime.utils'; import { invalidArgument } from '../../utils/error.utils'; import { assertValidationAsync } from '../../utils/schema.utils'; @@ -25,17 +22,17 @@ export const updateCollectionControl = async ({ owner, params: rawParams, }: Context) => { - const collectionDocRef = build5Db().doc(`${COL.COLLECTION}/${rawParams.uid}`); - const collection = await collectionDocRef.get(); + const collectionDocRef = build5Db().doc(COL.COLLECTION, rawParams.uid); + const collection = await collectionDocRef.get(); if (!collection) { throw invalidArgument(WenError.collection_does_not_exists); } const isMinted = collection.status === CollectionStatus.MINTED; const schema = isMinted ? updateMintedCollectionSchemaObject : updateCollectionSchemaObject; - const params = await assertValidationAsync(schema, rawParams); + const { discounts, ...params } = await assertValidationAsync(schema, rawParams); - const member = await build5Db().doc(`${COL.MEMBER}/${owner}`).get(); + const member = await build5Db().doc(COL.MEMBER, owner).get(); if (!member) { throw invalidArgument(WenError.member_does_not_exists); } @@ -64,13 +61,16 @@ export const updateCollectionControl = async ({ ...params, price, availablePrice: price, + access: convertEnum(params.access as Access, Access, PgAccess), uid: params.uid, }; - const discounts = params.discounts; + if (!params.access) { + delete collectionUpdateData.access; + } if (discounts) { - set(collectionUpdateData, 'discounts', await populateTokenUidOnDiscounts(discounts)); + const value = JSON.stringify(await populateTokenUidOnDiscounts(discounts)); + set(collectionUpdateData, 'discounts', value); } - batch.update(collectionDocRef, collectionUpdateData); if (!isMinted && collection.placeholderNft) { @@ -79,9 +79,9 @@ export const updateCollectionControl = async ({ description: (params as UpdateCollectionRequest).description || '', media: (params as UpdateCollectionRequest).placeholderUrl || '', space: collection.space, - type: collection.type, + type: convertEnum(collection.type, CollectionType, PgCollectionType), }; - const nftDocRef = build5Db().doc(`${COL.NFT}/${collection.placeholderNft}`); + const nftDocRef = build5Db().doc(COL.NFT, collection.placeholderNft); batch.update(nftDocRef, data); } await batch.commit(); @@ -95,28 +95,12 @@ export const updateCollectionControl = async ({ set(nftUpdateData, 'availableFrom', params.availableFrom); } if (!isEmpty(nftUpdateData)) { - for (const status of [NftStatus.PRE_MINTED, NftStatus.MINTED]) { - let lastNftId = ''; - do { - const lastDoc = await getSnapshot(COL.NFT, lastNftId); - const nfts = await build5Db() - .collection(COL.NFT) - .where('collection', '==', collection.uid) - .where('isOwned', '==', false) - .where('status', '==', status) - .limit(500) - .startAfter(lastDoc) - .get(); - lastNftId = last(nfts)?.uid || ''; - - const batch = build5Db().batch(); - for (const nft of nfts) { - batch.update(build5Db().doc(`${COL.NFT}/${nft.uid}`), nftUpdateData); - } - await batch.commit(); - } while (lastNftId); + for (const status of [PgNftStatus.PRE_MINTED, PgNftStatus.MINTED]) { + await build5Db() + .collection(COL.NFT) + .update(nftUpdateData, { collection: collection.uid, isOwned: false, status: status }); } } - return await build5Db().doc(`${COL.COLLECTION}/${params.uid}`).get(); + return await build5Db().doc(COL.COLLECTION, params.uid).get(); }; diff --git a/packages/functions/src/controls/credit/credit.controller.ts b/packages/functions/src/controls/credit/credit.controller.ts index 7e3c7cab89..4fbc221729 100644 --- a/packages/functions/src/controls/credit/credit.controller.ts +++ b/packages/functions/src/controls/credit/credit.controller.ts @@ -25,8 +25,8 @@ export const creditUnrefundableControl = ({ project, }: Context): Promise => build5Db().runTransaction(async (transaction) => { - const transactionDocRef = build5Db().doc(`${COL.TRANSACTION}/${params.transaction}`); - const creditTransaction = await transaction.get(transactionDocRef); + const transactionDocRef = build5Db().doc(COL.TRANSACTION, params.transaction); + const creditTransaction = await transaction.get(transactionDocRef); if ( !creditTransaction || @@ -49,8 +49,8 @@ export const creditUnrefundableControl = ({ const targetAddress = await wallet.getNewIotaAddressDetails(); const creditOrder = createCreditOrder(project, creditTransaction, owner, targetAddress.bech32); - const creditDocRef = build5Db().doc(`${COL.TRANSACTION}/${creditOrder.uid}`); - transaction.create(creditDocRef, creditOrder); + const creditDocRef = build5Db().doc(COL.TRANSACTION, creditOrder.uid); + await transaction.create(creditDocRef, creditOrder); return creditOrder; }); diff --git a/packages/functions/src/controls/member/member.create.ts b/packages/functions/src/controls/member/member.create.ts index 1ca3bdf59b..8ff0e63aa5 100644 --- a/packages/functions/src/controls/member/member.create.ts +++ b/packages/functions/src/controls/member/member.create.ts @@ -1,15 +1,10 @@ import { build5Db } from '@build-5/database'; -import { COL, Member } from '@build-5/interfaces'; +import { COL } from '@build-5/interfaces'; import { getRandomNonce } from '../../utils/wallet.utils'; import { Context } from '../common'; export const createMemberControl = async ({ owner }: Context) => { - const memberDocRef = build5Db().collection(COL.MEMBER).doc(owner); - const member = await memberDocRef.get(); - - if (!member) { - await memberDocRef.create({ uid: owner, nonce: getRandomNonce() }); - } - - return (await memberDocRef.get())!; + const memberDocRef = build5Db().doc(COL.MEMBER, owner); + await memberDocRef.upsert({ nonce: getRandomNonce() }); + return (await memberDocRef.get())!; }; diff --git a/packages/functions/src/controls/member/member.update.ts b/packages/functions/src/controls/member/member.update.ts index 7265f682df..bafa46163e 100644 --- a/packages/functions/src/controls/member/member.update.ts +++ b/packages/functions/src/controls/member/member.update.ts @@ -1,20 +1,12 @@ import { build5Db } from '@build-5/database'; -import { - COL, - Member, - MemberUpdateRequest, - Nft, - NftAvailable, - NftStatus, - WenError, -} from '@build-5/interfaces'; +import { COL, MemberUpdateRequest, NftAvailable, NftStatus, WenError } from '@build-5/interfaces'; import { invalidArgument } from '../../utils/error.utils'; import { cleanupParams } from '../../utils/schema.utils'; import { Context } from '../common'; export const updateMemberControl = async ({ owner, params }: Context) => { - const memberDocRef = build5Db().doc(`${COL.MEMBER}/${owner}`); - const member = await memberDocRef.get(); + const memberDocRef = build5Db().doc(COL.MEMBER, owner); + const member = await memberDocRef.get(); if (!member) { throw invalidArgument(WenError.member_does_not_exists); } @@ -24,7 +16,7 @@ export const updateMemberControl = async ({ owner, params }: Context(); + .get(); if (members.length > 0) { throw invalidArgument(WenError.member_username_exists); } @@ -36,26 +28,26 @@ export const updateMemberControl = async ({ owner, params }: Context).avatar = null; } if (member.avatarNft && member.avatarNft !== params.avatarNft) { - const currentAvatarDocRef = build5Db().doc(`${COL.NFT}/${member.avatarNft}`); + const currentAvatarDocRef = build5Db().doc(COL.NFT, member.avatarNft); batch.update(currentAvatarDocRef, { setAsAvatar: false }); } batch.update(memberDocRef, cleanupParams({ ...params })); await batch.commit(); - return (await memberDocRef.get())!; + return (await memberDocRef.get())!; }; const getNft = async (owner: string, nftId: string) => { - const nftDocRef = build5Db().doc(`${COL.NFT}/${nftId}`); - const nft = await nftDocRef.get(); + const nftDocRef = build5Db().doc(COL.NFT, nftId); + const nft = await nftDocRef.get(); if (!nft) { throw invalidArgument(WenError.nft_does_not_exists); } diff --git a/packages/functions/src/controls/nft/NftMetadataRequestSchema.ts b/packages/functions/src/controls/nft/NftMetadataRequestSchema.ts index 8b57d90c82..db646d6090 100644 --- a/packages/functions/src/controls/nft/NftMetadataRequestSchema.ts +++ b/packages/functions/src/controls/nft/NftMetadataRequestSchema.ts @@ -1,7 +1,7 @@ +import { MintMetadataNftRequest } from '@build-5/interfaces'; import Joi from 'joi'; import { CommonJoi, toJoiObject } from '../../services/joi/common'; import { AVAILABLE_NETWORKS } from '../common'; -import { MintMetadataNftRequest } from '@build-5/interfaces'; export const commonMetadataNftParams = { nftId: CommonJoi.uid(false).description('Nft network id. Only specify it in case of edit.'), diff --git a/packages/functions/src/controls/nft/nft.bid.control.ts b/packages/functions/src/controls/nft/nft.bid.control.ts index 63484ab7ac..2ee2a4124a 100644 --- a/packages/functions/src/controls/nft/nft.bid.control.ts +++ b/packages/functions/src/controls/nft/nft.bid.control.ts @@ -10,19 +10,19 @@ export const nftBidControl = async ({ params, project, }: Context): Promise => { - const memberDocRef = build5Db().doc(`${COL.MEMBER}/${owner}`); + const memberDocRef = build5Db().doc(COL.MEMBER, owner); const member = await memberDocRef.get(); if (!member) { throw invalidArgument(WenError.member_does_not_exists); } - const nftDocRef = build5Db().doc(`${COL.NFT}/${params.nft}`); + const nftDocRef = build5Db().doc(COL.NFT, params.nft); const nft = await nftDocRef.get(); const bidTransaction = await createBidOrder(project, owner, nft.auction || '', ip); - const transactionDocRef = build5Db().doc(`${COL.TRANSACTION}/${bidTransaction.uid}`); + 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 b98ece3c10..61905abbc0 100644 --- a/packages/functions/src/controls/nft/nft.create.ts +++ b/packages/functions/src/controls/nft/nft.create.ts @@ -7,7 +7,10 @@ import { MIN_IOTA_AMOUNT, Nft, NftAccess, + NftAvailable, NftCreateRequest, + NftStatus, + PropStats, WenError, } from '@build-5/interfaces'; import dayjs from 'dayjs'; @@ -39,8 +42,8 @@ export const createBatchNftControl = async ({ }; const getCollection = async (owner: string, collectionId: string) => { - const collectionDocRef = build5Db().doc(`${COL.COLLECTION}/${collectionId}`); - const collection = await collectionDocRef.get(); + const collectionDocRef = build5Db().doc(COL.COLLECTION, collectionId); + const collection = await collectionDocRef.get(); if (!collection) { throw invalidArgument(WenError.collection_does_not_exists); } @@ -101,8 +104,15 @@ const processOneCreateNft = async ( } const price = Math.max(Number(params.price) || 0, MIN_IOTA_AMOUNT); - const nft = { + const nft: Nft = { ...params, + name: params.name || '', + description: params.description || '', + media: params.media || '', + availableFrom: dateToTimestamp(params.availableFrom), + url: params.url || '', + properties: (params.properties || {}) as PropStats, + stats: (params.stats || {}) as PropStats, project, uid: getRandomEthAddress(), locked: false, @@ -110,32 +120,34 @@ const processOneCreateNft = async ( availablePrice: price, saleAccess: isEmpty(params.saleAccessMembers) ? NftAccess.OPEN : NftAccess.MEMBERS, position, - lockedBy: null, - ipfsMedia: null, - ipfsMetadata: null, + lockedBy: undefined, + ipfsMedia: '', + ipfsMetadata: '', sold: false, approved: collection.approved, rejected: collection.rejected, - owner: null, + owner: undefined, isOwned: false, - soldOn: null, - ipfsRetries: 0, - space: collection.space, + soldOn: undefined, + space: collection.space || '', type: collection.type, hidden: CollectionType.CLASSIC !== collection.type, createdBy: collection.createdBy, placeholderNft: false, - status: CollectionStatus.PRE_MINTED, + status: NftStatus.PRE_MINTED, + available: NftAvailable.UNAVAILABLE, + totalTrades: 0, + lastTradedOn: null, }; const batch = build5Db().batch(); - const nftDocRef = build5Db().doc(`${COL.NFT}/${nft.uid}`); + const nftDocRef = build5Db().doc(COL.NFT, nft.uid); batch.create(nftDocRef, nft); - const collectionDocRef = build5Db().doc(`${COL.COLLECTION}/${collection.uid}`); + const collectionDocRef = build5Db().doc(COL.COLLECTION, collection.uid); batch.update(collectionDocRef, { total: build5Db().inc(1) }); if (collection.placeholderNft) { - const placeholderNftDocRef = build5Db().doc(`${COL.NFT}/${collection.placeholderNft}`); + const placeholderNftDocRef = build5Db().doc(COL.NFT, collection.placeholderNft); batch.update(placeholderNftDocRef, { sold: false, availableFrom: params.availableFrom, @@ -144,5 +156,5 @@ const processOneCreateNft = async ( } await batch.commit(); - return (await nftDocRef.get())!; + return (await nftDocRef.get())!; }; diff --git a/packages/functions/src/controls/nft/nft.deposit.ts b/packages/functions/src/controls/nft/nft.deposit.ts index 0d651f8642..221ff32847 100644 --- a/packages/functions/src/controls/nft/nft.deposit.ts +++ b/packages/functions/src/controls/nft/nft.deposit.ts @@ -41,7 +41,7 @@ export const depositNftControl = async ({ void: false, }, }; - const orderDocRef = build5Db().doc(`${COL.TRANSACTION}/${order.uid}`); + const orderDocRef = build5Db().doc(COL.TRANSACTION, order.uid); await orderDocRef.create(order); return order; }; diff --git a/packages/functions/src/controls/nft/nft.metadata.control.ts b/packages/functions/src/controls/nft/nft.metadata.control.ts index e09cbd963f..33981e9226 100644 --- a/packages/functions/src/controls/nft/nft.metadata.control.ts +++ b/packages/functions/src/controls/nft/nft.metadata.control.ts @@ -4,6 +4,7 @@ import { MintMetadataNftRequest, Network, SUB_COL, + SpaceGuardian, TRANSACTION_AUTO_EXPIRY_MS, Transaction, TransactionPayloadType, @@ -43,14 +44,19 @@ export const mintMetadataNftControl = async ({ const batch = build5Db().batch(); if (aliasId === EMPTY_ALIAS_ID) { - const spaceDocRef = build5Db().doc(`${COL.SPACE}/${space.uid}`); + const spaceDocRef = build5Db().doc(COL.SPACE, space.uid); batch.create(spaceDocRef, space); - const guardian = { uid: owner, parentId: space.uid, parentCol: COL.SPACE }; - const guardianDocRef = spaceDocRef.collection(SUB_COL.GUARDIANS).doc(owner); + const guardian: SpaceGuardian = { + uid: owner, + parentId: space.uid, + parentCol: COL.SPACE, + createdOn: dateToTimestamp(dayjs()), + }; + const guardianDocRef = build5Db().doc(COL.SPACE, space.uid, SUB_COL.GUARDIANS, owner); batch.create(guardianDocRef, guardian); - const memberDocRef = spaceDocRef.collection(SUB_COL.MEMBERS).doc(owner); + const memberDocRef = build5Db().doc(COL.SPACE, space.uid, SUB_COL.MEMBERS, owner); batch.create(memberDocRef, guardian); } @@ -81,7 +87,7 @@ export const mintMetadataNftControl = async ({ metadata: params.metadata as { [key: string]: unknown }, }, }; - const orderDocRef = build5Db().doc(`${COL.TRANSACTION}/${order.uid}`); + const orderDocRef = build5Db().doc(COL.TRANSACTION, order.uid); batch.create(orderDocRef, order); await batch.commit(); diff --git a/packages/functions/src/controls/nft/nft.puchase.bulk.control.ts b/packages/functions/src/controls/nft/nft.puchase.bulk.control.ts index 88df487fbe..d97f65a81a 100644 --- a/packages/functions/src/controls/nft/nft.puchase.bulk.control.ts +++ b/packages/functions/src/controls/nft/nft.puchase.bulk.control.ts @@ -10,8 +10,8 @@ export const orderNftBulkControl = async ({ project, }: Context): Promise => { const order = await createNftBulkOrder(project, params.orders, owner, ip); - const orderDocRef = build5Db().doc(`${COL.TRANSACTION}/${order.uid}`); + const orderDocRef = build5Db().doc(COL.TRANSACTION, order.uid); await orderDocRef.create(order); - return (await orderDocRef.get())!; + return (await orderDocRef.get())!; }; diff --git a/packages/functions/src/controls/nft/nft.puchase.control.ts b/packages/functions/src/controls/nft/nft.puchase.control.ts index ed1077f3a9..3ba4aed64b 100644 --- a/packages/functions/src/controls/nft/nft.puchase.control.ts +++ b/packages/functions/src/controls/nft/nft.puchase.control.ts @@ -10,8 +10,7 @@ export const orderNftControl = async ({ project, }: Context): Promise => { const order = await createNftPuchaseOrder(project, params.collection, params.nft, owner, ip); - const orderDocRef = build5Db().doc(`${COL.TRANSACTION}/${order.uid}`); + const orderDocRef = build5Db().doc(COL.TRANSACTION, order.uid); await orderDocRef.create(order); - - return (await orderDocRef.get())!; + return (await orderDocRef.get())!; }; diff --git a/packages/functions/src/controls/nft/nft.set.for.sale.ts b/packages/functions/src/controls/nft/nft.set.for.sale.ts index 8a6f43114c..4f7419e773 100644 --- a/packages/functions/src/controls/nft/nft.set.for.sale.ts +++ b/packages/functions/src/controls/nft/nft.set.for.sale.ts @@ -1,5 +1,5 @@ import { build5Db } from '@build-5/database'; -import { COL, Member, Nft, NftSetForSaleRequest, WenError } from '@build-5/interfaces'; +import { COL, Nft, NftSetForSaleRequest, WenError } from '@build-5/interfaces'; import { getNftSetForSaleParams } from '../../services/payment/tangle-service/nft/nft-set-for-sale.service'; import { invalidArgument } from '../../utils/error.utils'; import { Context } from '../common'; @@ -9,8 +9,8 @@ export const setForSaleNftControl = async ({ params, project, }: Context): Promise => { - const memberDocRef = build5Db().doc(`${COL.MEMBER}/${owner}`); - const member = await memberDocRef.get(); + const memberDocRef = build5Db().doc(COL.MEMBER, owner); + const member = await memberDocRef.get(); if (!member) { throw invalidArgument(WenError.member_does_not_exists); } @@ -19,15 +19,15 @@ export const setForSaleNftControl = async ({ const batch = build5Db().batch(); - const nftDocRef = build5Db().doc(`${COL.NFT}/${params.nft}`); + const nftDocRef = build5Db().doc(COL.NFT, params.nft); batch.update(nftDocRef, nft); if (auction) { - const auctionDocRef = build5Db().doc(`${COL.AUCTION}/${auction.uid}`); + const auctionDocRef = build5Db().doc(COL.AUCTION, auction.uid); batch.create(auctionDocRef, auction); } await batch.commit(); - return (await nftDocRef.get())!; + return (await nftDocRef.get())!; }; diff --git a/packages/functions/src/controls/nft/nft.stake.ts b/packages/functions/src/controls/nft/nft.stake.ts index 984b719304..535b9ca01e 100644 --- a/packages/functions/src/controls/nft/nft.stake.ts +++ b/packages/functions/src/controls/nft/nft.stake.ts @@ -1,7 +1,7 @@ import { build5Db } from '@build-5/database'; import { COL, Network, NftStakeRequest, StakeType, Transaction } from '@build-5/interfaces'; -import { Context } from '../common'; import { createNftStakeOrder } from '../../services/payment/nft/nft-stake.service'; +import { Context } from '../common'; export const nftStakeControl = async ({ owner, @@ -15,7 +15,7 @@ export const nftStakeControl = async ({ params.weeks, params.type as StakeType, ); - const orderDocRef = build5Db().doc(`${COL.TRANSACTION}/${order.uid}`); + const orderDocRef = build5Db().doc(COL.TRANSACTION, order.uid); await orderDocRef.create(order); return order; }; diff --git a/packages/functions/src/controls/nft/nft.transfer.ts b/packages/functions/src/controls/nft/nft.transfer.ts index acdbfd3c15..088d173e3c 100644 --- a/packages/functions/src/controls/nft/nft.transfer.ts +++ b/packages/functions/src/controls/nft/nft.transfer.ts @@ -3,11 +3,7 @@ import { COL, NftTransferRequest, TransactionType } from '@build-5/interfaces'; import { createNftTransferData } from '../../services/payment/nft/nft-transfer.service'; import { Context } from '../common'; -export const transferNftsControl = async ({ - owner, - params, - project, -}: Context) => +export const transferNftsControl = ({ owner, params, project }: Context) => build5Db().runTransaction(async (transaction) => { const transfers = await createNftTransferData(transaction, project, owner, params.transfers); @@ -16,15 +12,19 @@ export const transferNftsControl = async ({ continue; } - const nftDocRef = build5Db().doc(`${COL.NFT}/${nftId}`); - transaction.update(nftDocRef, nftUpdateData); + if (nftUpdateData) { + const nftDocRef = build5Db().doc(COL.NFT, nftId); + await transaction.update(nftDocRef, nftUpdateData); + } - const tranDocRef = build5Db().doc(`${COL.TRANSACTION}/${order?.uid}`); - transaction.create(tranDocRef, order); + if (order) { + const tranDocRef = build5Db().doc(COL.TRANSACTION, order.uid); + await transaction.create(tranDocRef, order); + } if (order?.type === TransactionType.WITHDRAW_NFT) { - const collectionDocRef = build5Db().doc(`${COL.COLLECTION}/${order.payload.collection}`); - transaction.update(collectionDocRef, { total: build5Db().inc(-1) }); + const collectionDocRef = build5Db().doc(COL.COLLECTION, order.payload.collection!); + await transaction.update(collectionDocRef, { total: build5Db().inc(-1) }); } } diff --git a/packages/functions/src/controls/nft/nft.update.unsold.ts b/packages/functions/src/controls/nft/nft.update.unsold.ts index c37f96e598..a54281a818 100644 --- a/packages/functions/src/controls/nft/nft.update.unsold.ts +++ b/packages/functions/src/controls/nft/nft.update.unsold.ts @@ -4,13 +4,13 @@ import { invalidArgument } from '../../utils/error.utils'; import { assertIsGuardian } from '../../utils/token.utils'; import { Context } from '../common'; -export const updateUnsoldNftControl = async ({ +export const updateUnsoldNftControl = ({ owner, params, }: Context): Promise => build5Db().runTransaction(async (transaction) => { - const nftDocRef = build5Db().doc(`${COL.NFT}/${params.uid}`); - const nft = await transaction.get(nftDocRef); + const nftDocRef = build5Db().doc(COL.NFT, params.uid); + const nft = await transaction.get(nftDocRef); if (!nft) { throw invalidArgument(WenError.nft_does_not_exists); } @@ -24,6 +24,6 @@ export const updateUnsoldNftControl = async ({ throw invalidArgument(WenError.hidden_nft); } await assertIsGuardian(nft.space, owner); - transaction.update(nftDocRef, params); + await transaction.update(nftDocRef, params); return { ...nft, ...params }; }); diff --git a/packages/functions/src/controls/nft/nft.withdraw.ts b/packages/functions/src/controls/nft/nft.withdraw.ts index 19c3243a0f..f9e2b87e9f 100644 --- a/packages/functions/src/controls/nft/nft.withdraw.ts +++ b/packages/functions/src/controls/nft/nft.withdraw.ts @@ -1,37 +1,29 @@ import { build5Db } from '@build-5/database'; -import { - COL, - Collection, - CollectionStatus, - Member, - Nft, - NftWithdrawRequest, - WenError, -} from '@build-5/interfaces'; +import { COL, CollectionStatus, NftWithdrawRequest, WenError } from '@build-5/interfaces'; import { assertCanBeWithdrawn } from '../../services/payment/nft/nft-withdraw.service'; import { createNftWithdrawOrder } from '../../services/payment/tangle-service/nft/nft-purchase.service'; import { assertMemberHasValidAddress, getAddress } from '../../utils/address.utils'; import { invalidArgument } from '../../utils/error.utils'; import { Context } from '../common'; -export const withdrawNftControl = async ({ owner, params, project }: Context) => +export const withdrawNftControl = ({ owner, params, project }: Context) => build5Db().runTransaction(async (transaction) => { - const nftDocRef = build5Db().doc(`${COL.NFT}/${params.nft}`); - const nft = await transaction.get(nftDocRef); + const nftDocRef = build5Db().doc(COL.NFT, params.nft); + const nft = await transaction.get(nftDocRef); if (!nft) { throw invalidArgument(WenError.nft_does_not_exists); } assertCanBeWithdrawn(nft, owner); - const collectionDocRef = build5Db().doc(`${COL.COLLECTION}/${nft.collection}`); - const collection = await collectionDocRef.get(); + const collectionDocRef = build5Db().doc(COL.COLLECTION, nft.collection); + const collection = await collectionDocRef.get(); if (collection?.status !== CollectionStatus.MINTED) { throw invalidArgument(WenError.nft_not_minted); } - const memberDocRef = build5Db().doc(`${COL.MEMBER}/${owner}`); - const member = await memberDocRef.get(); + const memberDocRef = build5Db().doc(COL.MEMBER, owner); + const member = await memberDocRef.get(); assertMemberHasValidAddress(member, nft.mintingData?.network!); const { order, nftUpdateData } = createNftWithdrawOrder( @@ -40,9 +32,9 @@ export const withdrawNftControl = async ({ owner, params, project }: Context({ .description('Billing type of the project.'), tiers: Joi.array() .when('billing', { - is: Joi.exist().valid(ProjectBilling.TOKEN_BASE), + is: Joi.exist().valid(ProjectBilling.TOKEN_BASED), then: Joi.array().items(Joi.number().integer().min(0)).min(5).max(5).required(), otherwise: Joi.forbidden(), }) .description( - `Tiers for this project. Set only if billing type is ${ProjectBilling.TOKEN_BASE}`, + `Tiers for this project. Set only if billing type is ${ProjectBilling.TOKEN_BASED}`, ), tokenTradingFeeDiscountPercentage: Joi.array() .when('billing', { - is: Joi.exist().valid(ProjectBilling.TOKEN_BASE), + is: Joi.exist().valid(ProjectBilling.TOKEN_BASED), then: Joi.array().items(Joi.number().integer().min(0)).min(5).max(5).required(), otherwise: Joi.forbidden(), }) .description( - `Discounts for this project. Set only if billing type is ${ProjectBilling.TOKEN_BASE}`, + `Discounts for this project. Set only if billing type is ${ProjectBilling.TOKEN_BASED}`, ), nativeTokenSymbol: Joi.string() .when('billing', { - is: Joi.exist().valid(ProjectBilling.TOKEN_BASE), + is: Joi.exist().valid(ProjectBilling.TOKEN_BASED), then: CommonJoi.tokenSymbol(), otherwise: Joi.forbidden(), }) .description( - `Base token symbol for this project. Set only if billing type is ${ProjectBilling.TOKEN_BASE}`, + `Base token symbol for this project. Set only if billing type is ${ProjectBilling.TOKEN_BASED}`, ), }) .required() diff --git a/packages/functions/src/controls/project/project.create.control.ts b/packages/functions/src/controls/project/project.create.control.ts index 23e73f16e4..19810daa1a 100644 --- a/packages/functions/src/controls/project/project.create.control.ts +++ b/packages/functions/src/controls/project/project.create.control.ts @@ -30,7 +30,7 @@ export const createProjectControl = async ({ owner, params, }: Context): Promise => { - const memberDocRef = build5Db().doc(`${COL.MEMBER}/${owner}`); + const memberDocRef = build5Db().doc(COL.MEMBER, owner); const member = await memberDocRef.get(); if (!member) { throw invalidArgument(WenError.member_does_not_exists); @@ -45,21 +45,21 @@ export const createProjectControl = async ({ deactivated: false, } as Project; - if (projectData.config.billing === ProjectBilling.TOKEN_BASE) { + if (projectData.config.billing === ProjectBilling.TOKEN_BASED) { const token = await getTokenBySymbol(projectData.config.nativeTokenSymbol!); if (!token) { throw invalidArgument(WenError.token_does_not_exist); } set(projectData, 'config.nativeTokenUid', token.uid); } - const projectDocRef = build5Db().doc(`${COL.PROJECT}/${projectData.uid}`); + const projectDocRef = build5Db().doc(COL.PROJECT, projectData.uid); const otr = await createOtrs(batch, projectData.uid); set(projectData, 'otr', otr); batch.create(projectDocRef, projectData); - const adminDocRef = projectDocRef.collection(SUB_COL.ADMINS).doc(owner); + const adminDocRef = build5Db().doc(COL.PROJECT, projectData.uid, SUB_COL.ADMINS, owner); const admin: ProjectAdmin = { project: projectData.uid, uid: owner, @@ -76,13 +76,14 @@ export const createProjectControl = async ({ parentCol: COL.PROJECT, parentId: projectData.uid, token, + createdOn: dateToTimestamp(dayjs()), }; - const apiKeyDocRef = projectDocRef.collection(SUB_COL._API_KEY).doc(); + const apiKeyDocRef = build5Db().doc(COL.PROJECT, projectData.uid, SUB_COL._API_KEY, apiKey.uid); batch.create(apiKeyDocRef, apiKey); await batch.commit(); - return { project: (await projectDocRef.get())!, token }; + return { project: (await projectDocRef.get())!, token }; }; const createOtrs = async (batch: IBatch, project: string) => { @@ -110,10 +111,10 @@ const createOtrs = async (batch: IBatch, project: string) => { }); const otrs = await Promise.all(promise); - otrs.forEach((otr) => { - const docRef = build5Db().doc(`${COL.TRANSACTION}/${otr.uid}`); + for (const otr of otrs) { + const docRef = build5Db().doc(COL.TRANSACTION, otr.uid); batch.create(docRef, otr); - }); + } return otrs.reduce( (acc, act) => ({ diff --git a/packages/functions/src/controls/project/project.deactivate.control.ts b/packages/functions/src/controls/project/project.deactivate.control.ts index 967ad139d5..8d8b2d5ba7 100644 --- a/packages/functions/src/controls/project/project.deactivate.control.ts +++ b/packages/functions/src/controls/project/project.deactivate.control.ts @@ -6,7 +6,7 @@ import { Context } from '../common'; export const deactivateProjectControl = async ({ project, owner }: Context): Promise => { await assertIsProjectAdmin(project, owner); - const projectDocRef = build5Db().doc(`${COL.PROJECT}/${project}`); + const projectDocRef = build5Db().doc(COL.PROJECT, project); await projectDocRef.update({ deactivated: true }); - return (await projectDocRef.get())!; + return (await projectDocRef.get())!; }; diff --git a/packages/functions/src/controls/proposal/approve.reject.proposal.ts b/packages/functions/src/controls/proposal/approve.reject.proposal.ts index c59635901e..a7f7c0ba08 100644 --- a/packages/functions/src/controls/proposal/approve.reject.proposal.ts +++ b/packages/functions/src/controls/proposal/approve.reject.proposal.ts @@ -1,5 +1,5 @@ import { build5Db } from '@build-5/database'; -import { ApproveProposalRequest, COL, Proposal, RejectProposalRequest } from '@build-5/interfaces'; +import { ApproveProposalRequest, COL, RejectProposalRequest } from '@build-5/interfaces'; import { getProposalApprovalData } from '../../services/payment/tangle-service/proposal/ProposalApporvalService'; import { Context } from '../common'; @@ -7,7 +7,7 @@ export const proposalApprovalControl = (approve: boolean) => async ({ owner, params }: Context) => { const data = await getProposalApprovalData(owner, params.uid, approve); - const proposalDocRef = build5Db().doc(`${COL.PROPOSAL}/${params.uid}`); + const proposalDocRef = build5Db().doc(COL.PROPOSAL, params.uid); await proposalDocRef.update(data); - return (await proposalDocRef.get())!; + return (await proposalDocRef.get())!; }; diff --git a/packages/functions/src/controls/proposal/create.proposal.ts b/packages/functions/src/controls/proposal/create.proposal.ts index bda7fa07b0..5d23e0837e 100644 --- a/packages/functions/src/controls/proposal/create.proposal.ts +++ b/packages/functions/src/controls/proposal/create.proposal.ts @@ -1,5 +1,5 @@ import { build5Db } from '@build-5/database'; -import { COL, Proposal, ProposalCreateRequest, SUB_COL } from '@build-5/interfaces'; +import { COL, ProposalCreateRequest, SUB_COL } from '@build-5/interfaces'; import { createProposal } from '../../services/payment/tangle-service/proposal/ProposalCreateService'; import { Context } from '../common'; @@ -10,11 +10,16 @@ export const createProposalControl = async ({ }: Context) => { const { proposal, proposalOwner } = await createProposal(project, owner, { ...params }); - const proposalDocRef = build5Db().doc(`${COL.PROPOSAL}/${proposal.uid}`); + const proposalDocRef = build5Db().doc(COL.PROPOSAL, proposal.uid); await proposalDocRef.create(proposal); - const proposalOwnerDocRef = proposalDocRef.collection(SUB_COL.OWNERS).doc(proposal.uid); + const proposalOwnerDocRef = build5Db().doc( + COL.PROPOSAL, + proposal.uid, + SUB_COL.OWNERS, + proposal.uid, + ); await proposalOwnerDocRef.create(proposalOwner); - return (await proposalDocRef.get())!; + return (await proposalDocRef.get())!; }; diff --git a/packages/functions/src/controls/proposal/vote.on.proposal.ts b/packages/functions/src/controls/proposal/vote.on.proposal.ts index 2c21c617e7..35a89cf0bf 100644 --- a/packages/functions/src/controls/proposal/vote.on.proposal.ts +++ b/packages/functions/src/controls/proposal/vote.on.proposal.ts @@ -34,34 +34,40 @@ export const voteOnProposalControl = async ({ } if (params.voteWithStakedTokes) { - const voteTransaction = await build5Db().runTransaction(async (transaction) => + const voteTransaction = await build5Db().runTransaction((transaction) => voteWithStakedTokens(project, transaction, owner, proposal, [params.value]), ); return voteTransaction; } const order = await createVoteTransactionOrder(project, owner, proposal, [params.value], token); - const orderDocRef = build5Db().doc(`${COL.TRANSACTION}/${order.uid}`); + const orderDocRef = build5Db().doc(COL.TRANSACTION, order.uid); await orderDocRef.create(order); - return (await orderDocRef.get())!; + return (await orderDocRef.get())!; } - const voteData = await executeSimpleVoting(project, proposalMember, proposal, [params.value]); + const voteData = executeSimpleVoting(project, proposalMember, proposal, [params.value]); const batch = build5Db().batch(); - const proposalDocRef = build5Db().doc(`${COL.PROPOSAL}/${proposal.uid}`); - batch.set(proposalDocRef, voteData.proposal, true); - - const proposalMemberDocRef = proposalDocRef.collection(SUB_COL.MEMBERS).doc(proposalMember.uid); - batch.set(proposalMemberDocRef, voteData.proposalMember, true); + if (voteData.proposal) { + const proposalDocRef = build5Db().doc(COL.PROPOSAL, proposal.uid); + batch.update(proposalDocRef, voteData.proposal); + } - const voteTransactionDocRef = build5Db().doc( - `${COL.TRANSACTION}/${voteData.voteTransaction.uid}`, + const proposalMemberDocRef = build5Db().doc( + COL.PROPOSAL, + proposal.uid, + SUB_COL.MEMBERS, + proposalMember.uid, ); + batch.update(proposalMemberDocRef, voteData.proposalMember); + + const voteTransactionDocRef = build5Db().doc(COL.TRANSACTION, voteData.voteTransaction.uid); batch.create(voteTransactionDocRef, voteData.voteTransaction); + await batch.commit(); - const voteTransaction = await voteTransactionDocRef.get(); + const voteTransaction = await voteTransactionDocRef.get(); return voteTransaction!; }; diff --git a/packages/functions/src/controls/rank/rank.control.ts b/packages/functions/src/controls/rank/rank.control.ts index 5ff82b88e2..927b594263 100644 --- a/packages/functions/src/controls/rank/rank.control.ts +++ b/packages/functions/src/controls/rank/rank.control.ts @@ -1,6 +1,5 @@ -import { build5Db } from '@build-5/database'; -import { COL, Collection, Rank, RankRequest, SUB_COL, Token, WenError } from '@build-5/interfaces'; -import { set } from 'lodash'; +import { IDocument, PgCollectionStatsUpdate, Update, build5Db } from '@build-5/database'; +import { COL, RankRequest, SUB_COL, WenError } from '@build-5/interfaces'; import { hasStakedTokens } from '../../services/stake.service'; import { getRankingSpace } from '../../utils/config.utils'; import { invalidArgument } from '../../utils/error.utils'; @@ -13,52 +12,56 @@ export const rankControl = async ({ owner, params, project }: Context = build5Db().doc(col, params.uid); const parent = await parentDocRef.get(); if (!parent) { - const errorMsg = - params.collection === COL.COLLECTION - ? WenError.collection_does_not_exists - : WenError.token_does_not_exist; - throw invalidArgument(errorMsg); + if (col === COL.COLLECTION) { + throw invalidArgument(WenError.collection_does_not_exists); + } + throw invalidArgument(WenError.token_does_not_exist); } const rankingSpaceId = getRankingSpace(params.collection as COL); await assertIsGuardian(rankingSpaceId, owner); + const rankDocRef = build5Db().doc(col, params.uid, SUB_COL.RANKS, owner); + await build5Db().runTransaction(async (transaction) => { - const parent = (await transaction.get(parentDocRef))!; - const rankDocRef = parentDocRef.collection(SUB_COL.RANKS).doc(owner); - const prevRank = await transaction.get(rankDocRef); + const parent = (await transaction.get(parentDocRef))!; + const prevRank = await transaction.get(rankDocRef); - if (prevRank) { - transaction.update(rankDocRef, { rank: params.rank }); - } else { - transaction.create(rankDocRef, { - uid: owner, - parentCol: params.collection, - parentId: params.uid, - rank: params.rank, - }); - } + await transaction.upsert(rankDocRef, { + parentId: params.uid, + rank: params.rank, + }); - const ranks = { - count: (parent.rankCount || 0) + (prevRank ? 0 : 1), - sum: (parent.rankSum || 0) + (-(prevRank?.rank || 0) + params.rank), - avg: 0, - }; - set(ranks, 'avg', Number((ranks.sum / ranks.count).toFixed(3))); + const count = (parent.rankCount || 0) + (prevRank ? 0 : 1); + const sum = (parent.rankSum || 0) + (-(prevRank?.rank || 0) + params.rank); + const ranks = { count, sum, avg: Number((sum / count).toFixed(3)) }; - transaction.update(parentDocRef, { + await transaction.update(parentDocRef, { rankCount: ranks.count, rankSum: ranks.sum, rankAvg: ranks.avg, }); - const statsDocRef = parentDocRef.collection(SUB_COL.STATS).doc(params.uid); - transaction.set(statsDocRef, { ranks }, true); + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const statsDocRef: IDocument = build5Db().doc( + col, + params.uid, + SUB_COL.STATS, + params.uid, + ); + await transaction.upsert(statsDocRef, { + project: parent.project, + parentId: params.uid, + ranks_avg: ranks.avg, + ranks_sum: ranks.sum, + ranks_count: ranks.count, + }); }); - const rankDocRef = parentDocRef.collection(SUB_COL.RANKS).doc(owner); - return (await rankDocRef.get())!; + return (await rankDocRef.get())!; }; diff --git a/packages/functions/src/controls/space/member.accept.control.ts b/packages/functions/src/controls/space/member.accept.control.ts index 2eda09c367..1cca9983f3 100644 --- a/packages/functions/src/controls/space/member.accept.control.ts +++ b/packages/functions/src/controls/space/member.accept.control.ts @@ -1,5 +1,5 @@ import { build5Db } from '@build-5/database'; -import { COL, SpaceMember, SpaceMemberUpsertRequest, SUB_COL } from '@build-5/interfaces'; +import { COL, SpaceMemberUpsertRequest, SUB_COL } from '@build-5/interfaces'; import { acceptSpaceMember } from '../../services/payment/tangle-service/space/SpaceAcceptMemberService'; import { Context } from '../common'; @@ -10,17 +10,19 @@ export const acceptSpaceMemberControl = async ({ }: Context) => { 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); - const knockingMemberDocRef = spaceDocRef - .collection(SUB_COL.KNOCKING_MEMBERS) - .doc(spaceMember.uid); + const memberDocRef = build5Db().doc(COL.SPACE, params.uid, SUB_COL.MEMBERS, spaceMember.uid); + const knockingMemberDocRef = build5Db().doc( + COL.SPACE, + params.uid, + SUB_COL.KNOCKING_MEMBERS, + spaceMember.uid, + ); const batch = build5Db().batch(); - batch.set(memberDocRef, spaceMember); + batch.upsert(memberDocRef, { ...spaceMember, createdOn: spaceMember.createdOn.toDate() }); batch.delete(knockingMemberDocRef); - batch.update(spaceDocRef, space); + batch.update(build5Db().doc(COL.SPACE, params.uid), space); await batch.commit(); - return await memberDocRef.get(); + return await memberDocRef.get(); }; diff --git a/packages/functions/src/controls/space/member.block.control.ts b/packages/functions/src/controls/space/member.block.control.ts index c284da5e81..121483d5c6 100644 --- a/packages/functions/src/controls/space/member.block.control.ts +++ b/packages/functions/src/controls/space/member.block.control.ts @@ -1,5 +1,5 @@ import { build5Db } from '@build-5/database'; -import { COL, SpaceMember, SpaceMemberUpsertRequest, SUB_COL } from '@build-5/interfaces'; +import { COL, SpaceMemberUpsertRequest, SUB_COL } from '@build-5/interfaces'; import { getBlockMemberUpdateData } from '../../services/payment/tangle-service/space/SpaceBlockMemberService'; import { Context } from '../common'; @@ -16,15 +16,22 @@ export const blockMemberControl = async ({ member, ); - const spaceDocRef = build5Db().doc(`${COL.SPACE}/${params.uid}`); - const blockedMemberDocRef = spaceDocRef.collection(SUB_COL.BLOCKED_MEMBERS).doc(member); + const blockedMemberDocRef = build5Db().doc( + COL.SPACE, + params.uid, + SUB_COL.BLOCKED_MEMBERS, + member, + ); const batch = build5Db().batch(); - batch.set(blockedMemberDocRef, blockedMember); - batch.delete(spaceDocRef.collection(SUB_COL.MEMBERS).doc(member)); - batch.delete(spaceDocRef.collection(SUB_COL.KNOCKING_MEMBERS).doc(member)); - batch.update(spaceDocRef, space); + batch.upsert(blockedMemberDocRef, { + ...blockedMember, + createdOn: blockedMember.createdOn.toDate(), + }); + batch.delete(build5Db().doc(COL.SPACE, params.uid, SUB_COL.MEMBERS, member)); + batch.delete(build5Db().doc(COL.SPACE, params.uid, SUB_COL.KNOCKING_MEMBERS, member)); + batch.update(build5Db().doc(COL.SPACE, params.uid), space); await batch.commit(); - return await blockedMemberDocRef.get(); + return await blockedMemberDocRef.get(); }; diff --git a/packages/functions/src/controls/space/member.decline.control.ts b/packages/functions/src/controls/space/member.decline.control.ts index 1399d1e26d..afb671086f 100644 --- a/packages/functions/src/controls/space/member.decline.control.ts +++ b/packages/functions/src/controls/space/member.decline.control.ts @@ -9,14 +9,20 @@ export const declineMemberControl = async ({ }: Context) => { await assertIsGuardian(params.uid, owner); - const spaceDocRef = build5Db().doc(`${COL.SPACE}/${params.uid}`); - const knockingMemberDocRef = spaceDocRef.collection(SUB_COL.KNOCKING_MEMBERS).doc(params.member); + const knockingMemberDocRef = build5Db().doc( + COL.SPACE, + params.uid, + SUB_COL.KNOCKING_MEMBERS, + params.member, + ); const knockingMemberDoc = await knockingMemberDocRef.get(); const batch = build5Db().batch(); batch.delete(knockingMemberDocRef); - batch.update(spaceDocRef, { totalPendingMembers: build5Db().inc(knockingMemberDoc ? -1 : 0) }); + batch.update(build5Db().doc(COL.SPACE, params.uid), { + totalPendingMembers: build5Db().inc(knockingMemberDoc ? -1 : 0), + }); await batch.commit(); return { status: 'success' }; diff --git a/packages/functions/src/controls/space/member.leave.control.ts b/packages/functions/src/controls/space/member.leave.control.ts index 0a7b52e38d..e6a8ab2c80 100644 --- a/packages/functions/src/controls/space/member.leave.control.ts +++ b/packages/functions/src/controls/space/member.leave.control.ts @@ -4,18 +4,16 @@ import { getLeaveSpaceData } from '../../services/payment/tangle-service/space/S import { Context } from '../common'; export const leaveSpaceControl = async ({ owner, params }: Context) => { - const { space, member } = await getLeaveSpaceData(owner, params.uid); - - const spaceDocRef = build5Db().doc(`${COL.SPACE}/${params.uid}`); + const spaceUpdateData = await getLeaveSpaceData(owner, params.uid); const batch = build5Db().batch(); - batch.delete(spaceDocRef.collection(SUB_COL.MEMBERS).doc(owner)); - batch.delete(spaceDocRef.collection(SUB_COL.GUARDIANS).doc(owner)); - batch.update(spaceDocRef, space); + batch.delete(build5Db().doc(COL.SPACE, params.uid, SUB_COL.MEMBERS, owner)); + batch.delete(build5Db().doc(COL.SPACE, params.uid, SUB_COL.GUARDIANS, owner)); + batch.update(build5Db().doc(COL.SPACE, params.uid), spaceUpdateData); - const memberDocRef = build5Db().doc(`${COL.MEMBER}/${owner}`); - batch.set(memberDocRef, member, true); + const memberDocRef = build5Db().doc(COL.MEMBER, owner); + batch.update(memberDocRef, { spaces: { [params.uid]: { isMember: false } } }); await batch.commit(); diff --git a/packages/functions/src/controls/space/member.unblock.control.ts b/packages/functions/src/controls/space/member.unblock.control.ts index 038a482393..c9e12fa548 100644 --- a/packages/functions/src/controls/space/member.unblock.control.ts +++ b/packages/functions/src/controls/space/member.unblock.control.ts @@ -9,8 +9,12 @@ export const unblockMemberControl = async ({ }: Context) => { await assertIsGuardian(params.uid, owner); - const spaceDocRef = build5Db().doc(`${COL.SPACE}/${params.uid}`); - const blockedMemberDocRef = spaceDocRef.collection(SUB_COL.BLOCKED_MEMBERS).doc(params.member); + const blockedMemberDocRef = build5Db().doc( + COL.SPACE, + params.uid, + SUB_COL.BLOCKED_MEMBERS, + params.member, + ); await blockedMemberDocRef.delete(); return { status: 'success' }; diff --git a/packages/functions/src/controls/space/space.claim.control.ts b/packages/functions/src/controls/space/space.claim.control.ts index 7d5c499908..39b119bd0f 100644 --- a/packages/functions/src/controls/space/space.claim.control.ts +++ b/packages/functions/src/controls/space/space.claim.control.ts @@ -1,8 +1,6 @@ import { build5Db } from '@build-5/database'; import { COL, - Collection, - Space, SpaceClaimRequest, TRANSACTION_AUTO_EXPIRY_MS, Transaction, @@ -20,16 +18,16 @@ import { getRandomEthAddress } from '../../utils/wallet.utils'; import { Context } from '../common'; export const claimSpaceControl = async ({ owner, params, project }: Context) => { - const spaceDocRef = build5Db().doc(`${COL.SPACE}/${params.uid}`); - const space = await spaceDocRef.get(); + const spaceDocRef = build5Db().doc(COL.SPACE, params.uid); + const space = await spaceDocRef.get(); if (!space) { throw invalidArgument(WenError.space_does_not_exists); } if (!space.collectionId || space.claimed) { throw invalidArgument(WenError.space_not_claimable); } - const collectionDocRef = build5Db().doc(`${COL.COLLECTION}/${space.collectionId}`); - const collection = await collectionDocRef.get(); + const collectionDocRef = build5Db().doc(COL.COLLECTION, space.collectionId); + const collection = await collectionDocRef.get(); if (!collection) { throw invalidArgument(WenError.collection_does_not_exists); } @@ -55,7 +53,7 @@ export const claimSpaceControl = async ({ owner, params, project }: Context): Promise => { - const { space, guardian, member } = await getCreateSpaceData(project, owner, { ...params }); + const { space, guardian } = await getCreateSpaceData(project, owner, { ...params }); const batch = build5Db().batch(); - const spaceDocRef = build5Db().doc(`${COL.SPACE}/${space.uid}`); + const spaceDocRef = build5Db().doc(COL.SPACE, space.uid); batch.create(spaceDocRef, space); - const spaceGuardianDocRef = spaceDocRef.collection(SUB_COL.GUARDIANS).doc(owner); + const spaceGuardianDocRef = build5Db().doc(COL.SPACE, space.uid, SUB_COL.GUARDIANS, owner); batch.create(spaceGuardianDocRef, guardian); - const spaceMemberDocRef = spaceDocRef.collection(SUB_COL.MEMBERS).doc(owner); + const spaceMemberDocRef = build5Db().doc(COL.SPACE, space.uid, SUB_COL.MEMBERS, owner); batch.create(spaceMemberDocRef, guardian); - const memberDocRef = build5Db().doc(`${COL.MEMBER}/${owner}`); - batch.set(memberDocRef, member, true); + const memberDocRef = build5Db().doc(COL.MEMBER, owner); + batch.update(memberDocRef, { spaces: { [space.uid]: { uid: space.uid, isMember: true } } }); await batch.commit(); - return (await spaceDocRef.get())!; + return (await spaceDocRef.get())!; }; 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 4a2060f960..c18aa37cf3 100644 --- a/packages/functions/src/controls/space/space.guardian.edit.control.ts +++ b/packages/functions/src/controls/space/space.guardian.edit.control.ts @@ -1,11 +1,5 @@ import { build5Db } from '@build-5/database'; -import { - COL, - Proposal, - ProposalType, - SUB_COL, - SpaceMemberUpsertRequest, -} from '@build-5/interfaces'; +import { COL, ProposalType, SUB_COL, SpaceMemberUpsertRequest } from '@build-5/interfaces'; import { addRemoveGuardian } from '../../services/payment/tangle-service/space/SpaceGuardianService'; import { Context } from '../common'; @@ -18,16 +12,15 @@ export const editGuardianControl = { ...params }, type, ); - - const proposalDocRef = build5Db().doc(`${COL.PROPOSAL}/${proposal.uid}`); - const memberPromisses = members.map((member) => { - proposalDocRef.collection(SUB_COL.MEMBERS).doc(member.uid).set(member); - }); + const memberPromisses = members.map((member) => + build5Db().doc(COL.PROPOSAL, proposal.uid, SUB_COL.MEMBERS, member.uid).create(member), + ); await Promise.all(memberPromisses); - const transactionDocRef = build5Db().doc(`${COL.TRANSACTION}/${voteTransaction.uid}`); + const transactionDocRef = build5Db().doc(COL.TRANSACTION, voteTransaction.uid); await transactionDocRef.create(voteTransaction); + const proposalDocRef = build5Db().doc(COL.PROPOSAL, proposal.uid); await proposalDocRef.create(proposal); - return await proposalDocRef.get(); + return await proposalDocRef.get(); }; diff --git a/packages/functions/src/controls/space/space.join.control.ts b/packages/functions/src/controls/space/space.join.control.ts index 6208ed41d3..3610d9bbd1 100644 --- a/packages/functions/src/controls/space/space.join.control.ts +++ b/packages/functions/src/controls/space/space.join.control.ts @@ -1,31 +1,27 @@ import { build5Db } from '@build-5/database'; -import { COL, Space, SpaceJoinRequest, SUB_COL, WenError } from '@build-5/interfaces'; +import { COL, SpaceJoinRequest, SUB_COL, WenError } from '@build-5/interfaces'; import { getJoinSpaceData } from '../../services/payment/tangle-service/space/SpaceJoinService'; import { invalidArgument } from '../../utils/error.utils'; import { Context } from '../common'; export const joinSpaceControl = async ({ owner, params, project }: Context) => { - const spaceDocRef = build5Db().doc(`${COL.SPACE}/${params.uid}`); - const space = await spaceDocRef.get(); + 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(project, owner, space); + const { space: spaceUpdateData, spaceMember } = await getJoinSpaceData(project, owner, space); const batch = build5Db().batch(); - const joiningMemberDocRef = spaceDocRef - .collection(space.open || space.tokenBased ? SUB_COL.MEMBERS : SUB_COL.KNOCKING_MEMBERS) - .doc(owner); + const subCol = space.open || space.tokenBased ? SUB_COL.MEMBERS : SUB_COL.KNOCKING_MEMBERS; + const joiningMemberDocRef = build5Db().doc(COL.SPACE, params.uid, subCol, owner); - batch.set(joiningMemberDocRef, spaceMember); + batch.create(joiningMemberDocRef, spaceMember); batch.update(spaceDocRef, spaceUpdateData); - const memberDocRef = build5Db().doc(`${COL.MEMBER}/${owner}`); - batch.set(memberDocRef, member, true); + + const memberDocRef = build5Db().doc(COL.MEMBER, owner); + batch.update(memberDocRef, { spaces: { [space.uid]: { uid: space.uid, isMember: true } } }); await batch.commit(); return spaceMember; diff --git a/packages/functions/src/controls/space/space.update.control.ts b/packages/functions/src/controls/space/space.update.control.ts index bd72547550..db94b7ed08 100644 --- a/packages/functions/src/controls/space/space.update.control.ts +++ b/packages/functions/src/controls/space/space.update.control.ts @@ -7,7 +7,6 @@ import { Proposal, ProposalType, Space, - SpaceGuardian, SpaceUpdateRequest, SUB_COL, TokenStatus, @@ -31,8 +30,8 @@ export const updateSpaceControl = async ({ params, project, }: Context) => { - const spaceDocRef = build5Db().doc(`${COL.SPACE}/${params.uid}`); - const space = await spaceDocRef.get(); + const spaceDocRef = build5Db().doc(COL.SPACE, params.uid); + const space = await spaceDocRef.get(); if (!space) { throw invalidArgument(WenError.space_does_not_exists); @@ -55,9 +54,9 @@ export const updateSpaceControl = async ({ throw invalidArgument(WenError.ongoing_proposal); } - const guardianDocRef = build5Db().doc(`${COL.MEMBER}/${owner}`); - const guardian = await guardianDocRef.get(); - const guardians = await spaceDocRef.collection(SUB_COL.GUARDIANS).get(); + const guardianDocRef = build5Db().doc(COL.MEMBER, owner); + const guardian = await guardianDocRef.get(); + const guardians = await build5Db().collection(COL.SPACE, params.uid, SUB_COL.GUARDIANS).get(); const proposal = createUpdateSpaceProposal( project, @@ -84,12 +83,11 @@ export const updateSpaceControl = async ({ linkedTransactions: [], }; - const proposalDocRef = build5Db().doc(`${COL.PROPOSAL}/${proposal.uid}`); + const proposalDocRef = build5Db().doc(COL.PROPOSAL, proposal.uid); const memberPromisses = guardians.map((guardian) => { - proposalDocRef - .collection(SUB_COL.MEMBERS) - .doc(guardian.uid) - .set({ + build5Db() + .doc(COL.PROPOSAL, proposal.uid, SUB_COL.MEMBERS, guardian.uid) + .create({ uid: guardian.uid, weight: 1, voted: guardian.uid === owner, @@ -101,11 +99,11 @@ export const updateSpaceControl = async ({ }); await Promise.all(memberPromisses); - await build5Db().doc(`${COL.TRANSACTION}/${voteTransaction.uid}`).create(voteTransaction); + await build5Db().doc(COL.TRANSACTION, voteTransaction.uid).create(voteTransaction); await proposalDocRef.create(proposal); - return (await proposalDocRef.get())!; + return (await proposalDocRef.get())!; }; const createUpdateSpaceProposal = ( diff --git a/packages/functions/src/controls/stake/stake.deposit.ts b/packages/functions/src/controls/stake/stake.deposit.ts index da02089407..c4f7e32b10 100644 --- a/packages/functions/src/controls/stake/stake.deposit.ts +++ b/packages/functions/src/controls/stake/stake.deposit.ts @@ -16,6 +16,6 @@ export const depositStakeControl = async ({ params.type as StakeType, params.customMetadata, ); - await build5Db().doc(`${COL.TRANSACTION}/${order.uid}`).create(order); + await build5Db().doc(COL.TRANSACTION, order.uid).create(order); return order; }; diff --git a/packages/functions/src/controls/stake/stake.reward.revoke.ts b/packages/functions/src/controls/stake/stake.reward.revoke.ts index b262f314a6..9471676fa9 100644 --- a/packages/functions/src/controls/stake/stake.reward.revoke.ts +++ b/packages/functions/src/controls/stake/stake.reward.revoke.ts @@ -8,11 +8,9 @@ import { ProposalType, REMOVE_STAKE_REWARDS_THRESHOLD_PERCENTAGE, Space, - SpaceGuardian, StakeReward, SUB_COL, Timestamp, - Token, TokenStakeRewardsRemoveRequest, Transaction, TransactionType, @@ -33,8 +31,8 @@ export const removeStakeRewardControl = async ({ }: Context) => { const stakeRewardIds = params.stakeRewardIds as string[]; const stakeRewardPromises = stakeRewardIds.map(async (stakeId) => { - const docRef = build5Db().doc(`${COL.STAKE_REWARD}/${stakeId}`); - return await docRef.get(); + const docRef = build5Db().doc(COL.STAKE_REWARD, stakeId); + return await docRef.get(); }); const stakeRewards = await Promise.all(stakeRewardPromises); stakeRewards.sort((a, b) => a!.startDate.seconds - b!.startDate.seconds); @@ -53,8 +51,8 @@ export const removeStakeRewardControl = async ({ throw invalidArgument(WenError.invalid_params); } - const tokenDocRef = build5Db().doc(`${COL.TOKEN}/${tokenIds[0]}`); - const token = (await tokenDocRef.get())!; + const tokenDocRef = build5Db().doc(COL.TOKEN, tokenIds[0]); + const token = (await tokenDocRef.get())!; await assertIsTokenGuardian(token, owner); @@ -67,16 +65,12 @@ export const removeStakeRewardControl = async ({ throw invalidArgument(WenError.ongoing_proposal); } - const guardianDocRef = build5Db().doc(`${COL.MEMBER}/${owner}`); - const guardian = (await guardianDocRef.get())!; - const guardians = await build5Db() - .collection(COL.SPACE) - .doc(token.space) - .collection(SUB_COL.GUARDIANS) - .get(); + const guardianDocRef = build5Db().doc(COL.MEMBER, owner); + const guardian = (await guardianDocRef.get())!; + const guardians = await build5Db().collection(COL.SPACE, token.space, SUB_COL.GUARDIANS).get(); - const spaceDocRef = build5Db().doc(`${COL.SPACE}/${token.space}`); - const space = await spaceDocRef.get(); + const spaceDocRef = build5Db().doc(COL.SPACE, token.space!); + const space = await spaceDocRef.get(); const proposal = createUpdateSpaceProposal( project, guardian, @@ -102,12 +96,11 @@ export const removeStakeRewardControl = async ({ linkedTransactions: [], }; - const proposalDocRef = build5Db().doc(`${COL.PROPOSAL}/${proposal.uid}`); + const proposalDocRef = build5Db().doc(COL.PROPOSAL, proposal.uid); const memberPromisses = guardians.map((guardian) => { - proposalDocRef - .collection(SUB_COL.MEMBERS) - .doc(guardian.uid) - .set({ + build5Db() + .doc(COL.PROPOSAL, proposal.uid, SUB_COL.MEMBERS, guardian.uid) + .create({ project, uid: guardian.uid, weight: 1, @@ -120,11 +113,11 @@ export const removeStakeRewardControl = async ({ }); await Promise.all(memberPromisses); - await build5Db().doc(`${COL.TRANSACTION}/${voteTransaction.uid}`).create(voteTransaction); + await build5Db().doc(COL.TRANSACTION, voteTransaction.uid).create(voteTransaction); await proposalDocRef.create(proposal); - return (await proposalDocRef.get())!; + return (await proposalDocRef.get())!; }; const createUpdateSpaceProposal = ( diff --git a/packages/functions/src/controls/stake/stake.reward.ts b/packages/functions/src/controls/stake/stake.reward.ts index 1b15d50012..8dfd408d0a 100644 --- a/packages/functions/src/controls/stake/stake.reward.ts +++ b/packages/functions/src/controls/stake/stake.reward.ts @@ -3,7 +3,6 @@ import { COL, StakeReward, StakeRewardStatus, - Token, TokenStakeRewardsRequest, WenError, } from '@build-5/interfaces'; @@ -19,8 +18,8 @@ export const stakeRewardControl = async ({ params, project, }: Context) => { - const tokenDocRef = build5Db().doc(`${COL.TOKEN}/${params.token}`); - const token = await tokenDocRef.get(); + const tokenDocRef = build5Db().doc(COL.TOKEN, params.token); + const token = await tokenDocRef.get(); if (!token) { throw invalidArgument(WenError.token_does_not_exist); } @@ -38,10 +37,10 @@ export const stakeRewardControl = async ({ })); const batch = build5Db().batch(); - stakeRewards.forEach((stakeReward) => { - const docRef = build5Db().doc(`${COL.STAKE_REWARD}/${stakeReward.uid}`); + for (const stakeReward of stakeRewards) { + const docRef = build5Db().doc(COL.STAKE_REWARD, stakeReward.uid); batch.create(docRef, stakeReward); - }); + } await batch.commit(); return stakeRewards; diff --git a/packages/functions/src/controls/stamp/stamp.create.ts b/packages/functions/src/controls/stamp/stamp.create.ts index de28925c29..5285bbb038 100644 --- a/packages/functions/src/controls/stamp/stamp.create.ts +++ b/packages/functions/src/controls/stamp/stamp.create.ts @@ -1,6 +1,8 @@ import { build5Db } from '@build-5/database'; import { COL, Network, SUB_COL, StampRequest } from '@build-5/interfaces'; +import dayjs from 'dayjs'; import { createStampAndStampOrder } from '../../services/payment/tangle-service/stamp/StampTangleService'; +import { dateToTimestamp } from '../../utils/dateTime.utils'; import { Context } from '../common'; export const stampCreateControl = async ({ project, owner, params }: Context) => { @@ -16,21 +18,26 @@ export const stampCreateControl = async ({ project, owner, params }: Contextawait ownerDocRef.get(); assertMemberHasValidAddress(ownerData, params.network as Network); @@ -29,9 +29,9 @@ export const swapCreateControl = async ({ ); const batch = build5Db().batch(); - const orderDocRef = build5Db().doc(`${COL.TRANSACTION}/${order.uid}`); + const orderDocRef = build5Db().doc(COL.TRANSACTION, order.uid); batch.create(orderDocRef, order); - const swapDocRef = build5Db().doc(`${COL.SWAP}/${swap.uid}`); + const swapDocRef = build5Db().doc(COL.SWAP, swap.uid); batch.create(swapDocRef, swap); await batch.commit(); diff --git a/packages/functions/src/controls/swaps/swap.funded.control.ts b/packages/functions/src/controls/swaps/swap.funded.control.ts index 20ef72816a..2791044ba1 100644 --- a/packages/functions/src/controls/swaps/swap.funded.control.ts +++ b/packages/functions/src/controls/swaps/swap.funded.control.ts @@ -1,4 +1,4 @@ -import { build5Db } from '@build-5/database'; +import { PgSwapStatus, build5Db } from '@build-5/database'; import { COL, Swap, SwapSetFundedRequest, SwapStatus } from '@build-5/interfaces'; import { asksAreFulfilled, @@ -7,28 +7,28 @@ import { } from '../../services/payment/swap/swap-service'; import { Context } from '../common'; -export const swapFundedControl = async ({ +export const swapFundedControl = ({ project, owner, params, }: Context): Promise => build5Db().runTransaction(async (transaction) => { - const swapDocRef = build5Db().doc(`${COL.SWAP}/${params.uid}`); - const swap = await transaction.get(swapDocRef); + const swapDocRef = build5Db().doc(COL.SWAP, params.uid); + const swap = await transaction.get(swapDocRef); assertSwapCanBeSetAsFunded(owner, swap); if (asksAreFulfilled(swap!)) { - transaction.update(swapDocRef, { status: SwapStatus.FULFILLED }); + await transaction.update(swapDocRef, { status: PgSwapStatus.FULFILLED }); const transfers = await createSwapTransfers(project, swap!); for (const transfer of transfers) { - const docRef = build5Db().doc(`${COL.TRANSACTION}/${transfer.uid}`); - transaction.create(docRef, transfer); + const docRef = build5Db().doc(COL.TRANSACTION, transfer.uid); + await transaction.create(docRef, transfer); } return { ...swap!, status: SwapStatus.FULFILLED }; } - transaction.update(swapDocRef, { status: SwapStatus.FUNDED }); + await transaction.update(swapDocRef, { status: PgSwapStatus.FUNDED }); return swap!; }); diff --git a/packages/functions/src/controls/swaps/swap.reject.control.ts b/packages/functions/src/controls/swaps/swap.reject.control.ts index 0b55727d5f..5790922346 100644 --- a/packages/functions/src/controls/swaps/swap.reject.control.ts +++ b/packages/functions/src/controls/swaps/swap.reject.control.ts @@ -1,25 +1,25 @@ -import { build5Db } from '@build-5/database'; +import { PgSwapStatus, build5Db } from '@build-5/database'; import { COL, Swap, SwapRejectRequest, SwapStatus } from '@build-5/interfaces'; import { rejectSwap } from '../../services/payment/swap/swap-service'; import { Context } from '../common'; -export const swapRejectControl = async ({ +export const swapRejectControl = ({ project, owner, params, }: Context): Promise => build5Db().runTransaction(async (transaction) => { - const swapDocRef = build5Db().doc(`${COL.SWAP}/${params.uid}`); - const swap = await transaction.get(swapDocRef); + const swapDocRef = build5Db().doc(COL.SWAP, params.uid); + const swap = await transaction.get(swapDocRef); const credits = rejectSwap(project, owner, swap); for (const credit of credits) { - const docRef = build5Db().doc(`${COL.TRANSACTION}/${credit.uid}`); - transaction.create(docRef, credit); + const docRef = build5Db().doc(COL.TRANSACTION, credit.uid); + await transaction.create(docRef, credit); } - transaction.update(swapDocRef, { status: SwapStatus.REJECTED }); + await transaction.update(swapDocRef, { status: PgSwapStatus.REJECTED }); return { ...swap!, status: SwapStatus.REJECTED }; }); 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 d5962061e3..789eda0ea8 100644 --- a/packages/functions/src/controls/token-minting/airdrop-minted-token.ts +++ b/packages/functions/src/controls/token-minting/airdrop-minted-token.ts @@ -5,7 +5,6 @@ import { CreateAirdropsRequest, StakeType, TRANSACTION_AUTO_EXPIRY_MS, - Token, TokenDrop, TokenDropStatus, TokenStatus, @@ -34,9 +33,9 @@ export const airdropMintedTokenControl = async ({ owner, params, }: Context) => { - const tokenDocRef = build5Db().doc(`${COL.TOKEN}/${params.token}`); await build5Db().runTransaction(async (transaction) => { - const token = await transaction.get(tokenDocRef); + const tokenDocRef = build5Db().doc(COL.TOKEN, params.token); + const token = await transaction.get(tokenDocRef); if (!token) { throw invalidArgument(WenError.invalid_params); @@ -46,7 +45,8 @@ export const airdropMintedTokenControl = async ({ assertTokenApproved(token); }); - const token = (await tokenDocRef.get())!; + const tokenDocRef = build5Db().doc(COL.TOKEN, params.token); + const token = (await tokenDocRef.get())!; const drops = params.drops; const totalDropped = drops.reduce((acc, act) => acc + act.count, 0); @@ -97,12 +97,12 @@ export const airdropMintedTokenControl = async ({ const chunks = chunk(airdrops, 500); for (const chunk of chunks) { const batch = build5Db().batch(); - chunk.forEach((airdrop) => { - const docRef = build5Db().doc(`${COL.AIRDROP}/${airdrop.uid}`); + for (const airdrop of chunk) { + const docRef = build5Db().doc(COL.AIRDROP, airdrop.uid); batch.create(docRef, airdrop); - }); + } await batch.commit(); } - await build5Db().doc(`${COL.TRANSACTION}/${order.uid}`).create(order); + await build5Db().doc(COL.TRANSACTION, order.uid).create(order); return order; }; 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 0bfe62c7e9..b809731998 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 @@ -9,6 +9,6 @@ export const claimMintedTokenControl = async ({ project, }: Context) => { const order = await createMintedTokenAirdropClaimOrder(project, owner, params.symbol); - await build5Db().doc(`${COL.TRANSACTION}/${order.uid}`).create(order); + 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 0f8343e48c..c7f17be088 100644 --- a/packages/functions/src/controls/token-minting/import-minted-token.ts +++ b/packages/functions/src/controls/token-minting/import-minted-token.ts @@ -20,7 +20,7 @@ import { assertIsGuardian } from '../../utils/token.utils'; import { getRandomEthAddress } from '../../utils/wallet.utils'; import { Context } from '../common'; -export const importMintedTokenControl = async ({ +export const importMintedTokenControl = ({ owner, params, project, @@ -28,7 +28,7 @@ export const importMintedTokenControl = async ({ build5Db().runTransaction(async (transaction) => { await assertIsGuardian(params.space, owner); - const existingTokenDocRef = build5Db().doc(`${COL.TOKEN}/${params.tokenId}`); + const existingTokenDocRef = build5Db().doc(COL.TOKEN, params.tokenId); const existingToken = await transaction.get(existingTokenDocRef); if (existingToken) { throw invalidArgument(WenError.token_already_exists_for_space); @@ -60,7 +60,7 @@ export const importMintedTokenControl = async ({ tokenId: params.tokenId, }, }; - const orderDocRef = build5Db().doc(`${COL.TRANSACTION}/${order.uid}`); - transaction.create(orderDocRef, order); + const orderDocRef = build5Db().doc(COL.TRANSACTION, order.uid); + await transaction.create(orderDocRef, order); return order; }); 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 446a1c6ebf..523b98ca62 100644 --- a/packages/functions/src/controls/token-minting/token-mint.control.ts +++ b/packages/functions/src/controls/token-minting/token-mint.control.ts @@ -1,8 +1,8 @@ import { build5Db } from '@build-5/database'; import { COL, - Member, Network, + SUB_COL, TRANSACTION_AUTO_EXPIRY_MS, Token, TokenMintRequest, @@ -26,19 +26,14 @@ import { getVaultAndGuardianOutput, tokenToFoundryMetadata, } from '../../utils/token-minting-utils/foundry.utils'; -import { getOwnedTokenTotal } from '../../utils/token-minting-utils/member.utils'; -import { - assertIsTokenGuardian, - assertTokenStatus, - getUnclaimedAirdropTotalValue, -} from '../../utils/token.utils'; +import { assertIsTokenGuardian, assertTokenStatus } from '../../utils/token.utils'; import { getRandomEthAddress } from '../../utils/wallet.utils'; import { Context } from '../common'; export const mintTokenControl = ({ owner, params, project }: Context) => build5Db().runTransaction(async (transaction) => { - const tokenDocRef = build5Db().doc(`${COL.TOKEN}/${params.token}`); - const token = await transaction.get(tokenDocRef); + const tokenDocRef = build5Db().doc(COL.TOKEN, params.token); + const token = await transaction.get(tokenDocRef); if (!token) { throw invalidArgument(WenError.invalid_params); } @@ -50,14 +45,19 @@ export const mintTokenControl = ({ owner, params, project }: Context(); + const member = await build5Db().doc(COL.MEMBER, owner).get(); assertMemberHasValidAddress(member, params.network as Network); const wallet = await WalletService.newWallet(params.network as Network); const targetAddress = await wallet.getNewIotaAddressDetails(); - const totalDistributed = - (await getOwnedTokenTotal(token.uid)) + (await getUnclaimedAirdropTotalValue(token.uid)); + const totalOwned = await build5Db() + .collection(COL.TOKEN, token.uid, SUB_COL.DISTRIBUTION) + .getTotalOwned(); + const airdropTotal = await build5Db() + .collection(COL.AIRDROP) + .getUnclaimedAirdropTotalValue(token.uid); + const totalDistributed = totalOwned + airdropTotal; const storageDeposits = await getStorageDepositForMinting( token, totalDistributed, @@ -85,8 +85,8 @@ export const mintTokenControl = ({ owner, params, project }: Context({ symbol: CommonJoi.tokenSymbol().description('Symbol of the token to trade.'), diff --git a/packages/functions/src/controls/token-trading/token-trade-cancel.controller.ts b/packages/functions/src/controls/token-trading/token-trade-cancel.controller.ts index 2e7ffee4d2..c52abea501 100644 --- a/packages/functions/src/controls/token-trading/token-trade-cancel.controller.ts +++ b/packages/functions/src/controls/token-trading/token-trade-cancel.controller.ts @@ -2,7 +2,6 @@ import { build5Db } from '@build-5/database'; import { COL, CancelTokenTradeOrderRequest, - TokenTradeOrder, TokenTradeOrderStatus, WenError, } from '@build-5/interfaces'; @@ -12,8 +11,8 @@ import { Context } from '../common'; export const cancelTradeOrderControl = ({ owner, params }: Context) => build5Db().runTransaction(async (transaction) => { - const tradeOrderDocRef = build5Db().doc(`${COL.TOKEN_MARKET}/${params.uid}`); - const tradeOrder = await transaction.get(tradeOrderDocRef); + const tradeOrderDocRef = build5Db().doc(COL.TOKEN_MARKET, params.uid); + const tradeOrder = await transaction.get(tradeOrderDocRef); if (tradeOrder?.owner !== owner || tradeOrder.status !== TokenTradeOrderStatus.ACTIVE) { throw invalidArgument(WenError.invalid_params); } 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 57c35de418..e12466aa6c 100644 --- a/packages/functions/src/controls/token-trading/token-trade.controller.ts +++ b/packages/functions/src/controls/token-trading/token-trade.controller.ts @@ -2,7 +2,6 @@ import { build5Db } from '@build-5/database'; import { COL, SUB_COL, - Token, TokenTradeOrderType, TradeTokenRequest, WenError, @@ -19,10 +18,13 @@ export const tradeTokenControl = async ({ project, }: Context) => { let token = await getTokenBySymbol(params.symbol); + if (!token?.uid) { + throw invalidArgument(WenError.token_does_not_exist); + } return await build5Db().runTransaction(async (transaction) => { - const tokenDocRef = build5Db().doc(`${COL.TOKEN}/${token?.uid}`); - token = await transaction.get(tokenDocRef); + const tokenDocRef = build5Db().doc(COL.TOKEN, token?.uid!); + token = await transaction.get(tokenDocRef); if (!token) { throw invalidArgument(WenError.token_does_not_exist); } @@ -42,15 +44,13 @@ export const tradeTokenControl = async ({ ip, ); if (tradeOrder) { - const orderDocRef = build5Db().doc(`${COL.TOKEN_MARKET}/${tradeOrder.uid}`); - transaction.create(orderDocRef, tradeOrder); - const distributionDocRef = build5Db().doc( - `${COL.TOKEN}/${token?.uid}/${SUB_COL.DISTRIBUTION}/${owner}`, - ); - transaction.update(distributionDocRef, distribution); + const orderDocRef = build5Db().doc(COL.TOKEN_MARKET, tradeOrder.uid); + await transaction.create(orderDocRef, tradeOrder); + const distributionDocRef = build5Db().doc(COL.TOKEN, token?.uid, SUB_COL.DISTRIBUTION, owner); + await transaction.update(distributionDocRef, distribution); } else { - const tranDocRef = build5Db().doc(`${COL.TRANSACTION}/${tradeOrderTransaction.uid}`); - transaction.create(tranDocRef, tradeOrderTransaction); + const tranDocRef = build5Db().doc(COL.TRANSACTION, tradeOrderTransaction.uid); + await transaction.create(tranDocRef, tradeOrderTransaction); } return tradeOrder || tradeOrderTransaction; }); diff --git a/packages/functions/src/controls/token/TokenOrderRequestSchema.ts b/packages/functions/src/controls/token/TokenOrderRequestSchema.ts index 0aee5ec89d..f101ddebb5 100644 --- a/packages/functions/src/controls/token/TokenOrderRequestSchema.ts +++ b/packages/functions/src/controls/token/TokenOrderRequestSchema.ts @@ -1,5 +1,5 @@ import { OrderTokenRequest } from '@build-5/interfaces'; -import { toJoiObject, CommonJoi } from '../../services/joi/common'; +import { CommonJoi, toJoiObject } from '../../services/joi/common'; export const orderTokenSchema = toJoiObject({ token: CommonJoi.uid().description('Build5 id of the token'), diff --git a/packages/functions/src/controls/token/token.airdrop.claim.ts b/packages/functions/src/controls/token/token.airdrop.claim.ts index dde441721f..29d20157a0 100644 --- a/packages/functions/src/controls/token/token.airdrop.claim.ts +++ b/packages/functions/src/controls/token/token.airdrop.claim.ts @@ -4,7 +4,6 @@ import { ClaimPreMintedAirdroppedTokensRequest, DEFAULT_NETWORK, TRANSACTION_AUTO_EXPIRY_MS, - Token, TokenStatus, Transaction, TransactionPayloadType, @@ -27,8 +26,8 @@ export const claimAirdroppedTokenControl = async ({ params, project, }: Context): Promise => { - const tokenDocRef = build5Db().doc(`${COL.TOKEN}/${params.token}`); - const token = await tokenDocRef.get(); + const tokenDocRef = build5Db().doc(COL.TOKEN, params.token); + const token = await tokenDocRef.get(); if (!token) { throw invalidArgument(WenError.invalid_params); } @@ -36,7 +35,7 @@ export const claimAirdroppedTokenControl = async ({ assertTokenStatus(token, [TokenStatus.AVAILABLE, TokenStatus.PRE_MINTED]); const tranId = getRandomEthAddress(); - const orderDocRef = build5Db().doc(`${COL.TRANSACTION}/${tranId}`); + const orderDocRef = build5Db().doc(COL.TRANSACTION, tranId); const wallet = await WalletService.newWallet(); const targetAddress = await wallet.getNewIotaAddressDetails(); @@ -67,7 +66,7 @@ export const claimAirdroppedTokenControl = async ({ quantity, }, }; - transaction.create(orderDocRef, order); + await transaction.create(orderDocRef, order); }); return (await orderDocRef.get())!; diff --git a/packages/functions/src/controls/token/token.airdrop.ts b/packages/functions/src/controls/token/token.airdrop.ts index 16aefa2fd2..e7415e30e5 100644 --- a/packages/functions/src/controls/token/token.airdrop.ts +++ b/packages/functions/src/controls/token/token.airdrop.ts @@ -42,8 +42,8 @@ export const airdropTokenControl = async ({ const chunks = chunk(params.drops, 200); for (const chunk of chunks) { await build5Db().runTransaction(async (transaction) => { - const tokenDocRef = build5Db().doc(`${COL.TOKEN}/${params.token}`); - const token = await transaction.get(tokenDocRef); + const tokenDocRef = build5Db().doc(COL.TOKEN, params.token); + const token = await transaction.get(tokenDocRef); if (!token) { throw invalidArgument(WenError.token_does_not_exist); @@ -59,7 +59,7 @@ export const airdropTokenControl = async ({ throw invalidArgument(WenError.no_tokens_available_for_airdrop); } - transaction.update(tokenDocRef, { totalAirdropped: build5Db().inc(totalDropped) }); + await transaction.update(tokenDocRef, { totalAirdropped: build5Db().inc(totalDropped) }); for (const drop of chunk) { const airdrop: TokenDrop = { @@ -72,22 +72,19 @@ export const airdropTokenControl = async ({ count: drop.count, status: TokenDropStatus.UNCLAIMED, }; - const docRef = build5Db().doc(`${COL.AIRDROP}/${airdrop.uid}`); - transaction.create(docRef, airdrop); + const docRef = build5Db().doc(COL.AIRDROP, airdrop.uid); + await transaction.create(docRef, airdrop); - const distributionDocRef = tokenDocRef - .collection(SUB_COL.DISTRIBUTION) - .doc(drop.recipient.toLowerCase()); - transaction.set( - distributionDocRef, - { - parentId: token.uid, - parentCol: COL.TOKEN, - uid: drop.recipient.toLowerCase(), - totalUnclaimedAirdrop: build5Db().inc(drop.count), - }, - true, + const distributionDocRef = build5Db().doc( + COL.TOKEN, + params.token, + SUB_COL.DISTRIBUTION, + drop.recipient.toLowerCase(), ); + await transaction.upsert(distributionDocRef, { + parentId: token.uid, + totalUnclaimedAirdrop: build5Db().inc(drop.count), + }); } }); } diff --git a/packages/functions/src/controls/token/token.cancel.pub.sale.ts b/packages/functions/src/controls/token/token.cancel.pub.sale.ts index 049742c8ae..2e8c4d7ab0 100644 --- a/packages/functions/src/controls/token/token.cancel.pub.sale.ts +++ b/packages/functions/src/controls/token/token.cancel.pub.sale.ts @@ -1,5 +1,5 @@ -import { build5Db } from '@build-5/database'; -import { COL, CanelPublicSaleRequest, Token, TokenStatus, WenError } from '@build-5/interfaces'; +import { PgTokenStatus, build5Db } from '@build-5/database'; +import { COL, CanelPublicSaleRequest, WenError } from '@build-5/interfaces'; import dayjs from 'dayjs'; import { invalidArgument } from '../../utils/error.utils'; import { assertIsTokenGuardian } from '../../utils/token.utils'; @@ -9,10 +9,10 @@ export const cancelPublicSaleControl = async ({ owner, params, }: Context) => { - const tokenDocRef = build5Db().doc(`${COL.TOKEN}/${params.token}`); + const tokenDocRef = build5Db().doc(COL.TOKEN, params.token); await build5Db().runTransaction(async (transaction) => { - const token = await transaction.get(tokenDocRef); + const token = await transaction.get(tokenDocRef); if (!token) { throw invalidArgument(WenError.invalid_params); @@ -24,14 +24,14 @@ export const cancelPublicSaleControl = async ({ await assertIsTokenGuardian(token, owner); - transaction.update(tokenDocRef, { - saleStartDate: build5Db().deleteField(), - saleLength: build5Db().deleteField(), - coolDownEnd: build5Db().deleteField(), - status: TokenStatus.CANCEL_SALE, + await transaction.update(tokenDocRef, { + saleStartDate: undefined, + saleLength: undefined, + coolDownEnd: undefined, + status: PgTokenStatus.CANCEL_SALE, totalDeposit: 0, }); }); - return (await tokenDocRef.get())!; + return (await tokenDocRef.get())!; }; diff --git a/packages/functions/src/controls/token/token.create.ts b/packages/functions/src/controls/token/token.create.ts index 7e138e3243..512a0f665d 100644 --- a/packages/functions/src/controls/token/token.create.ts +++ b/packages/functions/src/controls/token/token.create.ts @@ -1,5 +1,6 @@ import { build5Db } from '@build-5/database'; import { + Access, COL, SOON_PROJECT_ID, Token, @@ -7,7 +8,6 @@ import { TokenStatus, WenError, } from '@build-5/interfaces'; -import { merge } from 'lodash'; import { hasStakedTokens } from '../../services/stake.service'; import { isProdEnv } from '../../utils/config.utils'; import { dateToTimestamp } from '../../utils/dateTime.utils'; @@ -29,7 +29,7 @@ export const createTokenControl = async ({ const space = params.space || ''; if (space) { - const tokens = await build5Db().collection(COL.TOKEN).where('space', '==', space).get(); + const tokens = await build5Db().collection(COL.TOKEN).where('space', '==', space).get(); const nonOrAllRejected = tokens.reduce( (acc, token) => acc && !token.approved && token.rejected, true, @@ -44,7 +44,7 @@ export const createTokenControl = async ({ .collection(COL.TOKEN) .where('symbol', '==', params.symbol) .where('rejected', '==', false) - .get(); + .get(); if (symbolSnapshot.length > 0) { throw invalidArgument(WenError.token_symbol_must_be_globally_unique); } @@ -58,7 +58,7 @@ export const createTokenControl = async ({ params.saleLength || 0, params.coolDownLength || 0, ) - : {}; + : { saleStartDate: undefined, saleLength: undefined, coolDownEnd: undefined }; const tokenUid = getRandomEthAddress(); const extraData = { @@ -76,7 +76,18 @@ export const createTokenControl = async ({ totalAirdropped: 0, tradingDisabled: true, }; - const data = merge(params, publicSaleTimeFrames, extraData); - await build5Db().collection(COL.TOKEN).doc(tokenUid).set(data); - return (await build5Db().doc(`${COL.TOKEN}/${tokenUid}`).get())!; + const data: Token = { + ...params, + ...publicSaleTimeFrames, + ...extraData, + pricePerToken: params.pricePerToken || 0, + allocations: params.allocations || [], + links: (params.links || []).map((l) => new URL(l)), + termsAndConditions: params.termsAndConditions || '', + access: params as unknown as Access, + ipfsMedia: '', + ipfsMetadata: '', + }; + await build5Db().doc(COL.TOKEN, tokenUid).create(data); + return (await build5Db().doc(COL.TOKEN, tokenUid).get())!; }; diff --git a/packages/functions/src/controls/token/token.credit.ts b/packages/functions/src/controls/token/token.credit.ts index 71ff1d49de..7f209ea364 100644 --- a/packages/functions/src/controls/token/token.credit.ts +++ b/packages/functions/src/controls/token/token.credit.ts @@ -6,8 +6,6 @@ import { MIN_IOTA_AMOUNT, Member, SUB_COL, - Token, - TokenDistribution, TokenStatus, Transaction, TransactionPayloadType, @@ -31,25 +29,28 @@ export const creditTokenControl = async ({ params, }: Context): Promise => { const tranId = getRandomEthAddress(); - const creditTranDoc = build5Db().doc(`${COL.TRANSACTION}/${tranId}`); + const creditTranDoc = build5Db().doc(COL.TRANSACTION, tranId); await build5Db().runTransaction(async (transaction) => { - const tokenDocRef = build5Db().doc(`${COL.TOKEN}/${params.token}`); - const distributionDocRef = tokenDocRef.collection(SUB_COL.DISTRIBUTION).doc(owner); - const distribution = await transaction.get(distributionDocRef); + const tokenDocRef = build5Db().doc(COL.TOKEN, params.token); + const distributionDocRef = build5Db().doc(COL.TOKEN, params.token, SUB_COL.DISTRIBUTION, owner); + const distribution = await transaction.get(distributionDocRef); if (!distribution || (distribution.totalDeposit || 0) < params.amount) { throw invalidArgument(WenError.not_enough_funds); } - const token = await tokenDocRef.get(); + const token = await tokenDocRef.get(); if (!token || !tokenIsInCoolDownPeriod(token) || token.status !== TokenStatus.AVAILABLE) { throw invalidArgument(WenError.token_not_in_cool_down_period); } const member = await memberDocRef(owner).get(); - const orderDocRef = build5Db().doc( - `${COL.TRANSACTION}/${tokenOrderTransactionDocId(owner, token)}`, - ); - const order = (await transaction.get(orderDocRef))!; - const payments = await transaction.getByQuery(allPaymentsQuery(owner, token.uid)); + const orderDocRef = build5Db().doc(COL.TRANSACTION, tokenOrderTransactionDocId(owner, token)); + const order = (await transaction.get(orderDocRef))!; + + const payments = await build5Db() + .collection(COL.TRANSACTION) + .where('member', '==', owner) + .where('payload_token', '==', token.uid) + .get(); const totalDepositLeft = (distribution.totalDeposit || 0) - params.amount; const refundAmount = @@ -60,10 +61,10 @@ export const creditTokenControl = async ({ totalDepositLeft || 0, token.pricePerToken, ); - transaction.update(distributionDocRef, { + await transaction.update(distributionDocRef, { totalDeposit: build5Db().inc(-refundAmount), }); - transaction.update(tokenDocRef, { + await transaction.update(tokenDocRef, { totalDeposit: build5Db().inc(-refundAmount), tokensOrdered: build5Db().inc(boughtByMemberDiff), }); @@ -87,14 +88,8 @@ export const creditTokenControl = async ({ tokenSymbol: token.symbol, }, }; - transaction.set(creditTranDoc, creditTransaction); + await transaction.create(creditTranDoc, creditTransaction); }); return (await creditTranDoc.get())!; }; - -const allPaymentsQuery = (member: string, token: string) => - build5Db() - .collection(COL.TRANSACTION) - .where('member', '==', member) - .where('payload.token', '==', token); diff --git a/packages/functions/src/controls/token/token.enable.trading.ts b/packages/functions/src/controls/token/token.enable.trading.ts index d29b3f2cf7..00da0d9433 100644 --- a/packages/functions/src/controls/token/token.enable.trading.ts +++ b/packages/functions/src/controls/token/token.enable.trading.ts @@ -1,5 +1,5 @@ import { build5Db } from '@build-5/database'; -import { COL, EnableTokenTradingRequest, Token, WenError } from '@build-5/interfaces'; +import { COL, EnableTokenTradingRequest, WenError } from '@build-5/interfaces'; import { invalidArgument } from '../../utils/error.utils'; import { assertIsTokenGuardian } from '../../utils/token.utils'; import { Context } from '../common'; @@ -8,8 +8,8 @@ export const enableTokenTradingControl = async ({ owner, params, }: Context) => { - const tokenDocRef = build5Db().doc(`${COL.TOKEN}/${params.uid}`); - const token = await tokenDocRef.get(); + const tokenDocRef = build5Db().doc(COL.TOKEN, params.uid); + const token = await tokenDocRef.get(); if (!token) { throw invalidArgument(WenError.token_does_not_exist); } @@ -20,7 +20,7 @@ export const enableTokenTradingControl = async ({ await assertIsTokenGuardian(token, owner); - await tokenDocRef.update({ tradingDisabled: build5Db().deleteField() }); + await tokenDocRef.update({ tradingDisabled: false }); - return (await tokenDocRef.get())!; + return (await tokenDocRef.get())!; }; diff --git a/packages/functions/src/controls/token/token.order.ts b/packages/functions/src/controls/token/token.order.ts index ca938b0560..519333fe28 100644 --- a/packages/functions/src/controls/token/token.order.ts +++ b/packages/functions/src/controls/token/token.order.ts @@ -3,10 +3,7 @@ import { COL, DEFAULT_NETWORK, Entity, - Member, OrderTokenRequest, - Space, - Token, TokenStatus, Transaction, TransactionPayloadType, @@ -31,11 +28,11 @@ export const orderTokenControl = async ({ params, project, }: Context) => { - const memberDocRef = build5Db().doc(`${COL.MEMBER}/${owner}`); - const member = await memberDocRef.get(); + const memberDocRef = build5Db().doc(COL.MEMBER, owner); + const member = await memberDocRef.get(); assertMemberHasValidAddress(member, DEFAULT_NETWORK); - const token = await build5Db().doc(`${COL.TOKEN}/${params.token}`).get(); + const token = await build5Db().doc(COL.TOKEN, params.token).get(); if (!token) { throw invalidArgument(WenError.invalid_params); } @@ -49,8 +46,7 @@ export const orderTokenControl = async ({ } const tranId = tokenOrderTransactionDocId(owner, token); - const orderDoc = build5Db().doc(`${COL.TRANSACTION}/${tranId}`); - const space = await build5Db().doc(`${COL.SPACE}/${token.space}`).get(); + const space = await build5Db().doc(COL.SPACE, token.space!).get(); await assertHasAccess( space!.uid, @@ -63,8 +59,10 @@ export const orderTokenControl = async ({ const network = DEFAULT_NETWORK; const newWallet = await WalletService.newWallet(network); const targetAddress = await newWallet.getNewIotaAddressDetails(); + const orderDoc = build5Db().doc(COL.TRANSACTION, tranId); + await build5Db().runTransaction(async (transaction) => { - const order = await transaction.get(orderDoc); + const order = await transaction.get(orderDoc); if (!order) { const data: Transaction = { project, @@ -91,9 +89,9 @@ export const orderTokenControl = async ({ }, linkedTransactions: [], }; - transaction.create(orderDoc, data); + await transaction.create(orderDoc, data); } }); - return (await orderDoc.get())!; + return (await orderDoc.get())!; }; diff --git a/packages/functions/src/controls/token/token.set.for.sale.ts b/packages/functions/src/controls/token/token.set.for.sale.ts index 36e1a2a362..2dc4f6ac34 100644 --- a/packages/functions/src/controls/token/token.set.for.sale.ts +++ b/packages/functions/src/controls/token/token.set.for.sale.ts @@ -3,8 +3,6 @@ import { COL, DEFAULT_NETWORK, SetTokenForSaleRequest, - Space, - Token, TokenStatus, WenError, } from '@build-5/interfaces'; @@ -23,10 +21,11 @@ export const setTokenAvailableForSaleControl = async ({ owner, params, }: Context) => { - const tokenDocRef = build5Db().doc(`${COL.TOKEN}/${params.token}`); + const tokenDocRef = build5Db().doc(COL.TOKEN, params.token); await build5Db().runTransaction(async (transaction) => { - const token = await transaction.get(tokenDocRef); + const token = await transaction.get(tokenDocRef); + if (!token) { throw invalidArgument(WenError.token_does_not_exist); } @@ -35,7 +34,7 @@ export const setTokenAvailableForSaleControl = async ({ throw invalidArgument(WenError.token_must_have_space); } - const spaceData = await build5Db().doc(`${COL.SPACE}/${token.space}`).get(); + const spaceData = await build5Db().doc(COL.SPACE, token.space).get(); assertSpaceHasValidAddress(spaceData, DEFAULT_NETWORK); assertTokenApproved(token); @@ -57,12 +56,14 @@ export const setTokenAvailableForSaleControl = async ({ params.saleLength, params.coolDownLength, ); - transaction.update(tokenDocRef, { + await transaction.update(tokenDocRef, { ...timeFrames, + saleStartDate: timeFrames.saleStartDate?.toDate(), + coolDownEnd: timeFrames.coolDownEnd?.toDate(), autoProcessAt100Percent: params.autoProcessAt100Percent || false, pricePerToken: Number(params.pricePerToken), }); }); - return await tokenDocRef.get(); + return await tokenDocRef.get(); }; diff --git a/packages/functions/src/controls/token/token.update.ts b/packages/functions/src/controls/token/token.update.ts index 757f961997..a42214cc6d 100644 --- a/packages/functions/src/controls/token/token.update.ts +++ b/packages/functions/src/controls/token/token.update.ts @@ -1,5 +1,5 @@ -import { build5Db } from '@build-5/database'; -import { COL, Token, TokenStatus, WenError } from '@build-5/interfaces'; +import { PgTokenUpdate, build5Db } from '@build-5/database'; +import { COL, TokenStatus, WenError } from '@build-5/interfaces'; import { invalidArgument } from '../../utils/error.utils'; import { assertValidationAsync } from '../../utils/schema.utils'; import { assertIsTokenGuardian, assertTokenStatus } from '../../utils/token.utils'; @@ -10,9 +10,9 @@ import { } from './TokenUpdateRequestSchema'; export const updateTokenControl = async ({ owner, params }: Context) => { - const tokenDocRef = build5Db().doc(`${COL.TOKEN}/${params.uid}`); + const tokenDocRef = build5Db().doc(COL.TOKEN, params.uid); await build5Db().runTransaction(async (transaction) => { - const token = await transaction.get(tokenDocRef); + const token = await transaction.get(tokenDocRef); if (!token) { throw invalidArgument(WenError.invalid_params); } @@ -26,8 +26,8 @@ export const updateTokenControl = async ({ owner, params }: Context(); + return await tokenDocRef.get(); }; diff --git a/packages/functions/src/controls/vote/vote.control.ts b/packages/functions/src/controls/vote/vote.control.ts index a01fc5caee..b40d00c337 100644 --- a/packages/functions/src/controls/vote/vote.control.ts +++ b/packages/functions/src/controls/vote/vote.control.ts @@ -1,5 +1,5 @@ -import { build5Db } from '@build-5/database'; -import { COL, Collection, SUB_COL, Token, Vote, VoteRequest, WenError } from '@build-5/interfaces'; +import { IDocument, PgTokenStatsUpdate, Update, build5Db } from '@build-5/database'; +import { COL, SUB_COL, VoteRequest, WenError } from '@build-5/interfaces'; import { hasStakedTokens } from '../../services/stake.service'; import { invalidArgument } from '../../utils/error.utils'; import { Context } from '../common'; @@ -10,28 +10,25 @@ export const voteControl = async ({ owner, params, project }: Context(); + const col = params.collection === 'collection' ? COL.COLLECTION : COL.TOKEN; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const parentDocRef: IDocument = build5Db().doc(col, params.uid); + const parent = await parentDocRef.get(); if (!parent) { - const errorMsg = - params.collection === COL.COLLECTION - ? WenError.collection_does_not_exists - : WenError.token_does_not_exist; - throw invalidArgument(errorMsg); + if (col === COL.COLLECTION) { + throw invalidArgument(WenError.collection_does_not_exists); + } + throw invalidArgument(WenError.token_does_not_exist); } await build5Db().runTransaction(async (transaction) => { - const voteDocRef = parentDocRef.collection(SUB_COL.VOTES).doc(owner); - const prevVote = await transaction.get(voteDocRef); + const voteDocRef = build5Db().doc(col, params.uid, SUB_COL.VOTES, owner); + const prevVote = await transaction.get(voteDocRef); if (!params.direction) { - prevVote && transaction.delete(voteDocRef); - } else if (prevVote) { - transaction.update(voteDocRef, { direction: params.direction }); + prevVote && (await transaction.delete(voteDocRef)); } else { - transaction.create(voteDocRef, { - uid: owner, - parentCol: params.collection, + await transaction.upsert(voteDocRef, { parentId: params.uid, direction: params.direction, }); @@ -43,14 +40,29 @@ export const voteControl = async ({ owner, params, project }: Context = build5Db().doc( + col, + params.uid, + SUB_COL.STATS, + params.uid, + ); + await transaction.upsert(statsDocRef, { + parentId: params.uid, + votes_upvotes: votes.upvotes, + votes_downvotes: votes.downvotes, + votes_voteDiff: votes.voteDiff, + }); }); - const voteDocRef = parentDocRef.collection(SUB_COL.VOTES).doc(owner); - return (await voteDocRef.get())!; + const voteDocRef = build5Db().doc(col, params.uid, SUB_COL.VOTES, owner); + return (await voteDocRef.get())!; }; const getVoteChagens = (prevDir: number, currDir: number) => { diff --git a/packages/functions/src/cron/auction.cron.ts b/packages/functions/src/cron/auction.cron.ts index 5e2435eb34..290a3f286e 100644 --- a/packages/functions/src/cron/auction.cron.ts +++ b/packages/functions/src/cron/auction.cron.ts @@ -1,4 +1,4 @@ -import { build5Db } from '@build-5/database'; +import { PgTransactionType, build5Db } from '@build-5/database'; import { Auction, AuctionType, @@ -19,7 +19,7 @@ export const finalizeAuctions = async () => { .collection(COL.AUCTION) .where('auctionTo', '<=', dayjs().toDate()) .where('active', '==', true) - .get(); + .get(); const promises = snap.map((a) => { switch (a.type) { case AuctionType.NFT: @@ -36,7 +36,7 @@ const finalizeNftAuction = (auction: string) => const tranService = new TransactionService(transaction); const service = new AuctionFinalizeService(tranService); await service.markAsFinalized(auction); - tranService.submit(); + await tranService.submit(); }); const finalizeOpenAuction = async (auction: Auction) => { @@ -44,17 +44,17 @@ const finalizeOpenAuction = async (auction: Auction) => { let targetAddress = auction.targetAddress; if (!targetAddress) { - const memberDocRef = build5Db().doc(`${COL.MEMBER}/${auction.createdBy}`); + const memberDocRef = build5Db().doc(COL.MEMBER, auction.createdBy!); const member = await memberDocRef.get(); targetAddress = getAddress(member, auction.network); } const payments = await build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.PAYMENT) - .where('payload.invalidPayment', '==', false) - .where('payload.auction', '==', auction.uid) - .get(); + .where('type', '==', PgTransactionType.PAYMENT) + .where('payload_invalidPayment', '==', false) + .where('payload_auction', '==', auction.uid) + .get(); for (const payment of payments) { const billPayment: Transaction = { @@ -75,7 +75,7 @@ const finalizeOpenAuction = async (auction: Auction) => { auction: auction.uid, }, }; - const billPaymentDocRef = build5Db().doc(`${COL.TRANSACTION}/${billPayment.uid}`); + const billPaymentDocRef = build5Db().doc(COL.TRANSACTION, billPayment.uid); batch.create(billPaymentDocRef, billPayment); } diff --git a/packages/functions/src/cron/award.cron.ts b/packages/functions/src/cron/award.cron.ts index 9c0646059b..12c3e1a936 100644 --- a/packages/functions/src/cron/award.cron.ts +++ b/packages/functions/src/cron/award.cron.ts @@ -1,5 +1,5 @@ import { build5Db } from '@build-5/database'; -import { Award, COL } from '@build-5/interfaces'; +import { COL } from '@build-5/interfaces'; import dayjs from 'dayjs'; export const processExpiredAwards = async () => { @@ -7,9 +7,9 @@ export const processExpiredAwards = async () => { .collection(COL.AWARD) .where('completed', '==', false) .where('endDate', '<=', dayjs().toDate()) - .get(); + .get(); const promises = snap.map(async (award) => { - const docRef = build5Db().doc(`${COL.AWARD}/${award.uid}`); + const docRef = build5Db().doc(COL.AWARD, award.uid); await docRef.update({ completed: true }); }); await Promise.all(promises); diff --git a/packages/functions/src/cron/bitfinex.cron.ts b/packages/functions/src/cron/bitfinex.cron.ts index 35c9e76a4b..6d7c25e752 100644 --- a/packages/functions/src/cron/bitfinex.cron.ts +++ b/packages/functions/src/cron/bitfinex.cron.ts @@ -14,17 +14,10 @@ export const getLatestBitfinexPricesCron = async () => { ).data; if (data[0][1] > 0) { - await build5Db().collection(COL.TICKER).doc(TICKERS.SMRUSD).set({ - uid: TICKERS.SMRUSD, - price: data[0][1], - }); + await build5Db().doc(COL.TICKER, TICKERS.SMRUSD).upsert({ price: data[0][1] }); } - if (data[1][1] > 0) { - await build5Db().collection(COL.TICKER).doc(TICKERS.IOTAUSD).set({ - uid: TICKERS.IOTAUSD, - price: data[1][1], - }); + await build5Db().doc(COL.TICKER, TICKERS.IOTAUSD).upsert({ price: data[1][1] }); } } catch (error) { console.error('Failed to get latest prices. Try again in 5 minutes', error); diff --git a/packages/functions/src/cron/collection.floor.price.cron.ts b/packages/functions/src/cron/collection.floor.price.cron.ts index caa7706642..002de26683 100644 --- a/packages/functions/src/cron/collection.floor.price.cron.ts +++ b/packages/functions/src/cron/collection.floor.price.cron.ts @@ -1,37 +1,5 @@ -import { build5Db, getSnapshot } from '@build-5/database'; -import { COL, Collection, Nft, NftAccess, NftAvailable } from '@build-5/interfaces'; -import { head, last } from 'lodash'; +import { build5Db } from '@build-5/database'; +import { COL } from '@build-5/interfaces'; -export const updateFloorPriceOnCollections = async () => { - let lastUid = ''; - do { - const lastDoc = await getSnapshot(COL.COLLECTION, lastUid); - const query = build5Db().collection(COL.COLLECTION).limit(400).startAfter(lastDoc); - const snap = await query.get(); - lastUid = last(snap)?.uid || ''; - - const batch = build5Db().batch(); - for (const collection of snap) { - const floorPrice = await updateCollectionFloorPrice(collection); - if (floorPrice !== undefined) { - const collectionDocRef = build5Db().doc(`${COL.COLLECTION}/${collection.uid}`); - batch.update(collectionDocRef, { floorPrice }); - } - } - await batch.commit(); - - await new Promise((resolve) => setTimeout(resolve, 1000)); - } while (lastUid); -}; - -const updateCollectionFloorPrice = async (collection: Collection) => { - const snap = await build5Db() - .collection(COL.NFT) - .where('collection', '==', collection.uid) - .where('saleAccess', '==', NftAccess.OPEN) - .where('available', 'in', [NftAvailable.SALE, NftAvailable.AUCTION_AND_SALE]) - .orderBy('availablePrice') - .limit(1) - .get(); - return head(snap)?.availablePrice || undefined; -}; +export const updateFloorPriceOnCollections = () => + build5Db().collection(COL.COLLECTION).updateFloorPrie(); diff --git a/packages/functions/src/cron/media.cron.ts b/packages/functions/src/cron/media.cron.ts index 9d3a2f20b9..978496cd18 100644 --- a/packages/functions/src/cron/media.cron.ts +++ b/packages/functions/src/cron/media.cron.ts @@ -1,10 +1,9 @@ -import { build5Db } from '@build-5/database'; +import { ICollection, PgMediaStatus, PgToken, PgTokenUpdate, build5Db } from '@build-5/database'; import { Award, COL, Collection, MAX_WALLET_RETRY, - MediaStatus, Nft, Space, Stamp, @@ -22,6 +21,8 @@ import { spaceToIpfsMetadata } from '../utils/space.utils'; export const MEDIA_UPLOAD_BACH_SIZE = 30; +type ColWithMedia = COL.NFT | COL.TOKEN | COL.COLLECTION | COL.AWARD | COL.SPACE | COL.STAMP; + export const uploadMediaToWeb3 = async () => { let batchSize = MEDIA_UPLOAD_BACH_SIZE; @@ -37,7 +38,7 @@ export const uploadMediaToWeb3 = async () => { const promises: Promise[] = []; for (const prop of props) { const upload = await uploadMedia( - prop.col, + prop.col as ColWithMedia, batchSize, prop.func as (data: unknown) => Promise, ); @@ -51,21 +52,21 @@ export const uploadMediaToWeb3 = async () => { }; const uploadMedia = async ( - col: COL, + col: ColWithMedia, batchSize: number, uploadFunc: (data: T) => Promise, ) => { if (!batchSize) { return { size: 0, promises: [] as Promise[] }; } - const snap = await pendingUploadQuery(col, batchSize).get>(); + const snap = await pendingUploadQuery(col, batchSize).get(); const promises = snap.map(async (data) => { try { await uploadFunc(data); } catch (error) { await setMediaStatusToError( col, - data.uid as string, + data.uid, (data.mediaUploadErrorCount as number) || 0, error, ); @@ -75,29 +76,40 @@ const uploadMedia = async ( }; const uploadNftMedia = async (nft: Nft) => { - const nftDocRef = build5Db().doc(`${COL.NFT}/${nft.uid}`); - const collectionDocRef = build5Db().doc(`${COL.COLLECTION}/${nft.collection}`); - const collection = (await collectionDocRef.get())!; + const nftDocRef = build5Db().doc(COL.NFT, nft.uid); + const collectionDocRef = build5Db().doc(COL.COLLECTION, nft.collection); + const collection = (await collectionDocRef.get())!; const metadata = nftToIpfsMetadata(collection, nft); const { car, ...ipfs } = await downloadMediaAndPackCar(nft.uid, nft.media, metadata); await putCar(car); const batch = build5Db().batch(); - batch.update(collectionDocRef, { 'mintingData.nftMediaToUpload': build5Db().inc(-1) }); - batch.update(nftDocRef, { mediaStatus: MediaStatus.UPLOADED, ...ipfs }); + batch.update(collectionDocRef, { mintingData_nftMediaToUpload: build5Db().inc(-1) }); + + batch.update(nftDocRef, { + mediaStatus: PgMediaStatus.UPLOADED, + ipfsMedia: ipfs.ipfsMedia, + ipfsMetadata: ipfs.ipfsMetadata, + ipfsRoot: ipfs.ipfsRoot, + }); await batch.commit(); }; const uploadTokenMedia = async (token: Token) => { - const tokenDocRef = build5Db().doc(`${COL.TOKEN}/${token.uid}`); + const tokenDocRef = build5Db().doc(COL.TOKEN, token.uid); const metadata = tokenToIpfsMetadata(token); const { car, ...ipfs } = await downloadMediaAndPackCar(token.uid, token.icon!, metadata); await putCar(car); - await tokenDocRef.update({ mediaStatus: MediaStatus.UPLOADED, ...ipfs }); + await tokenDocRef.update({ + mediaStatus: PgMediaStatus.UPLOADED, + ipfsMedia: ipfs.ipfsMedia, + ipfsMetadata: ipfs.ipfsMetadata, + ipfsRoot: ipfs.ipfsRoot, + }); }; const uploadCollectionMedia = async (collection: Collection) => { - const collectionDocRef = build5Db().doc(`${COL.COLLECTION}/${collection.uid}`); + const collectionDocRef = build5Db().doc(COL.COLLECTION, collection.uid); const metadata = collectionToIpfsMetadata(collection); const { car, ...ipfs } = await downloadMediaAndPackCar( collection.uid, @@ -106,55 +118,75 @@ const uploadCollectionMedia = async (collection: Collection) => { ); await putCar(car); - await collectionDocRef.update({ mediaStatus: MediaStatus.UPLOADED, ...ipfs }); + await collectionDocRef.update({ + mediaStatus: PgMediaStatus.UPLOADED, + ipfsMedia: ipfs.ipfsMedia, + ipfsMetadata: ipfs.ipfsMetadata, + ipfsRoot: ipfs.ipfsRoot, + }); }; const uploadAwardMedia = async (award: Award) => { if (!award.badge.image) { return; } - const awardDocRef = build5Db().doc(`${COL.AWARD}/${award.uid}`); + + const awardDocRef = build5Db().doc(COL.AWARD, award.uid); const metadata = awardToIpfsMetadata(award); const { car, ...ipfs } = await downloadMediaAndPackCar(award.uid, award.badge.image, metadata); await putCar(car); - await awardDocRef.update({ mediaStatus: MediaStatus.UPLOADED, ...ipfs }); + await awardDocRef.update({ + mediaStatus: PgMediaStatus.UPLOADED, + badge_ipfsMedia: ipfs.ipfsMedia, + badge_ipfsMetadata: ipfs.ipfsMetadata, + badge_ipfsRoot: ipfs.ipfsRoot, + }); }; const uploadSpaceMedia = async (space: Space) => { - const spaceDocRef = build5Db().doc(`${COL.SPACE}/${space.uid}`); + const spaceDocRef = build5Db().doc(COL.SPACE, space.uid); const metadata = spaceToIpfsMetadata(space); const { car, ...ipfs } = await downloadMediaAndPackCar(space.uid, space.bannerUrl!, metadata); await putCar(car); - await spaceDocRef.update({ mediaStatus: MediaStatus.UPLOADED, ...ipfs }); + await spaceDocRef.update({ + mediaStatus: PgMediaStatus.UPLOADED, + ipfsMedia: ipfs.ipfsMedia, + ipfsMetadata: ipfs.ipfsMetadata, + ipfsRoot: ipfs.ipfsRoot, + }); }; const uploadStampMedia = async (stamp: Stamp) => { - const stampDocRef = build5Db().doc(`${COL.STAMP}/${stamp.uid}`); + const stampDocRef = build5Db().doc(COL.STAMP, stamp.uid); const { car, ...ipfs } = await downloadMediaAndPackCar(stamp.uid, stamp.build5Url); await putCar(car); - stampDocRef.update({ - mediaStatus: MediaStatus.UPLOADED, + await stampDocRef.update({ + mediaStatus: PgMediaStatus.UPLOADED, ipfsMedia: ipfs.ipfsMedia, ipfsRoot: ipfs.ipfsRoot, }); }; -const pendingUploadQuery = (col: COL, batchSize: number) => - build5Db() - .collection(col) - .where('mediaStatus', '==', MediaStatus.PENDING_UPLOAD) +const pendingUploadQuery = (col: ColWithMedia, batchSize: number) => + (build5Db().collection(col) as ICollection) + .where('mediaStatus', '==', PgMediaStatus.PENDING_UPLOAD) .limit(batchSize); -const setMediaStatusToError = async (col: COL, uid: string, errorCount: number, error: unknown) => { +const setMediaStatusToError = async ( + col: ColWithMedia, + uid: string, + errorCount: number, + error: unknown, +) => { const data = { mediaUploadErrorCount: build5Db().inc(1), - mediaStatus: MediaStatus.PENDING_UPLOAD, + mediaStatus: PgMediaStatus.PENDING_UPLOAD, }; if (errorCount >= MAX_WALLET_RETRY) { - data.mediaStatus = MediaStatus.ERROR; + data.mediaStatus = PgMediaStatus.ERROR; console.error('Image upload error', col, uid, error); } - const docRef = build5Db().doc(`${col}/${uid}`); + const docRef = build5Db().doc(col, uid); await docRef.update(data); }; diff --git a/packages/functions/src/cron/nft.cron.ts b/packages/functions/src/cron/nft.cron.ts index 5b105c05ff..04c432e2f8 100644 --- a/packages/functions/src/cron/nft.cron.ts +++ b/packages/functions/src/cron/nft.cron.ts @@ -1,5 +1,5 @@ import { build5Db } from '@build-5/database'; -import { COL, Nft } from '@build-5/interfaces'; +import { COL } from '@build-5/interfaces'; import dayjs from 'dayjs'; export const hidePlaceholderAfterSoldOutCron = async () => { @@ -10,7 +10,7 @@ export const hidePlaceholderAfterSoldOutCron = async () => { .where('availableFrom', '==', null) .where('hidden', '==', false) .where('owner', '==', null) - .get(); + .get(); for (const nft of snap) { if ( nft.soldOn && diff --git a/packages/functions/src/cron/nftStake.cron.ts b/packages/functions/src/cron/nftStake.cron.ts index 1ef8e04c61..6cebb5e2a6 100644 --- a/packages/functions/src/cron/nftStake.cron.ts +++ b/packages/functions/src/cron/nftStake.cron.ts @@ -1,38 +1,25 @@ -import { build5Db, getSnapshot } from '@build-5/database'; -import { COL, NftStake } from '@build-5/interfaces'; +import { build5Db } from '@build-5/database'; +import { COL } from '@build-5/interfaces'; import dayjs from 'dayjs'; -import { last } from 'lodash'; export const processExpiredNftStakes = async () => { - let lastDocId = ''; - do { - const query = await getExpiredNftStakesQuery(lastDocId); - const snap = await query.get(); - lastDocId = last(snap)?.uid || ''; - - const promises = snap.map((stake) => processExpiredNftStake(stake.uid)); - await Promise.all(promises); - } while (lastDocId); -}; - -const getExpiredNftStakesQuery = async (lastDocId = '') => { - const lastDoc = await getSnapshot(COL.NFT_STAKE, lastDocId); - return build5Db() + const snap = await build5Db() .collection(COL.NFT_STAKE) .where('expiresAt', '<=', dayjs().toDate()) .where('expirationProcessed', '==', false) - .startAfter(lastDoc) - .limit(1000); + .get(); + const promises = snap.map((stake) => processExpiredNftStake(stake.uid)); + await Promise.all(promises); }; -const processExpiredNftStake = async (nftStakeId: string) => +const processExpiredNftStake = (nftStakeId: string) => build5Db().runTransaction(async (transaction) => { - const nftStakeDocRef = build5Db().doc(`${COL.NFT_STAKE}/${nftStakeId}`); - const nftStake = (await transaction.get(nftStakeDocRef))!; + const nftStakeDocRef = build5Db().doc(COL.NFT_STAKE, nftStakeId); + const nftStake = (await transaction.get(nftStakeDocRef))!; if (!nftStake.expirationProcessed) { - const collectionDocRef = build5Db().doc(`${COL.COLLECTION}/${nftStake.collection}`); - transaction.update(collectionDocRef, { stakedNft: build5Db().inc(-1) }); - transaction.update(nftStakeDocRef, { expirationProcessed: true }); + const collectionDocRef = build5Db().doc(COL.COLLECTION, nftStake.collection); + await transaction.update(collectionDocRef, { stakedNft: build5Db().inc(-1) }); + await transaction.update(nftStakeDocRef, { expirationProcessed: true }); } }); diff --git a/packages/functions/src/cron/orders.cron.ts b/packages/functions/src/cron/orders.cron.ts index 9b1c7cbe96..1eaf8c7427 100644 --- a/packages/functions/src/cron/orders.cron.ts +++ b/packages/functions/src/cron/orders.cron.ts @@ -1,5 +1,5 @@ -import { build5Db } from '@build-5/database'; -import { COL, Transaction, TransactionType } from '@build-5/interfaces'; +import { PgTransactionType, build5Db } from '@build-5/database'; +import { COL } from '@build-5/interfaces'; import dayjs from 'dayjs'; import { NftPurchaseService } from '../services/payment/nft/nft-purchase.service'; import { TransactionService } from '../services/payment/transaction-service'; @@ -7,21 +7,21 @@ import { TransactionService } from '../services/payment/transaction-service'; export const voidExpiredOrdersCron = async () => { const transactions = await build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.ORDER) - .where('payload.void', '==', false) - .where('payload.reconciled', '==', false) - .where('payload.expiresOn', '<=', dayjs().toDate()) - .get(); + .where('type', '==', PgTransactionType.ORDER) + .where('payload_void', '==', false) + .where('payload_reconciled', '==', false) + .where('payload_expiresOn', '<=', dayjs().toDate()) + .get(); for (const tran of transactions) { await build5Db().runTransaction(async (transaction) => { - const tranDocRef = build5Db().doc(`${COL.TRANSACTION}/${tran.uid}`); - const tranData = (await transaction.get(tranDocRef))!; + const tranDocRef = build5Db().doc(COL.TRANSACTION, tran.uid); + const tranData = (await transaction.get(tranDocRef))!; const tranService = new TransactionService(transaction); const service = new NftPurchaseService(tranService); await service.markAsVoid(tranData); - tranService.submit(); + await tranService.submit(); }); } diff --git a/packages/functions/src/cron/proposal.cron.ts b/packages/functions/src/cron/proposal.cron.ts index ff2643772f..c25bb27289 100644 --- a/packages/functions/src/cron/proposal.cron.ts +++ b/packages/functions/src/cron/proposal.cron.ts @@ -1,5 +1,5 @@ import { build5Db } from '@build-5/database'; -import { COL, Proposal } from '@build-5/interfaces'; +import { COL } from '@build-5/interfaces'; import dayjs from 'dayjs'; export const markExpiredProposalCompleted = async () => { @@ -8,16 +8,16 @@ export const markExpiredProposalCompleted = async () => { const snap = await build5Db() .collection(COL.PROPOSAL) .where('completed', '==', false) - .where('settings.endDate', '<', dayjs().toDate()) + .where('settings_endDate', '<', dayjs().toDate()) .limit(500) - .get(); + .get(); size = snap.length; const batch = build5Db().batch(); - snap.forEach((proposal) => { - const proposalDocRef = build5Db().doc(`${COL.PROPOSAL}/${proposal.uid}`); + for (const proposal of snap) { + const proposalDocRef = build5Db().doc(COL.PROPOSAL, proposal.uid); batch.update(proposalDocRef, { completed: true }); - }); + } await batch.commit(); } while (size); }; diff --git a/packages/functions/src/cron/stake.cron.ts b/packages/functions/src/cron/stake.cron.ts index 5bbd682df0..78c0412de6 100644 --- a/packages/functions/src/cron/stake.cron.ts +++ b/packages/functions/src/cron/stake.cron.ts @@ -1,36 +1,23 @@ -import { build5Db, getSnapshot } from '@build-5/database'; -import { COL, Stake, SUB_COL } from '@build-5/interfaces'; +import { build5Db } from '@build-5/database'; +import { COL, SUB_COL } from '@build-5/interfaces'; import dayjs from 'dayjs'; -import { last } from 'lodash'; import { onStakeExpired } from '../services/stake.service'; -import { dateToTimestamp } from '../utils/dateTime.utils'; export const removeExpiredStakesFromSpace = async () => { - let lastDocId = ''; - do { - const query = await getExpiredStakeQuery(lastDocId); - const snap = await query.get(); - lastDocId = last(snap)?.uid || ''; - - const promises = snap.map((d) => updateTokenStakeStats(d.uid)); - await Promise.all(promises); - } while (lastDocId); -}; - -const getExpiredStakeQuery = async (lastDocId = '') => { - const lastDoc = await getSnapshot(COL.STAKE, lastDocId); - return build5Db() + const snap = await build5Db() .collection(COL.STAKE) - .where('expiresAt', '<=', dateToTimestamp(dayjs().toDate())) + .where('expiresAt', '<=', dayjs().toDate()) .where('expirationProcessed', '==', false) - .startAfter(lastDoc) - .limit(1000); + .get(); + + const promises = snap.map((d) => updateTokenStakeStats(d.uid)); + await Promise.all(promises); }; -const updateTokenStakeStats = async (stakeId: string) => +const updateTokenStakeStats = (stakeId: string) => build5Db().runTransaction(async (transaction) => { - const stakeDocRef = build5Db().doc(`${COL.STAKE}/${stakeId}`); - const stake = await transaction.get(stakeDocRef); + const stakeDocRef = build5Db().doc(COL.STAKE, stakeId); + const stake = (await transaction.get(stakeDocRef))!; if (stake.expirationProcessed) { return; } @@ -38,27 +25,20 @@ const updateTokenStakeStats = async (stakeId: string) => await onStakeExpired(transaction, stake); const updateData = { - stakes: { - [stake.type]: { - amount: build5Db().inc(-stake.amount), - value: build5Db().inc(-stake.value), - }, - }, - stakeExpiry: { - [stake.type]: { - [stake.expiresAt.toMillis()]: build5Db().deleteField(), - }, - }, + [`stakes_${stake.type}_amount`]: build5Db().inc(-stake.amount), + [`stakes_${stake.type}_value`]: build5Db().inc(-stake.value), + stakeExpiry: { [stake.type]: { [stake.expiresAt.toMillis()]: null } }, }; - const spaceDocRef = build5Db().doc( - `${COL.TOKEN}/${stake.token}/${SUB_COL.STATS}/${stake.token}`, - ); - transaction.set(spaceDocRef, updateData, true); - - const spaceMemberDocRef = build5Db().doc( - `${COL.TOKEN}/${stake.token}/${SUB_COL.DISTRIBUTION}/${stake.member}`, + const spaceDocRef = build5Db().doc(COL.TOKEN, stake.token, SUB_COL.STATS, stake.token); + await transaction.upsert(spaceDocRef, updateData); + + const distributionDocRef = build5Db().doc( + COL.TOKEN, + stake.token, + SUB_COL.DISTRIBUTION, + stake.member, ); - transaction.set(spaceMemberDocRef, updateData, true); + await transaction.upsert(distributionDocRef, updateData); - transaction.update(stakeDocRef, { expirationProcessed: true }); + await transaction.update(stakeDocRef, { expirationProcessed: true }); }); diff --git a/packages/functions/src/cron/stakeReward.cron.ts b/packages/functions/src/cron/stakeReward.cron.ts index dea051984f..ff995cb866 100644 --- a/packages/functions/src/cron/stakeReward.cron.ts +++ b/packages/functions/src/cron/stakeReward.cron.ts @@ -1,93 +1,61 @@ -import { build5Db, getSnapshot } from '@build-5/database'; +import { PgStakeRewardStatus, build5Db } from '@build-5/database'; import { COL, Entity, IgnoreWalletReason, SUB_COL, Space, - Stake, StakeReward, - StakeRewardStatus, StakeType, Token, - TokenDistribution, TokenDrop, TokenDropStatus, Transaction, TransactionType, } from '@build-5/interfaces'; import dayjs from 'dayjs'; -import { isEmpty, last } from 'lodash'; +import { isEmpty } from 'lodash'; import { getProject } from '../utils/common.utils'; -import { serverTime } from '../utils/dateTime.utils'; import { getRandomEthAddress } from '../utils/wallet.utils'; export const onStakeRewardExpired = async () => { const stakeRewards = await getDueStakeRewards(); for (const stakeReward of stakeRewards) { - const stakeRewardDocRef = build5Db().doc(`${COL.STAKE_REWARD}/${stakeReward.uid}`); - await stakeRewardDocRef.update({ status: StakeRewardStatus.PROCESSED }); + const stakeRewardDocRef = build5Db().doc(COL.STAKE_REWARD, stakeReward.uid); + await stakeRewardDocRef.update({ status: PgStakeRewardStatus.PROCESSED }); try { const { totalAirdropped, totalStaked } = await executeStakeRewardDistribution(stakeReward); await stakeRewardDocRef.update({ totalStaked, totalAirdropped }); } catch (error) { console.error('Stake reward error', stakeReward.uid, error); - await stakeRewardDocRef.update({ status: StakeRewardStatus.ERROR }); + await stakeRewardDocRef.update({ status: PgStakeRewardStatus.ERROR }); } } }; const executeStakeRewardDistribution = async (stakeReward: StakeReward) => { - const stakedPerMember = await getStakedPerMember(stakeReward); + const stakedPerMember = await build5Db().collection(COL.STAKE).getStakeSumPerMember(stakeReward); if (isEmpty(stakedPerMember)) { await build5Db() - .doc(`${COL.STAKE_REWARD}/${stakeReward.uid}`) - .update({ status: StakeRewardStatus.PROCESSED_NO_STAKES }); + .doc(COL.STAKE_REWARD, stakeReward.uid) + .update({ status: PgStakeRewardStatus.PROCESSED_NO_STAKES }); return { totalStaked: 0, totalAirdropped: 0 }; } const totalStaked = Object.values(stakedPerMember).reduce((acc, act) => acc + act, 0); - const token = await build5Db().doc(`${COL.TOKEN}/${stakeReward.token}`).get(); + const token = await build5Db().doc(COL.TOKEN, stakeReward.token).get(); const totalAirdropped = await createAirdrops(token, stakeReward, totalStaked, stakedPerMember); return { totalStaked, totalAirdropped }; }; -export const getStakedPerMember = async (stakeReward: StakeReward) => { - const stakedPerMember: { [key: string]: number } = {}; - let lastDocId = ''; - const rewardEndDate = stakeReward.endDate.toDate(); - do { - const lastDoc = await getSnapshot(COL.STAKE, lastDocId); - const snap = await build5Db() - .collection(COL.STAKE) - .where('token', '==', stakeReward.token) - .where('type', '==', StakeType.DYNAMIC) - .where('expiresAt', '>=', stakeReward.startDate) - .orderBy('expiresAt') - .startAfter(lastDoc) - .limit(2000) - .select('createdOn', 'member', 'value') - .get(); - lastDocId = last(snap)?.uid || ''; - snap.forEach((stake) => { - if (dayjs(stake.createdOn?.toDate()).isAfter(rewardEndDate)) { - return; - } - stakedPerMember[stake.member] = (stakedPerMember[stake.member] || 0) + stake.value; - }); - } while (lastDocId); - - return stakedPerMember; -}; - const getDueStakeRewards = () => build5Db() .collection(COL.STAKE_REWARD) - .where('status', '==', StakeRewardStatus.UNPROCESSED) - .where('endDate', '<=', serverTime()) - .get(); + .where('status', '==', PgStakeRewardStatus.UNPROCESSED) + .where('endDate', '<=', dayjs().toDate()) + .get(); const createAirdrops = async ( token: Token, @@ -95,7 +63,7 @@ const createAirdrops = async ( totalStaked: number, stakedPerMember: { [key: string]: number }, ) => { - const space = await build5Db().doc(`${COL.SPACE}/${token.space}`).get(); + const space = await build5Db().doc(COL.SPACE, token.space!).get(); const rewards = Object.entries(stakedPerMember) .map(([member, staked]) => ({ @@ -120,15 +88,16 @@ const createAirdrops = async ( } const distributionDocRef = build5Db().doc( - `${COL.TOKEN}/${token.uid}/${SUB_COL.DISTRIBUTION}/${reward.member}`, + COL.TOKEN, + token.uid, + SUB_COL.DISTRIBUTION, + reward.member, ); - const distribution = await distributionDocRef.get(); + const distribution = await distributionDocRef.get(); if (distribution?.extraStakeRewards && distribution.extraStakeRewards > 0) { await distributionDocRef.update({ parentId: token.uid, - parentCol: COL.TOKEN, - uid: reward.member, extraStakeRewards: build5Db().inc(-reward.value), }); @@ -154,7 +123,7 @@ const createAirdrops = async ( stakeReward: stakeReward.uid, }, }; - await build5Db().doc(`${COL.TRANSACTION}/${billPayment.uid}`).create(billPayment); + await build5Db().doc(COL.TRANSACTION, billPayment.uid).create(billPayment); const remainingExtra = distribution.extraStakeRewards - reward.value; if (remainingExtra >= 0) { @@ -178,19 +147,13 @@ const createAirdrops = async ( stakeType: StakeType.DYNAMIC, }; - const airdropDocRef = build5Db().doc(`${COL.AIRDROP}/${airdrop.uid}`); + const airdropDocRef = build5Db().doc(COL.AIRDROP, airdrop.uid); batch.create(airdropDocRef, airdrop); - batch.set( - distributionDocRef, - { - parentId: token.uid, - parentCol: COL.TOKEN, - uid: reward.member, - stakeRewards: build5Db().inc(reward.value), - }, - true, - ); + batch.upsert(distributionDocRef, { + parentId: token.uid, + stakeRewards: build5Db().inc(reward.value), + }); await batch.commit(); return reward.value; diff --git a/packages/functions/src/cron/stamp.cron.ts b/packages/functions/src/cron/stamp.cron.ts index 939b9d3798..9322606bc2 100644 --- a/packages/functions/src/cron/stamp.cron.ts +++ b/packages/functions/src/cron/stamp.cron.ts @@ -7,12 +7,12 @@ import { getBucket } from '../utils/config.utils'; export const updateExpiredStamp = async () => { let stamps: Stamp[] = []; do { - stamps = await query.get(); + stamps = await query.get(); const batch = build5Db().batch(); - stamps.forEach((s) => { - const docRef = build5Db().doc(`${COL.STAMP}/${s.uid}`); + for (const s of stamps) { + const docRef = build5Db().doc(COL.STAMP, s.uid); batch.update(docRef, { expired: true }); - }); + } await batch.commit(); const promises = stamps.map(async (s) => { diff --git a/packages/functions/src/cron/token.cron.ts b/packages/functions/src/cron/token.cron.ts index d39218887a..4f34edfba1 100644 --- a/packages/functions/src/cron/token.cron.ts +++ b/packages/functions/src/cron/token.cron.ts @@ -1,49 +1,40 @@ -import { build5Db } from '@build-5/database'; -import { - COL, - Token, - TokenStatus, - TokenTradeOrder, - TokenTradeOrderStatus, -} from '@build-5/interfaces'; +import { PgTokenStatus, PgTokenTradeOrderStatus, build5Db } from '@build-5/database'; +import { COL, TokenTradeOrderStatus } from '@build-5/interfaces'; import dayjs from 'dayjs'; import { isEmpty } from 'lodash'; import { guardedRerun } from '../utils/common.utils'; -import { dateToTimestamp, serverTime } from '../utils/dateTime.utils'; import { cancelTradeOrderUtil } from '../utils/token-trade.utils'; export const tokenCoolDownOver = async () => { const tokens = await build5Db() .collection(COL.TOKEN) - .where('status', '==', TokenStatus.AVAILABLE) - .where('coolDownEnd', '<=', dateToTimestamp(dayjs().toDate())) - .get(); - const promises = tokens.map((token) => { - const tokenDocRef = build5Db().doc(`${COL.TOKEN}/${token.uid}`); - tokenDocRef.update({ status: TokenStatus.PROCESSING }); + .where('status', '==', PgTokenStatus.AVAILABLE) + .where('coolDownEnd', '<=', dayjs().toDate()) + .get(); + const promises = tokens.map(async (token) => { + const tokenDocRef = build5Db().doc(COL.TOKEN, token.uid); + await tokenDocRef.update({ status: PgTokenStatus.PROCESSING }); }); return Promise.allSettled(promises); }; export const cancelExpiredSale = async () => { - const runTransaction = () => + const runTransactions = () => build5Db().runTransaction(async (transaction) => { const snap = await build5Db() .collection(COL.TOKEN_MARKET) - .where('status', '==', TokenTradeOrderStatus.ACTIVE) - .where('expiresAt', '<=', serverTime()) + .where('status', '==', PgTokenTradeOrderStatus.ACTIVE) + .where('expiresAt', '<=', dayjs().toDate()) .orderBy('expiresAt') .limit(150) - .get(); - const docRefs = snap.map((order) => build5Db().doc(`${COL.TOKEN_MARKET}/${order.uid}`)); - const promises = ( - isEmpty(docRefs) ? [] : await transaction.getAll(...docRefs) - ) + .get(); + const docRefs = snap.map((order) => build5Db().doc(COL.TOKEN_MARKET, order.uid)); + const promises = (isEmpty(docRefs) ? [] : await transaction.getAll(...docRefs)) .filter((d) => d!.status === TokenTradeOrderStatus.ACTIVE) .map((d) => cancelTradeOrderUtil(transaction, d!, TokenTradeOrderStatus.EXPIRED)); return (await Promise.all(promises)).length; }); - await guardedRerun(async () => (await runTransaction()) !== 0); + await guardedRerun(async () => (await runTransactions()) !== 0); }; diff --git a/packages/functions/src/cron/token.purchase.cron.ts b/packages/functions/src/cron/token.purchase.cron.ts index b88976908a..5e91b1b707 100644 --- a/packages/functions/src/cron/token.purchase.cron.ts +++ b/packages/functions/src/cron/token.purchase.cron.ts @@ -1,5 +1,5 @@ import { build5Db } from '@build-5/database'; -import { COL, SUB_COL, TokenPurchase, TokenPurchaseAge } from '@build-5/interfaces'; +import { COL, SUB_COL, TokenPurchaseAge } from '@build-5/interfaces'; import dayjs from 'dayjs'; import { chunk } from 'lodash'; @@ -15,12 +15,12 @@ const removeExiredPurchaseFromStats = async (age: TokenPurchaseAge) => { for (const purchases of chunks) { const batch = build5Db().batch(); for (const purchase of purchases) { - const docRef = build5Db().doc(`${COL.TOKEN_PURCHASE}/${purchase.uid}`); - batch.set(docRef, { age: build5Db().arrayRemove(age) }, true); + const docRef = build5Db().doc(COL.TOKEN_PURCHASE, purchase.uid); + batch.update(docRef, { [age]: false }); const token = purchase.token; - const statsDocRef = build5Db().doc(`${COL.TOKEN}/${token}/${SUB_COL.STATS}/${token}`); - batch.set(statsDocRef, { volume: { [age]: build5Db().inc(-purchase.count) } }, true); + const statsDocRef = build5Db().doc(COL.TOKEN, token, SUB_COL.STATS, token); + batch.upsert(statsDocRef, { [`volume_${age}`]: build5Db().inc(-purchase.count) }); } await batch.commit(); } @@ -31,9 +31,9 @@ const getExpiredPurchases = (age: TokenPurchaseAge) => { const createdBefore = dayjs().subtract(days, 'd').toDate(); return build5Db() .collection(COL.TOKEN_PURCHASE) - .where('age', 'array-contains', age) + .where(age, '==', true) .where('createdOn', '<=', createdBefore) - .get(); + .get(); }; const toknePurchaseAgeToDayCount = (age: TokenPurchaseAge) => { diff --git a/packages/functions/src/cron/wallet.cron.ts b/packages/functions/src/cron/wallet.cron.ts index 8bab48bca0..1248dbb7a8 100644 --- a/packages/functions/src/cron/wallet.cron.ts +++ b/packages/functions/src/cron/wallet.cron.ts @@ -11,8 +11,8 @@ export const retryWallet = async () => { const snap = await getFailedTransactionsSnap(); const promises = snap.map((doc) => build5Db().runTransaction(async (transaction) => { - const docRef = build5Db().doc(`${COL.TRANSACTION}/${doc.uid}`); - const tran = (await transaction.get(docRef))!; + const docRef = build5Db().doc(COL.TRANSACTION, doc.uid); + const tran = (await transaction.get(docRef))!; return await rerunTransaction(transaction, tran); }), ); @@ -20,7 +20,7 @@ export const retryWallet = async () => { }; const rerunTransaction = async (transaction: ITransaction, data: Transaction) => { - const docRef = build5Db().doc(`${COL.TRANSACTION}/${data.uid}`); + const docRef = build5Db().doc(COL.TRANSACTION, data.uid); const walletReference = data.payload.walletReference!; const processedOn = dayjs(walletReference.processedOn.toDate()); const delay = RETRY_UNCOFIRMED_PAYMENT_DELAY[(walletReference.count || 1) - 1]; @@ -30,8 +30,8 @@ const rerunTransaction = async (transaction: ITransaction, data: Transaction) => } if (walletReference.count === MAX_WALLET_RETRY) { - const sourceMnemonicDocRef = build5Db().doc(`${COL.MNEMONIC}/${data.payload.sourceAddress}`); - transaction.update(sourceMnemonicDocRef, { + const sourceMnemonicDocRef = build5Db().doc(COL.MNEMONIC, data.payload.sourceAddress!); + await transaction.update(sourceMnemonicDocRef, { lockedBy: '', consumedOutputIds: [], consumedNftOutputIds: [], @@ -39,35 +39,34 @@ const rerunTransaction = async (transaction: ITransaction, data: Transaction) => }); if (data.payload.storageDepositSourceAddress) { const storageSourceDocRef = build5Db().doc( - `${COL.MNEMONIC}/${data.payload.storageDepositSourceAddress}`, + COL.MNEMONIC, + data.payload.storageDepositSourceAddress, ); - transaction.update(storageSourceDocRef, { + await transaction.update(storageSourceDocRef, { lockedBy: '', consumedOutputIds: [], consumedNftOutputIds: [], consumedAliasOutputIds: [], }); } - transaction.update(docRef, { - 'payload.walletReference.chainReference': null, - 'payload.walletReference.inProgress': false, - 'payload.walletReference.count': build5Db().inc(1), + await transaction.update(docRef, { + payload_walletReference_chainReference: undefined, + payload_walletReference_inProgress: false, + payload_walletReference_count: build5Db().inc(1), shouldRetry: false, }); } - transaction.update(docRef, { - 'payload.walletReference.chainReference': null, + await transaction.update(docRef, { + payload_walletReference_chainReference: undefined, shouldRetry: true, }); return data.uid; }; -const COUNT_IN = Array.from(Array(MAX_WALLET_RETRY + 1)).map((_, i) => i); - const getFailedTransactionsSnap = () => build5Db() .collection(COL.TRANSACTION) - .where('payload.walletReference.confirmed', '==', false) - .where('payload.walletReference.inProgress', '==', true) - .where('payload.walletReference.count', 'in', COUNT_IN) - .get(); + .where('payload_walletReference_confirmed', '==', false) + .where('payload_walletReference_inProgress', '==', true) + .where('payload_walletReference_count', '<=', MAX_WALLET_RETRY) + .get(); diff --git a/packages/functions/src/index.express.ts b/packages/functions/src/index.express.ts deleted file mode 100644 index 4eab507c2d..0000000000 --- a/packages/functions/src/index.express.ts +++ /dev/null @@ -1,101 +0,0 @@ -/* eslint-disable import/namespace */ -/* eslint-disable @typescript-eslint/no-var-requires */ -require('dotenv').config({ path: __dirname + '/.env' }); -import { WEN_FUNC } from '@build-5/interfaces'; -import { HTTP } from 'cloudevents'; -import cors from 'cors'; -import express from 'express'; -import { get } from 'lodash'; -import { loadSync } from 'protobufjs'; -import { flattenObject } from './common'; -import { pathToParts } from './runtime/common'; -import * as onScheduled from './runtime/cron/index'; -import { ScheduledFunction } from './runtime/cron/scheduled'; -import { HttpsFunction } from './runtime/https/https'; -import * as onRequests from './runtime/https/index'; -import { protoToJson } from './runtime/proto/protoToJson'; -import * as onStorage from './runtime/storage/index'; -import { StorageFunction } from './runtime/storage/storage'; -import * as onTriggers from './runtime/trigger/index'; -import { TriggeredFunction } from './runtime/trigger/trigger'; - -const app = express(); - -app.use(cors()); - -const httpRawParser = express.raw({ type: '*/*', limit: '100mb' }); -const protoRawParser = express.raw({ type: 'application/protobuf', limit: '2mb' }); -const jsonParser = express.json(); - -// HTTPS -Object.entries(flattenObject(onRequests)).forEach(([name, config]) => { - app.post(`/${name}`, name === WEN_FUNC.uploadFile ? httpRawParser : jsonParser, (req, res) => - (config as HttpsFunction).func(req, res), - ); -}); - -// TRIGGERS -Object.entries(flattenObject(onTriggers)).forEach(([name, config]) => { - app.post(`/${name}`, protoRawParser, async (req, res) => { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - let json: { [key: string]: any } = {}; - try { - const root = loadSync('./data.proto'); - const type = root.lookupType('DocumentEventData'); - const decoded = type.decode(req.body); - json = protoToJson(decoded); - const cloudEvent = HTTP.toEvent({ - headers: req.headers, - body: {}, - }); - const event = { - prev: json.oldValue?.fields, - curr: json.value?.fields, - path: get(cloudEvent, 'document', ''), - ...pathToParts(get(cloudEvent, 'document', '')), - }; - await (config as TriggeredFunction).handler(event); - } catch (error) { - console.error('onTriggers-error', name, JSON.stringify(json), error); - } finally { - res.sendStatus(200); - } - }); -}); - -// CRON -Object.entries(flattenObject(onScheduled)).forEach(([name, config]) => { - app.post(`/${name}`, async (_, res) => { - try { - await (config as ScheduledFunction).func(); - } catch (error) { - console.error('onScheduled-error', name, error); - } finally { - res.sendStatus(200); - } - }); -}); - -// Storage -Object.entries(flattenObject(onStorage)).forEach(([name, config]) => { - app.post(`/${name}`, express.json(), async (req, res) => { - try { - const event = HTTP.toEvent({ - headers: req.headers, - body: req.body, - }); - await (config as StorageFunction).func({ - metadata: get(event, 'data.metadata'), - name: get(event, 'data.name', ''), - bucket: get(event, 'data.bucket', ''), - contentType: get(event, 'data.contentType'), - }); - } catch (error) { - console.error('onStorage-error', name, error); - } finally { - res.sendStatus(200); - } - }); -}); - -app.listen(8080).setTimeout(0); diff --git a/packages/functions/src/index.ts b/packages/functions/src/index.ts index fedcfa1040..6fa4396642 100644 --- a/packages/functions/src/index.ts +++ b/packages/functions/src/index.ts @@ -1,71 +1,140 @@ -/* eslint-disable @typescript-eslint/no-explicit-any */ /* eslint-disable import/namespace */ -import * as functions from 'firebase-functions/v2'; +/* eslint-disable @typescript-eslint/no-var-requires */ +require('dotenv').config({ path: __dirname + '/.env' }); +import { BaseRecord, build5Db } from '@build-5/database'; +import { WEN_FUNC } from '@build-5/interfaces'; +import cors from 'cors'; +import dayjs from 'dayjs'; +import express from 'express'; +import { get } from 'lodash'; import { flattenObject } from './common'; -import { CloudFunctions, pathToParts } from './runtime/common'; +import * as onScheduled from './runtime/cron/index'; +import { ScheduledFunction } from './runtime/cron/scheduled'; import { HttpsFunction } from './runtime/https/https'; import * as onRequests from './runtime/https/index'; import * as onStorage from './runtime/storage/index'; import { StorageFunction } from './runtime/storage/storage'; import * as onTriggers from './runtime/trigger/index'; -import { TriggeredFunction, TriggeredFunctionType } from './runtime/trigger/trigger'; +import { TriggeredFunction } from './runtime/trigger/trigger'; +import { tangleClients } from './services/wallet/wallet.service'; +import { PgDocEvent } from './triggers/common'; +import { isEmulatorEnv } from './utils/config.utils'; -// On request functions -const toOnRequest = (config: HttpsFunction) => - functions.https.onRequest((req, res) => config.func(req, res)); +const app = express(); -export const https = Object.entries(flattenObject(onRequests)).reduce( - (acc, [name, config]) => ({ ...acc, [name]: toOnRequest(config as HttpsFunction) }), - {} as any, -); +app.use(cors()); -// Trigger functions -const getFirestoreHandler = (config: TriggeredFunction) => { - const triggerConfig = { - document: config.document, - timeoutSeconds: config.runtimeOptions.timeoutSeconds, - }; - if (config.type === TriggeredFunctionType.ON_CREATE) { - return functions.firestore.onDocumentCreated(triggerConfig, async (event) => { - const data = { - curr: event.data?.data(), - path: event.document, - ...pathToParts(event.document), +const httpRawParser = express.raw({ type: '*/*', limit: '100mb' }); +const jsonParser = express.json(); + +const loggingMiddleware = (name: string) => + isEmulatorEnv() + ? (_req: express.Request, res: express.Response, next: express.NextFunction) => { + const start = dayjs(); + console.log(`Beginning ${name}`); + next(); + res.once('finish', () => { + const end = dayjs(); + console.log(`Finished ${name} in ${end.diff(start)} ms`); + }); + } + : (_req: express.Request, _res: express.Response, next: express.NextFunction) => { + next(); }; - await config.handler(data); - }); - } - const firestoreFunc = - config.type === TriggeredFunctionType.ON_UPDATE - ? functions.firestore.onDocumentUpdated - : functions.firestore.onDocumentWritten; - return firestoreFunc(triggerConfig, async (event) => { - const data = { - prev: event.data?.before?.data(), - curr: event.data?.after?.data(), - path: event.document, - ...pathToParts(event.document), - }; - await config.handler(data); + +// HTTPS +Object.entries(flattenObject(onRequests)).forEach(([name, config]) => { + app.post( + `/${name}`, + name === WEN_FUNC.uploadFile ? httpRawParser : jsonParser, + loggingMiddleware(name), + (req, res) => (config as HttpsFunction).func(req, res), + ); +}); + +// TRIGGERS +Object.entries(flattenObject(onTriggers)).forEach(([name, config]) => { + app.post(`/${name}`, jsonParser, loggingMiddleware(name), async (req, res) => { + const pubSubMessage = req.body.message.data; + const raw = Buffer.from(pubSubMessage, 'base64').toString().trim(); + const processId = JSON.parse(raw).processId; + try { + const snap = await build5Db().getCon()('changes').first().where({ uid: processId }); + await (config as TriggeredFunction).handler({ + ...snap.change, + prev: snap.change.prev || undefined, + curr: snap.change.curr || undefined, + } as PgDocEvent); + } catch (error) { + console.error('onTriggers-error', name, error); + } finally { + await build5Db().getCon()('changes').delete().where({ uid: processId }); + res.sendStatus(200); + } }); -}; -export const triggers = Object.entries(flattenObject(onTriggers)).reduce( - (acc, [key, config]) => ({ ...acc, [key]: getFirestoreHandler(config) }), - {} as any, -); +}); + +// CRON +Object.entries(flattenObject(onScheduled)).forEach(([name, config]) => { + app.post(`/${name}`, async (_, res) => { + try { + await (config as ScheduledFunction).func(); + } catch (error) { + console.error('onScheduled-error', name, error); + } finally { + res.sendStatus(200); + } + }); +}); // Storage -export const stroage = Object.entries(flattenObject(onStorage)).reduce((acc, [name, value]) => { - const config = (value as CloudFunctions).runtimeOptions; - return { - ...acc, - [name]: functions.storage.onObjectFinalized({ bucket: config.bucket! }, (event) => - (value as StorageFunction).func({ - metadata: event.data.metadata, - name: event.data.name, - bucket: event.data.bucket, - contentType: event.data.contentType, - }), - ), - }; -}, {} as any); +Object.entries(flattenObject(onStorage)).forEach(([name, config]) => { + app.post(`/${name}`, jsonParser, loggingMiddleware(name), async (req, res) => { + try { + await (config as StorageFunction).func({ + metadata: get(req, 'body.metadata'), + name: get(req, 'body.name', ''), + bucket: get(req, 'body.bucket', ''), + contentType: get(req, 'body.contentType'), + }); + } catch (error) { + console.error('onStorage-error', name, error); + } finally { + res.sendStatus(200); + } + }); +}); + +app.on('close', async () => { + await build5Db().destroy(); +}); + +const server = app.listen(8080).setTimeout(0); + +process.on('exit', async () => { + await cleanup(); +}); + +process.on('SIGINT', () => { + server.close(async () => { + await cleanup(); + process.exit(0); + }); +}); + +process.on('uncaughtException', async () => { + await cleanup(); + process.exit(1); +}); + +process.on('unhandledRejection', async () => { + await cleanup(); + process.exit(1); +}); + +const cleanup = async () => { + await build5Db().destroy(); + for (const client of Object.values(tangleClients)) { + await client.destroy(); + } +}; diff --git a/packages/functions/src/runtime/common.ts b/packages/functions/src/runtime/common.ts index 24656650ea..79a43fb09c 100644 --- a/packages/functions/src/runtime/common.ts +++ b/packages/functions/src/runtime/common.ts @@ -1,7 +1,7 @@ import { COL, SUB_COL } from '@build-5/interfaces'; export enum WEN_FUNC_TRIGGER { - onProposalWrite = 'onproposaluwrite', + onProposalWrite = 'onproposalwrite', onAwardUpdated = 'onawardupdated', onCollectionUpdated = 'oncollectionupdated', onTokenStatusUpdated = 'ontokenstatusupdated', diff --git a/packages/functions/src/runtime/firebase/address/index.ts b/packages/functions/src/runtime/firebase/address/index.ts deleted file mode 100644 index 71b1832c5d..0000000000 --- a/packages/functions/src/runtime/firebase/address/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -import { WEN_FUNC } from '@build-5/interfaces'; -import { https } from '../../..'; - -export const validateAddress = https[WEN_FUNC.validateAddress]; diff --git a/packages/functions/src/runtime/firebase/auction/index.ts b/packages/functions/src/runtime/firebase/auction/index.ts deleted file mode 100644 index 22975354e3..0000000000 --- a/packages/functions/src/runtime/firebase/auction/index.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { WEN_FUNC } from '@build-5/interfaces'; -import { https } from '../../..'; - -export const auctionCreate = https[WEN_FUNC.createauction]; - -export const bidAuction = https[WEN_FUNC.bidAuction]; diff --git a/packages/functions/src/runtime/firebase/auth/index.ts b/packages/functions/src/runtime/firebase/auth/index.ts deleted file mode 100644 index f931291c29..0000000000 --- a/packages/functions/src/runtime/firebase/auth/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -import { WEN_FUNC } from '@build-5/interfaces'; -import { https } from '../../..'; - -export const generateCustomToken = https[WEN_FUNC.generateCustomToken]; diff --git a/packages/functions/src/runtime/firebase/award/index.ts b/packages/functions/src/runtime/firebase/award/index.ts deleted file mode 100644 index 95f2197719..0000000000 --- a/packages/functions/src/runtime/firebase/award/index.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { WEN_FUNC } from '@build-5/interfaces'; -import { https } from '../../..'; - -export const createAward = https[WEN_FUNC.createAward]; -export const addOwnerAward = https[WEN_FUNC.addOwnerAward]; -export const fundAward = https[WEN_FUNC.fundAward]; -export const rejectAward = https[WEN_FUNC.rejectAward]; -export const cancelAward = https[WEN_FUNC.cancelAward]; -export const awardParticipate = https[WEN_FUNC.participateAward]; -export const approveAwardParticipant = https[WEN_FUNC.approveParticipantAward]; diff --git a/packages/functions/src/runtime/firebase/collection/index.ts b/packages/functions/src/runtime/firebase/collection/index.ts deleted file mode 100644 index e312fe2986..0000000000 --- a/packages/functions/src/runtime/firebase/collection/index.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { WEN_FUNC } from '@build-5/interfaces'; -import { https } from '../../..'; - -export const createCollection = https[WEN_FUNC.createCollection]; -export const updateCollection = https[WEN_FUNC.updateCollection]; -export const rejectCollection = https[WEN_FUNC.rejectCollection]; -export const mintCollection = https[WEN_FUNC.mintCollection]; diff --git a/packages/functions/src/runtime/firebase/credit/index.ts b/packages/functions/src/runtime/firebase/credit/index.ts deleted file mode 100644 index 959dfd69e5..0000000000 --- a/packages/functions/src/runtime/firebase/credit/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -import { WEN_FUNC } from '@build-5/interfaces'; -import { https } from '../../..'; - -export const creditUnrefundable = https[WEN_FUNC.creditUnrefundable]; diff --git a/packages/functions/src/runtime/firebase/member/index.ts b/packages/functions/src/runtime/firebase/member/index.ts deleted file mode 100644 index a4be6082ea..0000000000 --- a/packages/functions/src/runtime/firebase/member/index.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { WEN_FUNC } from '@build-5/interfaces'; -import { https } from '../../..'; - -export const createMember = https[WEN_FUNC.createMember]; -export const updateMember = https[WEN_FUNC.updateMember]; diff --git a/packages/functions/src/runtime/firebase/nft/index.ts b/packages/functions/src/runtime/firebase/nft/index.ts deleted file mode 100644 index 1140e422a5..0000000000 --- a/packages/functions/src/runtime/firebase/nft/index.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { WEN_FUNC } from '@build-5/interfaces'; -import { https } from '../../..'; - -export const createNft = https[WEN_FUNC.createNft]; - -export const createBatchNft = https[WEN_FUNC.createBatchNft]; - -export const updateUnsoldNft = https[WEN_FUNC.updateUnsoldNft]; -export const setForSaleNft = https[WEN_FUNC.setForSaleNft]; - -export const withdrawNft = https[WEN_FUNC.withdrawNft]; - -export const depositNft = https[WEN_FUNC.depositNft]; - -export const orderNft = https[WEN_FUNC.orderNft]; - -export const orderNftBulk = https[WEN_FUNC.orderNftBulk]; - -export const stakeNft = https[WEN_FUNC.stakeNft]; - -export const openBid = https[WEN_FUNC.openBid]; - -export const nftTransfer = https[WEN_FUNC.nftTransfer]; - -export const mintMetadataNft = https[WEN_FUNC.mintMetadataNft]; diff --git a/packages/functions/src/runtime/firebase/project/index.ts b/packages/functions/src/runtime/firebase/project/index.ts deleted file mode 100644 index f125e76c37..0000000000 --- a/packages/functions/src/runtime/firebase/project/index.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { WEN_FUNC } from '@build-5/interfaces'; -import { https } from '../../..'; - -export const createProject = https[WEN_FUNC.createProject]; -export const deactivateProject = https[WEN_FUNC.deactivateProject]; diff --git a/packages/functions/src/runtime/firebase/proposal/index.ts b/packages/functions/src/runtime/firebase/proposal/index.ts deleted file mode 100644 index e50d70f617..0000000000 --- a/packages/functions/src/runtime/firebase/proposal/index.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { WEN_FUNC } from '@build-5/interfaces'; -import { https } from '../../..'; - -export const createProposal = https[WEN_FUNC.createProposal]; -export const approveProposal = https[WEN_FUNC.approveProposal]; -export const rejectProposal = https[WEN_FUNC.rejectProposal]; -export const voteOnProposal = https[WEN_FUNC.voteOnProposal]; diff --git a/packages/functions/src/runtime/firebase/rank/index.ts b/packages/functions/src/runtime/firebase/rank/index.ts deleted file mode 100644 index 3126101bd0..0000000000 --- a/packages/functions/src/runtime/firebase/rank/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -import { WEN_FUNC } from '@build-5/interfaces'; -import { https } from '../../..'; - -export const rankController = https[WEN_FUNC.rankController]; diff --git a/packages/functions/src/runtime/firebase/space/index.ts b/packages/functions/src/runtime/firebase/space/index.ts deleted file mode 100644 index 3c91c0a176..0000000000 --- a/packages/functions/src/runtime/firebase/space/index.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { WEN_FUNC } from '@build-5/interfaces'; -import { https } from '../../..'; - -export const createSpace = https[WEN_FUNC.createSpace]; - -export const addGuardian = https[WEN_FUNC.addGuardianSpace]; - -export const removeGuardian = https[WEN_FUNC.removeGuardianSpace]; -export const acceptMemberSpace = https[WEN_FUNC.acceptMemberSpace]; - -export const blockMember = https[WEN_FUNC.blockMemberSpace]; - -export const declineMemberSpace = https[WEN_FUNC.declineMemberSpace]; -export const unblockMember = https[WEN_FUNC.unblockMemberSpace]; - -export const updateSpace = https[WEN_FUNC.updateSpace]; - -export const leaveSpace = https[WEN_FUNC.leaveSpace]; - -export const joinSpace = https[WEN_FUNC.joinSpace]; - -export const claimSpace = https[WEN_FUNC.claimSpace]; diff --git a/packages/functions/src/runtime/firebase/stake/index.ts b/packages/functions/src/runtime/firebase/stake/index.ts deleted file mode 100644 index 392f7096e4..0000000000 --- a/packages/functions/src/runtime/firebase/stake/index.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { WEN_FUNC } from '@build-5/interfaces'; -import { https } from '../../..'; - -export const depositStake = https[WEN_FUNC.depositStake]; -export const stakeReward = https[WEN_FUNC.stakeReward]; -export const removeStakeReward = https[WEN_FUNC.removeStakeReward]; diff --git a/packages/functions/src/runtime/firebase/stamp/index.ts b/packages/functions/src/runtime/firebase/stamp/index.ts deleted file mode 100644 index 402ef4fec3..0000000000 --- a/packages/functions/src/runtime/firebase/stamp/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -import { WEN_FUNC } from '@build-5/interfaces'; -import { https } from '../../..'; - -export const stamp = https[WEN_FUNC.stamp]; diff --git a/packages/functions/src/runtime/firebase/storage/file.upload.ts b/packages/functions/src/runtime/firebase/storage/file.upload.ts deleted file mode 100644 index 2660d6f4c6..0000000000 --- a/packages/functions/src/runtime/firebase/storage/file.upload.ts +++ /dev/null @@ -1,4 +0,0 @@ -import { WEN_FUNC } from '@build-5/interfaces'; -import { https } from '../../..'; - -export const uploadFile = https[WEN_FUNC.uploadFile]; diff --git a/packages/functions/src/runtime/firebase/swap/index.ts b/packages/functions/src/runtime/firebase/swap/index.ts deleted file mode 100644 index 05360009a5..0000000000 --- a/packages/functions/src/runtime/firebase/swap/index.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { WEN_FUNC } from '@build-5/interfaces'; -import { https } from '../../..'; - -export const createSwap = https[WEN_FUNC.createSwap]; - -export const setSwapFunded = https[WEN_FUNC.setSwapFunded]; - -export const rejectSwap = https[WEN_FUNC.rejectSwap]; diff --git a/packages/functions/src/runtime/firebase/token/base/index.ts b/packages/functions/src/runtime/firebase/token/base/index.ts deleted file mode 100644 index 2c34bd0a52..0000000000 --- a/packages/functions/src/runtime/firebase/token/base/index.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { WEN_FUNC } from '@build-5/interfaces'; -import { https } from '../../../..'; - -export const createToken = https[WEN_FUNC.createToken]; - -export const updateToken = https[WEN_FUNC.updateToken]; - -export const setTokenAvailableForSale = https[WEN_FUNC.setTokenAvailableForSale]; - -export const cancelPublicSale = https[WEN_FUNC.cancelPublicSale]; - -export const creditToken = https[WEN_FUNC.creditToken]; - -export const orderToken = https[WEN_FUNC.orderToken]; - -export const enableTokenTrading = https[WEN_FUNC.enableTokenTrading]; - -export const airdropToken = https[WEN_FUNC.airdropToken]; - -export const claimAirdroppedToken = https[WEN_FUNC.claimAirdroppedToken]; diff --git a/packages/functions/src/runtime/firebase/token/minting/index.ts b/packages/functions/src/runtime/firebase/token/minting/index.ts deleted file mode 100644 index 80c79c1423..0000000000 --- a/packages/functions/src/runtime/firebase/token/minting/index.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { WEN_FUNC } from '@build-5/interfaces'; -import { https } from '../../../..'; - -export const airdropMintedToken = https[WEN_FUNC.airdropMintedToken]; - -export const claimMintedTokenOrder = https[WEN_FUNC.claimMintedTokenOrder]; - -export const mintTokenOrder = https[WEN_FUNC.mintTokenOrder]; - -export const importMintedToken = https[WEN_FUNC.importMintedToken]; diff --git a/packages/functions/src/runtime/firebase/token/trading/index.ts b/packages/functions/src/runtime/firebase/token/trading/index.ts deleted file mode 100644 index e76d6b8d32..0000000000 --- a/packages/functions/src/runtime/firebase/token/trading/index.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { WEN_FUNC } from '@build-5/interfaces'; -import { https } from '../../../..'; - -export const cancelTradeOrder = https[WEN_FUNC.cancelTradeOrder]; -export const tradeToken = https[WEN_FUNC.tradeToken]; diff --git a/packages/functions/src/runtime/firebase/vote/index.ts b/packages/functions/src/runtime/firebase/vote/index.ts deleted file mode 100644 index e5796b8fb1..0000000000 --- a/packages/functions/src/runtime/firebase/vote/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -import { WEN_FUNC } from '@build-5/interfaces'; -import { https } from '../../..'; - -export const voteController = https[WEN_FUNC.voteController]; diff --git a/packages/functions/src/runtime/https/https.ts b/packages/functions/src/runtime/https/https.ts index 8490b3966f..3889e72675 100644 --- a/packages/functions/src/runtime/https/https.ts +++ b/packages/functions/src/runtime/https/https.ts @@ -49,11 +49,15 @@ export const onRequest = (params: OnRequest) => { const result = await params.handler(context); res.send(result || {}); } catch (error) { - res.status(get(error, 'httpErrorCode.status', 400)); + const code = get(error, 'eCode', 500); + if (code === 500) { + console.error(error); + } + res.status(get(error, 'status', 500)); res.send({ - code: get(error, 'details.code', 0), - key: get(error, 'details.key', ''), - message: get(error, 'message', ''), + code, + key: get(error, 'eKey', ''), + message: get(error, 'eMessage', code === 500 ? 'Internal server error' : ''), }); } }; diff --git a/packages/functions/src/runtime/proto/protoToJson.ts b/packages/functions/src/runtime/proto/protoToJson.ts deleted file mode 100644 index 87524fd367..0000000000 --- a/packages/functions/src/runtime/proto/protoToJson.ts +++ /dev/null @@ -1,48 +0,0 @@ -/* eslint-disable @typescript-eslint/no-explicit-any */ -import { Timestamp } from 'firebase-admin/firestore'; -import { set } from 'lodash'; -import { Message } from 'protobufjs'; - -export const protoToJson = (proto: Message) => { - const json = proto.toJSON(); - - const current = json.value?.fields; - if (current) { - set(json, 'value.fields', protoJsonToJson(current)); - } - const prev = json.oldValue?.fields; - if (prev !== undefined) { - set(json, 'oldValue.fields', protoJsonToJson(prev)); - } - return json; -}; - -const protoJsonToJson = (protoJson: { [key: string]: any }) => - Object.entries(protoJson).reduce( - (acc, [key, value]) => ({ ...acc, [key]: valueToJson(value) }), - {} as { [key: string]: any }, - ); - -const valueToJson = (data: { [key: string]: any }): any => { - const [type, value] = Object.entries(data)[0]; - switch (type) { - case 'nullValue': - return null; - case 'booleanValue': - return Boolean(value); - case 'integerValue': - case 'doubleValue': - return Number(value); - case 'timestampValue': - return new Timestamp(Number(value.seconds), Number(value.nanos || 0)); - case 'stringValue': - return String(value); - case 'bytes': - case 'referenceValue': - return value; - case 'arrayValue': - return ((value.values as any[]) || []).map(valueToJson); - case 'mapValue': - return protoJsonToJson(value.fields || {}); - } -}; diff --git a/packages/functions/src/runtime/trigger/index.ts b/packages/functions/src/runtime/trigger/index.ts index 86af7ad86a..d45ff9d27d 100644 --- a/packages/functions/src/runtime/trigger/index.ts +++ b/packages/functions/src/runtime/trigger/index.ts @@ -17,60 +17,61 @@ import { WEN_FUNC_TRIGGER } from '../common'; import { onCreate, onUpdate, onWrite } from './trigger'; exports[WEN_FUNC_TRIGGER.onProposalWrite] = onWrite({ - document: `${COL.PROPOSAL}/{docId}`, + col: COL.PROPOSAL, handler: onProposalWrite, }); exports[WEN_FUNC_TRIGGER.onAwardUpdated] = onUpdate({ - document: `${COL.AWARD}/{docId}`, + col: COL.AWARD, options: TRIGGER_SCALE[WEN_FUNC_TRIGGER.onAwardUpdated], handler: onAwardUpdated, }); exports[WEN_FUNC_TRIGGER.onCollectionUpdated] = onUpdate({ - document: `${COL.COLLECTION}/{docId}`, + col: COL.COLLECTION, options: TRIGGER_SCALE[WEN_FUNC_TRIGGER.onCollectionUpdated], handler: onCollectionUpdated, }); exports[WEN_FUNC_TRIGGER.onTokenStatusUpdated] = onUpdate({ - document: `${COL.TOKEN}/{docId}`, + col: COL.TOKEN, options: TRIGGER_SCALE[WEN_FUNC_TRIGGER.onTokenStatusUpdated], handler: onTokenStatusUpdated, }); exports[WEN_FUNC_TRIGGER.onTokenTradeOrderWrite] = onWrite({ - document: `${COL.TOKEN_MARKET}/{docId}`, + col: COL.TOKEN_MARKET, options: TRIGGER_SCALE[WEN_FUNC_TRIGGER.onTokenTradeOrderWrite], handler: onTokenTradeOrderWrite, }); exports[WEN_FUNC_TRIGGER.onTokenPurchaseCreated] = onCreate({ - document: `${COL.TOKEN_PURCHASE}/{docId}`, + col: COL.TOKEN_PURCHASE, options: TRIGGER_SCALE[WEN_FUNC_TRIGGER.onTokenPurchaseCreated], handler: onTokenPurchaseCreated, }); exports[WEN_FUNC_TRIGGER.onNftWrite] = onWrite({ - document: `${COL.NFT}/{docId}`, + col: COL.NFT, options: TRIGGER_SCALE[WEN_FUNC_TRIGGER.onNftWrite], handler: onNftWrite, }); exports[WEN_FUNC_TRIGGER.onTransactionWrite] = onWrite({ - document: `${COL.TRANSACTION}/{docId}`, + col: COL.TRANSACTION, options: TRIGGER_SCALE[WEN_FUNC_TRIGGER.onTransactionWrite], handler: onTransactionWrite, }); exports[WEN_FUNC_TRIGGER.onMnemonicUpdated] = onUpdate({ - document: `${COL.MNEMONIC}/{docId}`, + col: COL.MNEMONIC, options: TRIGGER_SCALE[WEN_FUNC_TRIGGER.onMnemonicUpdated], handler: onMnemonicUpdated, }); exports[WEN_FUNC_TRIGGER.onCollectionStatsWrite] = onWrite({ - document: `${COL.COLLECTION}/{docId}/${SUB_COL.STATS}/{subDocId}`, + col: COL.COLLECTION, + subCol: SUB_COL.STATS, options: TRIGGER_SCALE[WEN_FUNC_TRIGGER.onCollectionStatsWrite], handler: onCollectionStatsWrite, }); @@ -79,7 +80,7 @@ export const algolia = (isEmulatorEnv() ? [] : ALGOLIA_COLLECTIONS).reduce( (acc, act) => ({ ...acc, [`${WEN_FUNC_TRIGGER.algolia}${act}`]: onWrite({ - document: `${act}/{docId}`, + col: act, options: ALGOLIA_TRIGGER_SCALE[act], handler: algoliaTrigger, }), @@ -92,7 +93,8 @@ const getMilestoneTrigger = (networks: Network[]) => (acc, act) => ({ ...acc, [`${WEN_FUNC_TRIGGER.onMilestoneTransactionWrite}${act}`]: onWrite({ - document: `${getMilestoneCol(act)}/{docId}/${SUB_COL.TRANSACTIONS}/{subDocId}`, + col: getMilestoneCol(act), + subCol: SUB_COL.TRANSACTIONS, options: TRIGGER_SCALE[WEN_FUNC_TRIGGER.onMilestoneTransactionWrite], handler: handleMilestoneTransactionWrite(act), }), diff --git a/packages/functions/src/runtime/trigger/trigger.ts b/packages/functions/src/runtime/trigger/trigger.ts index 600c6d7349..cc53f88b93 100644 --- a/packages/functions/src/runtime/trigger/trigger.ts +++ b/packages/functions/src/runtime/trigger/trigger.ts @@ -1,6 +1,7 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ -import { FirestoreDocEvent } from '../../triggers/common'; +import { COL, SUB_COL } from '@build-5/interfaces'; +import { PgDocEvent } from '../../triggers/common'; import { CloudFunctions, RuntimeOptions } from '../common'; export enum TriggeredFunctionType { @@ -12,8 +13,9 @@ export enum TriggeredFunctionType { export class TriggeredFunction extends CloudFunctions { constructor( public readonly type: TriggeredFunctionType, - public readonly document: string, - public readonly handler: (event: FirestoreDocEvent) => Promise, + public readonly col: COL, + public readonly subCol: SUB_COL | undefined = undefined, + public readonly handler: (event: PgDocEvent) => Promise, options?: RuntimeOptions, ) { super({ @@ -24,31 +26,37 @@ export class TriggeredFunction extends CloudFunctions { } export const onCreate = ({ - document, + col, + subCol, handler, options, }: { - document: string; - handler: (event: FirestoreDocEvent) => Promise; + col: COL; + subCol?: SUB_COL; + handler: (event: PgDocEvent) => Promise; options?: RuntimeOptions; -}) => new TriggeredFunction(TriggeredFunctionType.ON_CREATE, document, handler, options); +}) => new TriggeredFunction(TriggeredFunctionType.ON_CREATE, col, subCol, handler, options); export const onUpdate = ({ - document, + col, + subCol, handler, options, }: { - document: string; - handler: (event: FirestoreDocEvent) => Promise; + col: COL; + subCol?: SUB_COL; + handler: (event: PgDocEvent) => Promise; options?: RuntimeOptions; -}) => new TriggeredFunction(TriggeredFunctionType.ON_UPDATE, document, handler, options); +}) => new TriggeredFunction(TriggeredFunctionType.ON_UPDATE, col, subCol, handler, options); export const onWrite = ({ - document, + col, + subCol, handler, options, }: { - document: string; - handler: (event: FirestoreDocEvent) => Promise; + col: COL; + subCol?: SUB_COL; + handler: (event: PgDocEvent) => Promise; options?: RuntimeOptions; -}) => new TriggeredFunction(TriggeredFunctionType.ON_WRITE, document, handler, options); +}) => new TriggeredFunction(TriggeredFunctionType.ON_WRITE, col, subCol, handler, options); diff --git a/packages/functions/src/services/joi/common.ts b/packages/functions/src/services/joi/common.ts index f37ec26b92..1949954e98 100644 --- a/packages/functions/src/services/joi/common.ts +++ b/packages/functions/src/services/joi/common.ts @@ -9,7 +9,7 @@ const maxAddressLength = 255; export class CommonJoi { public static uid(required = true): Joi.StringSchema { const base = Joi.string().alphanum().min(minAddressLength).max(maxAddressLength).lowercase(); - return required ? base.required() : base; + return required ? base.required() : base.allow(null, ''); } public static storageUrl(required = true): Joi.StringSchema { const base = Joi.string().custom((url: string, helpers) => { @@ -33,16 +33,13 @@ export const isStorageUrl = (url: string | undefined) => export const BUCKET_BASE_URLS = { [Bucket.PROD]: 'https://' + Bucket.PROD + '/', [Bucket.TEST]: 'https://' + Bucket.TEST + '/', - [Bucket.DEV]: `https://firebasestorage.googleapis.com/v0/b/${Bucket.DEV}/o/`, - local: `http://127.0.0.1:9199/download/storage/v1/b/soonaverse-dev-custom-bucket/o/`, + [Bucket.DEV]: `https://storage.googleapis.com/download/storage/v1/b/${Bucket.DEV}/o/`, }; const startsWithBaseUrl = (url: string) => { if (isEmulatorEnv()) { return ( - url.startsWith(BUCKET_BASE_URLS[Bucket.DEV]) || - url.startsWith(BUCKET_BASE_URLS[Bucket.TEST]) || - url.startsWith(BUCKET_BASE_URLS['local']) + url.startsWith(BUCKET_BASE_URLS[Bucket.DEV]) || url.startsWith(BUCKET_BASE_URLS[Bucket.TEST]) ); } if (isProdEnv()) { diff --git a/packages/functions/src/services/payment/address/address-member.service.ts b/packages/functions/src/services/payment/address/address-member.service.ts index 42f729580b..9dc83a012f 100644 --- a/packages/functions/src/services/payment/address/address-member.service.ts +++ b/packages/functions/src/services/payment/address/address-member.service.ts @@ -1,15 +1,18 @@ -import { build5Db, getSnapshot } from '@build-5/database'; +import { + PgNetwork, + PgTransactionPayloadType, + PgTransactionType, + build5Db, + convertEnum, +} from '@build-5/database'; import { COL, DEFAULT_NETWORK, Entity, Network, NetworkAddress, - Transaction, TransactionPayloadType, - TransactionType, } from '@build-5/interfaces'; -import { last } from 'lodash'; import { HandlerParams } from '../base'; import { BaseAddressService } from './common'; @@ -23,7 +26,7 @@ export class MemberAddressService extends BaseAddressService { ); if (credit) { await this.setValidatedAddress(credit, Entity.MEMBER); - await claimBadges( + await this.claimBadges( order.member!, credit.payload.targetAddress!, order.network || DEFAULT_NETWORK, @@ -31,41 +34,34 @@ export class MemberAddressService extends BaseAddressService { } this.transactionService.markAsReconciled(order, match.msgId); }; -} -const claimBadges = async (member: string, memberAddress: NetworkAddress, network: Network) => { - let lastDocId = ''; - do { - const lastDoc = await getSnapshot(COL.TRANSACTION, lastDocId); + private claimBadges = async (member: string, memberAddress: NetworkAddress, network: Network) => { const snap = await build5Db() .collection(COL.TRANSACTION) - .where('network', '==', network) - .where('type', '==', TransactionType.AWARD) + .where('network', '==', convertEnum(network, Network, PgNetwork)) + .where('type', '==', PgTransactionType.AWARD) .where('member', '==', member) .where('ignoreWallet', '==', true) - .where('payload.type', '==', TransactionPayloadType.BADGE) - .limit(500) - .startAfter(lastDoc) - .get(); - lastDocId = last(snap)?.uid || ''; + .where('payload_type', '==', PgTransactionPayloadType.BADGE) + .get(); const promises = snap.map((badgeTransaction) => updateBadgeTransaction(badgeTransaction.uid, memberAddress), ); await Promise.all(promises); - } while (lastDocId); -}; + }; +} -const updateBadgeTransaction = async (transactionId: string, memberAddress: NetworkAddress) => +const updateBadgeTransaction = (transactionId: string, memberAddress: NetworkAddress) => build5Db().runTransaction(async (transaction) => { - const badgeDocRef = build5Db().doc(`${COL.TRANSACTION}/${transactionId}`); - const badge = await transaction.get(badgeDocRef); + const badgeDocRef = build5Db().doc(COL.TRANSACTION, transactionId); + const badge = await transaction.get(badgeDocRef); if (badge?.ignoreWallet) { const data = { ignoreWallet: false, - 'payload.targetAddress': memberAddress, + payload_targetAddress: memberAddress, shouldRetry: true, }; - transaction.update(badgeDocRef, data); + await transaction.update(badgeDocRef, data); } }); 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 6f4446ef2a..18c98188ac 100644 --- a/packages/functions/src/services/payment/address/address.space.service.ts +++ b/packages/functions/src/services/payment/address/address.space.service.ts @@ -8,7 +8,6 @@ import { ProposalType, SUB_COL, Space, - SpaceGuardian, Transaction, TransactionPayloadType, TransactionType, @@ -19,6 +18,7 @@ import { getAddress } from '../../../utils/address.utils'; import { dateToTimestamp } from '../../../utils/dateTime.utils'; import { getRandomEthAddress } from '../../../utils/wallet.utils'; import { BaseService, HandlerParams } from '../base'; +import { Action } from '../transaction-service'; export class SpaceAddressService extends BaseService { public handleRequest = async ({ project, order, match }: HandlerParams) => { @@ -30,13 +30,13 @@ export class SpaceAddressService extends BaseService { ); this.transactionService.markAsReconciled(order, match.msgId); - const spaceDocRef = build5Db().doc(`${COL.SPACE}/${order.space}`); - const space = await this.transactionService.get(spaceDocRef); + const spaceDocRef = build5Db().doc(COL.SPACE, order.space!); + const space = await this.transaction.get(spaceDocRef); - const ownerDocRef = build5Db().doc(`${COL.MEMBER}/${order.member}`); - const owner = await ownerDocRef.get(); + const ownerDocRef = build5Db().doc(COL.MEMBER, order.member!); + const owner = await this.transaction.get(ownerDocRef); - const guardians = await spaceDocRef.collection(SUB_COL.GUARDIANS).get(); + const guardians = await build5Db().collection(COL.SPACE, order.space!, SUB_COL.GUARDIANS).get(); const proposal = createUpdateSpaceValidatedAddressProposal( project, order, @@ -62,34 +62,37 @@ export class SpaceAddressService extends BaseService { linkedTransactions: [], }; - const proposalDocRef = build5Db().doc(`${COL.PROPOSAL}/${proposal.uid}`); - const memberPromisses = guardians.map((guardian) => { - proposalDocRef - .collection(SUB_COL.MEMBERS) - .doc(guardian.uid) - .set({ - uid: guardian.uid, + for (const guardian of guardians) { + const memberDocRef = build5Db().doc( + COL.PROPOSAL, + proposal.uid, + SUB_COL.MEMBERS, + guardian.uid, + ); + this.transactionService.push({ + ref: memberDocRef, + data: { weight: 1, voted: guardian.uid === owner.uid, tranId: guardian.uid === owner.uid ? voteTransaction.uid : '', - parentId: proposal.uid, - parentCol: COL.PROPOSAL, - values: guardian.uid === owner.uid ? [{ [1]: 1 }] : [], - }); - }); - await Promise.all(memberPromisses); + }, + action: Action.UPS, + }); + } - const voteTransactionDocRef = build5Db().doc(`${COL.TRANSACTION}/${voteTransaction.uid}`); - this.transactionService.push({ - ref: voteTransactionDocRef, - data: voteTransaction, - action: 'set', - }); + const proposalDocRef = build5Db().doc(COL.PROPOSAL, proposal.uid); this.transactionService.push({ ref: proposalDocRef, data: proposal, - action: 'set', + action: Action.C, + }); + + const voteTransactionDocRef = build5Db().doc(COL.TRANSACTION, voteTransaction.uid); + this.transactionService.push({ + ref: voteTransactionDocRef, + data: voteTransaction, + action: Action.C, }); }; } @@ -106,6 +109,7 @@ const createUpdateSpaceValidatedAddressProposal = ( `${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`; + const prevAddress = getAddress(space, order.network!); return { project, createdBy: owner.uid, @@ -124,15 +128,13 @@ const createUpdateSpaceValidatedAddressProposal = ( spaceUpdateData: { uid: space.uid, validatedAddress: { [order.network!]: validatedAddress }, - prevValidatedAddresses: getAddress(space, order.network!), + prevValidatedAddresses: prevAddress ? [prevAddress] : [], }, }, questions: [ { text: "Do you want to update the space's validate address?", - additionalInfo: `${order.network!.toUpperCase()}: ${validatedAddress} (previously: ${ - getAddress(space, order.network!) || 'None' - })\n`, + additionalInfo: `${order.network!.toUpperCase()}: ${validatedAddress} (previously: ${getAddress(space, order.network!) || 'None'})\n`, answers: [ { text: 'No', diff --git a/packages/functions/src/services/payment/address/common.ts b/packages/functions/src/services/payment/address/common.ts index 72138fc1f5..8fef82f346 100644 --- a/packages/functions/src/services/payment/address/common.ts +++ b/packages/functions/src/services/payment/address/common.ts @@ -1,20 +1,28 @@ -import { build5Db } from '@build-5/database'; +import { IDocument, PgSpaceUpdate, build5Db } from '@build-5/database'; import { COL, DEFAULT_NETWORK, Entity, Transaction } from '@build-5/interfaces'; import { getAddress } from '../../../utils/address.utils'; import { BaseService } from '../base'; +import { Action } from '../transaction-service'; export abstract class BaseAddressService extends BaseService { protected async setValidatedAddress(credit: Transaction, type: Entity): Promise { const collection = type === Entity.MEMBER ? COL.MEMBER : COL.SPACE; - const id = type === Entity.MEMBER ? credit.member : credit.space; - const ref = build5Db().doc(`${collection}/${id}`); - const docData = await ref.get>(); + const id = type === Entity.MEMBER ? credit.member! : credit.space!; + + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const ref: IDocument = build5Db().doc(collection, id); + + const docData = await this.transaction.get(ref); const network = credit.network || DEFAULT_NETWORK; const currentAddress = getAddress(docData, network); - const data = { [`validatedAddress.${network}`]: credit.payload.targetAddress }; - if (currentAddress) { - data.prevValidatedAddresses = build5Db().arrayUnion(currentAddress); - } - this.transactionService.push({ ref, data, action: 'update' }); + + const data = currentAddress + ? { + [`${network}Address`]: credit.payload.targetAddress, + prevValidatedAddresses: build5Db().arrayUnion(currentAddress), + } + : { [`${network}Address`]: credit.payload.targetAddress }; + + this.transactionService.push({ ref, data, action: Action.U }); } } diff --git a/packages/functions/src/services/payment/auction/auction-bid.service.ts b/packages/functions/src/services/payment/auction/auction-bid.service.ts index 9b081232c4..59c4b4fc37 100644 --- a/packages/functions/src/services/payment/auction/auction-bid.service.ts +++ b/packages/functions/src/services/payment/auction/auction-bid.service.ts @@ -1,4 +1,4 @@ -import { build5Db } from '@build-5/database'; +import { PgTransactionType, build5Db } from '@build-5/database'; import { Auction, AuctionBid, @@ -7,17 +7,15 @@ import { Member, Transaction, TransactionPayloadType, - TransactionType, } from '@build-5/interfaces'; import dayjs from 'dayjs'; import { head, set } from 'lodash'; import { NotificationService } from '../../notification/notification'; +import { BaseAddressService } from '../address/common'; import { HandlerParams } from '../base'; -import { TransactionService } from '../transaction-service'; - -export class AuctionBidService { - constructor(readonly transactionService: TransactionService) {} +import { Action } from '../transaction-service'; +export class AuctionBidService extends BaseAddressService { public handleRequest = async ({ order, match, @@ -26,8 +24,8 @@ export class AuctionBidService { build5Tran, owner, }: HandlerParams) => { - const auctionDocRef = build5Db().doc(`${COL.AUCTION}/${order.payload.auction!}`); - const auction = await this.transactionService.get(auctionDocRef); + const auctionDocRef = build5Db().doc(COL.AUCTION, order.payload.auction!); + const auction = await this.transaction.get(auctionDocRef); if (!auction.active) { await this.transactionService.processAsInvalid(tran, order, tranEntry, build5Tran); @@ -70,36 +68,36 @@ export class AuctionBidService { private creditInvalidPayments = async (auction: Auction, invalidBid: AuctionBid) => { const payments = await build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.PAYMENT) + .where('type', '==', PgTransactionType.PAYMENT) .where('member', '==', invalidBid.bidder) - .where('payload.invalidPayment', '==', false) - .where('payload.auction', '==', auction.uid) - .get(); + .where('payload_invalidPayment', '==', false) + .where('payload_auction', '==', auction.uid) + .get(); for (const payment of payments) { await this.creditAsInvalidPayment(payment); } - const invalidBidderDocRef = build5Db().doc(`${COL.MEMBER}/${invalidBid.bidder}`); - const invalidBidder = await this.transactionService.get(invalidBidderDocRef); + const invalidBidderDocRef = build5Db().doc(COL.MEMBER, invalidBid.bidder); + const invalidBidder = await this.transaction.get(invalidBidderDocRef); const notification = NotificationService.prepareLostBid( invalidBidder, invalidBid.amount, auction.uid, ); - const notificationDocRef = build5Db().doc(`${COL.NOTIFICATION}/${notification.uid}`); - this.transactionService.push({ ref: notificationDocRef, data: notification, action: 'set' }); + const notificationDocRef = build5Db().doc(COL.NOTIFICATION, notification.uid); + this.transactionService.push({ ref: notificationDocRef, data: notification, action: Action.C }); }; private creditAsInvalidPayment = async (payment: Transaction) => { - const paymentDocRef = build5Db().doc(`${COL.TRANSACTION}/${payment.uid}`); + const paymentDocRef = build5Db().doc(COL.TRANSACTION, payment.uid); this.transactionService.push({ ref: paymentDocRef, - data: { 'payload.invalidPayment': true }, - action: 'update', + data: { payload_invalidPayment: true }, + action: Action.U, }); const paymentPayload = payment.payload; - set(payment, 'payload.invalidPayment', true); + set(payment, 'payload_invalidPayment', true); await this.transactionService.createCredit(TransactionPayloadType.INVALID_PAYMENT, payment, { msgId: paymentPayload.chainReference!, to: { @@ -112,49 +110,58 @@ export class AuctionBidService { }; private onAuctionHighestBidChange = async (order: Transaction, auction: Auction) => { - const memberDocRef = build5Db().doc(`${COL.MEMBER}/${order.member!}`); - const member = await this.transactionService.get(memberDocRef); + const memberDocRef = build5Db().doc(COL.MEMBER, order.member!); + const member = await memberDocRef.get(); const bidNotification = NotificationService.prepareBid( member, auction.auctionHighestBid!, auction.uid, ); - const notificationDocRef = build5Db().doc(`${COL.NOTIFICATION}/${bidNotification.uid}`); - this.transactionService.push({ ref: notificationDocRef, data: bidNotification, action: 'set' }); + const notificationDocRef = build5Db().doc(COL.NOTIFICATION, bidNotification.uid); + this.transactionService.push({ + ref: notificationDocRef, + data: bidNotification, + action: Action.C, + }); }; private getAuctionUpdateData = (auction: Auction, bids: AuctionBid[]) => { - const auctionUpdateData = { - ...auction, + const uData = { bids, auctionHighestBidder: head(bids)?.bidder || '', auctionHighestBid: head(bids)?.amount || 0, + auctionTo: auction.auctionTo, + auctionLength: auction.auctionLength, }; const auctionTTL = dayjs(auction.auctionTo!.toDate()).diff(dayjs()); if ( auction.auctionLength < (auction.extendedAuctionLength || 0) && auctionTTL < (auction.extendAuctionWithin || 0) ) { - set(auctionUpdateData, 'auctionTo', auction.extendedAuctionTo || null); - set(auctionUpdateData, 'auctionLength', auction.extendedAuctionLength || null); + uData.auctionTo = auction.extendedAuctionTo!; + uData.auctionLength = auction.extendedAuctionLength || 0; } - const auctionDocRef = build5Db().doc(`${COL.AUCTION}/${auction.uid}`); - this.transactionService.push({ ref: auctionDocRef, data: auctionUpdateData, action: 'update' }); - return auctionUpdateData as Auction; + const auctionDocRef = build5Db().doc(COL.AUCTION, auction.uid); + this.transactionService.push({ + ref: auctionDocRef, + data: { ...uData, auctionTo: uData.auctionTo?.toDate(), bids: JSON.stringify(uData.bids) }, + action: Action.U, + }); + return { ...auction, ...uData } as Auction; }; private updateNft = (auction: Auction) => { const nftUpdateData = { - auctionTo: auction.auctionTo, + auctionTo: auction.auctionTo?.toDate(), auctionLength: auction.auctionLength, auctionHighestBid: auction.auctionHighestBid, auctionHighestBidder: auction.auctionHighestBidder, }; this.transactionService.push({ - ref: build5Db().doc(`${COL.NFT}/${auction.nftId}`), + ref: build5Db().doc(COL.NFT, auction.nftId!), data: nftUpdateData, - action: 'update', + action: Action.U, }); }; } @@ -197,7 +204,6 @@ const placeBid = (auction: Auction, order: string, bidder: string, amount: numbe bids.push({ bidder, amount, order }); bids.sort((a, b) => b.amount - a.amount); } - return { bids: bids.slice(0, auction.maxBids), invalidBid: head(bids.slice(auction.maxBids)), diff --git a/packages/functions/src/services/payment/auction/auction.finalize.service.ts b/packages/functions/src/services/payment/auction/auction.finalize.service.ts index d1bbac8e4d..7fe7511839 100644 --- a/packages/functions/src/services/payment/auction/auction.finalize.service.ts +++ b/packages/functions/src/services/payment/auction/auction.finalize.service.ts @@ -1,4 +1,4 @@ -import { build5Db } from '@build-5/database'; +import { ITransaction, PgTransactionType, build5Db } from '@build-5/database'; import { Auction, AuctionType, @@ -7,36 +7,36 @@ import { Nft, NftStatus, Transaction, - TransactionType, WenError, } from '@build-5/interfaces'; import { invalidArgument } from '../../../utils/error.utils'; import { NotificationService } from '../../notification/notification'; import { BaseNftService } from '../nft/common'; -import { TransactionService } from '../transaction-service'; +import { Action, TransactionService } from '../transaction-service'; export class AuctionFinalizeService { - constructor(readonly transactionService: TransactionService) {} + private transaction: ITransaction; + constructor(readonly transactionService: TransactionService) { + this.transaction = transactionService.transaction; + } public markAsFinalized = async (auctionId: string) => { - const auctionDocRef = build5Db().doc(`${COL.AUCTION}/${auctionId}`); - const auction = await this.transactionService.get(auctionDocRef); + const auctionDocRef = build5Db().doc(COL.AUCTION, auctionId); + const auction = await this.transaction.get(auctionDocRef); if (!auction.active) { throw invalidArgument(WenError.auction_not_active); } - this.transactionService.push({ ref: auctionDocRef, data: { active: false }, action: 'update' }); + this.transactionService.push({ ref: auctionDocRef, data: { active: false }, action: Action.U }); const payments = await build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.PAYMENT) - .where('payload.invalidPayment', '==', false) - .where('payload.auction', '==', auction.uid) - .get(); + .where('type', '==', PgTransactionType.PAYMENT) + .where('payload_invalidPayment', '==', false) + .where('payload_auction', '==', auction.uid) + .get(); for (const payment of payments) { - const orderDocRef = build5Db().doc( - `${COL.TRANSACTION}/${payment.payload.sourceTransaction![0]}`, - ); + const orderDocRef = build5Db().doc(COL.TRANSACTION, payment.payload.sourceTransaction![0]); const order = await orderDocRef.get(); this.transactionService.createBillPayment(order, payment); } @@ -48,8 +48,8 @@ export class AuctionFinalizeService { }; private finalizeNftAuction = async (auction: Auction) => { - const nftDocRef = build5Db().doc(`${COL.NFT}/${auction.nftId}`); - const nft = await this.transactionService.get(nftDocRef); + const nftDocRef = build5Db().doc(COL.NFT, auction.nftId!); + const nft = await this.transaction.get(nftDocRef); if (!auction.auctionHighestBidder) { this.transactionService.push({ @@ -65,12 +65,12 @@ export class AuctionFinalizeService { auctionHighestBidder: null, auction: null, }, - action: 'update', + action: Action.U, }); return; } - const orderDocRef = build5Db().doc(`${COL.TRANSACTION}/${auction.bids[0].order}`); + const orderDocRef = build5Db().doc(COL.TRANSACTION, auction.bids[0].order); const order = await orderDocRef.get(); const nftService = new BaseNftService(this.transactionService); @@ -84,11 +84,10 @@ export class AuctionFinalizeService { auction.auctionHighestBid!, auction.uid, ); - const notificationDocRef = build5Db().doc(`${COL.NOTIFICATION}/${notification.uid}`); this.transactionService.push({ - ref: notificationDocRef, + ref: build5Db().doc(COL.NOTIFICATION, notification.uid), data: notification, - action: 'set', + action: Action.C, }); nftService.setTradingStats(nft); diff --git a/packages/functions/src/services/payment/award/award-service.ts b/packages/functions/src/services/payment/award/award-service.ts index f6964f2fa5..04823cea64 100644 --- a/packages/functions/src/services/payment/award/award-service.ts +++ b/packages/functions/src/services/payment/award/award-service.ts @@ -1,10 +1,9 @@ -import { build5Db } from '@build-5/database'; +import { PgMediaStatus, build5Db } from '@build-5/database'; import { Award, AwardBadgeType, COL, KEY_NAME_TANGLE, - MediaStatus, Space, Token, Transaction, @@ -23,13 +22,14 @@ import { createAliasOutput } from '../../../utils/token-minting-utils/alias.util import { getRandomEthAddress } from '../../../utils/wallet.utils'; import { Wallet } from '../../wallet/wallet'; import { BaseService, HandlerParams } from '../base'; +import { Action } from '../transaction-service'; export class AwardFundService extends BaseService { public handleRequest = async ({ order, match }: HandlerParams) => { const payment = await this.transactionService.createPayment(order, match); - const awardDocRef = build5Db().doc(`${COL.AWARD}/${order.payload.award}`); - const award = await this.transactionService.get(awardDocRef); + const awardDocRef = build5Db().doc(COL.AWARD, order.payload.award!); + const award = await this.transaction.get(awardDocRef); if (award.funded) { await this.transactionService.createCredit( @@ -64,9 +64,9 @@ export class AwardFundService extends BaseService { address: order.payload.targetAddress, fundedBy: order.member, fundingAddress: match.from, - mediaStatus: MediaStatus.PENDING_UPLOAD, + mediaStatus: PgMediaStatus.PENDING_UPLOAD, }, - action: 'update', + action: Action.U, }); const mintAliasOrder: Transaction = { @@ -84,21 +84,22 @@ export class AwardFundService extends BaseService { award: award.uid, }, }; - const mintAliasTranDocRef = build5Db().doc(`${COL.TRANSACTION}/${mintAliasOrder.uid}`); + const mintAliasTranDocRef = build5Db().doc(COL.TRANSACTION, mintAliasOrder.uid); this.transactionService.push({ ref: mintAliasTranDocRef, data: mintAliasOrder, - action: 'set', + action: Action.C, }); if (order.payload.legacyAwardFundRequestId) { const legacyAwardFundRequesDocRef = build5Db().doc( - `${COL.TRANSACTION}/${order.payload.legacyAwardFundRequestId}`, + COL.TRANSACTION, + order.payload.legacyAwardFundRequestId, ); this.transactionService.push({ ref: legacyAwardFundRequesDocRef, - data: { 'payload.legacyAwardsBeeingFunded': build5Db().inc(-1) }, - action: 'update', + data: { payload_legacyAwardsBeeingFunded: build5Db().inc(-1) }, + action: Action.U, }); } }; @@ -177,7 +178,7 @@ export const getAwardgStorageDeposits = async (award: Award, token: Token, walle const collectioIssuerAddress = new AliasAddress(aliasOutput.aliasId); - const spaceDocRef = build5Db().doc(`${COL.SPACE}/${award.space}`); + const spaceDocRef = build5Db().doc(COL.SPACE, award.space); const space = await spaceDocRef.get(); const collectionMetadata = await awardToCollectionMetadata(award, space); diff --git a/packages/functions/src/services/payment/credit-service.ts b/packages/functions/src/services/payment/credit-service.ts index 2bbe205dd3..adfea63f5b 100644 --- a/packages/functions/src/services/payment/credit-service.ts +++ b/packages/functions/src/services/payment/credit-service.ts @@ -1,18 +1,17 @@ import { build5Db } from '@build-5/database'; import { COL, Transaction, TransactionPayloadType, TransactionType } from '@build-5/interfaces'; -import { get, isEmpty } from 'lodash'; +import { isEmpty } from 'lodash'; import { getProject } from '../../utils/common.utils'; import { getRandomEthAddress } from '../../utils/wallet.utils'; import { BaseService, HandlerParams } from './base'; +import { Action } from './transaction-service'; export class CreditService extends BaseService { public handleRequest = async ({ order, match }: HandlerParams) => { const payment = await this.transactionService.createPayment(order, match); - const transactionDocRef = build5Db().doc( - `${COL.TRANSACTION}/${get(order, 'payload.transaction', '')}`, - ); - const transaction = await transactionDocRef.get(); + const transactionDocRef = build5Db().doc(COL.TRANSACTION, order.payload.transaction || ''); + const transaction = await this.transaction.get(transactionDocRef); if (!isEmpty(transaction.payload.unlockedBy)) { await this.transactionService.createCredit( @@ -44,15 +43,15 @@ export class CreditService extends BaseService { }, }; this.transactionService.push({ - ref: build5Db().doc(`${COL.TRANSACTION}/${credit.uid}`), + ref: build5Db().doc(COL.TRANSACTION, credit.uid), data: credit, - action: 'set', + action: Action.C, }); this.transactionService.push({ ref: transactionDocRef, - data: { 'payload.unlockedBy': credit.uid }, - action: 'update', + data: { payload_unlockedBy: credit.uid }, + action: Action.U, }); }; } diff --git a/packages/functions/src/services/payment/metadataNft-service.ts b/packages/functions/src/services/payment/metadataNft-service.ts index 44c45266bb..23e4d18276 100644 --- a/packages/functions/src/services/payment/metadataNft-service.ts +++ b/packages/functions/src/services/payment/metadataNft-service.ts @@ -1,19 +1,21 @@ -import { build5Db } from '@build-5/database'; +import { PgTransaction, build5Db } from '@build-5/database'; import { Access, COL, + Collection, CollectionStatus, CollectionType, + Network, NetworkAddress, Nft, NftAccess, NftAvailable, NftStatus, - Space, Transaction, TransactionPayloadType, TransactionType, } from '@build-5/interfaces'; +import { get } from 'lodash'; import { getCollectionByMintingId, getNftByMintingId, @@ -21,6 +23,7 @@ import { import { getProject } from '../../utils/common.utils'; import { getRandomEthAddress } from '../../utils/wallet.utils'; import { BaseService, HandlerParams } from './base'; +import { Action } from './transaction-service'; export class MetadataNftService extends BaseService { public handleRequest = async ({ project, order, match }: HandlerParams) => { @@ -52,19 +55,23 @@ export class MetadataNftService extends BaseService { }, }; this.transactionService.push({ - ref: build5Db().doc(`${COL.TRANSACTION}/${mintAlias.uid}`), + ref: build5Db().doc(COL.TRANSACTION, mintAlias.uid), data: mintAlias, - action: 'set', + action: Action.C, }); return; } if (!collectionId) { const collection = createMetadataCollection(getProject(order), order.space!); - const collectionDocRef = build5Db().doc(`${COL.COLLECTION}/${collection.uid}`); - this.transactionService.push({ ref: collectionDocRef, data: collection, action: 'set' }); + const collectionDocRef = build5Db().doc(COL.COLLECTION, collection.uid); + this.transactionService.push({ + ref: collectionDocRef, + data: collection as Collection, + action: Action.C, + }); - const space = await build5Db().doc(`${COL.SPACE}/${order.space}`).get(); + const space = await build5Db().doc(COL.SPACE, order.space!).get(); const mintCollectionOrder = createMintMetadataCollectionOrder( order, collection.uid, @@ -72,8 +79,12 @@ export class MetadataNftService extends BaseService { order.uid, space?.alias?.address!, ); - const orderDocRef = build5Db().doc(`${COL.TRANSACTION}/${mintCollectionOrder.uid}`); - this.transactionService.push({ ref: orderDocRef, data: mintCollectionOrder, action: 'set' }); + const orderDocRef = build5Db().doc(COL.TRANSACTION, mintCollectionOrder.uid); + this.transactionService.push({ + ref: orderDocRef, + data: mintCollectionOrder, + action: Action.C, + }); return; } @@ -88,11 +99,11 @@ export class MetadataNftService extends BaseService { order.payload.metadata || {}, ); if (!nftId) { - const nftDocRef = build5Db().doc(`${COL.NFT}/${nft.uid}`); - this.transactionService.push({ ref: nftDocRef, data: nft, action: 'set' }); + const nftDocRef = build5Db().doc(COL.NFT, nft.uid); + this.transactionService.push({ ref: nftDocRef, data: nft, action: Action.C }); } - const space = await build5Db().doc(`${COL.SPACE}/${order.space}`).get(); + const space = await build5Db().doc(COL.SPACE, order.space!).get(); const mintNftOrder = createMintMetadataNftOrder( order, @@ -101,8 +112,8 @@ export class MetadataNftService extends BaseService { order.payload.collectionId || '', order.uid, ); - const orderDocRef = build5Db().doc(`${COL.TRANSACTION}/${mintNftOrder.uid}`); - this.transactionService.push({ ref: orderDocRef, data: mintNftOrder, action: 'set' }); + const orderDocRef = build5Db().doc(COL.TRANSACTION, mintNftOrder.uid); + this.transactionService.push({ ref: orderDocRef, data: mintNftOrder, action: Action.C }); return; }; } @@ -153,7 +164,7 @@ export const createMetadataCollection = (project: string, space: string) => ({ }); export const createMintMetadataCollectionOrder = ( - transaction: Transaction, + transaction: Transaction | PgTransaction, collection: string, aliasId: string, orderId: string, @@ -165,11 +176,13 @@ export const createMintMetadataCollectionOrder = ( uid: getRandomEthAddress(), member: transaction.member, space: transaction.space, - network: transaction.network, + network: get(transaction, 'network') as Network, payload: { type: TransactionPayloadType.MINT_COLLECTION, - sourceAddress: transaction.payload.targetAddress, - targetAddress: transaction.payload.targetAddress, + sourceAddress: + get(transaction, 'payload.targetAddress') || get(transaction, 'payload_sourceAddress'), + targetAddress: + get(transaction, 'payload.targetAddress') || get(transaction, 'payload_targetAddress'), collection, aliasId, aliasBlockId, @@ -179,7 +192,7 @@ export const createMintMetadataCollectionOrder = ( }); export const createMintMetadataNftOrder = ( - transaction: Transaction, + transaction: Transaction | PgTransaction, nft: Nft, aliasGovAddress: NetworkAddress, collectionId: string, @@ -190,15 +203,17 @@ export const createMintMetadataNftOrder = ( uid: getRandomEthAddress(), member: nft.owner, space: nft.space, - network: transaction.network, + network: transaction.network as Network, payload: { type: nft.mintingData?.nftId ? TransactionPayloadType.UPDATE_MINTED_NFT : TransactionPayloadType.MINT_NFT, - sourceAddress: transaction.payload.targetAddress, + sourceAddress: + get(transaction, 'payload.targetAddress') || get(transaction, 'payload_targetAddress'), aliasGovAddress, - targetAddress: transaction.payload.targetAddress, - aliasId: transaction.payload.aliasId || '', + targetAddress: + get(transaction, 'payload.targetAddress') || get(transaction, 'payload_targetAddress'), + aliasId: get(transaction, 'payload.aliasId') || get(transaction, 'payload_aliasId', ''), collectionId, orderId: baseOrderId, nft: nft.uid, diff --git a/packages/functions/src/services/payment/nft/collection-minting.service.ts b/packages/functions/src/services/payment/nft/collection-minting.service.ts index 1dbb19877f..7c90dc22cb 100644 --- a/packages/functions/src/services/payment/nft/collection-minting.service.ts +++ b/packages/functions/src/services/payment/nft/collection-minting.service.ts @@ -1,18 +1,26 @@ -import { build5Db } from '@build-5/database'; +import { + PgCollectionStatus, + PgCollectionUpdate, + PgNetwork, + PgUnsoldMintingOptions, + build5Db, + convertEnum, +} from '@build-5/database'; import { COL, Collection, CollectionStatus, + Network, TransactionPayloadType, UnsoldMintingOptions, } from '@build-5/interfaces'; -import { get } from 'lodash'; import { BaseService, HandlerParams } from '../base'; +import { Action } from '../transaction-service'; export class CollectionMintingService extends BaseService { public handleRequest = async ({ order, match }: HandlerParams) => { - const collectionDocRef = build5Db().doc(`${COL.COLLECTION}/${order.payload.collection}`); - const collection = await this.transactionService.get(collectionDocRef); + const collectionDocRef = build5Db().doc(COL.COLLECTION, order.payload.collection!); + const collection = await this.transaction.get(collectionDocRef); const payment = await this.transactionService.createPayment(order, match); if (collection.status !== CollectionStatus.PRE_MINTED) { @@ -25,29 +33,32 @@ export class CollectionMintingService extends BaseService { } this.transactionService.markAsReconciled(order, match.msgId); - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const data: any = { - 'mintingData.mintingOrderId': order.uid, - 'mintingData.network': order.network, - 'mintingData.mintedBy': order.member, - 'mintingData.unsoldMintingOptions': get( - order, - 'payload.unsoldMintingOptions', - UnsoldMintingOptions.KEEP_PRICE, + const collectionUpdateData: PgCollectionUpdate = { + mintingData_mintingOrderId: order.uid, + mintingData_network: convertEnum(order.network, Network, PgNetwork), + mintingData_mintedBy: order.member, + mintingData_unsoldMintingOptions: convertEnum( + order.payload.unsoldMintingOptions || UnsoldMintingOptions.KEEP_PRICE, + UnsoldMintingOptions, + PgUnsoldMintingOptions, ), - 'mintingData.newPrice': get(order, 'payload.newPrice', 0), - 'mintingData.aliasStorageDeposit': get(order, 'payload.aliasStorageDeposit', 0), - 'mintingData.storageDeposit': get(order, 'payload.collectionStorageDeposit', 0), - 'mintingData.nftsStorageDeposit': get(order, 'payload.nftsStorageDeposit', 0), - 'mintingData.address': order.payload.targetAddress, - status: CollectionStatus.MINTING, + mintingData_newPrice: order.payload.newPrice || 0, + mintingData_aliasStorageDeposit: order.payload.aliasStorageDeposit || 0, + mintingData_storageDeposit: order.payload.collectionStorageDeposit || 0, + mintingData_nftsStorageDeposit: order.payload.nftsStorageDeposit || 0, + mintingData_address: order.payload.targetAddress, + status: PgCollectionStatus.MINTING, }; - // We have to set new default price on collection as well. - if (get(order, 'payload.newPrice', 0)) { - data.price = get(order, 'payload.newPrice', 0); + const newPrice = order.payload.newPrice || 0; + if (newPrice) { + collectionUpdateData.price = newPrice; } - this.transactionService.push({ ref: collectionDocRef, data, action: 'update' }); + this.transactionService.push({ + ref: collectionDocRef, + data: collectionUpdateData, + action: Action.U, + }); }; } diff --git a/packages/functions/src/services/payment/nft/common.ts b/packages/functions/src/services/payment/nft/common.ts index ae1544172c..4f5f49a221 100644 --- a/packages/functions/src/services/payment/nft/common.ts +++ b/packages/functions/src/services/payment/nft/common.ts @@ -1,25 +1,25 @@ import { build5Db } from '@build-5/database'; -import { COL, Collection, Member, Nft, NftAccess, Transaction } from '@build-5/interfaces'; +import { COL, Member, Nft, NftAccess, Transaction } from '@build-5/interfaces'; +import dayjs from 'dayjs'; import { getAddress } from '../../../utils/address.utils'; import { getProject } from '../../../utils/common.utils'; -import { serverTime } from '../../../utils/dateTime.utils'; import { createNftWithdrawOrder } from '../tangle-service/nft/nft-purchase.service'; -import { TransactionService } from '../transaction-service'; +import { Action, TransactionService } from '../transaction-service'; export class BaseNftService { constructor(private readonly transactionService: TransactionService) {} public setTradingStats = (nft: Nft) => { - const data = { lastTradedOn: serverTime(), totalTrades: build5Db().inc(1) }; - const collectionDocRef = build5Db().doc(`${COL.COLLECTION}/${nft.collection}`); - this.transactionService.push({ ref: collectionDocRef, data, action: 'update' }); + const data = { lastTradedOn: dayjs().toDate(), totalTrades: build5Db().inc(1) }; + const collectionDocRef = build5Db().doc(COL.COLLECTION, nft.collection); + this.transactionService.push({ ref: collectionDocRef, data, action: Action.U }); - const nftDocRef = build5Db().doc(`${COL.NFT}/${nft.uid}`); - this.transactionService.push({ ref: nftDocRef, data, action: 'update' }); + const nftDocRef = build5Db().doc(COL.NFT, nft.uid); + this.transactionService.push({ ref: nftDocRef, data, action: Action.U }); }; public withdrawNft = async (order: Transaction, nft: Nft) => { - const membderDocRef = build5Db().doc(`${COL.MEMBER}/${order.member}`); + const membderDocRef = build5Db().doc(COL.MEMBER, order.member!); const member = await membderDocRef.get(); const { order: withdrawOrder, nftUpdateData } = createNftWithdrawOrder( getProject(order), @@ -28,20 +28,20 @@ export class BaseNftService { getAddress(member, order.network!), ); this.transactionService.push({ - ref: build5Db().doc(`${COL.TRANSACTION}/${withdrawOrder.uid}`), + ref: build5Db().doc(COL.TRANSACTION, withdrawOrder.uid), data: withdrawOrder, - action: 'set', + action: Action.C, }); this.transactionService.push({ - ref: build5Db().doc(`${COL.NFT}/${nft.uid}`), + ref: build5Db().doc(COL.NFT, nft.uid), data: nftUpdateData, - action: 'update', + action: Action.U, }); }; public setNftOwner = async (order: Transaction, amount: number) => { const nftDocRef = build5Db().collection(COL.NFT).doc(order.payload.nft!); - const nft = await this.transactionService.get(nftDocRef); + const nft = await nftDocRef.get(); const nftUpdateData = { owner: order.member, @@ -51,7 +51,7 @@ export class BaseNftService { locked: false, lockedBy: null, hidden: false, - soldOn: nft.soldOn || serverTime(), + soldOn: nft.soldOn?.toDate() || dayjs().toDate(), availableFrom: null, availablePrice: null, auctionFrom: null, @@ -69,20 +69,20 @@ export class BaseNftService { this.transactionService.push({ ref: nftDocRef, data: nftUpdateData, - action: 'update', + action: Action.U, }); if (order.payload.beneficiary === 'space') { - const collectionDocRef = build5Db().doc(`${COL.COLLECTION}/${order.payload.collection}`); + const collectionDocRef = build5Db().doc(COL.COLLECTION, order.payload.collection!); this.transactionService.push({ ref: collectionDocRef, data: { sold: build5Db().inc(1) }, - action: 'update', + action: Action.U, }); - const collection = (await this.transactionService.get(collectionDocRef))!; + const collection = (await collectionDocRef.get())!; if (collection.placeholderNft && collection.total === collection.sold + 1) { - const placeholderNftDocRef = build5Db().doc(`${COL.NFT}/${collection.placeholderNft}`); + const placeholderNftDocRef = build5Db().doc(COL.NFT, collection.placeholderNft); this.transactionService.push({ ref: placeholderNftDocRef, data: { @@ -90,10 +90,10 @@ export class BaseNftService { owner: null, availablePrice: null, availableFrom: null, - soldOn: serverTime(), + soldOn: dayjs().toDate(), hidden: false, }, - action: 'update', + action: Action.U, }); } } 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 b24fb6316d..45b1a87d6b 100644 --- a/packages/functions/src/services/payment/nft/nft-deposit.service.ts +++ b/packages/functions/src/services/payment/nft/nft-deposit.service.ts @@ -1,7 +1,14 @@ -import { ITransaction, build5Db, build5Storage } from '@build-5/database'; +import { + ITransaction, + PgNetwork, + PgNftStatus, + PgNftUpdate, + build5Db, + build5Storage, + convertEnum, +} from '@build-5/database'; import { Access, - Award, COL, Categories, Collection, @@ -9,6 +16,7 @@ import { CollectionType, MediaStatus, MilestoneTransactionEntry, + Network, Nft, NftAccess, NftAvailable, @@ -17,14 +25,16 @@ import { Space, Transaction, TransactionPayloadType, + ValidatedAddress, WenError, } from '@build-5/interfaces'; import { NftOutput } from '@iota/sdk'; +import dayjs from 'dayjs'; import { head, isEmpty, set } from 'lodash'; import { getNftByMintingId } from '../../../utils/collection-minting-utils/nft.utils'; import { getProject } from '../../../utils/common.utils'; import { getBucket } from '../../../utils/config.utils'; -import { serverTime } from '../../../utils/dateTime.utils'; +import { dateToTimestamp, serverTime } from '../../../utils/dateTime.utils'; import { migrateUriToSotrage, uriToUrl } from '../../../utils/media.utils'; import { collectionIrc27Scheam, @@ -38,7 +48,7 @@ import { getRandomEthAddress } from '../../../utils/wallet.utils'; import { NftWallet } from '../../wallet/NftWallet'; import { WalletService } from '../../wallet/wallet.service'; import { BaseService, HandlerParams } from '../base'; -import { TransactionMatch } from '../transaction-service'; +import { Action, TransactionMatch } from '../transaction-service'; export class NftDepositService extends BaseService { public handleRequest = async ({ order, match, tranEntry }: HandlerParams) => { @@ -47,11 +57,11 @@ export class NftDepositService extends BaseService { await this.transactionService.createPayment(order, match); this.transactionService.markAsReconciled(order, match.msgId); - const orderDocRef = build5Db().doc(`${COL.TRANSACTION}/${order.uid}`); + const orderDocRef = build5Db().doc(COL.TRANSACTION, order.uid); this.transactionService.push({ ref: orderDocRef, - data: { 'payload.nft': nft.uid }, - action: 'update', + data: { payload_nft: nft.uid }, + action: Action.U, }); } catch (error) { const payment = await this.transactionService.createPayment(order, match, true); @@ -88,19 +98,45 @@ export class NftDepositService extends BaseService { nftOutput: NftOutput, match: TransactionMatch, ) => { - const collectionDocRef = build5Db().doc(`${COL.COLLECTION}/${nft.collection}`); - const collection = await this.transactionService.get(collectionDocRef); + const collectionDocRef = build5Db().doc(COL.COLLECTION, nft.collection); + const collection = await this.transaction.get(collectionDocRef); if (!collection.approved) { throw WenError.collection_must_be_approved; } - const data = { + const data: PgNftUpdate = { + status: PgNftStatus.MINTED, + depositData_address: order.payload.targetAddress, + depositData_network: convertEnum(order.network, Network, PgNetwork), + depositData_mintedOn: dayjs().toDate(), + depositData_mintedBy: order.member, + depositData_blockId: match.msgId, + depositData_nftId: nftOutput.nftId, + depositData_storageDeposit: match.to.amount, + depositData_mintingOrderId: order.uid, + hidden: false, + isOwned: true, + owner: order.member, + }; + const nftDocRef = build5Db().doc(COL.NFT, nft.uid); + this.transactionService.push({ ref: nftDocRef, data, action: Action.U }); + this.transactionService.push({ + ref: build5Db().doc(COL.TRANSACTION, order.uid), + data: { + space: nft.space, + payload_amount: match.to.amount, + payload_nft: nft.uid, + }, + action: Action.U, + }); + return { + ...nft, status: NftStatus.MINTED, depositData: { address: order.payload.targetAddress, network: order.network, - mintedOn: serverTime(), + mintedOn: dateToTimestamp(dayjs().toDate()), mintedBy: order.member, blockId: match.msgId, nftId: nftOutput.nftId, @@ -111,18 +147,6 @@ export class NftDepositService extends BaseService { isOwned: true, owner: order.member, }; - const nftDocRef = build5Db().doc(`${COL.NFT}/${nft.uid}`); - this.transactionService.push({ ref: nftDocRef, data, action: 'update' }); - this.transactionService.push({ - ref: build5Db().doc(`${COL.TRANSACTION}/${order.uid}`), - data: { - space: nft.space, - 'payload.amount': match.to.amount, - 'payload.nft': nft.uid, - }, - action: 'update', - }); - return { ...nft, ...data } as Nft; }; private depositNftMintedOutsideBuild5 = async ( @@ -228,20 +252,19 @@ export class NftDepositService extends BaseService { } const collectionDocRef = build5Db().doc( - `${COL.COLLECTION}/${(existingCollection || migratedCollection).uid}`, + COL.COLLECTION, + (existingCollection || migratedCollection).uid, ); + this.transactionService.push({ ref: collectionDocRef, - data: existingCollection - ? { total: build5Db().inc(1) } - : { ...migratedCollection, total: build5Db().inc(1) }, - action: 'set', - merge: true, + data: existingCollection ? { total: build5Db().inc(1) } : migratedCollection, + action: existingCollection ? Action.U : Action.C, }); if (isNewSpace) { - const spaceDocRef = build5Db().doc(`${COL.SPACE}/${space.uid}`); - this.transactionService.push({ ref: spaceDocRef, data: space, action: 'set' }); + const spaceDocRef = build5Db().doc(COL.SPACE, space.uid); + this.transactionService.push({ ref: spaceDocRef, data: space, action: Action.C }); } if (!existingCollection && !isEmpty(metadata.collection.royalties)) { @@ -252,19 +275,24 @@ export class NftDepositService extends BaseService { name: 'Royalty space for ' + migratedCollection.name, collectionId: migratedCollection.uid, claimed: false, - validatedAddress: { [order.network!]: royaltyAddress }, + validatedAddress: { [order.network!]: royaltyAddress } as unknown as ValidatedAddress, + createdBy: order.member!, + totalGuardians: 0, + totalMembers: 0, + totalPendingMembers: 0, + guardians: {}, + members: {}, }; - const royaltySpaceDocRef = build5Db().doc(`${COL.SPACE}/${royaltySpace.uid}`); + const royaltySpaceDocRef = build5Db().doc(COL.SPACE, royaltySpace.uid); this.transactionService.push({ ref: royaltySpaceDocRef, data: royaltySpace, - action: 'set', - merge: true, + action: Action.C, }); } - const nftDocRef = build5Db().doc(`${COL.NFT}/${nft.uid}`); - this.transactionService.push({ ref: nftDocRef, data: nft, action: 'set' }); + const nftDocRef = build5Db().doc(COL.NFT, nft.uid); + this.transactionService.push({ ref: nftDocRef, data: nft, action: Action.C }); return nft; }; @@ -300,15 +328,15 @@ export class NftDepositService extends BaseService { const getCollection = async (transaction: ITransaction, collectionId: string) => { const collectionSnap = await build5Db() .collection(COL.COLLECTION) - .where('mintingData.nftId', '==', collectionId) - .get(); + .where('mintingData_nftId', '==', collectionId) + .get(); if (collectionSnap.length) { - const docRef = build5Db().doc(`${COL.COLLECTION}/${collectionSnap[0].uid}`); - return await transaction.get(docRef); + const docRef = build5Db().doc(COL.COLLECTION, collectionSnap[0].uid); + return await transaction.get(docRef); } - const collectionDocRef = build5Db().doc(`${COL.COLLECTION}/${collectionId}`); - return await transaction.get(collectionDocRef); + const collectionDocRef = build5Db().doc(COL.COLLECTION, collectionId); + return await transaction.get(collectionDocRef); }; const getSpace = async ( @@ -317,7 +345,7 @@ const getSpace = async ( collectionId: string, ) => { if (collection) { - const spaceDocRef = build5Db().doc(`${COL.SPACE}/${collection.space}`); + const spaceDocRef = build5Db().doc(COL.SPACE, collection.space!); const space = await spaceDocRef.get(); return { space, isNewSpace: false }; } @@ -326,11 +354,11 @@ const getSpace = async ( .collection(COL.AWARD) .where('collectionId', '==', collectionId) .limit(1) - .get(); + .get(); if (awardsSnap.length) { const award = awardsSnap[0]; - const spaceDocRef = build5Db().doc(`${COL.SPACE}/${award.space}`); + const spaceDocRef = build5Db().doc(COL.SPACE, award.space); const space = await spaceDocRef.get(); return { space, isNewSpace: false }; } diff --git a/packages/functions/src/services/payment/nft/nft-purchase.bulk.service.ts b/packages/functions/src/services/payment/nft/nft-purchase.bulk.service.ts index af35c4d344..ad774a1cdd 100644 --- a/packages/functions/src/services/payment/nft/nft-purchase.bulk.service.ts +++ b/packages/functions/src/services/payment/nft/nft-purchase.bulk.service.ts @@ -24,6 +24,7 @@ import { getRandomEthAddress } from '../../../utils/wallet.utils'; import { WalletService } from '../../wallet/wallet.service'; import { BaseService, HandlerParams } from '../base'; import { assertNftCanBePurchased, getMember } from '../tangle-service/nft/nft-purchase.service'; +import { Action } from '../transaction-service'; import { NftPurchaseService } from './nft-purchase.service'; export class NftPurchaseBulkService extends BaseService { @@ -35,15 +36,15 @@ export class NftPurchaseBulkService extends BaseService { ); const nftOrders = await Promise.all(promises); - const orderDocRef = build5Db().doc(`${COL.TRANSACTION}/${order.uid}`); + const orderDocRef = build5Db().doc(COL.TRANSACTION, order.uid); this.transactionService.push({ ref: orderDocRef, data: { - 'payload.nftOrders': nftOrders, - 'payload.reconciled': true, - 'payload.chainReference': match.msgId, + payload_nftOrders: JSON.stringify(nftOrders), + payload_reconciled: true, + payload_chainReference: match.msgId, }, - action: 'update', + action: Action.U, }); const total = nftOrders.reduce((acc, act) => acc + act.price, 0); @@ -65,8 +66,8 @@ export class NftPurchaseBulkService extends BaseService { void: false, }, }; - const docRef = build5Db().doc(`${COL.TRANSACTION}/${credit.uid}`); - this.transactionService.push({ ref: docRef, data: credit, action: 'set' }); + const docRef = build5Db().doc(COL.TRANSACTION, credit.uid); + this.transactionService.push({ ref: docRef, data: credit, action: Action.C }); } if (total) { @@ -87,13 +88,11 @@ export class NftPurchaseBulkService extends BaseService { targetAddresses, sourceTransaction: [payment.uid], expiresOn: dateToTimestamp(dayjs().add(TRANSACTION_AUTO_EXPIRY_MS)), - milestoneTransactionPath: `${getMilestoneCol(order.network!)}/${tran.milestone}/${ - SUB_COL.TRANSACTIONS - }/${tran.uid}`, + milestoneTransactionPath: `${getMilestoneCol(order.network!)}/${tran.milestone}/${SUB_COL.TRANSACTIONS}/${tran.uid}`, }, }; - const docRef = build5Db().doc(`${COL.TRANSACTION}/${transfer.uid}`); - this.transactionService.push({ ref: docRef, data: transfer, action: 'set' }); + const docRef = build5Db().doc(COL.TRANSACTION, transfer.uid); + this.transactionService.push({ ref: docRef, data: transfer, action: Action.C }); } }; @@ -106,13 +105,13 @@ export class NftPurchaseBulkService extends BaseService { return { ...nftOrder, targetAddress: '' }; } - const nftDocRef = build5Db().doc(`${COL.NFT}/${nftOrder.nft}`); - const nft = await this.transactionService.get(nftDocRef); + const nftDocRef = build5Db().doc(COL.NFT, nftOrder.nft); + const nft = await this.transaction.get(nftDocRef); - const collectionDocRef = build5Db().doc(`${COL.COLLECTION}/${nft.collection}`); + const collectionDocRef = build5Db().doc(COL.COLLECTION, nft.collection); const collection = await collectionDocRef.get(); - const spaceDocRef = build5Db().doc(`${COL.SPACE}/${nft.space}`); + const spaceDocRef = build5Db().doc(COL.SPACE, nft.space); const space = await spaceDocRef.get(); try { await assertNftCanBePurchased( @@ -136,11 +135,10 @@ export class NftPurchaseBulkService extends BaseService { const nftPurchaseOrderId = getRandomEthAddress(); - const nftDocRef = build5Db().doc(`${COL.NFT}/${nft.uid}`); this.transactionService.push({ - ref: nftDocRef, + ref: build5Db().doc(COL.NFT, nft.uid), data: { locked: true, lockedBy: order.uid }, - action: 'update', + action: Action.U, }); const currentOwner = nft.owner ? await getMember(nft.owner) : space; @@ -173,15 +171,15 @@ export class NftPurchaseBulkService extends BaseService { }, linkedTransactions: [], }; - const docRef = build5Db().doc(`${COL.TRANSACTION}/${nftPurchaseOrder.uid}`); - this.transactionService.push({ ref: docRef, data: nftPurchaseOrder, action: 'set' }); + const docRef = build5Db().doc(COL.TRANSACTION, nftPurchaseOrder.uid); + this.transactionService.push({ ref: docRef, data: nftPurchaseOrder, action: Action.C }); return { ...nftOrder, targetAddress: targetAddress.bech32 }; } catch (error) { return { ...nftOrder, price: 0, - error: get(error, 'details.code', 0), + error: get(error, 'eCode', 0), targetAddress: '', } as NftBulkOrder; } diff --git a/packages/functions/src/services/payment/nft/nft-purchase.service.ts b/packages/functions/src/services/payment/nft/nft-purchase.service.ts index 679fa61f3a..e01fe2415c 100644 --- a/packages/functions/src/services/payment/nft/nft-purchase.service.ts +++ b/packages/functions/src/services/payment/nft/nft-purchase.service.ts @@ -1,4 +1,4 @@ -import { build5Db } from '@build-5/database'; +import { PgTransactionType, build5Db } from '@build-5/database'; import { Auction, COL, @@ -6,15 +6,15 @@ import { NftStatus, Transaction, TransactionPayloadType, - TransactionType, } from '@build-5/interfaces'; import { BaseService, HandlerParams } from '../base'; +import { Action } from '../transaction-service'; import { BaseNftService } from './common'; export class NftPurchaseService extends BaseService { public handleRequest = async ({ order, match, tran, tranEntry, build5Tran }: HandlerParams) => { - const nftDocRef = build5Db().doc(`${COL.NFT}/${order.payload.nft}`); - const nft = await this.transactionService.get(nftDocRef); + const nftDocRef = build5Db().doc(COL.NFT, order.payload.nft!); + const nft = await this.transaction.get(nftDocRef); if (nft.availableFrom === null) { await this.transactionService.processAsInvalid(tran, order, tranEntry, build5Tran); @@ -43,22 +43,22 @@ export class NftPurchaseService extends BaseService { }; public creditBids = async (auctionId: string) => { - const auctionDocRef = build5Db().doc(`${COL.AUCTION}/${auctionId}`); + const auctionDocRef = build5Db().doc(COL.AUCTION, auctionId); const auction = await this.transaction.get(auctionDocRef); this.transactionService.push({ ref: auctionDocRef, data: { active: false }, - action: 'update', + action: Action.U, }); for (const bid of auction.bids) { const payments = await build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.PAYMENT) + .where('type', '==', PgTransactionType.PAYMENT) .where('member', '==', bid.bidder) - .where('payload.invalidPayment', '==', false) - .where('payload.auction', '==', auctionId) - .get(); + .where('payload_invalidPayment', '==', false) + .where('payload_auction', '==', auctionId) + .get(); for (const payment of payments) { await this.transactionService.createCredit(TransactionPayloadType.NONE, payment, { msgId: payment.payload.chainReference || '', @@ -73,42 +73,44 @@ export class NftPurchaseService extends BaseService { }; public markAsVoid = async (transaction: Transaction): Promise => { - const refSource = build5Db().doc(`${COL.TRANSACTION}/${transaction.uid}`); - const data = (await this.transactionService.get(refSource))!; + const tranDocRef = build5Db().doc(COL.TRANSACTION, transaction.uid); + + const setVoid = () => { + this.transactionService.push({ + ref: tranDocRef, + data: { payload_void: true }, + action: Action.U, + }); + }; + if (transaction.payload.nft) { if (transaction.payload.type === TransactionPayloadType.NFT_PURCHASE) { - const payload = data.payload; - payload.void = true; - this.transactionService.push({ ref: refSource, data: data, action: 'update' }); + setVoid(); - // Unlock NFT. - const refNft = build5Db().collection(COL.NFT).doc(transaction.payload.nft); this.transactionService.push({ - ref: refNft, + ref: build5Db().doc(COL.NFT, transaction.payload.nft), data: { locked: false, lockedBy: null }, - action: 'update', + action: Action.U, }); - } else if ( - [TransactionPayloadType.AUCTION_BID, TransactionPayloadType.NFT_BID].includes( - transaction.payload.type!, - ) + return; + } + if ( + transaction.payload.type === TransactionPayloadType.AUCTION_BID || + transaction.payload.type === TransactionPayloadType.NFT_BID ) { const payments = await build5Db() .collection(COL.TRANSACTION) - .where('payload.invalidPayment', '==', false) - .where('payload.sourceTransaction', 'array-contains', transaction.uid) + .where('payload_invalidPayment', '==', false) + // eslint-disable-next-line @typescript-eslint/no-explicit-any + .where('payload_sourceTransaction', 'array-contains', transaction.uid as any) .limit(1) .get(); if (payments.length === 0) { - const payload = data.payload; - payload.void = true; - this.transactionService.push({ ref: refSource, data: data, action: 'update' }); + setVoid(); } } - } else { - const payload = data.payload; - payload.void = true; - this.transactionService.push({ ref: refSource, data, action: 'update' }); } + + setVoid(); }; } 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 5fbfeb28dd..720c4d6cf9 100644 --- a/packages/functions/src/services/payment/nft/nft-stake.service.ts +++ b/packages/functions/src/services/payment/nft/nft-stake.service.ts @@ -20,12 +20,13 @@ import { Utils, } from '@iota/sdk'; import dayjs from 'dayjs'; -import { cloneDeep, get } from 'lodash'; +import { cloneDeep } from 'lodash'; import { dateToTimestamp } from '../../../utils/dateTime.utils'; import { getRandomEthAddress } from '../../../utils/wallet.utils'; import { WalletService } from '../../wallet/wallet.service'; import { BaseService, HandlerParams } from '../base'; import { createNftWithdrawOrder } from '../tangle-service/nft/nft-purchase.service'; +import { Action } from '../transaction-service'; import { NftDepositService } from './nft-deposit.service'; export class NftStakeService extends BaseService { @@ -49,31 +50,31 @@ export class NftStakeService extends BaseService { nft, order.member!, match.from, - get(order, 'payload.weeks', 0), - get(order, 'payload.stakeType', StakeType.DYNAMIC), + order.payload.weeks || 0, + order.payload.stakeType || StakeType.DYNAMIC, ); - const withdrawOrderDocRef = build5Db().doc(`${COL.TRANSACTION}/${withdrawOrder.uid}`); + const withdrawOrderDocRef = build5Db().doc(COL.TRANSACTION, withdrawOrder.uid); this.transactionService.push({ ref: withdrawOrderDocRef, data: withdrawOrder, - action: 'set', + action: Action.C, }); - const nftDocRef = build5Db().doc(`${COL.NFT}/${nftUpdateData.uid}`); + const nftDocRef = build5Db().doc(COL.NFT, nft.uid); this.transactionService.push({ ref: nftDocRef, data: nftUpdateData, - action: 'update', + action: Action.U, }); await this.transactionService.createPayment(order, match); this.transactionService.markAsReconciled(order, match.msgId); - const orderDocRef = build5Db().doc(`${COL.TRANSACTION}/${order.uid}`); + const orderDocRef = build5Db().doc(COL.TRANSACTION, order.uid); this.transactionService.push({ ref: orderDocRef, - data: { 'payload.nft': nft.uid, 'payload.collection': nft.collection }, - action: 'update', + data: { payload_nft: nft.uid, payload_collection: nft.collection }, + action: Action.U, }); // eslint-disable-next-line @typescript-eslint/no-explicit-any } catch (error: any) { @@ -91,7 +92,7 @@ export class NftStakeService extends BaseService { private getNftOutputAmount = async (order: Transaction, tranEntry: MilestoneTransactionEntry) => { const wallet = await WalletService.newWallet(order.network); - const weeks = get(order, 'payload.weeks', 0); + const weeks = order.payload.weeks || 0; const params: NftOutputBuilderParams = cloneDeep(tranEntry.nftOutput as NftOutput); params.features = params.features?.filter( (f) => f.type !== FeatureType.Tag && f.type !== FeatureType.Sender, diff --git a/packages/functions/src/services/payment/nft/nft-transfer.service.ts b/packages/functions/src/services/payment/nft/nft-transfer.service.ts index 3c16f3750d..95d183abab 100644 --- a/packages/functions/src/services/payment/nft/nft-transfer.service.ts +++ b/packages/functions/src/services/payment/nft/nft-transfer.service.ts @@ -1,4 +1,4 @@ -import { ITransaction, build5Db } from '@build-5/database'; +import { ITransaction, PgNftUpdate, build5Db } from '@build-5/database'; import { COL, Entity, @@ -22,7 +22,7 @@ interface NftTransfer { interface NftTransferResponse { code: number; - nftUpdateData?: unknown; + nftUpdateData?: PgNftUpdate; order?: Transaction; } @@ -35,8 +35,8 @@ export const createNftTransferData = async ( const members: { [uid: string]: Member } = {}; const getTarget = async (nft: Nft, transfer: NftTransfer) => { - const memberDocRef = build5Db().doc(`${COL.MEMBER}/${transfer.target}`); - const member = members[transfer.target] || (await memberDocRef.get()); + const memberDocRef = build5Db().doc(COL.MEMBER, transfer.target); + const member = members[transfer.target] || (await memberDocRef.get()); if (member) { members[transfer.target] = member; @@ -58,7 +58,7 @@ export const createNftTransferData = async ( try { assertCanBeWithdrawn(nft, owner); } catch (error) { - return { [transfer.nft]: { code: get(error, 'details.code', 0) } }; + return { [transfer.nft]: { code: get(error, 'eCode', 0) } }; } const { targetAddress, withdraw } = await getTarget(nft, transfer); @@ -91,7 +91,7 @@ export const createNftTransferData = async ( } const { order, nftUpdateData } = createNftWithdrawOrder(project, nft, owner, targetAddress); - return { [transfer.nft]: { code: 200, nftUpdateData: nftUpdateData, order } }; + return { [transfer.nft]: { code: 200, nftUpdateData, order } }; }, ); @@ -99,14 +99,14 @@ export const createNftTransferData = async ( }; const getNft = async (transaction: ITransaction, uidOrTangleId: string) => { - const nftDocRef = build5Db().doc(`${COL.NFT}/${uidOrTangleId}`); - const nft = await transaction.get(nftDocRef); + const nftDocRef = build5Db().doc(COL.NFT, uidOrTangleId); + const nft = await transaction.get(nftDocRef); if (nft) { return nft; } const snap = await build5Db() .collection(COL.NFT) - .where('mintingData.nftId', '==', uidOrTangleId) - .get(); + .where('mintingData_nftId', '==', uidOrTangleId) + .get(); return head(snap); }; diff --git a/packages/functions/src/services/payment/payment-processing.ts b/packages/functions/src/services/payment/payment-processing.ts index 5feb8a7866..37454c056e 100644 --- a/packages/functions/src/services/payment/payment-processing.ts +++ b/packages/functions/src/services/payment/payment-processing.ts @@ -1,4 +1,4 @@ -import { ITransaction, build5Db } from '@build-5/database'; +import { ITransaction, PgTransactionType, build5Db } from '@build-5/database'; import { COL, MilestoneTransaction, @@ -38,7 +38,7 @@ import { TokenMintedAirdropService } from './token/token-minted-airdrop.service' import { MintedTokenClaimService } from './token/token-minted-claim.service'; import { TokenPurchaseService } from './token/token-purchase.service'; import { TokenTradeService } from './token/token-trade.service'; -import { TransactionService } from './transaction-service'; +import { Action, TransactionService } from './transaction-service'; import { VotingService } from './voting-service'; export class ProcessingService { @@ -77,8 +77,8 @@ export class ProcessingService { orderId: string, build5Tran: Transaction | undefined, ): Promise { - const orderRef = build5Db().doc(`${COL.TRANSACTION}/${orderId}`); - const order = await this.tranService.transaction.get(orderRef); + const orderRef = build5Db().doc(COL.TRANSACTION, orderId); + const order = await this.transaction.get(orderRef); if (!order) { return; @@ -103,7 +103,7 @@ export class ProcessingService { const type = tranEntry.nftOutput ? TransactionPayloadType.UNLOCK_NFT : TransactionPayloadType.UNLOCK_FUNDS; - await this.tranService.createUnlockTransaction( + this.tranService.createUnlockTransaction( undefined, order, tran, @@ -138,7 +138,7 @@ export class ProcessingService { ...this.tranService.linkedTransactions, ], }, - action: 'update', + action: Action.U, }); } @@ -203,10 +203,10 @@ export class ProcessingService { private findOrderForAddress = async (address: NetworkAddress) => { const snap = await build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.ORDER) - .where('payload.targetAddress', '==', address) + .where('type', '==', PgTransactionType.ORDER) + .where('payload_targetAddress', '==', address) .limit(1) - .get(); + .get(); return head(snap); }; @@ -214,7 +214,7 @@ export class ProcessingService { if (isEmpty(tran.build5TransactionId)) { return; } - const docRef = build5Db().doc(`${COL.TRANSACTION}/${tran.build5TransactionId}`); - return docRef.get(); + const docRef = build5Db().doc(COL.TRANSACTION, tran.build5TransactionId!); + return docRef.get(); }; } diff --git a/packages/functions/src/services/payment/space/space-service.ts b/packages/functions/src/services/payment/space/space-service.ts index 11f2c2a327..2d6f332326 100644 --- a/packages/functions/src/services/payment/space/space-service.ts +++ b/packages/functions/src/services/payment/space/space-service.ts @@ -21,6 +21,7 @@ import { getProject } from '../../../utils/common.utils'; import { serverTime } from '../../../utils/dateTime.utils'; import { WalletService } from '../../wallet/wallet.service'; import { BaseService, HandlerParams } from '../base'; +import { Action } from '../transaction-service'; export class SpaceClaimService extends BaseService { public handleRequest = async ({ order, match }: HandlerParams) => { @@ -31,13 +32,13 @@ export class SpaceClaimService extends BaseService { match, ); - const spaceDocRef = build5Db().doc(`${COL.SPACE}/${order.space}`); - const space = await this.transactionService.get(spaceDocRef); + const spaceDocRef = build5Db().doc(COL.SPACE, order.space!); + const space = await this.transaction.get(spaceDocRef); if (!space.collectionId || space.claimed) { return; } - const collectionDocRef = build5Db().doc(`${COL.COLLECTION}/${space.collectionId}`); + const collectionDocRef = build5Db().doc(COL.COLLECTION, space.collectionId); const collection = await collectionDocRef.get(); const senderIsIssuer = await senderIsCollectionIssuer(order.network!, match.from, collection); @@ -52,33 +53,43 @@ export class SpaceClaimService extends BaseService { parentCol: COL.SPACE, createdOn: serverTime(), }; - const spaceGuardianDocRef = spaceDocRef.collection(SUB_COL.GUARDIANS).doc(order.member!); + const spaceGuardianDocRef = build5Db().doc( + COL.SPACE, + order.space!, + SUB_COL.GUARDIANS, + order.member!, + ); this.transactionService.push({ ref: spaceGuardianDocRef, data: spaceMember, - action: 'set', - merge: true, + action: Action.C, }); - const spaceMemberDocRef = spaceDocRef.collection(SUB_COL.MEMBERS).doc(order.member!); + const spaceMemberDocRef = build5Db().doc( + COL.SPACE, + order.space!, + SUB_COL.MEMBERS, + order.member!, + ); this.transactionService.push({ ref: spaceMemberDocRef, data: spaceMember, - action: 'set', - merge: true, + action: Action.C, }); this.transactionService.push({ ref: spaceDocRef, - data: { totalMembers: build5Db().inc(1), totalGuardians: build5Db().inc(1), claimed: true }, - action: 'update', + data: { + totalMembers: build5Db().inc(1), + totalGuardians: build5Db().inc(1), + claimed: true, + }, + action: Action.U, }); - const memberDocRef = build5Db().doc(`${COL.MEMBER}/${order.member}`); this.transactionService.push({ - ref: memberDocRef, + ref: build5Db().doc(COL.MEMBER, order.member!), data: { spaces: { [space.uid]: { uid: space.uid, isMember: true } } }, - action: 'update', - merge: true, + action: Action.U, }); }; } diff --git a/packages/functions/src/services/payment/stake-service.ts b/packages/functions/src/services/payment/stake-service.ts index d5d4f575a5..2cd26e1ea4 100644 --- a/packages/functions/src/services/payment/stake-service.ts +++ b/packages/functions/src/services/payment/stake-service.ts @@ -11,11 +11,11 @@ import { calcStakedMultiplier, } from '@build-5/interfaces'; import dayjs from 'dayjs'; -import { get } from 'lodash'; import { getProject } from '../../utils/common.utils'; import { dateToTimestamp } from '../../utils/dateTime.utils'; import { getRandomEthAddress } from '../../utils/wallet.utils'; import { BaseService, HandlerParams } from './base'; +import { Action } from './transaction-service'; export class StakeService extends BaseService { public handleRequest = async ({ project, order, match }: HandlerParams) => { @@ -23,7 +23,7 @@ export class StakeService extends BaseService { const matchAmount = match.to.amount; const nativeTokens = (match.to.nativeTokens || []).map((nt) => ({ ...nt, amount: nt.amount })); - const tokenId = get(order, 'payload.tokenId', ''); + const tokenId = order.payload.tokenId || ''; const stakeAmount = Number(nativeTokens.find((nt) => nt.id === tokenId)?.amount || 0); if (!stakeAmount || nativeTokens.length > 1 || matchAmount < order.payload.amount!) { @@ -36,12 +36,12 @@ export class StakeService extends BaseService { } this.transactionService.markAsReconciled(order, match.msgId); - const weeks = get(order, 'payload.weeks', 1); + const weeks = order.payload.weeks || 1; const stakedValue = Math.floor(stakeAmount * calcStakedMultiplier(weeks)); const expiresAt = dateToTimestamp(dayjs().add(weeks, 'week').toDate()); - const tokenUid = get(order, 'payload.token', ''); - const tokenDocRef = build5Db().doc(`${COL.TOKEN}/${tokenUid}`); + const tokenUid = order.payload.token || ''; + const tokenDocRef = build5Db().doc(COL.TOKEN, tokenUid); const token = await tokenDocRef.get(); const billPayment: Transaction = { @@ -65,7 +65,7 @@ export class StakeService extends BaseService { royalty: false, void: false, vestingAt: expiresAt, - customMetadata: get(order, 'payload.customMetadata', {}), + customMetadata: order.payload.customMetadata || {}, token: token!.uid, tokenSymbol: token!.symbol, }, @@ -76,7 +76,7 @@ export class StakeService extends BaseService { uid: getRandomEthAddress(), member: order.member!, token: order.payload.token!, - type: get(order, 'payload.stakeType', StakeType.DYNAMIC), + type: order.payload.stakeType || StakeType.DYNAMIC, space: order.space!, amount: stakeAmount, value: stakedValue, @@ -85,20 +85,20 @@ export class StakeService extends BaseService { expirationProcessed: false, orderId: order.uid, billPaymentId: billPayment.uid, - customMetadata: get(order, 'payload.customMetadata', {}), + customMetadata: order.payload.customMetadata || {}, }; billPayment.payload.stake = stake.uid; this.transactionService.push({ - ref: build5Db().doc(`${COL.STAKE}/${stake.uid}`), + ref: build5Db().doc(COL.STAKE, stake.uid), data: stake, - action: 'set', + action: Action.C, }); this.transactionService.push({ - ref: build5Db().doc(`${COL.TRANSACTION}/${billPayment.uid}`), + ref: build5Db().doc(COL.TRANSACTION, billPayment.uid), data: billPayment, - action: 'set', + action: Action.C, }); }; } diff --git a/packages/functions/src/services/payment/stamp.service.ts b/packages/functions/src/services/payment/stamp.service.ts index e07219b21e..c79ca8dbbe 100644 --- a/packages/functions/src/services/payment/stamp.service.ts +++ b/packages/functions/src/services/payment/stamp.service.ts @@ -1,4 +1,4 @@ -import { build5Db, build5Storage } from '@build-5/database'; +import { PgMediaStatus, build5Db, build5Storage, convertEnum } from '@build-5/database'; import { COL, MediaStatus, @@ -13,19 +13,19 @@ import { set } from 'lodash'; import { packBasicOutput } from '../../utils/basic-output.utils'; import { getProject } from '../../utils/common.utils'; import { getBucket, getStampRoyaltyAddress } from '../../utils/config.utils'; -import { dateToTimestamp } from '../../utils/dateTime.utils'; import { migrateUriToSotrage, uriToUrl } from '../../utils/media.utils'; import { getRandomEthAddress } from '../../utils/wallet.utils'; import { isStorageUrl } from '../joi/common'; import { WalletService } from '../wallet/wallet.service'; import { BaseService, HandlerParams } from './base'; import { getStampDailyCost } from './tangle-service/stamp/StampTangleService'; +import { Action } from './transaction-service'; export class StampService extends BaseService { public handleRequest = async ({ order, match }: HandlerParams) => { const payment = await this.transactionService.createPayment(order, match); - const stampDocRef = build5Db().doc(`${COL.STAMP}/${order.payload.stamp}`); + const stampDocRef = build5Db().doc(COL.STAMP, order.payload.stamp!); const stamp = await this.transaction.get(stampDocRef); const mintAmount = stamp.funded @@ -84,11 +84,10 @@ export class StampService extends BaseService { void: false, }, }; - const creditDocRef = build5Db().doc(`${COL.TRANSACTION}/${credit.uid}`); this.transactionService.push({ - ref: creditDocRef, + ref: build5Db().doc(COL.TRANSACTION, credit.uid), data: credit, - action: 'set', + action: Action.C, }); } } @@ -98,8 +97,12 @@ export class StampService extends BaseService { ); const updateData = { funded: true, - mediaStatus: stamp.mediaStatus || MediaStatus.PENDING_UPLOAD, - expiresAt: dateToTimestamp(expiresAt), + mediaStatus: convertEnum( + stamp.mediaStatus || MediaStatus.PENDING_UPLOAD, + MediaStatus, + PgMediaStatus, + ), + expiresAt: expiresAt.toDate(), }; if (!stamp.funded && !isStorageUrl(stamp.originUri)) { const bucket = build5Storage().bucket(getBucket()); @@ -113,7 +116,7 @@ export class StampService extends BaseService { ); set(updateData, 'build5Url', build5Url); } - this.transactionService.push({ ref: stampDocRef, data: updateData, action: 'update' }); + this.transactionService.push({ ref: stampDocRef, data: updateData, action: Action.U }); const aliasId = order.payload.aliasId; @@ -136,21 +139,19 @@ export class StampService extends BaseService { void: false, }, }; - const royaltyPaymentDocRef = build5Db().doc(`${COL.TRANSACTION}/${royaltyPayment.uid}`); this.transactionService.push({ - ref: royaltyPaymentDocRef, + ref: build5Db().doc(COL.TRANSACTION, royaltyPayment.uid), data: royaltyPayment, - action: 'set', + action: Action.C, }); - const orderDocRef = build5Db().doc(`${COL.TRANSACTION}/${order.uid}`); this.transactionService.push({ - ref: orderDocRef, + ref: build5Db().doc(COL.TRANSACTION, order.uid), data: { - 'payload.days': build5Db().deleteField(), - 'payload.amount': Number(royaltyOutput.amount), + payload_days: undefined, + payload_amount: Number(royaltyOutput.amount), }, - action: 'update', + action: Action.U, }); if (stamp.funded) { @@ -177,14 +178,14 @@ export class StampService extends BaseService { }, }; this.transactionService.push({ - ref: build5Db().doc(`${COL.TRANSACTION}/${mintAlias.uid}`), + ref: build5Db().doc(COL.TRANSACTION, mintAlias.uid), data: mintAlias, - action: 'set', + action: Action.C, }); return; } - const spaceDocRef = build5Db().doc(`${COL.SPACE}/${stamp.space}`); + const spaceDocRef = build5Db().doc(COL.SPACE, stamp.space); const space = await spaceDocRef.get(); const mintNftOrder: Transaction = { @@ -205,11 +206,11 @@ export class StampService extends BaseService { stamp: order.payload.stamp, }, }; - const nftMintOrderDocRef = build5Db().doc(`${COL.TRANSACTION}/${mintNftOrder.uid}`); + const nftMintOrderDocRef = build5Db().doc(COL.TRANSACTION, mintNftOrder.uid); this.transactionService.push({ ref: nftMintOrderDocRef, data: mintNftOrder, - action: 'set', + action: Action.C, }); return; diff --git a/packages/functions/src/services/payment/swap/swap-service.ts b/packages/functions/src/services/payment/swap/swap-service.ts index a7bf482a08..460cc28d95 100644 --- a/packages/functions/src/services/payment/swap/swap-service.ts +++ b/packages/functions/src/services/payment/swap/swap-service.ts @@ -1,10 +1,9 @@ -import { build5Db } from '@build-5/database'; +import { PgSwapStatus, build5Db } from '@build-5/database'; import { COL, Entity, Member, Network, - Nft, Swap, SwapCreateRequest, SwapCreateTangleRequest, @@ -25,17 +24,17 @@ import { invalidArgument } from '../../../utils/error.utils'; import { getRandomEthAddress } from '../../../utils/wallet.utils'; import { Wallet } from '../../wallet/wallet'; import { BaseService, HandlerParams } from '../base'; -import { TransactionMatch } from '../transaction-service'; +import { Action, TransactionMatch } from '../transaction-service'; export class SwapService extends BaseService { handleRequest = async ({ project, order, match }: HandlerParams) => { const payment = await this.transactionService.createPayment(order, match); - const swapDocRef = build5Db().doc(`${COL.SWAP}/${order.payload.swap!}`); - const swap = await swapDocRef.get(); + const swapDocRef = build5Db().doc(COL.SWAP, order.payload.swap!); + const swap = await this.transaction.get(swapDocRef); if (swap.status == SwapStatus.FULFILLED || swap.status === SwapStatus.REJECTED) { - await this.createCredit(payment, match); + this.createCredit(payment, match); return; } @@ -51,8 +50,8 @@ export class SwapService extends BaseService { const fieldName = this.getUpdateFieldName(swap, swapOutput); this.transactionService.push({ ref: swapDocRef, - data: { [fieldName]: build5Db().arrayUnion(swapOutput) }, - action: 'update', + data: { [fieldName]: JSON.stringify([...get(swap, fieldName, []), swapOutput]) }, + action: Action.U, }); if (fieldName !== 'askOutputs') { @@ -66,14 +65,14 @@ export class SwapService extends BaseService { const transfers = await createSwapTransfers(project, { ...swap, askOutputs }); for (const transfer of transfers) { - const docRef = build5Db().doc(`${COL.TRANSACTION}/${transfer.uid}`); - this.transactionService.push({ ref: docRef, data: transfer, action: 'set' }); + const docRef = build5Db().doc(COL.TRANSACTION, transfer.uid); + this.transactionService.push({ ref: docRef, data: transfer, action: Action.C }); } this.transactionService.push({ ref: swapDocRef, - data: { status: SwapStatus.FULFILLED }, - action: 'update', + data: { status: PgSwapStatus.FULFILLED }, + action: Action.U, }); }; @@ -90,17 +89,17 @@ export class SwapService extends BaseService { return swap.baseTokenAmountAsk ? 'askOutputs' : 'bidOutputs'; }; - private createCredit = async (payment: Transaction, match: TransactionMatch) => { + private createCredit = (payment: Transaction, match: TransactionMatch) => { if (match.to.nftOutput?.nftId) { this.transactionService.createNftCredit(payment, match); return; } this.transactionService.createCredit(TransactionPayloadType.SWAP, payment, match); - const paymentDocRef = build5Db().doc(`${COL.TRANSACTION}/${payment.uid}`); + const paymentDocRef = build5Db().doc(COL.TRANSACTION, payment.uid); this.transactionService.push({ ref: paymentDocRef, - data: { 'payload.invalidPayment': true }, - action: 'set', + data: { payload_invalidPayment: true }, + action: Action.U, }); }; } @@ -168,8 +167,8 @@ export const createSwapOrder = async ( }; const getNftTangleId = async (wallet: Wallet, uidOrTangleId: string) => { - const docRef = build5Db().doc(`${COL.NFT}/${uidOrTangleId}`); - const nft = await docRef.get(); + const docRef = build5Db().doc(COL.NFT, uidOrTangleId); + const nft = await docRef.get(); if (nft?.mintingData?.nftId) { return nft.mintingData.nftId; } @@ -324,7 +323,7 @@ export const asksAreFulfilled = (swap: Swap) => { }; export const createSwapTransfers = async (project: string, swap: Swap) => { - const targetMemberDocRef = build5Db().doc(`${COL.MEMBER}/${swap.recipient}`); + const targetMemberDocRef = build5Db().doc(COL.MEMBER, swap.recipient); const targetMember = await targetMemberDocRef.get(); const bidTransfers = (swap.bidOutputs || []).map((bid) => { @@ -339,7 +338,7 @@ export const createSwapTransfers = async (project: string, swap: Swap) => { ); }); - const memberDocRef = build5Db().doc(`${COL.MEMBER}/${swap.createdBy}`); + const memberDocRef = build5Db().doc(COL.MEMBER, swap.createdBy!); const mmber = await memberDocRef.get(); const askTransfers = (swap.askOutputs || []).map((ask) => { const func = ask.nftId ? createNftTransfer : createAssetTransfer; diff --git a/packages/functions/src/services/payment/tangle-service/TangleRequestService.ts b/packages/functions/src/services/payment/tangle-service/TangleRequestService.ts index fe029ae402..83b0f120d7 100644 --- a/packages/functions/src/services/payment/tangle-service/TangleRequestService.ts +++ b/packages/functions/src/services/payment/tangle-service/TangleRequestService.ts @@ -1,12 +1,12 @@ import { build5Db } from '@build-5/database'; import { COL, - Member, Network, NetworkAddress, TangleRequestType, TangleResponse, Transaction, + ValidatedAddress, WenError, } from '@build-5/interfaces'; import { get, isEmpty } from 'lodash'; @@ -78,8 +78,8 @@ export class TangleRequestService extends BaseTangleService { match, { status: 'error', - code: get(error, 'details.code', 1000), - message: get(error, 'details.key', 'none'), + code: get(error, 'eCode', 1000), + message: get(error, 'eKey', 'none'), }, tranEntry.outputId!, ); @@ -164,17 +164,17 @@ export class TangleRequestService extends BaseTangleService { }; private getOwner = async (senderAddress: NetworkAddress, network: Network) => { - const docRef = build5Db().doc(`${COL.MEMBER}/${senderAddress}`); - const member = await docRef.get(); + const docRef = build5Db().doc(COL.MEMBER, senderAddress); + const member = await docRef.get(); if (member) { return senderAddress; } const snap = await build5Db() .collection(COL.MEMBER) - .where(`validatedAddress.${network}`, '==', senderAddress) + .where(`${network}Address`, '==', senderAddress) .limit(2) - .get(); + .get(); if (snap.length > 1) { throw invalidArgument(WenError.multiple_members_with_same_address); @@ -189,7 +189,7 @@ export class TangleRequestService extends BaseTangleService { nonce: getRandomNonce(), validatedAddress: { [network as string]: senderAddress, - }, + } as unknown as ValidatedAddress, }; await docRef.create(memberData); 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 0540e0ab13..a690264d76 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 @@ -2,7 +2,6 @@ import { build5Db } from '@build-5/database'; import { COL, Network, - Space, TRANSACTION_AUTO_EXPIRY_MS, TangleResponse, Transaction, @@ -21,6 +20,7 @@ import { assertIsGuardian } from '../../../../utils/token.utils'; import { getRandomEthAddress } from '../../../../utils/wallet.utils'; import { WalletService } from '../../../wallet/wallet.service'; import { BaseTangleService, HandlerParams } from '../../base'; +import { Action } from '../../transaction-service'; import { validateAddressSchemaObject } from './AddressValidationTangleRequestSchema'; export class TangleAddressValidationService extends BaseTangleService { @@ -43,9 +43,9 @@ export class TangleAddressValidationService extends BaseTangleService { - const spaceDocRef = build5Db().doc(`${COL.SPACE}/${spaceId}`); - const space = spaceId ? await spaceDocRef.get() : undefined; + const spaceDocRef = build5Db().doc(COL.SPACE, spaceId!); + const space = spaceId ? await spaceDocRef.get() : undefined; if (spaceId && !space) { throw invalidArgument(WenError.space_does_not_exists); } diff --git a/packages/functions/src/services/payment/tangle-service/auction/auction.bid.order.ts b/packages/functions/src/services/payment/tangle-service/auction/auction.bid.order.ts index ebccb5054a..5c1b7c771a 100644 --- a/packages/functions/src/services/payment/tangle-service/auction/auction.bid.order.ts +++ b/packages/functions/src/services/payment/tangle-service/auction/auction.bid.order.ts @@ -3,14 +3,11 @@ import { Auction, AuctionType, COL, - Collection, CollectionStatus, Entity, MIN_AMOUNT_TO_TRANSFER, - Member, Nft, NftAccess, - Space, Transaction, TransactionPayloadType, TransactionType, @@ -33,8 +30,8 @@ export const createBidOrder = async ( auctionId: string, ip = '', ): Promise => { - const auctionDocRef = build5Db().doc(`${COL.AUCTION}/${auctionId}`); - const auction = await auctionDocRef.get(); + const auctionDocRef = build5Db().doc(COL.AUCTION, auctionId); + const auction = await auctionDocRef.get(); if (!auction) { throw invalidArgument(WenError.auction_does_not_exist); } @@ -76,14 +73,14 @@ export const createBidOrder = async ( if (auction.type === AuctionType.NFT) { const nft = validationResponse as Nft; - const collectionDocRef = build5Db().doc(`${COL.COLLECTION}/${nft.collection}`); - const collection = (await collectionDocRef.get())!; + const collectionDocRef = build5Db().doc(COL.COLLECTION, nft.collection); + const collection = (await collectionDocRef.get())!; - const spaceDocRef = build5Db().doc(`${COL.SPACE}/${collection.space}`); - const space = await spaceDocRef.get(); + const spaceDocRef = build5Db().doc(COL.SPACE, collection.space!); + const space = await spaceDocRef.get(); - const prevOwnerDocRef = build5Db().doc(`${COL.MEMBER}/${nft.owner}`); - const prevOwner = await prevOwnerDocRef.get(); + const prevOwnerDocRef = build5Db().doc(COL.MEMBER, nft.owner!); + const prevOwner = await prevOwnerDocRef.get(); assertMemberHasValidAddress(prevOwner, network); const royaltySpace = await getSpace(collection.royaltiesSpace); @@ -126,8 +123,8 @@ const assertAuctionData = async (owner: string, ip: string, auction: Auction) => }; const assertNftAuction = async (owner: string, ip: string, auction: Auction) => { - const nftDocRef = build5Db().doc(`${COL.NFT}/${auction.nftId}`); - const nft = await nftDocRef.get(); + const nftDocRef = build5Db().doc(COL.NFT, auction.nftId!); + const nft = await nftDocRef.get(); if (!nft) { throw invalidArgument(WenError.nft_does_not_exists); } @@ -136,8 +133,8 @@ const assertNftAuction = async (owner: string, ip: string, auction: Auction) => await assertIpNotBlocked(ip, nft.uid, 'nft'); } - const collectionDocRef = build5Db().doc(`${COL.COLLECTION}/${nft.collection}`); - const collection = (await collectionDocRef.get())!; + const collectionDocRef = build5Db().doc(COL.COLLECTION, nft.collection); + const collection = (await collectionDocRef.get())!; if (![CollectionStatus.PRE_MINTED, CollectionStatus.MINTED].includes(collection.status!)) { throw invalidArgument(WenError.invalid_collection_status); diff --git a/packages/functions/src/services/payment/tangle-service/auction/auction.bid.service.ts b/packages/functions/src/services/payment/tangle-service/auction/auction.bid.service.ts index bb41f7e47b..19a714f089 100644 --- a/packages/functions/src/services/payment/tangle-service/auction/auction.bid.service.ts +++ b/packages/functions/src/services/payment/tangle-service/auction/auction.bid.service.ts @@ -1,8 +1,9 @@ import { build5Db } from '@build-5/database'; -import { COL, Nft, TangleResponse, TransactionPayloadType, WenError } from '@build-5/interfaces'; +import { COL, TangleResponse, TransactionPayloadType, WenError } from '@build-5/interfaces'; import { invalidArgument } from '../../../../utils/error.utils'; import { assertValidationAsync } from '../../../../utils/schema.utils'; import { BaseTangleService, HandlerParams } from '../../base'; +import { Action } from '../../transaction-service'; import { auctionBidTangleSchema } from './AuctionBidTangleRequestSchema'; import { nftBidSchema } from './NftBidTangleRequestSchema'; import { createBidOrder } from './auction.bid.order'; @@ -19,8 +20,8 @@ export class TangleNftAuctionBidService extends BaseTangleService { const params = await assertValidationAsync(nftBidSchema, request); - const nftDocRef = build5Db().doc(`${COL.NFT}/${params.nft}`); - const nft = await nftDocRef.get(); + const nftDocRef = build5Db().doc(COL.NFT, params.nft); + const nft = await nftDocRef.get(); const order = await createBidOrder(project, owner, nft?.auction || ''); order.payload.tanglePuchase = true; @@ -31,10 +32,9 @@ export class TangleNftAuctionBidService extends BaseTangleService { } this.transactionService.push({ - ref: build5Db().doc(`${COL.TRANSACTION}/${order.uid}`), + ref: build5Db().doc(COL.TRANSACTION, order.uid), data: order, - action: 'set', - merge: true, + action: Action.C, }); this.transactionService.createUnlockTransaction( diff --git a/packages/functions/src/services/payment/tangle-service/auction/auction.create.service.ts b/packages/functions/src/services/payment/tangle-service/auction/auction.create.service.ts index 8ee89f4838..7c8bd85f0a 100644 --- a/packages/functions/src/services/payment/tangle-service/auction/auction.create.service.ts +++ b/packages/functions/src/services/payment/tangle-service/auction/auction.create.service.ts @@ -15,6 +15,7 @@ import { dateToTimestamp } from '../../../../utils/dateTime.utils'; import { assertValidationAsync } from '../../../../utils/schema.utils'; import { getRandomEthAddress } from '../../../../utils/wallet.utils'; import { BaseTangleService, HandlerParams } from '../../base'; +import { Action } from '../../transaction-service'; import { auctionCreateTangleSchema } from './AuctionCreateTangleRequestSchema'; export class TangleAuctionCreateService extends BaseTangleService { @@ -25,13 +26,13 @@ export class TangleAuctionCreateService extends BaseTangleService => { const params = await assertValidationAsync(auctionCreateTangleSchema, request); - const memberDocRef = build5Db().doc(`${COL.MEMBER}/${owner}`); + const memberDocRef = build5Db().doc(COL.MEMBER, owner); const member = await memberDocRef.get(); const auction = getAuctionData(project, member, params); - const auctionDocRef = build5Db().doc(`${COL.AUCTION}/${auction.uid}`); + const auctionDocRef = build5Db().doc(COL.AUCTION, auction.uid); - this.transactionService.push({ ref: auctionDocRef, data: auction, action: 'set' }); + this.transactionService.push({ ref: auctionDocRef, data: auction, action: Action.C }); return { auction: auction.uid }; }; 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 61e864cb14..939e18dbce 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 @@ -1,10 +1,8 @@ -import { ITransaction, build5Db } from '@build-5/database'; +import { ITransaction, PgMemberUpdate, build5Db } from '@build-5/database'; import { ApiError, - Award, AwardApproveParticipantTangleResponse, AwardBadgeType, - AwardParticipant, COL, IgnoreWalletReason, Member, @@ -48,8 +46,8 @@ export class AwardApproveParticipantService extends BaseTangleService async (transaction: ITransaction) => { - const awardDocRef = build5Db().doc(`${COL.AWARD}/${awardId}`); - const award = await transaction.get(awardDocRef); + const awardDocRef = build5Db().doc(COL.AWARD, awardId); + const award = await transaction.get(awardDocRef); + if (!award) { throw invalidArgument(WenError.award_does_not_exists); } @@ -81,30 +80,23 @@ export const approveAwardParticipant = const memberId = member?.uid || uidOrAddress; const memberAddress = getTargetAddres(member, award.network, uidOrAddress); - const participantDocRef = awardDocRef.collection(SUB_COL.PARTICIPANTS).doc(memberId); - const participant = await transaction.get(participantDocRef); + const participantDocRef = build5Db().doc(COL.AWARD, awardId, SUB_COL.PARTICIPANTS, memberId); + const participant = await transaction.get(participantDocRef); const count = (award.issued || 0) + 1; - const data = { - uid: award.uid, - issued: count, - completed: count === award.badge.total, - }; - transaction.update(awardDocRef, data); + const data = { issued: count, completed: count === award.badge.total }; + await transaction.update(awardDocRef, data); const participantUpdateData = { - uid: memberId, parentId: award.uid, - parentCol: COL.AWARD, completed: true, count: build5Db().inc(1), - createdOn: participant?.createdOn || serverTime(), tokenReward: build5Db().inc(award.badge.tokenReward), }; if (!participant) { set(participantUpdateData, 'project', project); } - transaction.set(participantDocRef, participantUpdateData, true); + await transaction.upsert(participantDocRef, participantUpdateData); const badgeTransaction: Transaction = { project, @@ -128,37 +120,32 @@ export const approveAwardParticipant = void: false, }, }; - const badgeTransactionDocRef = build5Db().doc(`${COL.TRANSACTION}/${badgeTransaction.uid}`); - transaction.create(badgeTransactionDocRef, badgeTransaction); - - const memberUpdateData = { - uid: memberId, + const badgeTransactionDocRef = build5Db().doc(COL.TRANSACTION, badgeTransaction.uid); + await transaction.create(badgeTransactionDocRef, badgeTransaction); + const memberUpdateData: PgMemberUpdate = { awardsCompleted: build5Db().inc(1), - totalReward: build5Db().inc(award.badge.tokenReward), spaces: { [award.space]: { uid: award.space, - createdOn: (member?.spaces || {})[award.space]?.createdOn || serverTime(), - updatedOn: serverTime(), + createdOn: (member?.spaces || {})[award.space]?.createdOn || dayjs().toDate(), + updatedOn: dayjs().toDate(), awardStat: { [award.badge.tokenUid]: { tokenSymbol: award.badge.tokenSymbol, badges: build5Db().arrayUnion(badgeTransaction.uid), completed: build5Db().inc(1), - totalReward: build5Db().inc(award.badge.tokenReward), }, }, awardsCompleted: build5Db().inc(1), - totalReward: build5Db().inc(award.badge.tokenReward), }, }, }; - const memberDocRef = build5Db().doc(`${COL.MEMBER}/${memberId}`); - transaction.set(memberDocRef, memberUpdateData, true); + const memberDocRef = build5Db().doc(COL.MEMBER, memberId); + await transaction.update(memberDocRef, memberUpdateData); if (award.badge.tokenReward) { const airdrop: TokenDrop = { @@ -174,33 +161,36 @@ export const approveAwardParticipant = sourceAddress: award.address, isBaseToken: award.badge.type === AwardBadgeType.BASE, }; - const airdropDocRef = build5Db().doc(`${COL.AIRDROP}/${airdrop.uid}`); - transaction.create(airdropDocRef, airdrop); + const airdropDocRef = build5Db().doc(COL.AIRDROP, airdrop.uid); + await transaction.create(airdropDocRef, airdrop); const distribution = { parentId: airdrop.token, - parentCol: COL.TOKEN, uid: memberId, totalUnclaimedAirdrop: build5Db().inc(airdrop.count), }; - const tokenDocRef = build5Db().doc(`${COL.TOKEN}/${airdrop.token}`); - const distributionDocRef = tokenDocRef.collection(SUB_COL.DISTRIBUTION).doc(memberId); - transaction.set(distributionDocRef, distribution, true); + const distributionDocRef = build5Db().doc( + COL.TOKEN, + airdrop.token, + SUB_COL.DISTRIBUTION, + memberId, + ); + await transaction.upsert(distributionDocRef, distribution); } - return badgeTransaction; }; const getMember = async (network: Network, uidOrAddress: NetworkAddress) => { - const memberDocRef = build5Db().doc(`${COL.MEMBER}/${uidOrAddress}`); - const member = await memberDocRef.get(); + const memberDocRef = build5Db().doc(COL.MEMBER, uidOrAddress); + const member = await memberDocRef.get(); if (member) { return member; } const members = await build5Db() .collection(COL.MEMBER) - .where(`validatedAddress.${network}`, '==', uidOrAddress) - .get(); + .where(`${network}Address`, '==', uidOrAddress) + .limit(1) + .get(); return head(members); }; 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 7cf7113293..5ef9bdfd9d 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 @@ -26,8 +26,9 @@ import { getTokenBySymbol } from '../../../../utils/token.utils'; import { getRandomEthAddress } from '../../../../utils/wallet.utils'; import { isStorageUrl } from '../../../joi/common'; import { WalletService } from '../../../wallet/wallet.service'; -import { getAwardgStorageDeposits as getAwardStorageDeposits } from '../../award/award-service'; +import { getAwardgStorageDeposits } from '../../award/award-service'; import { BaseTangleService, HandlerParams } from '../../base'; +import { Action } from '../../transaction-service'; import { awardCreateSchema } from './AwardCreateTangleRequestSchema'; import { createAwardFundOrder } from './award.fund.service'; @@ -40,22 +41,22 @@ export class AwardCreateService extends BaseTangleService { @@ -28,8 +29,8 @@ export class AwardFundService extends BaseTangleService { const award = await getAwardForFunding(owner, params.uid); const order = await createAwardFundOrder(project, owner, award); - const orderDocRef = build5Db().doc(`${COL.TRANSACTION}/${order.uid}`); - this.transactionService.push({ ref: orderDocRef, data: order, action: 'set' }); + const orderDocRef = build5Db().doc(COL.TRANSACTION, order.uid); + this.transactionService.push({ ref: orderDocRef, data: order, action: Action.C }); const response = { amount: order.payload.amount!, @@ -82,8 +83,8 @@ export const createAwardFundOrder = async ( }; export const getAwardForFunding = async (owner: string, awardId: string) => { - const awardDocRef = build5Db().doc(`${COL.AWARD}/${awardId}`); - const award = await awardDocRef.get(); + const awardDocRef = build5Db().doc(COL.AWARD, awardId); + const award = await awardDocRef.get(); if (!award) { throw invalidArgument(WenError.award_does_not_exists); diff --git a/packages/functions/src/services/payment/tangle-service/build5/verify.eth.for.b5.service.ts b/packages/functions/src/services/payment/tangle-service/build5/verify.eth.for.b5.service.ts index 1f5bc2c13d..e2e6f45de6 100644 --- a/packages/functions/src/services/payment/tangle-service/build5/verify.eth.for.b5.service.ts +++ b/packages/functions/src/services/payment/tangle-service/build5/verify.eth.for.b5.service.ts @@ -1,8 +1,9 @@ import { build5Db } from '@build-5/database'; -import { COL, SoonSnap, TangleResponse } from '@build-5/interfaces'; +import { COL, TangleResponse } from '@build-5/interfaces'; import axios from 'axios'; import { assertValidationAsync } from '../../../../utils/schema.utils'; import { BaseTangleService, HandlerParams } from '../../base'; +import { Action } from '../../transaction-service'; import { verifyEthForB5TangleSchema } from './VerifyEthForB5TangleRequest'; export class VerifyEthForBuil5TangleService extends BaseTangleService { @@ -10,11 +11,11 @@ export class VerifyEthForBuil5TangleService extends BaseTangleService(soonSnapDocRef); + let soonSnapDocRef = build5Db().doc(COL.SOON_SNAP, match.from); + let soonSnap = await this.transaction.get(soonSnapDocRef); if (!soonSnap) { - soonSnapDocRef = build5Db().doc(`${COL.SOON_SNAP}/${ethAddress}`); - soonSnap = await this.transaction.get(soonSnapDocRef); + soonSnapDocRef = build5Db().doc(COL.SOON_SNAP, ethAddress); + soonSnap = await this.transaction.get(soonSnapDocRef); } ethAddress = soonSnap?.ethAddress || ethAddress; @@ -30,11 +31,8 @@ export class VerifyEthForBuil5TangleService extends BaseTangleService { @@ -84,15 +84,20 @@ export class MintMetadataNftService extends BaseTangleService { } if (aliasId === EMPTY_ALIAS_ID) { - const spaceDocRef = build5Db().doc(`${COL.SPACE}/${space.uid}`); - this.transactionService.push({ ref: spaceDocRef, data: space, action: 'set' }); + const spaceDocRef = build5Db().doc(COL.SPACE, space.uid); + this.transactionService.push({ ref: spaceDocRef, data: space, action: Action.C }); - const guardian = { uid: owner, parentId: space.uid, parentCol: COL.SPACE }; - const guardianDocRef = spaceDocRef.collection(SUB_COL.GUARDIANS).doc(owner); - this.transactionService.push({ ref: guardianDocRef, data: guardian, action: 'set' }); + const guardian = { + uid: owner, + parentId: space.uid, + parentCol: COL.SPACE, + createdOn: dateToTimestamp(dayjs()), + }; + const guardianDocRef = build5Db().doc(COL.SPACE, space.uid, SUB_COL.GUARDIANS, owner); + this.transactionService.push({ ref: guardianDocRef, data: guardian, action: Action.C }); - const memberDocRef = spaceDocRef.collection(SUB_COL.MEMBERS).doc(owner); - this.transactionService.push({ ref: memberDocRef, data: guardian, action: 'set' }); + const memberDocRef = build5Db().doc(COL.SPACE, space.uid, SUB_COL.MEMBERS, owner); + this.transactionService.push({ ref: memberDocRef, data: guardian, action: Action.C }); } const order: Transaction = { @@ -120,8 +125,8 @@ export class MintMetadataNftService extends BaseTangleService { tag: match.msgId, }, }; - const orderDocRef = build5Db().doc(`${COL.TRANSACTION}/${order.uid}`); - this.transactionService.push({ ref: orderDocRef, data: order, action: 'set' }); + const orderDocRef = build5Db().doc(COL.TRANSACTION, order.uid); + this.transactionService.push({ ref: orderDocRef, data: order, action: Action.C }); this.transactionService.createUnlockTransaction( payment, @@ -175,9 +180,8 @@ const getAliasOutputAmount = async (owner: string, space: Space, wallet: Wallet) if (!space.alias?.address) { throw invalidArgument(WenError.not_alias_governor); } - const spaceDocRef = build5Db().doc(`${COL.SPACE}/${space.uid}`); - const guardianDocRef = spaceDocRef.collection(SUB_COL.GUARDIANS).doc(owner); - const guardian = await guardianDocRef.get(); + const guardianDocRef = build5Db().doc(COL.SPACE, space.uid, SUB_COL.GUARDIANS, owner); + const guardian = await guardianDocRef.get(); if (!guardian) { throw invalidArgument(WenError.not_alias_governor); 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 8ada43986a..84b18e121f 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 @@ -14,6 +14,7 @@ import { dateToTimestamp } from '../../../../utils/dateTime.utils'; import { getRandomEthAddress } from '../../../../utils/wallet.utils'; import { WalletService } from '../../../wallet/wallet.service'; import { BaseTangleService, HandlerParams } from '../../base'; +import { Action } from '../../transaction-service'; export class NftDepositService extends BaseTangleService { public handleRequest = async ({ owner, tran, tranEntry, ...params }: HandlerParams) => { @@ -36,8 +37,8 @@ export class NftDepositService extends BaseTangleService { void: false, }, }; - const orderDocRef = build5Db().doc(`${COL.TRANSACTION}/${order.uid}`); - this.transactionService.push({ ref: orderDocRef, data: order, action: 'set' }); + const orderDocRef = build5Db().doc(COL.TRANSACTION, order.uid); + this.transactionService.push({ ref: orderDocRef, data: order, action: Action.C }); this.transactionService.createUnlockTransaction( params.payment, diff --git a/packages/functions/src/services/payment/tangle-service/nft/nft-purchase.bulk.service.ts b/packages/functions/src/services/payment/tangle-service/nft/nft-purchase.bulk.service.ts index eba0d2ecb2..479da8f5cd 100644 --- a/packages/functions/src/services/payment/tangle-service/nft/nft-purchase.bulk.service.ts +++ b/packages/functions/src/services/payment/tangle-service/nft/nft-purchase.bulk.service.ts @@ -5,7 +5,6 @@ import { CollectionType, Member, Network, - Nft, TRANSACTION_AUTO_EXPIRY_MS, TangleResponse, Transaction, @@ -27,6 +26,7 @@ import { getSpace } from '../../../../utils/space.utils'; import { getRandomEthAddress } from '../../../../utils/wallet.utils'; import { WalletService } from '../../../wallet/wallet.service'; import { BaseTangleService, HandlerParams } from '../../base'; +import { Action } from '../../transaction-service'; import { nftPurchaseBulkSchema } from './NftPurchaseBulkTangleRequestSchema'; import { assertCurrentOwnerAddress, @@ -60,9 +60,9 @@ export class TangleNftPurchaseBulkService extends BaseTangleService, + CollectionNftGroup: Dictionary, member: Member, ip: string, ) => { const defaultNetwork = isProdEnv() ? Network.IOTA : Network.ATOI; - const pricesPromises = Object.entries(colletionNftGroup).map( + const pricesPromises = Object.entries(CollectionNftGroup).map( async ([collectionId, nftOrders]) => { const nftIds = nftOrders.map((o) => o.nft!); const { collection, nfts } = await getNfts(collectionId, nftIds); @@ -176,7 +176,7 @@ const getNftPrices = async ( nft: nft.uid, requestedNft: nftIdParam, price: 0, - error: get(error, 'details.code', 0), + error: get(error, 'eCode', 0), }; } }); @@ -196,8 +196,8 @@ const getNfts = async (collectionId: string, nftIds: (string | undefined)[]) => }; const getNft = async (nftId: string) => { - const docRef = build5Db().doc(`${COL.NFT}/${nftId}`); - const nft = (await getNftByMintingId(nftId)) || (await docRef.get()); + const docRef = build5Db().doc(COL.NFT, nftId); + const nft = (await getNftByMintingId(nftId)) || (await docRef.get()); if (nft) { return nft; } 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 a947a795f9..5954636914 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 @@ -1,4 +1,11 @@ -import { build5Db } from '@build-5/database'; +import { + PgEntity, + PgNftStatus, + PgNftUpdate, + PgTransactionPayloadType, + PgTransactionType, + build5Db, +} from '@build-5/database'; import { COL, Collection, @@ -12,7 +19,6 @@ import { NetworkAddress, Nft, NftAccess, - NftStatus, Space, StakeType, TRANSACTION_AUTO_EXPIRY_MS, @@ -38,6 +44,7 @@ import { getRandomEthAddress } from '../../../../utils/wallet.utils'; import { assertHasAccess } from '../../../validators/access'; import { WalletService } from '../../../wallet/wallet.service'; import { BaseTangleService, HandlerParams } from '../../base'; +import { Action } from '../../transaction-service'; import { nftPurchaseSchema } from './NftPurchaseTangleRequestSchema'; export class TangleNftPurchaseService extends BaseTangleService { @@ -63,9 +70,9 @@ export class TangleNftPurchaseService extends BaseTangleService order.payload.disableWithdraw = params.disableWithdraw || false; this.transactionService.push({ - ref: build5Db().doc(`${COL.TRANSACTION}/${order.uid}`), + ref: build5Db().doc(COL.TRANSACTION, order.uid), data: order, - action: 'set', + action: Action.C, }); if (tranEntry.amount !== order.payload.amount || tangleOrder.network !== order.network) { @@ -158,8 +165,8 @@ export const createNftPuchaseOrder = async ( }; export const getCollection = async (id: string) => { - const collectionDocRef = build5Db().doc(`${COL.COLLECTION}/${id}`); - const collection = await collectionDocRef.get(); + const collectionDocRef = build5Db().doc(COL.COLLECTION, id); + const collection = await collectionDocRef.get(); if (!collection) { throw invalidArgument(WenError.collection_does_not_exists); } @@ -171,14 +178,14 @@ export const getCollection = async (id: string) => { }; export const getMember = async (id: string) => { - const memberDocRef = build5Db().doc(`${COL.MEMBER}/${id}`); + const memberDocRef = build5Db().doc(COL.MEMBER, id); return await memberDocRef.get(); }; const getNft = async (collection: Collection, nftId: string | undefined) => { if (nftId) { - const docRef = build5Db().doc(`${COL.NFT}/${nftId}`); - const nft = (await getNftByMintingId(nftId)) || (await docRef.get()); + const docRef = build5Db().doc(COL.NFT, nftId); + const nft = (await getNftByMintingId(nftId)) || (await docRef.get()); if (nft) { return nft; } @@ -214,7 +221,7 @@ export const getNftAbove = (collection: Collection, position: number, limit = 1) .where('position', '>=', position) .orderBy('position', 'asc') .limit(limit) - .get(); + .get(); export const getNftBelow = (collection: Collection, position: number, limit = 1) => build5Db() @@ -224,9 +231,9 @@ export const getNftBelow = (collection: Collection, position: number, limit = 1) .where('placeholderNft', '==', false) .where('collection', '==', collection.uid) .where('position', '<=', position) - .orderBy('position', 'asc') - .limitToLast(limit) - .get(); + .orderBy('position', 'desc') + .limit(limit) + .get(); export const assertNftCanBePurchased = async ( space: Space, @@ -294,9 +301,9 @@ export const assertUserHasOnlyOneNft = async (collection: Collection, owner: str const snap = await build5Db() .collection(COL.TRANSACTION) .where('member', '==', owner) - .where('type', '==', TransactionType.BILL_PAYMENT) - .where('payload.collection', '==', collection.uid) - .where('payload.previousOwnerEntity', '==', 'space') + .where('type', '==', PgTransactionType.BILL_PAYMENT) + .where('payload_collection', '==', collection.uid) + .where('payload_previousOwnerEntity', '==', PgEntity.SPACE) .get(); if (snap.length) { throw invalidArgument(WenError.you_can_only_own_one_nft_from_collection); @@ -306,11 +313,11 @@ export const assertUserHasOnlyOneNft = async (collection: Collection, owner: str export const assertNoOrderInProgress = async (owner: string) => { const orderInProgress = await build5Db() .collection(COL.TRANSACTION) - .where('payload.reconciled', '==', false) - .where('payload.type', '==', TransactionPayloadType.NFT_PURCHASE) + .where('payload_reconciled', '==', false) + .where('payload_type', '==', PgTransactionPayloadType.NFT_PURCHASE) .where('member', '==', owner) - .where('type', '==', TransactionType.ORDER) - .where('payload.void', '==', false) + .where('type', '==', PgTransactionType.ORDER) + .where('payload_void', '==', false) .get(); if (orderInProgress.length) { @@ -342,14 +349,14 @@ export const getDiscount = (collection: Collection, member: Member) => { return 1; }; -export const lockNft = async (nftId: string, orderId: string) => +export const lockNft = (nftId: string, orderId: string) => build5Db().runTransaction(async (transaction) => { - const docRef = build5Db().doc(`${COL.NFT}/${nftId}`); + const docRef = build5Db().doc(COL.NFT, nftId); const nft = await transaction.get(docRef); if (nft.locked) { throw invalidArgument(WenError.nft_locked_for_sale); } - transaction.update(docRef, { locked: true, lockedBy: orderId }); + await transaction.update(docRef, { locked: true, lockedBy: orderId }); }); export const getNftFinalPrice = (nft: Nft, discount: number) => { @@ -388,12 +395,27 @@ export const createNftWithdrawOrder = ( nftId: nft.mintingData?.nftId || '', }, }; - const nftUpdateData = { - uid: nft.uid, - status: stakeType ? NftStatus.STAKED : NftStatus.WITHDRAWN, + const nftUpdateData: PgNftUpdate = { + status: stakeType ? PgNftStatus.STAKED : PgNftStatus.WITHDRAWN, hidden: true, - depositData: build5Db().deleteField(), - owner: null, + depositData_address: undefined, + depositData_network: undefined, + depositData_mintedOn: undefined, + depositData_mintedBy: undefined, + depositData_blockId: undefined, + depositData_nftId: undefined, + depositData_storageDeposit: undefined, + depositData_aliasBlockId: undefined, + depositData_aliasId: undefined, + depositData_aliasStorageDeposit: undefined, + depositData_mintingOrderId: undefined, + depositData_nftsToMint: undefined, + depositData_nftMediaToUpload: undefined, + depositData_nftMediaToPrepare: undefined, + depositData_unsoldMintingOptions: undefined, + depositData_newPrice: undefined, + depositData_nftsStorageDeposit: undefined, + owner: undefined, isOwned: false, }; return { order, nftUpdateData }; diff --git a/packages/functions/src/services/payment/tangle-service/nft/nft-set-for-sale.service.ts b/packages/functions/src/services/payment/tangle-service/nft/nft-set-for-sale.service.ts index b5f288a555..a67bb126f4 100644 --- a/packages/functions/src/services/payment/tangle-service/nft/nft-set-for-sale.service.ts +++ b/packages/functions/src/services/payment/tangle-service/nft/nft-set-for-sale.service.ts @@ -1,9 +1,8 @@ -import { build5Db } from '@build-5/database'; +import { PgNftAccess, build5Db, convertEnum } from '@build-5/database'; import { Auction, AuctionType, COL, - Collection, CollectionStatus, DEFAULT_NETWORK, EXTEND_AUCTION_WITHIN, @@ -22,21 +21,22 @@ import { invalidArgument } from '../../../../utils/error.utils'; import { assertValidationAsync } from '../../../../utils/schema.utils'; import { getRandomEthAddress } from '../../../../utils/wallet.utils'; import { BaseTangleService, HandlerParams } from '../../base'; +import { Action } from '../../transaction-service'; import { setNftForSaleTangleSchema } from './NftSetForSaleTangleRequestSchema'; export class TangleNftSetForSaleService extends BaseTangleService { public handleRequest = async ({ owner, request, project }: HandlerParams) => { const params = await assertValidationAsync(setNftForSaleTangleSchema, request); - const memberDocRef = build5Db().doc(`${COL.MEMBER}/${owner}`); - const member = await memberDocRef.get(); + const memberDocRef = build5Db().doc(COL.MEMBER, owner); + const member = await memberDocRef.get(); const { nft, auction } = await getNftSetForSaleParams(member!, project, params); - const nftDocRef = build5Db().doc(`${COL.NFT}/${params.nft}`); - this.transactionService.push({ ref: nftDocRef, data: nft, action: 'update' }); + const nftDocRef = build5Db().doc(COL.NFT, params.nft); + this.transactionService.push({ ref: nftDocRef, data: nft, action: Action.U }); if (auction) { - const auctionDocRef = build5Db().doc(`${COL.AUCTION}/${auction.uid}`); - this.transactionService.push({ ref: auctionDocRef, data: auction, action: 'set' }); + const auctionDocRef = build5Db().doc(COL.AUCTION, auction.uid); + this.transactionService.push({ ref: auctionDocRef, data: auction, action: Action.C }); } return { status: 'success' }; @@ -48,8 +48,8 @@ export const getNftSetForSaleParams = async ( project: string, params: NftSetForSaleRequest, ) => { - const nftDocRef = build5Db().doc(`${COL.NFT}/${params.nft}`); - const nft = await nftDocRef.get(); + const nftDocRef = build5Db().doc(COL.NFT, params.nft); + const nft = await nftDocRef.get(); if (!nft) { throw invalidArgument(WenError.nft_does_not_exists); } @@ -84,8 +84,8 @@ export const getNftSetForSaleParams = async ( params.auctionFrom = dateToTimestamp(params.auctionFrom, true).toDate(); } - const collectionDocRef = build5Db().doc(`${COL.COLLECTION}/${nft.collection}`); - const collection = await collectionDocRef.get(); + const collectionDocRef = build5Db().doc(COL.COLLECTION, nft.collection); + const collection = await collectionDocRef.get(); if (![CollectionStatus.PRE_MINTED, CollectionStatus.MINTED].includes(collection?.status!)) { throw invalidArgument(WenError.invalid_collection_status); } @@ -96,7 +96,7 @@ export const getNftSetForSaleParams = async ( const getNftUpdateData = (params: NftSetForSaleRequest) => { const update: Record = { - saleAccess: params.access || NftAccess.OPEN, + saleAccess: convertEnum((params.access || NftAccess.OPEN) as NftAccess, NftAccess, PgNftAccess), saleAccessMembers: params.accessMembers || [], }; @@ -137,7 +137,12 @@ const getNftUpdateData = (params: NftSetForSaleRequest) => { return update; }; -const getAuctionData = (project: string, owner: string, params: NftSetForSaleRequest, nft: Nft) => { +const getAuctionData = ( + project: string, + owner: string, + params: NftSetForSaleRequest, + nft: Nft, +): Auction | undefined => { if (!params.auctionFrom) { return; } @@ -165,7 +170,9 @@ const getAuctionData = (project: string, owner: string, params: NftSetForSaleReq if (params.extendedAuctionLength) { return { ...auction, - extendedAuctionTo: dayjs(params.auctionFrom).add(params.extendedAuctionLength).toDate(), + extendedAuctionTo: dateToTimestamp( + dayjs(params.auctionFrom).add(params.extendedAuctionLength), + ), extendedAuctionLength: params.extendedAuctionLength || 0, extendAuctionWithin: params.extendAuctionWithin || EXTEND_AUCTION_WITHIN, }; diff --git a/packages/functions/src/services/payment/tangle-service/nft/nft-transfer.service.ts b/packages/functions/src/services/payment/tangle-service/nft/nft-transfer.service.ts index 1550547138..22c4fa0066 100644 --- a/packages/functions/src/services/payment/tangle-service/nft/nft-transfer.service.ts +++ b/packages/functions/src/services/payment/tangle-service/nft/nft-transfer.service.ts @@ -3,6 +3,7 @@ import { COL, TangleResponse, TransactionType } from '@build-5/interfaces'; import { assertValidationAsync } from '../../../../utils/schema.utils'; import { BaseTangleService, HandlerParams } from '../../base'; import { createNftTransferData } from '../../nft/nft-transfer.service'; +import { Action } from '../../transaction-service'; import { nftTangleTransferSchema } from './NftTransferTangleRequestSchema'; export class TangleNftTransferService extends BaseTangleService { @@ -20,19 +21,21 @@ export class TangleNftTransferService extends BaseTangleService if (code !== 200) { continue; } - - const nftDocRef = build5Db().doc(`${COL.NFT}/${nftId}`); - this.transactionService.push({ ref: nftDocRef, data: nftUpdateData, action: 'update' }); - - const tranDocRef = build5Db().doc(`${COL.TRANSACTION}/${order?.uid}`); - this.transactionService.push({ ref: tranDocRef, data: order, action: 'set' }); + if (nftUpdateData) { + const nftDocRef = build5Db().doc(COL.NFT, nftId); + this.transactionService.push({ ref: nftDocRef, data: nftUpdateData, action: Action.U }); + } + if (order) { + const tranDocRef = build5Db().doc(COL.TRANSACTION, order?.uid!); + this.transactionService.push({ ref: tranDocRef, data: order, action: Action.C }); + } if (order?.type === TransactionType.WITHDRAW_NFT) { - const collectionDocRef = build5Db().doc(`${COL.COLLECTION}/${order.payload.collection}`); + const collectionDocRef = build5Db().doc(COL.COLLECTION, order.payload.collection!); this.transactionService.push({ ref: collectionDocRef, data: { total: build5Db().inc(-1) }, - action: 'update', + action: Action.U, }); } } diff --git a/packages/functions/src/services/payment/tangle-service/proposal/ProposalApporvalService.ts b/packages/functions/src/services/payment/tangle-service/proposal/ProposalApporvalService.ts index af37eeed6c..7d47610891 100644 --- a/packages/functions/src/services/payment/tangle-service/proposal/ProposalApporvalService.ts +++ b/packages/functions/src/services/payment/tangle-service/proposal/ProposalApporvalService.ts @@ -1,9 +1,10 @@ import { build5Db } from '@build-5/database'; -import { COL, Proposal, TangleRequestType, TangleResponse, WenError } from '@build-5/interfaces'; +import { COL, TangleRequestType, TangleResponse, WenError } from '@build-5/interfaces'; import { invalidArgument } from '../../../../utils/error.utils'; import { assertValidationAsync } from '../../../../utils/schema.utils'; import { assertIsGuardian } from '../../../../utils/token.utils'; import { BaseTangleService, HandlerParams } from '../../base'; +import { Action } from '../../transaction-service'; import { proposalApproveSchema } from './ProposalApproveTangleRequestSchema'; export class ProposalApprovalService extends BaseTangleService { @@ -14,8 +15,8 @@ export class ProposalApprovalService extends BaseTangleService { params.uid, params.requestType === TangleRequestType.PROPOSAL_APPROVE, ); - const docRef = build5Db().doc(`${COL.PROPOSAL}/${params.uid}`); - this.transactionService.push({ ref: docRef, data, action: 'update' }); + const docRef = build5Db().doc(COL.PROPOSAL, params.uid); + this.transactionService.push({ ref: docRef, data, action: Action.U }); return { status: 'success' }; }; @@ -26,8 +27,8 @@ export const getProposalApprovalData = async ( proposalId: string, approve: boolean, ) => { - const proposalDocRef = build5Db().doc(`${COL.PROPOSAL}/${proposalId}`); - const proposal = await proposalDocRef.get(); + const proposalDocRef = build5Db().doc(COL.PROPOSAL, proposalId); + const proposal = await proposalDocRef.get(); if (!proposal) { throw invalidArgument(WenError.proposal_does_not_exists); } 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 f449fd5d4b..b9130ea604 100644 --- a/packages/functions/src/services/payment/tangle-service/proposal/ProposalCreateService.ts +++ b/packages/functions/src/services/payment/tangle-service/proposal/ProposalCreateService.ts @@ -16,6 +16,7 @@ import { assertValidationAsync } from '../../../../utils/schema.utils'; import { getTokenForSpace } from '../../../../utils/token.utils'; import { getRandomEthAddress } from '../../../../utils/wallet.utils'; import { BaseTangleService, HandlerParams } from '../../base'; +import { Action } from '../../transaction-service'; import { proposalCreateSchemaObject } from './ProposalCreateTangleRequestSchema'; export class ProposalCreateService extends BaseTangleService { @@ -28,14 +29,19 @@ export class ProposalCreateService extends BaseTangleService, ) => { - const spaceDocRef = build5Db().doc(`${COL.SPACE}/${params.space}`); - const spaceMemberDocRef = spaceDocRef.collection(SUB_COL.MEMBERS).doc(owner); - const spaceMember = await spaceMemberDocRef.get(); + const spaceMemberDocRef = build5Db().doc( + COL.SPACE, + params.space! as string, + SUB_COL.MEMBERS, + owner, + ); + const spaceMember = await spaceMemberDocRef.get(); if (!spaceMember) { throw invalidArgument(WenError.you_are_not_part_of_space); } @@ -98,16 +108,13 @@ export const createProposal = async ( 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 spaceMembers = await build5Db().collection(COL.SPACE, proposal.space, subCol).get(); const promises = spaceMembers.map(async (spaceMember) => { const proposalMember = createProposalMember(project, proposal, spaceMember); if (proposalMember.weight || proposal.type === ProposalType.NATIVE) { - const proposalDocRef = build5Db().doc(`${COL.PROPOSAL}/${proposal.uid}`); - await proposalDocRef - .collection(SUB_COL.MEMBERS) - .doc(proposalMember.uid) + await build5Db() + .doc(COL.PROPOSAL, proposal.uid, SUB_COL.MEMBERS, proposalMember.uid) .create(proposalMember); } return proposalMember.weight || 0; 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 295c6cba96..14b9d36e00 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 @@ -24,6 +24,7 @@ import { assertValidationAsync } from '../../../../../utils/schema.utils'; import { getTokenForSpace } from '../../../../../utils/token.utils'; import { getRandomEthAddress } from '../../../../../utils/wallet.utils'; import { BaseTangleService, HandlerParams } from '../../../base'; +import { Action } from '../../../transaction-service'; import { voteOnProposalSchemaObject } from './ProposalVoteTangleRequestSchema'; import { executeSimpleVoting } from './simple.voting'; import { voteWithStakedTokens } from './staked.token.voting'; @@ -73,7 +74,7 @@ export class ProposalVoteService extends BaseTangleService { const order = await createVoteTransactionOrder(project, owner, proposal, values, token); - const orderDocRef = build5Db().doc(`${COL.TRANSACTION}/${order.uid}`); + const orderDocRef = build5Db().doc(COL.TRANSACTION, order.uid); this.transactionService.push({ ref: orderDocRef, data: order, - action: 'set', + action: Action.C, }); this.transactionService.createUnlockTransaction( @@ -107,38 +108,41 @@ export class ProposalVoteService extends BaseTangleService { - const proposalDocRef = build5Db().doc(`${COL.PROPOSAL}/${proposal.uid}`); - const proposalMemberDocRef = proposalDocRef.collection(SUB_COL.MEMBERS).doc(proposalMember.uid); + const proposalDocRef = build5Db().doc(COL.PROPOSAL, proposal.uid); + const proposalMemberDocRef = build5Db().doc( + COL.PROPOSAL, + proposal.uid, + SUB_COL.MEMBERS, + proposalMember.uid, + ); - const voteData = await executeSimpleVoting(project, proposalMember, proposal, values); + const voteData = executeSimpleVoting(project, proposalMember, proposal, values); - this.transactionService.push({ - ref: proposalDocRef, - data: voteData.proposal, - action: 'set', - merge: true, - }); + if (voteData.proposal) { + this.transactionService.push({ + ref: proposalDocRef, + data: voteData.proposal, + action: Action.U, + }); + } this.transactionService.push({ ref: proposalMemberDocRef, data: voteData.proposalMember, - action: 'set', - merge: true, + action: Action.U, }); - const voteTransactionDocRef = build5Db().doc( - `${COL.TRANSACTION}/${voteData.voteTransaction.uid}`, - ); + const voteTransactionDocRef = build5Db().doc(COL.TRANSACTION, voteData.voteTransaction.uid); this.transactionService.push({ ref: voteTransactionDocRef, data: voteData.voteTransaction, - action: 'set', + action: Action.C, }); return { status: 'success' }; @@ -146,8 +150,8 @@ export class ProposalVoteService extends BaseTangleService { - const proposalDocRef = build5Db().doc(`${COL.PROPOSAL}/${proposalUid}`); - const proposal = await proposalDocRef.get(); + const proposalDocRef = build5Db().doc(COL.PROPOSAL, proposalUid); + const proposal = await proposalDocRef.get(); if (!proposal) { throw invalidArgument(WenError.proposal_does_not_exists); } @@ -177,9 +181,8 @@ export const getProposal = async (proposalUid: string) => { }; export const getProposalMember = async (owner: string, proposal: Proposal, value: number) => { - const proposalDocRef = build5Db().doc(`${COL.PROPOSAL}/${proposal.uid}`); - const proposalMemberDocRef = proposalDocRef.collection(SUB_COL.MEMBERS).doc(owner); - const proposalMember = await proposalMemberDocRef.get(); + const proposalMemberDocRef = build5Db().doc(COL.PROPOSAL, proposal.uid, SUB_COL.MEMBERS, owner); + const proposalMember = await proposalMemberDocRef.get(); if (!proposalMember) { throw invalidArgument(WenError.you_are_not_allowed_to_vote_on_this_proposal); } 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 beca61924b..63a16e6389 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 @@ -3,7 +3,7 @@ import { Proposal, ProposalMember } from '@build-5/interfaces'; import { head } from 'lodash'; import { createVoteTransaction } from './ProposalVoteService'; -export const executeSimpleVoting = async ( +export const executeSimpleVoting = ( project: string, member: ProposalMember, proposal: Proposal, @@ -16,7 +16,7 @@ export const executeSimpleVoting = async ( uid: member.uid, voted: true, tranId: voteTransaction.uid, - values: [{ [values[0]]: weight }], + values: JSON.stringify({ [voteTransaction.uid]: { value: values[0], weight } }), }; return { proposal: proposalUpdateData, @@ -32,10 +32,9 @@ const getProposalUpdateDataAfterVote = ( ) => { const prevAnswer = head(Object.keys(head(proposalMember.values) || {})); if (prevAnswer === values[0].toString()) { - return { uid: proposalMember.parentId }; + return undefined; } const data = { - uid: proposalMember.parentId, results: { voted: build5Db().inc(proposalMember.voted ? 0 : weight), answers: { [`${values[0]}`]: build5Db().inc(weight) }, 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 430892c593..4507e2159b 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 @@ -1,13 +1,5 @@ import { build5Db, ITransaction } from '@build-5/database'; -import { - COL, - Proposal, - Stake, - SUB_COL, - TokenDistribution, - Transaction, - WenError, -} from '@build-5/interfaces'; +import { COL, Proposal, Stake, SUB_COL, WenError } from '@build-5/interfaces'; import dayjs from 'dayjs'; import { invalidArgument } from '../../../../../utils/error.utils'; import { getTokenVoteMultiplier } from '../../../voting-service'; @@ -20,12 +12,13 @@ export const voteWithStakedTokens = async ( proposal: Proposal, values: number[], ) => { - const distributionDocRef = build5Db() - .collection(COL.TOKEN) - .doc(proposal.token!) - .collection(SUB_COL.DISTRIBUTION) - .doc(member); - const distribution = (await transaction.get(distributionDocRef))!; + const distributionDocRef = build5Db().doc( + COL.TOKEN, + proposal.token!, + SUB_COL.DISTRIBUTION, + member, + ); + const distribution = (await transaction.get(distributionDocRef))!; if (distribution.stakeVoteTransactionId) { await expireStakeVoteTransaction(transaction, proposal, distribution.stakeVoteTransactionId); } @@ -50,36 +43,29 @@ export const voteWithStakedTokens = async ( values, stakes.map((s) => s.uid), ); - const voteTransactionDocRef = build5Db().doc(`${COL.TRANSACTION}/${voteTransaction.uid}`); - transaction.create(voteTransactionDocRef, voteTransaction); - - const proposalDocRef = build5Db().doc(`${COL.PROPOSAL}/${proposal.uid}`); - const proposalMemberDocRef = proposalDocRef.collection(SUB_COL.MEMBERS).doc(member); - transaction.set( - proposalMemberDocRef, - { - voted: true, - voteTransactions: build5Db().inc(1), - tranId: voteTransaction.uid, - weightPerAnswer: { [values[0]]: build5Db().inc(weight) }, - values: build5Db().arrayUnion({ - [values[0]]: weight, - voteTransaction: voteTransaction.uid, - }), - }, - true, - ); + const voteTransactionDocRef = build5Db().doc(COL.TRANSACTION, voteTransaction.uid); + await transaction.create(voteTransactionDocRef, voteTransaction); + + const proposalDocRef = build5Db().doc(COL.PROPOSAL, proposal.uid); + const proposalMemberDocRef = build5Db().doc(COL.PROPOSAL, proposal.uid, SUB_COL.MEMBERS, member); - const proposalData = { + const value = values[0].toString(); + await transaction.update(proposalDocRef, { results: { total: build5Db().inc(weight), voted: build5Db().inc(weight), - answers: { [`${values[0]}`]: build5Db().inc(weight) }, + answers: { [value]: build5Db().inc(weight) }, }, - }; - transaction.set(proposalDocRef, proposalData, true); + }); + + await transaction.upsert(proposalMemberDocRef, { + voted: true, + tranId: voteTransaction.uid, + weight: build5Db().inc(weight), + values: { [voteTransaction.uid]: { value, weight: build5Db().inc(weight) } }, + }); - transaction.update(distributionDocRef, { stakeVoteTransactionId: voteTransaction.uid }); + await transaction.update(distributionDocRef, { stakeVoteTransactionId: voteTransaction.uid }); return voteTransaction; }; @@ -89,21 +75,18 @@ const expireStakeVoteTransaction = async ( currentProposal: Proposal, voteTransactionId: string, ) => { - const voteTransactionDocRef = build5Db().doc(`${COL.TRANSACTION}/${voteTransactionId}`); - const voteTransaction = (await transaction.get(voteTransactionDocRef))!; + const voteTransactionDocRef = build5Db().doc(COL.TRANSACTION, voteTransactionId); + const voteTransaction = (await transaction.get(voteTransactionDocRef))!; let proposal = currentProposal; - let proposalDocRef = build5Db().doc(`${COL.PROPOSAL}/${currentProposal.uid}`); + let proposalDocRef = build5Db().doc(COL.PROPOSAL, currentProposal.uid); if (voteTransaction.payload.proposalId !== currentProposal.uid) { - proposalDocRef = build5Db().doc(`${COL.PROPOSAL}/${voteTransaction.payload.proposalId}`); - proposal = (await proposalDocRef.get())!; + proposalDocRef = build5Db().doc(COL.PROPOSAL, voteTransaction.payload.proposalId!); + proposal = (await proposalDocRef.get())!; } if (dayjs().isAfter(dayjs(proposal.settings.endDate.toDate()))) { return; } - const proposalMemberDocRef = proposalDocRef - .collection(SUB_COL.MEMBERS) - .doc(voteTransaction.member!); const stakes = await getStakesById(voteTransaction.payload.stakes!); const weight = getWeightForStakes( @@ -113,33 +96,22 @@ const expireStakeVoteTransaction = async ( dayjs(), ); - transaction.update(voteTransactionDocRef, { - 'payload.weight': weight, - 'payload.outputConsumed': true, - 'payload.outputConsumedOn': dayjs().toDate(), + await transaction.update(voteTransactionDocRef, { + payload_weight: weight, + payload_outputConsumed: true, + payload_outputConsumedOn: dayjs().toDate(), }); const prevWeight = voteTransaction.payload.weight!; - const prevValue = voteTransaction.payload.values![0]; - - transaction.set( - proposalMemberDocRef, - { - values: build5Db().arrayRemove({ - [prevValue]: prevWeight, - voteTransaction: voteTransaction.uid, - }), - voteTransactions: build5Db().inc(-1), - weightPerAnswer: { [prevValue]: build5Db().inc(-prevWeight + weight) }, - }, - true, + const prevValue = voteTransaction.payload.values![0].toString(); + + const proposalMemberDocRef = build5Db().doc( + COL.PROPOSAL, + proposal.uid, + SUB_COL.MEMBERS, + voteTransaction.member!, ); - transaction.update(proposalMemberDocRef, { - values: build5Db().arrayUnion({ - [prevValue]: weight, - voteTransaction: voteTransaction.uid, - }), - }); + await transaction.update(proposalMemberDocRef, { values: { [voteTransaction.uid]: { weight } } }); const data = { results: { @@ -148,13 +120,13 @@ const expireStakeVoteTransaction = async ( answers: { [prevValue]: build5Db().inc(-prevWeight + weight) }, }, }; - transaction.set(proposalDocRef, data, true); + await transaction.update(proposalDocRef, data); }; const getStakesById = (stakeIds: string[]) => { const promises = stakeIds.map(async (uid) => { - const docRef = build5Db().doc(`${COL.STAKE}/${uid}`); - return (await docRef.get())!; + const docRef = build5Db().doc(COL.STAKE, uid); + return (await docRef.get())!; }); return Promise.all(promises); }; @@ -181,6 +153,6 @@ const getActiveStakes = async (member: string, token: string) => { .where('member', '==', member) .where('token', '==', token) .where('expirationProcessed', '==', false) - .get(); + .get(); return stakes.filter((s) => dayjs(s.expiresAt.toDate()).isAfter(dayjs())); }; 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 1e3aa4613d..8eb5b1468d 100644 --- a/packages/functions/src/services/payment/tangle-service/space/SpaceAcceptMemberService.ts +++ b/packages/functions/src/services/payment/tangle-service/space/SpaceAcceptMemberService.ts @@ -1,10 +1,13 @@ import { build5Db } from '@build-5/database'; -import { COL, Space, SpaceMember, SUB_COL, TangleResponse, WenError } from '@build-5/interfaces'; +import { COL, SUB_COL, TangleResponse, WenError } from '@build-5/interfaces'; +import dayjs from 'dayjs'; import { getProject } from '../../../../utils/common.utils'; +import { dateToTimestamp } from '../../../../utils/dateTime.utils'; import { invalidArgument } from '../../../../utils/error.utils'; import { assertValidationAsync } from '../../../../utils/schema.utils'; import { assertIsGuardian } from '../../../../utils/token.utils'; import { BaseTangleService, HandlerParams } from '../../base'; +import { Action } from '../../transaction-service'; import { editSpaceMemberSchemaObject } from './SpaceEditMemberTangleRequestSchema'; export class SpaceAcceptMemberService extends BaseTangleService { @@ -18,22 +21,29 @@ export class SpaceAcceptMemberService extends BaseTangleService params.member, ); - const spaceDocRef = build5Db().doc(`${COL.SPACE}/${params.uid}`); - const spaceMemberDocRef = spaceDocRef.collection(SUB_COL.MEMBERS).doc(spaceMember.uid); - const knockingMemberDocRef = spaceDocRef - .collection(SUB_COL.KNOCKING_MEMBERS) - .doc(spaceMember.uid); + const spaceMemberDocRef = build5Db().doc( + COL.SPACE, + params.uid, + SUB_COL.MEMBERS, + spaceMember.uid, + ); + const knockingMemberDocRef = build5Db().doc( + COL.SPACE, + params.uid, + SUB_COL.KNOCKING_MEMBERS, + spaceMember.uid, + ); this.transactionService.push({ ref: spaceMemberDocRef, data: spaceMember, - action: 'set', + action: Action.C, }); - this.transactionService.push({ ref: knockingMemberDocRef, data: {}, action: 'delete' }); + this.transactionService.push({ ref: knockingMemberDocRef, data: undefined, action: Action.D }); this.transactionService.push({ - ref: spaceDocRef, + ref: build5Db().doc(COL.SPACE, params.uid), data: space, - action: 'update', + action: Action.U, }); return { status: 'success' }; @@ -48,21 +58,21 @@ export const acceptSpaceMember = async ( ) => { await assertIsGuardian(spaceId, owner); - const spaceDocRef = build5Db().doc(`${COL.SPACE}/${spaceId}`); - const knockingMember = await spaceDocRef - .collection(SUB_COL.KNOCKING_MEMBERS) - .doc(member) - .get(); + const spaceDocRef = build5Db().doc(COL.SPACE, spaceId); + const knockingMember = await build5Db() + .doc(COL.SPACE, spaceId, SUB_COL.KNOCKING_MEMBERS, member) + .get(); if (!knockingMember) { throw invalidArgument(WenError.member_did_not_request_to_join); } - const space = await spaceDocRef.get(); + const space = await spaceDocRef.get(); const spaceMember = { project, uid: member, - parentId: space, + parentId: space?.uid!, parentCol: COL.SPACE, + createdOn: dateToTimestamp(dayjs()), }; const spaceUpdateData = { 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 a33340c7dd..98c2022ab0 100644 --- a/packages/functions/src/services/payment/tangle-service/space/SpaceBlockMemberService.ts +++ b/packages/functions/src/services/payment/tangle-service/space/SpaceBlockMemberService.ts @@ -1,10 +1,13 @@ import { build5Db } from '@build-5/database'; import { COL, Space, SUB_COL, TangleResponse, WenError } from '@build-5/interfaces'; +import dayjs from 'dayjs'; import { getProject } from '../../../../utils/common.utils'; +import { dateToTimestamp } from '../../../../utils/dateTime.utils'; import { invalidArgument } from '../../../../utils/error.utils'; import { assertValidationAsync } from '../../../../utils/schema.utils'; import { assertIsGuardian } from '../../../../utils/token.utils'; import { BaseTangleService, HandlerParams } from '../../base'; +import { Action } from '../../transaction-service'; import { editSpaceMemberSchemaObject } from './SpaceEditMemberTangleRequestSchema'; export class SpaceBlockMemberService extends BaseTangleService { @@ -19,31 +22,36 @@ export class SpaceBlockMemberService extends BaseTangleService { member, ); - const spaceDocRef = build5Db().doc(`${COL.SPACE}/${params.uid}`); - const blockedMemberDocRef = spaceDocRef.collection(SUB_COL.BLOCKED_MEMBERS).doc(member); + const spaceDocRef = build5Db().doc(COL.SPACE, params.uid); + const blockedMemberDocRef = build5Db().doc( + COL.SPACE, + params.uid, + SUB_COL.BLOCKED_MEMBERS, + member, + ); this.transactionService.push({ ref: blockedMemberDocRef, data: blockedMember, - action: 'set', + action: Action.C, }); this.transactionService.push({ - ref: spaceDocRef.collection(SUB_COL.MEMBERS).doc(member), - data: {}, - action: 'delete', + ref: build5Db().doc(COL.SPACE, params.uid, SUB_COL.MEMBERS, member), + data: undefined, + action: Action.D, }); this.transactionService.push({ - ref: spaceDocRef.collection(SUB_COL.KNOCKING_MEMBERS).doc(member), - data: {}, - action: 'delete', + ref: build5Db().doc(COL.SPACE, params.uid, SUB_COL.KNOCKING_MEMBERS, member), + data: undefined, + action: Action.D, }); this.transactionService.push({ ref: spaceDocRef, data: space, - action: 'update', + action: Action.U, }); return { status: 'success' }; @@ -56,16 +64,18 @@ export const getBlockMemberUpdateData = async ( spaceId: string, member: string, ) => { - const spaceDocRef = build5Db().doc(`${COL.SPACE}/${spaceId}`); + const spaceDocRef = build5Db().doc(COL.SPACE, spaceId); await assertIsGuardian(spaceId, owner); - const spaceMember = await spaceDocRef.collection(SUB_COL.MEMBERS).doc(member).get(); - const knockingMember = await spaceDocRef.collection(SUB_COL.KNOCKING_MEMBERS).doc(member).get(); + const spaceMember = await build5Db().doc(COL.SPACE, spaceId, SUB_COL.MEMBERS, member).get(); + const knockingMember = await build5Db() + .doc(COL.SPACE, spaceId, SUB_COL.KNOCKING_MEMBERS, member) + .get(); if (!spaceMember && !knockingMember) { throw invalidArgument(WenError.member_is_not_part_of_the_space); } - const blockedMemberDocRef = spaceDocRef.collection(SUB_COL.BLOCKED_MEMBERS).doc(member); + const blockedMemberDocRef = build5Db().doc(COL.SPACE, spaceId, SUB_COL.BLOCKED_MEMBERS, member); const blockedMemberDoc = await blockedMemberDocRef.get(); if (blockedMemberDoc) { throw invalidArgument(WenError.member_is_already_blocked); @@ -76,7 +86,7 @@ export const getBlockMemberUpdateData = async ( throw invalidArgument(WenError.at_least_one_member_must_be_in_the_space); } - const guardian = await spaceDocRef.collection(SUB_COL.GUARDIANS).doc(member).get(); + const guardian = await build5Db().doc(COL.SPACE, spaceId, SUB_COL.GUARDIANS, member).get(); if (guardian) { throw invalidArgument(WenError.can_not_block_guardian); } @@ -86,6 +96,7 @@ export const getBlockMemberUpdateData = async ( uid: member, parentId: spaceId, parentCol: COL.SPACE, + createdOn: dateToTimestamp(dayjs()), }; const spaceUpdateData = { totalMembers: build5Db().inc(spaceMember ? -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 9246dcbafa..fc0d7c1106 100644 --- a/packages/functions/src/services/payment/tangle-service/space/SpaceCreateService.ts +++ b/packages/functions/src/services/payment/tangle-service/space/SpaceCreateService.ts @@ -1,8 +1,17 @@ import { build5Db, build5Storage } from '@build-5/database'; -import { COL, MediaStatus, Network, SUB_COL, SpaceCreateTangleResponse } from '@build-5/interfaces'; -import { get, set } from 'lodash'; +import { + COL, + MediaStatus, + Network, + SUB_COL, + SpaceCreateTangleResponse, + SpaceGuardian, +} from '@build-5/interfaces'; +import dayjs from 'dayjs'; +import { set } from 'lodash'; import { downloadMediaAndPackCar } from '../../../../utils/car.utils'; import { getBucket, isProdEnv } from '../../../../utils/config.utils'; +import { dateToTimestamp } from '../../../../utils/dateTime.utils'; import { migrateUriToSotrage, uriToUrl } from '../../../../utils/media.utils'; import { assertValidationAsync } from '../../../../utils/schema.utils'; import { spaceToIpfsMetadata } from '../../../../utils/space.utils'; @@ -10,6 +19,7 @@ import { getRandomEthAddress } from '../../../../utils/wallet.utils'; import { isStorageUrl } from '../../../joi/common'; import { WalletService } from '../../../wallet/wallet.service'; import { BaseTangleService, HandlerParams } from '../../base'; +import { Action } from '../../transaction-service'; import { createSpaceSchemaObject } from './SpaceCreateTangleRequestSchema'; export class SpaceCreateService extends BaseTangleService { @@ -20,30 +30,30 @@ export class SpaceCreateService extends BaseTangleService => { await assertValidationAsync(createSpaceSchemaObject, request); - const { space, guardian, member } = await getCreateSpaceData(project, owner, request); + const { space, guardian } = await getCreateSpaceData(project, owner, request); - const spaceDocRef = build5Db().doc(`${COL.SPACE}/${space.uid}`); - this.transactionService.push({ ref: spaceDocRef, data: space, action: 'set' }); + this.transactionService.push({ + ref: build5Db().doc(COL.SPACE, space.uid), + data: space, + action: Action.C, + }); - const spaceGuardianDocRef = spaceDocRef.collection(SUB_COL.GUARDIANS).doc(owner); this.transactionService.push({ - ref: spaceGuardianDocRef, + ref: build5Db().doc(COL.SPACE, space.uid, SUB_COL.GUARDIANS, owner), data: guardian, - action: 'set', + action: Action.C, }); - const spaceMemberDocRef = spaceDocRef.collection(SUB_COL.MEMBERS).doc(owner); this.transactionService.push({ - ref: spaceMemberDocRef, + ref: build5Db().doc(COL.SPACE, space.uid, SUB_COL.MEMBERS, owner), data: guardian, - action: 'set', + action: Action.C, }); - const memberDocRef = build5Db().doc(`${COL.MEMBER}/${owner}`); + const memberDocRef = build5Db().doc(COL.MEMBER, owner); this.transactionService.push({ ref: memberDocRef, - data: member, - action: 'update', - merge: true, + data: { spaces: { [space.uid]: { uid: space.uid, isMember: true } } }, + action: Action.U, }); return { space: space.uid }; @@ -62,6 +72,7 @@ export const getCreateSpaceData = async ( uid: getRandomEthAddress(), project, ...params, + bannerUrl: (params.bannerUrl as string) || '', createdBy: owner, open: params.open === false ? false : true, totalMembers: 1, @@ -71,7 +82,7 @@ export const getCreateSpaceData = async ( vaultAddress: vaultAddress.bech32, }; - let bannerUrl = get(space, 'bannerUrl', ''); + let bannerUrl = space.bannerUrl || ''; if (bannerUrl) { // eslint-disable-next-line @typescript-eslint/no-explicit-any const metadata = spaceToIpfsMetadata(space as any); @@ -95,16 +106,16 @@ export const getCreateSpaceData = async ( set(space, 'mediaStatus', MediaStatus.PENDING_UPLOAD); } - const guardian = { + const guardian: SpaceGuardian = { project, uid: owner, parentId: space.uid, parentCol: COL.SPACE, + createdOn: dateToTimestamp(dayjs()), }; return { space: { ...space, guardians: { [owner]: guardian }, members: { [owner]: guardian } }, guardian, - member: { spaces: { [space.uid]: { uid: space.uid, isMember: true } } }, }; }; diff --git a/packages/functions/src/services/payment/tangle-service/space/SpaceDeclineMemberService.ts b/packages/functions/src/services/payment/tangle-service/space/SpaceDeclineMemberService.ts index 507cbcd67d..28e0097d00 100644 --- a/packages/functions/src/services/payment/tangle-service/space/SpaceDeclineMemberService.ts +++ b/packages/functions/src/services/payment/tangle-service/space/SpaceDeclineMemberService.ts @@ -3,6 +3,7 @@ import { COL, SUB_COL, TangleResponse } from '@build-5/interfaces'; import { assertValidationAsync } from '../../../../utils/schema.utils'; import { assertIsGuardian } from '../../../../utils/token.utils'; import { BaseTangleService, HandlerParams } from '../../base'; +import { Action } from '../../transaction-service'; import { editSpaceMemberSchemaObject } from './SpaceEditMemberTangleRequestSchema'; export class SpaceDeclineMemberService extends BaseTangleService { @@ -11,19 +12,22 @@ export class SpaceDeclineMemberService extends BaseTangleService await assertIsGuardian(params.uid, owner); - const spaceDocRef = build5Db().doc(`${COL.SPACE}/${params.uid}`); - const knockingMemberDocRef = spaceDocRef - .collection(SUB_COL.KNOCKING_MEMBERS) - .doc(params.member); + const spaceDocRef = build5Db().doc(COL.SPACE, params.uid); + const knockingMemberDocRef = build5Db().doc( + COL.SPACE, + params.uid, + SUB_COL.KNOCKING_MEMBERS, + params.member, + ); const knockingMember = await knockingMemberDocRef.get(); - this.transactionService.push({ ref: knockingMemberDocRef, data: {}, action: 'delete' }); + this.transactionService.push({ ref: knockingMemberDocRef, data: undefined, action: Action.D }); this.transactionService.push({ ref: spaceDocRef, data: { totalPendingMembers: build5Db().inc(knockingMember ? -1 : 0) }, - action: 'update', + action: Action.U, }); return { status: 'success' }; diff --git a/packages/functions/src/services/payment/tangle-service/space/SpaceGuardianService.ts b/packages/functions/src/services/payment/tangle-service/space/SpaceGuardianService.ts index 24b838f214..12036096c5 100644 --- a/packages/functions/src/services/payment/tangle-service/space/SpaceGuardianService.ts +++ b/packages/functions/src/services/payment/tangle-service/space/SpaceGuardianService.ts @@ -9,7 +9,6 @@ import { ProposalType, Space, SpaceGuardianUpsertTangleResponse, - SpaceMember, SUB_COL, TangleRequestType, Transaction, @@ -24,6 +23,7 @@ import { assertValidationAsync } from '../../../../utils/schema.utils'; import { assertIsGuardian } from '../../../../utils/token.utils'; import { getRandomEthAddress } from '../../../../utils/wallet.utils'; import { BaseTangleService, HandlerParams } from '../../base'; +import { Action } from '../../transaction-service'; import { editSpaceMemberSchemaObject } from './SpaceEditMemberTangleRequestSchema'; export class SpaceGuardianService extends BaseTangleService { @@ -46,22 +46,20 @@ export class SpaceGuardianService extends BaseTangleService { - proposalDocRef.collection(SUB_COL.MEMBERS).doc(member.uid).set(member); - }); + const memberPromisses = members.map((member) => + build5Db().doc(COL.PROPOSAL, proposal.uid, SUB_COL.MEMBERS, member.uid).create(member), + ); await Promise.all(memberPromisses); - const transactionDocRef = build5Db().doc(`${COL.TRANSACTION}/${voteTransaction.uid}`); this.transactionService.push({ - ref: transactionDocRef, + ref: build5Db().doc(COL.TRANSACTION, voteTransaction.uid), data: voteTransaction, - action: 'set', + action: Action.C, }); this.transactionService.push({ - ref: proposalDocRef, + ref: build5Db().doc(COL.PROPOSAL, proposal.uid), data: proposal, - action: 'set', + action: Action.C, }); return { proposal: proposal.uid }; @@ -77,18 +75,16 @@ export const addRemoveGuardian = async ( const isAddGuardian = type === ProposalType.ADD_GUARDIAN; await assertIsGuardian(params.uid as string, owner); - const spaceDocRef = build5Db().doc(`${COL.SPACE}/${params.uid}`); - const spaceMemberDoc = await spaceDocRef - .collection(SUB_COL.MEMBERS) - .doc(params.member as string) + const spaceDocRef = build5Db().doc(COL.SPACE, params.uid as string); + const spaceMemberDoc = await build5Db() + .doc(COL.SPACE, params.uid as string, SUB_COL.MEMBERS, params.member as string) .get(); if (!spaceMemberDoc) { throw invalidArgument(WenError.member_is_not_part_of_the_space); } - const spaceGuardianMember = await spaceDocRef - .collection(SUB_COL.GUARDIANS) - .doc(params.member as string) + const spaceGuardianMember = await build5Db() + .doc(COL.SPACE, params.uid as string, SUB_COL.GUARDIANS, params.member as string) .get(); if (isAddGuardian && spaceGuardianMember) { throw invalidArgument(WenError.member_is_already_guardian_of_space); @@ -98,7 +94,7 @@ export const addRemoveGuardian = async ( const ongoingProposalSnap = await build5Db() .collection(COL.PROPOSAL) - .where('settings.addRemoveGuardian', '==', params.member) + .where('settings_addRemoveGuardian', '==', params.member as string) .where('completed', '==', false) .get(); @@ -115,13 +111,14 @@ export const addRemoveGuardian = async ( }); } - const guardian = await build5Db().doc(`${COL.MEMBER}/${owner}`).get(); - const member = await build5Db().doc(`${COL.MEMBER}/${params.member}`).get(); + const guardian = await build5Db().doc(COL.MEMBER, owner).get(); + const member = await build5Db() + .doc(COL.MEMBER, params.member as string) + .get(); const guardians = await build5Db() - .doc(`${COL.SPACE}/${params.uid}`) - .collection(SUB_COL.GUARDIANS) - .get(); - const space = await spaceDocRef.get(); + .collection(COL.SPACE, params.uid as string, SUB_COL.GUARDIANS) + .get(); + const space = await spaceDocRef.get(); const proposal = getProposalData( project, guardian, @@ -153,7 +150,7 @@ export const addRemoveGuardian = async ( voted: guardian.uid === owner, tranId: guardian.uid === owner ? voteTransaction.uid : '', parentId: proposal.uid, - parentCol: COL.PROPOSAL, + parentCol: COL.SPACE, values: guardian.uid === owner ? [{ [1]: 1 }] : [], })); @@ -169,9 +166,7 @@ const getProposalData = ( guardiansCount: number, ): Proposal => { const additionalInfo = - `${owner.name || owner.uid} wants to ${isAddGuardian ? 'add' : 'remove'} ${ - member.name - } as guardian. ` + + `${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 { 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 3242fcfcdd..f00b0ca58c 100644 --- a/packages/functions/src/services/payment/tangle-service/space/SpaceJoinService.ts +++ b/packages/functions/src/services/payment/tangle-service/space/SpaceJoinService.ts @@ -6,7 +6,6 @@ import { StakeType, SUB_COL, TangleResponse, - TokenDistribution, WenError, } from '@build-5/interfaces'; import { getProject } from '../../../../utils/common.utils'; @@ -16,45 +15,44 @@ import { assertValidationAsync } from '../../../../utils/schema.utils'; import { getTokenForSpace } from '../../../../utils/token.utils'; import { getStakeForType } from '../../../stake.service'; import { BaseTangleService, HandlerParams } from '../../base'; +import { Action } from '../../transaction-service'; import { joinSpaceSchema } from './SpaceJoinTangleRequestSchema'; export class SpaceJoinService extends BaseTangleService { public handleRequest = async ({ order, owner, request }: HandlerParams) => { const params = await assertValidationAsync(joinSpaceSchema, request); - const spaceDocRef = build5Db().doc(`${COL.SPACE}/${params.uid}`); + 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(getProject(order), owner, space); + const { space: spaceUpdateData, spaceMember } = await getJoinSpaceData( + getProject(order), + owner, + space, + ); - const joiningMemberDocRef = spaceDocRef - .collection(space.open || space.tokenBased ? SUB_COL.MEMBERS : SUB_COL.KNOCKING_MEMBERS) - .doc(owner); + const subCol = space.open || space.tokenBased ? SUB_COL.MEMBERS : SUB_COL.KNOCKING_MEMBERS; + const joiningMemberDocRef = build5Db().doc(COL.SPACE, params.uid, subCol, owner); this.transactionService.push({ ref: joiningMemberDocRef, data: spaceMember, - action: 'set', + action: Action.C, }); this.transactionService.push({ ref: spaceDocRef, data: spaceUpdateData, - action: 'update', + action: Action.U, }); - const memberDocRef = build5Db().doc(`${COL.MEMBER}/${owner}`); + const memberDocRef = build5Db().doc(COL.MEMBER, owner); this.transactionService.push({ ref: memberDocRef, - data: member, - action: 'set', - merge: true, + data: { spaces: { [space.uid]: { uid: space.uid, isMember: true } } }, + action: Action.U, }); return { status: 'success' }; @@ -62,21 +60,20 @@ export class SpaceJoinService extends BaseTangleService { } 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(); + const joinedMemberSnap = await build5Db().doc(COL.SPACE, space.uid, SUB_COL.MEMBERS, owner).get(); if (joinedMemberSnap) { throw invalidArgument(WenError.you_are_already_part_of_space); } - const blockedMemberSnap = await spaceDocRef.collection(SUB_COL.BLOCKED_MEMBERS).doc(owner).get(); + const blockedMemberSnap = await build5Db() + .doc(COL.SPACE, space.uid, SUB_COL.BLOCKED_MEMBERS, owner) + .get(); if (blockedMemberSnap) { throw invalidArgument(WenError.you_are_not_allowed_to_join_space); } - const knockingMemberSnap = await spaceDocRef - .collection(SUB_COL.KNOCKING_MEMBERS) - .doc(owner) + const knockingMemberSnap = await build5Db() + .doc(COL.SPACE, space.uid, SUB_COL.KNOCKING_MEMBERS, owner) .get(); if (knockingMemberSnap) { throw invalidArgument(WenError.member_already_knocking); @@ -105,9 +102,8 @@ export const getJoinSpaceData = async (project: string, owner: string, space: Sp const assertMemberHasEnoughStakedTokens = async (space: Space, member: string) => { const token = await getTokenForSpace(space.uid); - const tokenDocRef = build5Db().doc(`${COL.TOKEN}/${token?.uid}`); - const distributionDocRef = tokenDocRef.collection(SUB_COL.DISTRIBUTION).doc(member); - const distribution = await distributionDocRef.get(); + const distributionDocRef = build5Db().doc(COL.TOKEN, token?.uid!, SUB_COL.DISTRIBUTION, member); + const distribution = await distributionDocRef.get(); const stakeValue = getStakeForType(distribution, StakeType.DYNAMIC); if (stakeValue < (space.minStakedValue || 0)) { throw invalidArgument(WenError.not_enough_staked_tokens); diff --git a/packages/functions/src/services/payment/tangle-service/space/SpaceLeaveService.ts b/packages/functions/src/services/payment/tangle-service/space/SpaceLeaveService.ts index 4e93506ae1..040ab1ec5e 100644 --- a/packages/functions/src/services/payment/tangle-service/space/SpaceLeaveService.ts +++ b/packages/functions/src/services/payment/tangle-service/space/SpaceLeaveService.ts @@ -3,41 +3,40 @@ import { COL, Space, SUB_COL, TangleResponse, WenError } from '@build-5/interfac import { invalidArgument } from '../../../../utils/error.utils'; import { assertValidationAsync } from '../../../../utils/schema.utils'; import { BaseTangleService, HandlerParams } from '../../base'; +import { Action } from '../../transaction-service'; import { leaveSpaceSchema } from './SpaceLeaveTangleRequestSchema'; export class SpaceLeaveService extends BaseTangleService { public handleRequest = async ({ owner, request }: HandlerParams) => { const params = await assertValidationAsync(leaveSpaceSchema, request); - const { space, member } = await getLeaveSpaceData(owner, params.uid); + const spaceUpdateData = await getLeaveSpaceData(owner, params.uid); - const spaceDocRef = build5Db().doc(`${COL.SPACE}/${params.uid}`); + const spaceDocRef = build5Db().doc(COL.SPACE, params.uid); this.transactionService.push({ - ref: spaceDocRef.collection(SUB_COL.MEMBERS).doc(owner), - data: {}, - action: 'delete', + ref: build5Db().doc(COL.SPACE, params.uid, SUB_COL.MEMBERS, owner), + data: undefined, + action: Action.D, }); this.transactionService.push({ - ref: spaceDocRef.collection(SUB_COL.GUARDIANS).doc(owner), - data: {}, - action: 'delete', + ref: build5Db().doc(COL.SPACE, params.uid, SUB_COL.GUARDIANS, owner), + data: undefined, + action: Action.D, }); this.transactionService.push({ ref: spaceDocRef, - data: space, - action: 'update', + data: spaceUpdateData, + action: Action.U, }); - const memberDocRef = build5Db().doc(`${COL.MEMBER}/${owner}`); - + const memberSpaceStats = build5Db().doc(COL.MEMBER, owner); this.transactionService.push({ - ref: memberDocRef, - data: member, - action: 'set', - merge: true, + ref: memberSpaceStats, + data: { spaces: { [params.uid]: { isMember: false } } }, + action: Action.U, }); return { status: 'success' }; @@ -45,9 +44,9 @@ export class SpaceLeaveService extends BaseTangleService { } export const getLeaveSpaceData = async (owner: string, spaceId: string) => { - const spaceDocRef = build5Db().doc(`${COL.SPACE}/${spaceId}`); + const spaceDocRef = build5Db().doc(COL.SPACE, spaceId); - const spaceMember = await spaceDocRef.collection(SUB_COL.MEMBERS).doc(owner).get(); + const spaceMember = await build5Db().doc(COL.SPACE, spaceId, SUB_COL.MEMBERS, owner).get(); if (!spaceMember) { throw invalidArgument(WenError.you_are_not_part_of_the_space); } @@ -57,16 +56,14 @@ export const getLeaveSpaceData = async (owner: string, spaceId: string) => { throw invalidArgument(WenError.at_least_one_member_must_be_in_the_space); } - const guardianDoc = await spaceDocRef.collection(SUB_COL.GUARDIANS).doc(owner).get(); + const guardianDoc = await build5Db().doc(COL.SPACE, spaceId, SUB_COL.GUARDIANS, owner).get(); const isGuardian = guardianDoc !== undefined; if (space.totalGuardians === 1 && isGuardian) { throw invalidArgument(WenError.at_least_one_guardian_must_be_in_the_space); } - const spaceUpdateData = { + return { totalMembers: build5Db().inc(-1), totalGuardians: build5Db().inc(isGuardian ? -1 : 0), }; - const member = { spaces: { [space.uid]: { uid: space.uid, isMember: false } } }; - return { space: spaceUpdateData, member }; }; diff --git a/packages/functions/src/services/payment/tangle-service/stamp/StampTangleService.ts b/packages/functions/src/services/payment/tangle-service/stamp/StampTangleService.ts index 3c4f7c1dfe..bbb2567297 100644 --- a/packages/functions/src/services/payment/tangle-service/stamp/StampTangleService.ts +++ b/packages/functions/src/services/payment/tangle-service/stamp/StampTangleService.ts @@ -6,7 +6,6 @@ import { STAMP_COST_PER_MB, SUB_COL, Space, - SpaceGuardian, Stamp, TRANSACTION_AUTO_EXPIRY_MS, TangleResponse, @@ -23,7 +22,7 @@ import { packBasicOutput } from '../../../../utils/basic-output.utils'; import { downloadMediaAndPackCar } from '../../../../utils/car.utils'; import { createNftOutput } from '../../../../utils/collection-minting-utils/nft.utils'; import { getProject } from '../../../../utils/common.utils'; -import { dateToTimestamp } from '../../../../utils/dateTime.utils'; +import { dateToTimestamp, serverTime } from '../../../../utils/dateTime.utils'; import { invalidArgument } from '../../../../utils/error.utils'; import { getRandomBuild5Url, uriToUrl } from '../../../../utils/media.utils'; import { assertValidationAsync } from '../../../../utils/schema.utils'; @@ -37,6 +36,7 @@ import { isStorageUrl } from '../../../joi/common'; import { Wallet } from '../../../wallet/wallet'; import { WalletService } from '../../../wallet/wallet.service'; import { BaseTangleService, HandlerParams } from '../../base'; +import { Action } from '../../transaction-service'; import { stampTangleSchema } from './StampTangleRequestSchema'; export class StampTangleService extends BaseTangleService { @@ -62,22 +62,27 @@ export class StampTangleService extends BaseTangleService { ); if (!params.aliasId) { - const spaceDocRef = build5Db().doc(`${COL.SPACE}/${space.uid}`); - this.transactionService.push({ ref: spaceDocRef, data: space, action: 'set' }); + const spaceDocRef = build5Db().doc(COL.SPACE, space.uid); + this.transactionService.push({ ref: spaceDocRef, data: space, action: Action.C }); - const guardian = { uid: owner, parentId: space.uid, parentCol: COL.SPACE }; - const guardianDocRef = spaceDocRef.collection(SUB_COL.GUARDIANS).doc(owner); - this.transactionService.push({ ref: guardianDocRef, data: guardian, action: 'set' }); + const guardian = { + uid: owner, + parentId: space.uid, + parentCol: COL.SPACE, + createdOn: serverTime(), + }; + const guardianDocRef = build5Db().doc(COL.SPACE, space.uid, SUB_COL.GUARDIANS, owner); + this.transactionService.push({ ref: guardianDocRef, data: guardian, action: Action.C }); - const memberDocRef = spaceDocRef.collection(SUB_COL.MEMBERS).doc(owner); - this.transactionService.push({ ref: memberDocRef, data: guardian, action: 'set' }); + const memberDocRef = build5Db().doc(COL.SPACE, space.uid, SUB_COL.MEMBERS, owner); + this.transactionService.push({ ref: memberDocRef, data: guardian, action: Action.C }); } - const orderDocRef = build5Db().doc(`${COL.TRANSACTION}/${order.uid}`); - this.transactionService.push({ ref: orderDocRef, data: order, action: 'set' }); + const orderDocRef = build5Db().doc(COL.TRANSACTION, order.uid); + this.transactionService.push({ ref: orderDocRef, data: order, action: Action.C }); - const stampDocRef = build5Db().doc(`${COL.STAMP}/${stamp.uid}`); - this.transactionService.push({ ref: stampDocRef, data: stamp, action: 'set' }); + const stampDocRef = build5Db().doc(COL.STAMP, stamp.uid); + this.transactionService.push({ ref: stampDocRef, data: stamp, action: Action.C }); if (match.to.amount < order.payload.amount!) { return { @@ -222,9 +227,8 @@ const getAliasOutputAmount = async (stamp: Stamp, space: Space, wallet: Wallet) if (!space.alias?.address) { throw invalidArgument(WenError.not_alias_governor); } - const spaceDocRef = build5Db().doc(`${COL.SPACE}/${space.uid}`); - const guardianDocRef = spaceDocRef.collection(SUB_COL.GUARDIANS).doc(stamp.createdBy); - const guardian = await guardianDocRef.get(); + const guardianDocRef = build5Db().doc(COL.SPACE, space.uid, SUB_COL.GUARDIANS, stamp.createdBy); + const guardian = await guardianDocRef.get(); if (!guardian) { throw invalidArgument(WenError.not_alias_governor); diff --git a/packages/functions/src/services/payment/tangle-service/swap/SwapCreateTangleService.ts b/packages/functions/src/services/payment/tangle-service/swap/SwapCreateTangleService.ts index 02b10db14f..bc541ea7e8 100644 --- a/packages/functions/src/services/payment/tangle-service/swap/SwapCreateTangleService.ts +++ b/packages/functions/src/services/payment/tangle-service/swap/SwapCreateTangleService.ts @@ -4,6 +4,7 @@ import { assertValidationAsync } from '../../../../utils/schema.utils'; import { WalletService } from '../../../wallet/wallet.service'; import { BaseTangleService, HandlerParams } from '../../base'; import { createSwapOrder } from '../../swap/swap-service'; +import { Action } from '../../transaction-service'; import { swapCreateTangleSchema } from './SwapCreateTangleRequestSchema'; export class SwapCreateTangleService extends BaseTangleService { @@ -43,11 +44,11 @@ export class SwapCreateTangleService extends BaseTangleService { bids, ); - const orderDocRef = build5Db().doc(`${COL.TRANSACTION}/${order.uid}`); - this.transactionService.push({ ref: orderDocRef, data: order, action: 'set' }); + const orderDocRef = build5Db().doc(COL.TRANSACTION, order.uid); + this.transactionService.push({ ref: orderDocRef, data: order, action: Action.C }); - const swapDocRef = build5Db().doc(`${COL.SWAP}/${swap.uid}`); - this.transactionService.push({ ref: swapDocRef, data: swap, action: 'set' }); + const swapDocRef = build5Db().doc(COL.SWAP, swap.uid); + this.transactionService.push({ ref: swapDocRef, data: swap, action: Action.C }); if (params.setFunded) { return {}; diff --git a/packages/functions/src/services/payment/tangle-service/swap/SwapRejectTangleService.ts b/packages/functions/src/services/payment/tangle-service/swap/SwapRejectTangleService.ts index d382ecbb7b..874eb00d1d 100644 --- a/packages/functions/src/services/payment/tangle-service/swap/SwapRejectTangleService.ts +++ b/packages/functions/src/services/payment/tangle-service/swap/SwapRejectTangleService.ts @@ -1,8 +1,9 @@ -import { build5Db } from '@build-5/database'; -import { COL, Swap, SwapStatus, TangleResponse } from '@build-5/interfaces'; +import { PgSwapStatus, build5Db } from '@build-5/database'; +import { COL, TangleResponse } from '@build-5/interfaces'; import { assertValidationAsync } from '../../../../utils/schema.utils'; import { BaseTangleService, HandlerParams } from '../../base'; import { rejectSwap } from '../../swap/swap-service'; +import { Action } from '../../transaction-service'; import { swapRejectTangleSchema } from './SwapRejectTangleRequestSchema'; export class SwapRejectTangleService extends BaseTangleService { @@ -13,20 +14,20 @@ export class SwapRejectTangleService extends BaseTangleService { }: HandlerParams): Promise => { const params = await assertValidationAsync(swapRejectTangleSchema, request); - const swapDocRef = build5Db().doc(`${COL.SWAP}/${params.uid}`); - const swap = await this.transactionService.get(swapDocRef); + const swapDocRef = build5Db().doc(COL.SWAP, params.uid); + const swap = await this.transaction.get(swapDocRef); const credits = rejectSwap(project, owner, swap); for (const credit of credits) { - const docRef = build5Db().doc(`${COL.TRANSACTION}/${credit.uid}`); - this.transactionService.push({ ref: docRef, data: credit, action: 'set' }); + const docRef = build5Db().doc(COL.TRANSACTION, credit.uid); + this.transactionService.push({ ref: docRef, data: credit, action: Action.C }); } this.transactionService.push({ ref: swapDocRef, - data: { status: SwapStatus.REJECTED }, - action: 'update', + data: { status: PgSwapStatus.REJECTED }, + action: Action.U, }); return { status: 'success' }; diff --git a/packages/functions/src/services/payment/tangle-service/swap/SwapSetFundedTangleService.ts b/packages/functions/src/services/payment/tangle-service/swap/SwapSetFundedTangleService.ts index d8b059bf4f..dfc64ea528 100644 --- a/packages/functions/src/services/payment/tangle-service/swap/SwapSetFundedTangleService.ts +++ b/packages/functions/src/services/payment/tangle-service/swap/SwapSetFundedTangleService.ts @@ -1,5 +1,5 @@ -import { build5Db } from '@build-5/database'; -import { COL, Swap, SwapStatus, TangleResponse } from '@build-5/interfaces'; +import { PgSwapStatus, build5Db } from '@build-5/database'; +import { COL, TangleResponse } from '@build-5/interfaces'; import { assertValidationAsync } from '../../../../utils/schema.utils'; import { BaseTangleService, HandlerParams } from '../../base'; import { @@ -7,6 +7,7 @@ import { assertSwapCanBeSetAsFunded, createSwapTransfers, } from '../../swap/swap-service'; +import { Action } from '../../transaction-service'; import { swapSetFundedTangleSchema } from './SwapSetFundedTangleRequestSchema'; export class SwapSetFundedTangleService extends BaseTangleService { @@ -17,26 +18,25 @@ export class SwapSetFundedTangleService extends BaseTangleService => { const params = await assertValidationAsync(swapSetFundedTangleSchema, request); - const swapDocRef = build5Db().doc(`${COL.SWAP}/${params.uid}`); - const swap = await this.transactionService.get(swapDocRef); + const swapDocRef = build5Db().doc(COL.SWAP, params.uid); + const swap = await this.transaction.get(swapDocRef); assertSwapCanBeSetAsFunded(owner, swap); if (asksAreFulfilled(swap!)) { const transfers = await createSwapTransfers(project, swap!); for (const transfer of transfers) { - const docRef = build5Db().doc(`${COL.TRANSACTION}/${transfer.uid}`); this.transactionService.push({ - ref: docRef, + ref: build5Db().doc(COL.TRANSACTION, transfer.uid), data: transfer, - action: 'set', + action: Action.C, }); } this.transactionService.push({ ref: swapDocRef, - data: { status: SwapStatus.FULFILLED }, - action: 'update', + data: { status: PgSwapStatus.FULFILLED }, + action: Action.U, }); return { status: 'success' }; @@ -44,8 +44,8 @@ export class SwapSetFundedTangleService extends BaseTangleService { @@ -44,9 +45,9 @@ export class TangleStakeService extends BaseTangleService { set(order, 'payload.amount', tranEntry.amount); this.transactionService.push({ - ref: build5Db().doc(`${COL.TRANSACTION}/${order.uid}`), + ref: build5Db().doc(COL.TRANSACTION, order.uid), data: order, - action: 'set', + action: Action.C, }); this.transactionService.createUnlockTransaction( 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 ab9a021562..18e1264ffa 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 @@ -5,7 +5,6 @@ import { SUB_COL, TRANSACTION_AUTO_EXPIRY_MS, TangleResponse, - TokenDistribution, TokenDrop, TokenDropStatus, TokenStatus, @@ -26,6 +25,7 @@ import { getTokenBySymbol, getUnclaimedDrops } from '../../../../utils/token.uti import { getRandomEthAddress } from '../../../../utils/wallet.utils'; import { WalletService } from '../../../wallet/wallet.service'; import { BaseTangleService, HandlerParams } from '../../base'; +import { Action } from '../../transaction-service'; import { tokenClaimSchema } from './TokenClaimTangleRequestSchema'; export class TangleTokenClaimService extends BaseTangleService { @@ -33,9 +33,9 @@ export class TangleTokenClaimService extends BaseTangleService { const params = await assertValidationAsync(tokenClaimSchema, request); const order = await createMintedTokenAirdropClaimOrder(project, owner, params.symbol); this.transactionService.push({ - ref: build5Db().doc(`${COL.TRANSACTION}/${order.uid}`), + ref: build5Db().doc(COL.TRANSACTION, order.uid), data: order, - action: 'set', + action: Action.C, }); return { amount: order.payload.amount!, address: order.payload.targetAddress! }; }; @@ -55,7 +55,7 @@ export const createMintedTokenAirdropClaimOrder = async ( throw invalidArgument(WenError.token_in_invalid_status); } - const member = await build5Db().doc(`${COL.MEMBER}/${owner}`).get(); + const member = await build5Db().doc(COL.MEMBER, owner).get(); assertMemberHasValidAddress(member, token.mintingData?.network!); const drops = await getClaimableDrops(token.uid, owner); @@ -95,9 +95,8 @@ export const createMintedTokenAirdropClaimOrder = async ( const getClaimableDrops = async (token: string, member: string) => { const airdops = await getUnclaimedDrops(token, member); - const tokenDocRef = build5Db().doc(`${COL.TOKEN}/${token}`); - const distributionDocRef = tokenDocRef.collection(SUB_COL.DISTRIBUTION).doc(member); - const distribution = await distributionDocRef.get(); + const distributionDocRef = build5Db().doc(COL.TOKEN, token, SUB_COL.DISTRIBUTION, member); + const distribution = await distributionDocRef.get(); if (distribution?.mintedClaimedOn || !distribution?.tokenOwned) { return airdops; } 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 75a181345c..30bb1f5f9f 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 @@ -1,16 +1,14 @@ -import { ITransaction, build5Db } from '@build-5/database'; +import { ITransaction, PgTokenTradeOrderStatus, build5Db } from '@build-5/database'; import { COL, DEFAULT_NETWORK, MAX_TOTAL_TOKEN_SUPPLY, MIN_PRICE_PER_TOKEN, - Member, Network, SUB_COL, TRANSACTION_MAX_EXPIRY_MS, TangleResponse, Token, - TokenDistribution, TokenStatus, TokenTradeOrder, TokenTradeOrderStatus, @@ -41,6 +39,7 @@ import { import { getRandomEthAddress } from '../../../../utils/wallet.utils'; import { WalletService } from '../../../wallet/wallet.service'; import { BaseTangleService, HandlerParams } from '../../base'; +import { Action } from '../../transaction-service'; import { tradeMintedTokenSchema } from './TokenTradeTangleRequestSchema'; export class TangleTokenTradeService extends BaseTangleService { @@ -63,8 +62,8 @@ export class TangleTokenTradeService extends BaseTangleService { params.symbol || (type === TokenTradeOrderType.SELL ? order.network : getNetworkPair(order.network)); let token = await getTokenBySymbol(symbol); - const tokenDocRef = build5Db().doc(`${COL.TOKEN}/${token?.uid}`); - token = await this.transactionService.get(tokenDocRef); + const tokenDocRef = build5Db().doc(COL.TOKEN, token?.uid!); + token = await this.transaction.get(tokenDocRef); if (!token) { throw invalidArgument(WenError.token_does_not_exist); } @@ -79,7 +78,7 @@ export class TangleTokenTradeService extends BaseTangleService { token, type, getCount(params, type), - await getPrice(params, type, token.uid), + await getPrice(this.transactionService.transaction, params, type, token.uid), params.targetAddress, '', [TokenStatus.BASE, TokenStatus.MINTED], @@ -93,9 +92,9 @@ export class TangleTokenTradeService extends BaseTangleService { set(tradeOrderTransaction, 'payload.amount', tranEntry.amount); } this.transactionService.push({ - ref: build5Db().doc(`${COL.TRANSACTION}/${tradeOrderTransaction.uid}`), + ref: build5Db().doc(COL.TRANSACTION, tradeOrderTransaction.uid), data: tradeOrderTransaction, - action: 'set', + action: Action.C, }); this.transactionService.createUnlockTransaction( @@ -139,7 +138,7 @@ export const createTokenTradeOrder = async ( assertTokenStatus(token, acceptedTokenStatuses); const [sourceNetwork, targetNetwork] = getSourceAndTargetNetwork(token, isSell); - const member = await build5Db().doc(`${COL.MEMBER}/${owner}`).get(); + const member = await build5Db().doc(COL.MEMBER, owner).get(); assertMemberHasValidAddress(member, sourceNetwork); if (targetAddress) { if (!targetAddress.startsWith(targetNetwork === Network.ATOI ? 'rms' : targetNetwork)) { @@ -164,9 +163,8 @@ export const createTokenTradeOrder = async ( return { tradeOrderTransaction, tradeOrder: undefined, distribution: undefined }; } - const tokenDocRef = build5Db().doc(`${COL.TOKEN}/${token.uid}`); - const distributionDocRef = tokenDocRef.collection(SUB_COL.DISTRIBUTION).doc(owner); - const distribution = await transaction.get(distributionDocRef); + const distributionDocRef = build5Db().doc(COL.TOKEN, token.uid, SUB_COL.DISTRIBUTION, owner); + const distribution = await transaction.get(distributionDocRef); if (!distribution) { throw invalidArgument(WenError.invalid_params); } @@ -260,6 +258,7 @@ const createTradeOrderTransaction = async ( }; const getPrice = async ( + transaction: ITransaction, params: TradeTokenTangleRequest, type: TokenTradeOrderType, token: string, @@ -274,10 +273,10 @@ const getPrice = async ( const snap = await build5Db() .collection(COL.TOKEN_MARKET) .where('token', '==', token) - .where('status', '==', TokenTradeOrderStatus.ACTIVE) + .where('status', '==', PgTokenTradeOrderStatus.ACTIVE) .orderBy('price', 'desc') .limit(1) - .get(); + .get(); const highestSell = head(snap); if (!highestSell) { throw invalidArgument(WenError.no_active_sells); 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 d43529e9e4..b3ad047c1e 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 @@ -29,15 +29,15 @@ import { isAliasGovernor } from '../../../utils/token-minting-utils/alias.utils' import { Wallet } from '../../wallet/wallet'; import { WalletService } from '../../wallet/wallet.service'; import { BaseService, HandlerParams } from '../base'; -import { TransactionMatch } from '../transaction-service'; +import { Action, TransactionMatch } from '../transaction-service'; export class ImportMintedTokenService extends BaseService { public handleRequest = async ({ order, match }: HandlerParams) => { let error: { [key: string]: unknown } = {}; try { const tokenId = order.payload.tokenId!; - const existingTokenDocRef = build5Db().doc(`${COL.TOKEN}/${tokenId}`); - const existingToken = await this.transactionService.get(existingTokenDocRef); + const existingTokenDocRef = build5Db().doc(COL.TOKEN, tokenId); + const existingToken = await this.transaction.get(existingTokenDocRef); if (existingToken) { throw WenError.token_does_not_exist; @@ -99,8 +99,8 @@ export class ImportMintedTokenService extends BaseService { pricePerToken: 0, decimals: metadata.decimals, }; - const tokenDocRef = build5Db().doc(`${COL.TOKEN}/${token.uid}`); - this.transactionService.push({ ref: tokenDocRef, data: token, action: 'set' }); + const tokenDocRef = build5Db().doc(COL.TOKEN, token.uid); + this.transactionService.push({ ref: tokenDocRef, data: token, action: Action.C }); } catch (err) { error = { status: 'error', diff --git a/packages/functions/src/services/payment/token/token-mint.service.ts b/packages/functions/src/services/payment/token/token-mint.service.ts index 2d3316563e..dcee6458df 100644 --- a/packages/functions/src/services/payment/token/token-mint.service.ts +++ b/packages/functions/src/services/payment/token/token-mint.service.ts @@ -1,13 +1,13 @@ -import { build5Db } from '@build-5/database'; -import { COL, Token, TokenStatus, TransactionPayloadType } from '@build-5/interfaces'; +import { PgNetwork, PgTokenStatus, build5Db, convertEnum } from '@build-5/database'; +import { COL, Network, Token, TokenStatus, TransactionPayloadType } from '@build-5/interfaces'; import dayjs from 'dayjs'; -import { get } from 'lodash'; import { BaseService, HandlerParams } from '../base'; +import { Action } from '../transaction-service'; export class TokenMintService extends BaseService { public handleRequest = async ({ order, match }: HandlerParams) => { - const tokenDocRef = build5Db().doc(`${COL.TOKEN}/${order.payload.token}`); - const token = await this.transactionService.get(tokenDocRef); + const tokenDocRef = build5Db().doc(COL.TOKEN, order.payload.token!); + const token = await this.transaction.get(tokenDocRef); const payment = await this.transactionService.createPayment(order, match); if (![TokenStatus.AVAILABLE, TokenStatus.PRE_MINTED].includes(token.status)) { @@ -33,17 +33,17 @@ export class TokenMintService extends BaseService { this.transactionService.push({ ref: tokenDocRef, data: { - status: TokenStatus.MINTING, - 'mintingData.mintedBy': order.member, - 'mintingData.network': order.network, - 'mintingData.aliasStorageDeposit': get(order, 'payload.aliasStorageDeposit', 0), - 'mintingData.foundryStorageDeposit': get(order, 'payload.foundryStorageDeposit', 0), - 'mintingData.vaultStorageDeposit': get(order, 'payload.vaultStorageDeposit', 0), - 'mintingData.guardianStorageDeposit': get(order, 'payload.guardianStorageDeposit', 0), - 'mintingData.tokensInVault': get(order, 'payload.tokensInVault', 0), - 'mintingData.vaultAddress': order.payload.targetAddress, + status: PgTokenStatus.MINTING, + mintingData_mintedBy: order.member, + mintingData_network: convertEnum(order.network, Network, PgNetwork), + mintingData_aliasStorageDeposit: order.payload.aliasStorageDeposit || 0, + mintingData_foundryStorageDeposit: order.payload.foundryStorageDeposit || 0, + mintingData_vaultStorageDeposit: order.payload.vaultStorageDeposit || 0, + mintingData_guardianStorageDeposit: order.payload.guardianStorageDeposit || 0, + mintingData_tokensInVault: order.payload.tokensInVault || 0, + mintingData_vaultAddress: order.payload.targetAddress, }, - action: 'update', + action: Action.U, }); }; } diff --git a/packages/functions/src/services/payment/token/token-minted-airdrop.service.ts b/packages/functions/src/services/payment/token/token-minted-airdrop.service.ts index 42df057148..dfbe9c6662 100644 --- a/packages/functions/src/services/payment/token/token-minted-airdrop.service.ts +++ b/packages/functions/src/services/payment/token/token-minted-airdrop.service.ts @@ -1,25 +1,18 @@ -import { build5Db, getSnapshot } from '@build-5/database'; -import { - COL, - SUB_COL, - Token, - TokenDrop, - TokenDropStatus, - TransactionPayloadType, -} from '@build-5/interfaces'; -import { get, last } from 'lodash'; +import { PgTokenDropStatus, build5Db } from '@build-5/database'; +import { COL, SUB_COL, Token, TransactionPayloadType } from '@build-5/interfaces'; import { BaseService, HandlerParams } from '../base'; +import { Action } from '../transaction-service'; export class TokenMintedAirdropService extends BaseService { public handleRequest = async ({ order, match, tranEntry }: HandlerParams) => { const payment = await this.transactionService.createPayment(order, match); - const tokenDocRef = build5Db().doc(`${COL.TOKEN}/${order.payload.token}`); + const tokenDocRef = build5Db().doc(COL.TOKEN, order.payload.token!); const token = await tokenDocRef.get(); const tokensSent = (tranEntry.nativeTokens || []).reduce( (acc, act) => (act.id === token.mintingData?.tokenId ? acc + Number(act.amount) : acc), 0, ); - const tokensExpected = get(order, 'payload.totalAirdropCount', 0); + const tokensExpected = order.payload.totalAirdropCount || 0; if (tokensSent !== tokensExpected || (tranEntry.nativeTokens || []).length > 1) { await this.transactionService.createCredit( @@ -29,48 +22,34 @@ export class TokenMintedAirdropService extends BaseService { ); return; } + const snap = await build5Db() + .collection(COL.AIRDROP) + .where('orderId', '==', order.uid) + .where('status', '==', PgTokenDropStatus.DEPOSIT_NEEDED) + .get(); - let lastDocId = ''; - do { - const lastDoc = await getSnapshot(COL.AIRDROP, lastDocId); - const snap = await build5Db() - .collection(COL.AIRDROP) - .where('orderId', '==', order.uid) - .limit(250) - .startAfter(lastDoc) - .get(); - lastDocId = last(snap)?.uid || ''; - - const batch = build5Db().batch(); - snap.forEach((airdrop) => { - const distributionDocRef = build5Db() - .collection(COL.TOKEN) - .doc(airdrop.token) - .collection(SUB_COL.DISTRIBUTION) - .doc(airdrop.member); + for (const airdrop of snap) { + const distributionDocRef = build5Db().doc( + COL.TOKEN, + airdrop.token, + SUB_COL.DISTRIBUTION, + airdrop.member, + ); - batch.set( - distributionDocRef, - { - parentId: airdrop.token, - parentCol: COL.TOKEN, - uid: airdrop.member, - totalUnclaimedAirdrop: build5Db().inc(airdrop.count), - }, - true, - ); - const docRef = build5Db().doc(`${COL.AIRDROP}/${airdrop.uid}`); - batch.update(docRef, { status: TokenDropStatus.UNCLAIMED }); + await this.transaction.upsert(distributionDocRef, { + parentId: airdrop.token, + totalUnclaimedAirdrop: build5Db().inc(airdrop.count), }); - await batch.commit(); - } while (lastDocId); + const docRef = build5Db().doc(COL.AIRDROP, airdrop.uid); + await this.transaction.update(docRef, { status: PgTokenDropStatus.UNCLAIMED }); + } this.transactionService.markAsReconciled(order, match.msgId); this.transactionService.push({ - ref: build5Db().doc(`${COL.TRANSACTION}/${order.uid}`), - data: { 'payload.amount': tranEntry.amount }, - action: 'update', + ref: build5Db().doc(COL.TRANSACTION, order.uid), + data: { payload_amount: tranEntry.amount }, + action: Action.U, }); }; } diff --git a/packages/functions/src/services/payment/token/token-purchase.service.ts b/packages/functions/src/services/payment/token/token-purchase.service.ts index a02ad70018..8ed3e4fbee 100644 --- a/packages/functions/src/services/payment/token/token-purchase.service.ts +++ b/packages/functions/src/services/payment/token/token-purchase.service.ts @@ -1,9 +1,8 @@ -import { build5Db } from '@build-5/database'; +import { PgTokenStatus, build5Db } from '@build-5/database'; import { COL, SUB_COL, Token, - TokenDistribution, TokenStatus, Transaction, TransactionPayloadType, @@ -11,7 +10,7 @@ import { import bigDecimal from 'js-big-decimal'; import { getBoughtByMemberDiff, getTotalPublicSupply } from '../../../utils/token.utils'; import { BaseService, HandlerParams } from '../base'; -import { TransactionMatch } from '../transaction-service'; +import { Action, TransactionMatch } from '../transaction-service'; export class TokenPurchaseService extends BaseService { public handleRequest = async ({ order, match }: HandlerParams) => { @@ -24,10 +23,15 @@ export class TokenPurchaseService extends BaseService { tran: TransactionMatch, payment: Transaction, ) { - const tokenRef = build5Db().doc(`${COL.TOKEN}/${order.payload.token}`); - const distributionRef = tokenRef.collection(SUB_COL.DISTRIBUTION).doc(order.member!); + const tokenRef = build5Db().doc(COL.TOKEN, order.payload.token!); + const distributionRef = build5Db().doc( + COL.TOKEN, + order.payload.token!, + SUB_COL.DISTRIBUTION, + order.member!, + ); - const token = await this.transactionService.get(tokenRef); + const token = await this.transaction.get(tokenRef); if (token.status !== TokenStatus.AVAILABLE) { await this.transactionService.createCredit( TransactionPayloadType.DATA_NO_LONGER_VALID, @@ -37,8 +41,7 @@ export class TokenPurchaseService extends BaseService { return; } - const distribution = - await this.transactionService.transaction.get(distributionRef); + const distribution = await this.transaction.get(distributionRef); const currentTotalDeposit = Number( bigDecimal.add(distribution?.totalDeposit || 0, tran.to.amount), ); @@ -59,21 +62,15 @@ export class TokenPurchaseService extends BaseService { ref: tokenRef, data: tokensOrdered >= totalPublicSupply && token.autoProcessAt100Percent - ? { ...tokenUpdateData, status: TokenStatus.PROCESSING } + ? { ...tokenUpdateData, status: PgTokenStatus.PROCESSING } : tokenUpdateData, - action: 'update', + action: Action.U, }); this.transactionService.push({ ref: distributionRef, - data: { - uid: order.member, - totalDeposit: build5Db().inc(tran.to.amount), - parentId: order.payload.token, - parentCol: COL.TOKEN, - }, - action: 'set', - merge: true, + data: { totalDeposit: build5Db().inc(tran.to.amount) }, + action: Action.UPS, }); } } diff --git a/packages/functions/src/services/payment/token/token-service.ts b/packages/functions/src/services/payment/token/token-service.ts index 3a90be4fd3..36db762c71 100644 --- a/packages/functions/src/services/payment/token/token-service.ts +++ b/packages/functions/src/services/payment/token/token-service.ts @@ -1,4 +1,4 @@ -import { build5Db, getSnapshot } from '@build-5/database'; +import { ITransaction, PgTokenDropStatus, PgTokenStatus, build5Db } from '@build-5/database'; import { COL, DEFAULT_NETWORK, @@ -7,9 +7,6 @@ import { SUB_COL, TRANSACTION_MAX_EXPIRY_MS, Token, - TokenDistribution, - TokenDrop, - TokenDropStatus, TokenStatus, TokenTradeOrder, TokenTradeOrderStatus, @@ -20,14 +17,17 @@ import { } from '@build-5/interfaces'; import dayjs from 'dayjs'; import bigDecimal from 'js-big-decimal'; -import { get, head, last, set } from 'lodash'; +import { head, set } from 'lodash'; import { dateToTimestamp } from '../../../utils/dateTime.utils'; import { getBoughtByMemberDiff, getTotalPublicSupply } from '../../../utils/token.utils'; import { getRandomEthAddress } from '../../../utils/wallet.utils'; -import { TransactionMatch, TransactionService } from '../transaction-service'; +import { Action, TransactionMatch, TransactionService } from '../transaction-service'; export class TokenService { - constructor(readonly transactionService: TransactionService) {} + private transaction: ITransaction; + constructor(readonly transactionService: TransactionService) { + this.transaction = transactionService.transaction; + } public async handleTokenPurchaseRequest(order: Transaction, match: TransactionMatch) { const payment = await this.transactionService.createPayment(order, match); @@ -50,13 +50,13 @@ export class TokenService { match: TransactionMatch, ) { const payment = await this.transactionService.createPayment(order, match); - const tokenDocRef = build5Db().doc(`${COL.TOKEN}/${order.payload.token}`); + const tokenDocRef = build5Db().doc(COL.TOKEN, order.payload.token!); const token = await tokenDocRef.get(); const tokensSent = (tranOutput.nativeTokens || []).reduce( (acc, act) => (act.id === token.mintingData?.tokenId ? acc + Number(act.amount) : acc), 0, ); - const tokensExpected = get(order, 'payload.totalAirdropCount', 0); + const tokensExpected = order.payload.totalAirdropCount || 0; if (tokensSent !== tokensExpected || (tranOutput.nativeTokens || []).length > 1) { await this.transactionService.createCredit( @@ -67,47 +67,34 @@ export class TokenService { return; } - let lastDocId = ''; - do { - const lastDoc = await getSnapshot(COL.AIRDROP, lastDocId); - const snap = await build5Db() - .collection(COL.AIRDROP) - .where('orderId', '==', order.uid) - .limit(250) - .startAfter(lastDoc) - .get(); - lastDocId = last(snap)?.uid || ''; - - const batch = build5Db().batch(); - snap.forEach((airdrop) => { - const distributionDocRef = build5Db() - .collection(COL.TOKEN) - .doc(airdrop.token) - .collection(SUB_COL.DISTRIBUTION) - .doc(airdrop.member); + const snap = await build5Db() + .collection(COL.AIRDROP) + .where('orderId', '==', order.uid) + .where('status', '==', PgTokenDropStatus.DEPOSIT_NEEDED) + .get(); + + for (const airdrop of snap) { + const distributionDocRef = build5Db().doc( + COL.TOKEN, + airdrop.token, + SUB_COL.DISTRIBUTION, + airdrop.member, + ); - batch.set( - distributionDocRef, - { - parentId: airdrop.token, - parentCol: COL.TOKEN, - uid: airdrop.member, - totalUnclaimedAirdrop: build5Db().inc(airdrop.count), - }, - true, - ); - const docRef = build5Db().doc(`${COL.AIRDROP}/${airdrop.uid}`); - batch.update(docRef, { status: TokenDropStatus.UNCLAIMED }); + await this.transaction.upsert(distributionDocRef, { + parentId: airdrop.token, + totalUnclaimedAirdrop: build5Db().inc(airdrop.count), }); - await batch.commit(); - } while (lastDocId); + const docRef = build5Db().doc(COL.AIRDROP, airdrop.uid); + await this.transaction.update(docRef, { status: PgTokenDropStatus.UNCLAIMED }); + } this.transactionService.markAsReconciled(order, match.msgId); this.transactionService.push({ - ref: build5Db().doc(`${COL.TRANSACTION}/${order.uid}`), - data: { 'payload.amount': tranOutput.amount }, - action: 'update', + ref: build5Db().doc(COL.TRANSACTION, order.uid), + data: { payload_amount: tranOutput.amount }, + action: Action.U, }); } @@ -134,7 +121,7 @@ export class TokenService { this.transactionService.markAsReconciled(order, match.msgId); await this.createDistributionDocRef(order.payload.token!, order.member!); - const token = await build5Db().doc(`${COL.TOKEN}/${order.payload.token}`).get(); + const token = await build5Db().doc(COL.TOKEN, order.payload.token!).get(); const network = order.network || DEFAULT_NETWORK; const data = { uid: getRandomEthAddress(), @@ -145,8 +132,8 @@ export class TokenService { order.payload.type === TransactionPayloadType.SELL_TOKEN ? TokenTradeOrderType.SELL : TokenTradeOrderType.BUY, - count: nativeTokens || get(order, 'payload.count', 0), - price: get(order, 'payload.price', 0), + count: nativeTokens || order.payload.count || 0, + price: order.payload.price || 0, totalDeposit: nativeTokens || order.payload.amount, balance: nativeTokens || order.payload.amount, fulfilled: 0, @@ -163,18 +150,18 @@ export class TokenService { set(data, 'targetAddress', order.payload.tokenTradeOderTargetAddress); } - const ref = build5Db().doc(`${COL.TOKEN_MARKET}/${data.uid}`); - this.transactionService.push({ ref, data, action: 'set' }); + const ref = build5Db().doc(COL.TOKEN_MARKET, data.uid); + this.transactionService.push({ ref, data, action: Action.C }); if ( order.payload.type === TransactionPayloadType.SELL_TOKEN && token.status === TokenStatus.MINTED ) { - const orderDocRef = build5Db().doc(`${COL.TRANSACTION}/${order.uid}`); + const orderDocRef = build5Db().doc(COL.TRANSACTION, order.uid); this.transactionService.push({ ref: orderDocRef, - data: { 'payload.amount': match.to.amount }, - action: 'update', + data: { payload_amount: match.to.amount }, + action: Action.U, }); } } @@ -184,10 +171,15 @@ export class TokenService { tran: TransactionMatch, payment: Transaction, ) { - const tokenRef = build5Db().doc(`${COL.TOKEN}/${order.payload.token}`); - const distributionRef = tokenRef.collection(SUB_COL.DISTRIBUTION).doc(order.member!); + const tokenRef = build5Db().doc(COL.TOKEN, order.payload.token!); + const distributionRef = build5Db().doc( + COL.TOKEN, + order.payload.token!, + SUB_COL.DISTRIBUTION, + order.member!, + ); - const token = await this.transactionService.get(tokenRef); + const token = await tokenRef.get(); if (token.status !== TokenStatus.AVAILABLE) { await this.transactionService.createCredit( TransactionPayloadType.DATA_NO_LONGER_VALID, @@ -197,8 +189,7 @@ export class TokenService { return; } - const distribution = - await this.transactionService.transaction.get(distributionRef); + const distribution = await distributionRef.get(); const currentTotalDeposit = Number( bigDecimal.add(distribution?.totalDeposit || 0, tran.to.amount), ); @@ -219,41 +210,27 @@ export class TokenService { ref: tokenRef, data: tokensOrdered >= totalPublicSupply && token.autoProcessAt100Percent - ? { ...tokenUpdateData, status: TokenStatus.PROCESSING } + ? { ...tokenUpdateData, status: PgTokenStatus.PROCESSING } : tokenUpdateData, - action: 'update', + action: Action.U, }); this.transactionService.push({ ref: distributionRef, data: { - uid: order.member, totalDeposit: build5Db().inc(tran.to.amount), parentId: order.payload.token, - parentCol: COL.TOKEN, }, - action: 'set', - merge: true, + action: Action.UPS, }); } private createDistributionDocRef = async (token: string, member: string) => { - const distributionDocRef = build5Db().doc( - `${COL.TOKEN}/${token}/${SUB_COL.DISTRIBUTION}/${member}`, - ); - const distributionDoc = await this.transactionService.transaction.get(distributionDocRef); + const distributionDocRef = build5Db().doc(COL.TOKEN, token, SUB_COL.DISTRIBUTION, member); + const distributionDoc = await this.transaction.get(distributionDocRef); if (!distributionDoc) { - const data = { - uid: member, - parentId: token, - parentCol: COL.TOKEN, - }; - this.transactionService.push({ - ref: distributionDocRef, - data, - action: 'set', - merge: true, - }); + const data = { uid: member, parentId: token, parentCol: COL.TOKEN }; + this.transactionService.push({ ref: distributionDocRef, data, action: Action.C }); } }; } 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 3aacb40e5c..2ec1e366f2 100644 --- a/packages/functions/src/services/payment/token/token-trade.service.ts +++ b/packages/functions/src/services/payment/token/token-trade.service.ts @@ -17,10 +17,11 @@ import { getNetworkPair, } from '@build-5/interfaces'; import dayjs from 'dayjs'; -import { get, head, isEqual, set } from 'lodash'; +import { head, isEqual, set } from 'lodash'; import { dateToTimestamp } from '../../../utils/dateTime.utils'; import { getRandomEthAddress } from '../../../utils/wallet.utils'; import { BaseService, HandlerParams } from '../base'; +import { Action } from '../transaction-service'; export class TokenTradeService extends BaseService { public handleRequest = async ({ @@ -49,14 +50,14 @@ export class TokenTradeService extends BaseService { const nativeTokens = Number(head(tranEntry.nativeTokens)?.amount); await this.createDistributionDocRef(order.payload.token!, order.member!); - const token = await build5Db().doc(`${COL.TOKEN}/${order.payload.token}`).get(); + const token = await build5Db().doc(COL.TOKEN, order.payload.token!).get(); const network = order.network || DEFAULT_NETWORK; const type = order.payload.type === TransactionPayloadType.SELL_TOKEN ? TokenTradeOrderType.SELL : TokenTradeOrderType.BUY; - const price = get(order, 'payload.price', 0); + const price = order.payload.price || 0; const count = getCount(order, tranEntry, type); const data: TokenTradeOrder = { @@ -84,34 +85,27 @@ export class TokenTradeService extends BaseService { set(data, 'targetAddress', order.payload.tokenTradeOderTargetAddress); } - const ref = build5Db().doc(`${COL.TOKEN_MARKET}/${data.uid}`); - this.transactionService.push({ ref, data, action: 'set' }); + const ref = build5Db().doc(COL.TOKEN_MARKET, data.uid); + this.transactionService.push({ ref, data, action: Action.C }); - const orderDocRef = build5Db().doc(`${COL.TRANSACTION}/${order.uid}`); + const orderDocRef = build5Db().doc(COL.TRANSACTION, order.uid); this.transactionService.push({ ref: orderDocRef, - data: { 'payload.amount': match.to.amount, 'payload.count': count }, - action: 'update', + data: { payload_amount: match.to.amount, payload_count: count }, + action: Action.U, }); }; private createDistributionDocRef = async (token: string, member: string) => { - const distributionDocRef = build5Db().doc( - `${COL.TOKEN}/${token}/${SUB_COL.DISTRIBUTION}/${member}`, - ); - const distributionDoc = await this.transactionService.transaction.get(distributionDocRef); + const distributionDocRef = build5Db().doc(COL.TOKEN, token, SUB_COL.DISTRIBUTION, member); + const distributionDoc = await this.transaction.get(distributionDocRef); if (!distributionDoc) { const data = { uid: member, parentId: token, parentCol: COL.TOKEN, }; - this.transactionService.push({ - ref: distributionDocRef, - data, - action: 'set', - merge: true, - }); + this.transactionService.push({ ref: distributionDocRef, data, action: Action.UPS }); } }; } @@ -124,5 +118,5 @@ const getCount = ( if (type === TokenTradeOrderType.SELL) { return Number(head(tranEntry.nativeTokens)?.amount || 0) || tranEntry.amount; } - return get(order, 'payload.count', MAX_TOTAL_TOKEN_SUPPLY); + return order.payload.count || MAX_TOTAL_TOKEN_SUPPLY; }; diff --git a/packages/functions/src/services/payment/transaction-service.ts b/packages/functions/src/services/payment/transaction-service.ts index 133b3c6df4..5e43dab57b 100644 --- a/packages/functions/src/services/payment/transaction-service.ts +++ b/packages/functions/src/services/payment/transaction-service.ts @@ -1,4 +1,4 @@ -import { IDocument, ITransaction, build5Db } from '@build-5/database'; +import { BaseRecord, IDocument, ITransaction, Update, build5Db } from '@build-5/database'; import { COL, DEFAULT_NETWORK, @@ -10,7 +10,6 @@ import { StorageReturn, TRANSACTION_AUTO_EXPIRY_MS, Timestamp, - Token, Transaction, TransactionPayloadType, TransactionType, @@ -24,44 +23,64 @@ import { MilestoneTransactionAdapter } from '../../triggers/milestone-transactio import { getOutputMetadata } from '../../utils/basic-output.utils'; import { getProject } from '../../utils/common.utils'; import { dateToTimestamp, serverTime } from '../../utils/dateTime.utils'; +import { getPathParts } from '../../utils/milestone'; import { getRandomEthAddress } from '../../utils/wallet.utils'; + export interface TransactionMatch { msgId: string; from: string; to: MilestoneTransactionEntry; } -interface TransactionUpdates { - ref: IDocument; - // eslint-disable-next-line @typescript-eslint/no-explicit-any - data: any; - action: 'update' | 'set' | 'delete'; - merge?: boolean; +export enum Action { + C = 'create', + U = 'update', + UPS = 'upsert', + D = 'delete', +} + +// prettier-ignore +type DataType = + A extends Action.C ? C : + A extends Action.U ? U : + A extends Action.UPS ? U : + A extends Action.D ? undefined : + never; + +interface TransactionUpdates { + ref: IDocument; + data: DataType; + action: A; } export class TransactionService { public readonly linkedTransactions: string[] = []; - private readonly updates: TransactionUpdates[] = []; + private readonly updates: TransactionUpdates[] = []; constructor(public readonly transaction: ITransaction) {} - public submit(): void { - this.updates.forEach((params) => { - if (params.action === 'set') { - this.transaction.set(params.ref, params.data, params.merge || false); - } else if (params.action === 'update') { - this.transaction.update(params.ref, params.data); - } else if (params.action === 'delete') { - this.transaction.delete(params.ref); + public submit = async () => { + for (const params of this.updates) { + if (params.action === Action.C) { + await this.transaction.create(params.ref, params.data); + } else if (params.action === Action.UPS) { + await this.transaction.upsert(params.ref, params.data as Update); + } else if (params.action === Action.U) { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + await this.transaction.update(params.ref, params.data as any); + } else if (params.action === Action.D) { + await this.transaction.delete(params.ref); } else { throw Error('Invalid action ' + params.action); } - }); - } - - public push = (update: TransactionUpdates) => this.updates.push(update); + } + }; - public get = (docRef: IDocument) => this.transaction.get(docRef); + public push = ( + update: TransactionUpdates, + ) => + // eslint-disable-next-line @typescript-eslint/no-explicit-any + this.updates.push(update as any); public async createPayment( order: Transaction, @@ -79,7 +98,6 @@ export class TransactionService { space: order.space || '', network: order.network || DEFAULT_NETWORK, payload: { - // This must be the amount they send. As we're handing both correct amount from order or invalid one. amount: tran.to.amount, nativeTokens: (tran.to.nativeTokens || []).map((nt) => ({ ...nt, @@ -107,18 +125,14 @@ export class TransactionService { } if (order.payload.token) { - const tokenDocRef = build5Db().doc(`${COL.TOKEN}/${order.payload.token}`); - const token = await tokenDocRef.get(); + const tokenDocRef = build5Db().doc(COL.TOKEN, order.payload.token); + const token = await tokenDocRef.get(); if (token) { set(data, 'payload.token', token.uid); set(data, 'payload.tokenSymbol', token.symbol); } } - this.updates.push({ - ref: build5Db().doc(`${COL.TRANSACTION}/${data.uid}`), - data, - action: 'set', - }); + this.push({ ref: build5Db().doc(COL.TRANSACTION, data.uid), data, action: Action.C }); if (order.payload.type !== TransactionPayloadType.TANGLE_REQUEST) { this.linkedTransactions.push(data.uid); } @@ -163,14 +177,10 @@ export class TransactionService { void: false, collection: order.payload.collection || null, quantity: (order.payload.quantity || null) as number, - restrictions: get(order, 'payload.restrictions', {}), + restrictions: order.payload.restrictions || {}, }, }; - this.updates.push({ - ref: build5Db().doc(`${COL.TRANSACTION}/${data.uid}`), - data, - action: 'set', - }); + this.push({ ref: build5Db().doc(COL.TRANSACTION, data.uid), data, action: Action.C }); transOut.push(data); this.linkedTransactions.push(data.uid); } @@ -196,13 +206,13 @@ export class TransactionService { nft: order.payload.nft || null, collection: order.payload.collection || null, quantity: (order.payload.quantity || null) as number, - restrictions: get(order, 'payload.restrictions', {}), + restrictions: order.payload.restrictions || {}, }, }; - this.updates.push({ - ref: build5Db().doc(`${COL.TRANSACTION}/${data.uid}`), + this.push({ + ref: build5Db().doc(COL.TRANSACTION, data.uid), data, - action: 'set', + action: Action.C, }); transOut.push(data); this.linkedTransactions.push(data.uid); @@ -261,18 +271,14 @@ export class TransactionService { } if (payment.payload.token) { - const tokenDocRef = build5Db().doc(`${COL.TOKEN}/${payment.payload.token}`); - const token = await tokenDocRef.get(); + const tokenDocRef = build5Db().doc(COL.TOKEN, payment.payload.token); + const token = await tokenDocRef.get(); if (token) { set(data, 'payload.token', token.uid); set(data, 'payload.tokenSymbol', token.symbol); } } - this.updates.push({ - ref: build5Db().doc(`${COL.TRANSACTION}/${data.uid}`), - data: data, - action: 'set', - }); + this.push({ ref: build5Db().doc(COL.TRANSACTION, data.uid), data, action: Action.C }); setLink && this.linkedTransactions.push(data.uid); return data; } @@ -309,10 +315,10 @@ export class TransactionService { }, linkedTransactions: [], }; - this.updates.push({ - ref: build5Db().doc(`${COL.TRANSACTION}/${data.uid}`), + this.push({ + ref: build5Db().doc(COL.TRANSACTION, data.uid), data: data, - action: 'set', + action: Action.C, }); return data; } @@ -357,23 +363,20 @@ export class TransactionService { if (expiresOn) { set(transaction, 'payload.expiresOn', expiresOn); } - this.updates.push({ - ref: build5Db().doc(`${COL.TRANSACTION}/${transaction.uid}`), + this.push({ + ref: build5Db().doc(COL.TRANSACTION, transaction.uid), data: transaction, - action: 'set', + action: Action.C, }); this.linkedTransactions.push(transaction.uid); return transaction; } public markAsReconciled = (transaction: Transaction, chainRef: string) => - this.updates.push({ - ref: build5Db().doc(`${COL.TRANSACTION}/${transaction.uid}`), - data: { - 'payload.reconciled': true, - 'payload.chainReference': chainRef, - }, - action: 'update', + this.push({ + ref: build5Db().doc(COL.TRANSACTION, transaction.uid), + data: { payload_reconciled: true, payload_chainReference: chainRef }, + action: Action.U, }); private getFromAddress = async ( @@ -382,9 +385,10 @@ export class TransactionService { build5Transaction?: Transaction, ) => { if (build5Transaction?.type === TransactionType.UNLOCK) { - const doc = (await build5Db() - .doc(build5Transaction.payload?.milestoneTransactionPath!) - .get>())!; + const { col, colId, subCol, subColId } = getPathParts( + build5Transaction.payload?.milestoneTransactionPath!, + ); + const doc = (await build5Db().doc(col, colId, subCol, subColId).get())!; const adapter = new MilestoneTransactionAdapter(order.network!); const milestoneTransaction = await adapter.toMilestoneTransaction(doc); return milestoneTransaction.fromAddresses[0]; @@ -529,19 +533,13 @@ export class TransactionService { : tranOutput.address, sourceTransaction: [payment?.uid || order.uid], expiresOn: expiresOn || dateToTimestamp(dayjs().add(TRANSACTION_AUTO_EXPIRY_MS)), - milestoneTransactionPath: `${getMilestoneCol(network)}/${tran.milestone}/${ - SUB_COL.TRANSACTIONS - }/${tran.uid}`, + milestoneTransactionPath: `${getMilestoneCol(network)}/${tran.milestone}/${SUB_COL.TRANSACTIONS}/${tran.uid}`, outputToConsume, customMetadata: getOutputMetadata(tranOutput.output), nftId: tranOutput.nftOutput?.nftId || '', }, }; - this.updates.push({ - ref: build5Db().doc(`${COL.TRANSACTION}/${data.uid}`), - data, - action: 'set', - }); + this.push({ ref: build5Db().doc(COL.TRANSACTION, data.uid), data, action: Action.C }); }; public getExpirationUnlock = (unlockCondition: UnlockCondition[] = []) => diff --git a/packages/functions/src/services/payment/voting-service.ts b/packages/functions/src/services/payment/voting-service.ts index b62cf424da..bc6d3ae20d 100644 --- a/packages/functions/src/services/payment/voting-service.ts +++ b/packages/functions/src/services/payment/voting-service.ts @@ -8,11 +8,12 @@ import { TransactionType, } from '@build-5/interfaces'; import dayjs from 'dayjs'; -import { get, head } from 'lodash'; +import { head } from 'lodash'; import { getProject } from '../../utils/common.utils'; import { getTokenForSpace } from '../../utils/token.utils'; import { getRandomEthAddress } from '../../utils/wallet.utils'; import { BaseService, HandlerParams } from './base'; +import { Action } from './transaction-service'; export class VotingService extends BaseService { public handleRequest = async ({ order, match }: HandlerParams) => { @@ -22,8 +23,8 @@ export class VotingService extends BaseService { const nativeTokens = match.to.nativeTokens || []; const hasValidToken = head(nativeTokens)?.id === token?.mintingData?.tokenId; - const proposalId = get(order, 'payload.proposalId', ''); - const values = get(order, 'payload.voteValues', []); + const proposalId = order.payload.proposalId || ''; + const values = order.payload.voteValues || []; const customData = hasValidToken ? { proposalId, values } : undefined; const storageReturn = match.to.amount >= order.payload.amount! ? match.from : undefined; @@ -47,10 +48,15 @@ export class VotingService extends BaseService { return; } - const proposalDocRef = build5Db().doc(`${COL.PROPOSAL}/${proposalId}`); + const proposalDocRef = build5Db().doc(COL.PROPOSAL, proposalId); const proposal = await proposalDocRef.get(); - const proposalMemberDocRef = proposalDocRef.collection(SUB_COL.MEMBERS).doc(order.member!); + const proposalMemberDocRef = build5Db().doc( + COL.PROPOSAL, + proposalId, + SUB_COL.MEMBERS, + order.member!, + ); const tokenAmount = Number(nativeTokens[0].amount); const weightMultiplier = getTokenVoteMultiplier(proposal, dayjs()); @@ -65,34 +71,29 @@ export class VotingService extends BaseService { values, ); + const value = values[0].toString(); this.transactionService.push({ ref: proposalMemberDocRef, data: { voted: true, - voteTransactions: build5Db().inc(1), + parentId: proposalId, tranId: voteTransaction.uid, - weightPerAnswer: { [values[0]]: build5Db().inc(weight) }, - values: build5Db().arrayUnion({ - [values[0]]: weight, - voteTransaction: voteTransaction.uid, - }), + weight, + values: { [voteTransaction.uid]: { value, weight: build5Db().inc(weight) } }, }, - action: 'set', - merge: true, + action: Action.UPS, }); - const data = { - results: { - total: build5Db().inc(weight), - voted: build5Db().inc(weight), - answers: { [`${values[0]}`]: build5Db().inc(weight) }, - }, - }; this.transactionService.push({ ref: proposalDocRef, - data, - action: 'set', - merge: true, + data: { + results: { + total: build5Db().inc(weight), + voted: build5Db().inc(weight), + answers: { [value]: build5Db().inc(weight) }, + }, + }, + action: Action.U, }); }; @@ -124,11 +125,10 @@ export class VotingService extends BaseService { linkedTransactions: [], }; - const voteTransactionDocRef = build5Db().doc(`${COL.TRANSACTION}/${voteTransaction.uid}`); this.transactionService.push({ - ref: voteTransactionDocRef, + ref: build5Db().doc(COL.TRANSACTION, voteTransaction.uid), data: voteTransaction, - action: 'set', + action: Action.C, }); return voteTransaction; }; diff --git a/packages/functions/src/services/stake.service.ts b/packages/functions/src/services/stake.service.ts index c9668286e3..ea708958b8 100644 --- a/packages/functions/src/services/stake.service.ts +++ b/packages/functions/src/services/stake.service.ts @@ -1,25 +1,28 @@ import { build5Db, ITransaction } from '@build-5/database'; import { COL, - Project, ProjectBilling, - Space, Stake, StakeType, SUB_COL, TokenDistribution, } from '@build-5/interfaces'; -import { getTokenSaleConfig } from '../utils/config.utils'; import { getProject } from '../utils/common.utils'; +import { getTokenSaleConfig } from '../utils/config.utils'; export const hasStakedTokens = async (projectId: string, member: string, type?: StakeType) => { - const project = (await build5Db().get(COL.PROJECT, projectId))!; - if (project.config?.billing !== ProjectBilling.TOKEN_BASE) { + const projectDocRef = build5Db().doc(COL.PROJECT, projectId); + const project = (await projectDocRef.get())!; + if (project.config?.billing !== ProjectBilling.TOKEN_BASED) { return true; } - const tokenDocRef = build5Db().doc(`${COL.TOKEN}/${project.config.nativeTokenUid}`); - const distributionDocRef = tokenDocRef.collection(SUB_COL.DISTRIBUTION).doc(member); - const distribution = await distributionDocRef.get(); + const distributionDocRef = build5Db().doc( + COL.TOKEN, + project.config.nativeTokenUid!, + SUB_COL.DISTRIBUTION, + member, + ); + const distribution = await distributionDocRef.get(); const stakeTypes = type ? [type] : Object.values(StakeType); const hasAny = stakeTypes.reduce( @@ -43,7 +46,7 @@ export const onStakeCreated = async (transaction: ITransaction, stake: Stake) => stake.value, ); } - updateStakingMembersStats(transaction, distribution, stake.token, stake.type, stake.value); + await updateStakingMembersStats(transaction, distribution, stake.token, stake.type, stake.value); }; export const onStakeExpired = async (transaction: ITransaction, stake: Stake) => { @@ -58,13 +61,12 @@ export const onStakeExpired = async (transaction: ITransaction, stake: Stake) => ); await removeMemberFromSpace(transaction, distribution, stake); } - updateStakingMembersStats(transaction, distribution, stake.token, stake.type, -stake.value); + await updateStakingMembersStats(transaction, distribution, stake.token, stake.type, -stake.value); }; const getTokenDistribution = async (transaction: ITransaction, token: string, member: string) => { - const tokenDocRef = build5Db().doc(`${COL.TOKEN}/${token}`); - const distirbutionDocRef = tokenDocRef.collection(SUB_COL.DISTRIBUTION).doc(member); - return await transaction.get(distirbutionDocRef); + const distirbutionDocRef = build5Db().doc(COL.TOKEN, token, SUB_COL.DISTRIBUTION, member); + return await transaction.get(distirbutionDocRef); }; const updateMemberTokenDiscountPercentage = async ( @@ -74,7 +76,8 @@ const updateMemberTokenDiscountPercentage = async ( member: string, stakeValueDiff: number, ) => { - const project = await build5Db().get(COL.PROJECT, projectId); + const projectDocRef = build5Db().doc(COL.PROJECT, projectId); + const project = await projectDocRef.get(); const stakeValue = getStakeForType(distribution, StakeType.DYNAMIC) + stakeValueDiff; const tier = getTier(project?.config?.tiers || [], stakeValue); @@ -84,8 +87,8 @@ const updateMemberTokenDiscountPercentage = async ( const discount = (project?.config?.tokenTradingFeeDiscountPercentage || [])[tier] / 100; const tokenTradingFeePercentage = getTokenSaleConfig.percentage * (1 - discount); - const memberDocRef = build5Db().doc(`${COL.MEMBER}/${member}`); - transaction.update(memberDocRef, { tokenTradingFeePercentage }); + const memberDocRef = build5Db().doc(COL.MEMBER, member); + await transaction.update(memberDocRef, { tokenTradingFeePercentage }); }; export const getTier = (tiers: number[], stakeValue: number) => { @@ -96,32 +99,28 @@ export const getTier = (tiers: number[], stakeValue: number) => { return tier - 1; }; -const updateStakingMembersStats = ( +const updateStakingMembersStats = async ( transaction: ITransaction, distribution: TokenDistribution | undefined, token: string, type: StakeType, stakeValueDiff: number, ) => { - const tokenStatsDocRef = build5Db().doc(`${COL.TOKEN}/${token}/${SUB_COL.STATS}/${token}`); + const tokenStatsDocRef = build5Db().doc(COL.TOKEN, token, SUB_COL.STATS, token); const prevStakedAmount = getStakeForType(distribution, type); if (!prevStakedAmount) { - transaction.set( - tokenStatsDocRef, - { stakes: { [type]: { stakingMembersCount: build5Db().inc(1) } } }, - true, - ); + await transaction.upsert(tokenStatsDocRef, { + [`stakes_${type}_stakingMembersCount`]: build5Db().inc(1), + }); return; } const currentStakedAmount = prevStakedAmount + stakeValueDiff; if (!currentStakedAmount) { - transaction.set( - tokenStatsDocRef, - { stakes: { [type]: { stakingMembersCount: build5Db().inc(-1) } } }, - true, - ); + await transaction.upsert(tokenStatsDocRef, { + [`stakes_${type}_stakingMembersCount`]: build5Db().inc(-1), + }); return; } }; @@ -131,23 +130,23 @@ const removeMemberFromSpace = async ( distribution: TokenDistribution | undefined, stake: Stake, ) => { - const spaceDocRef = build5Db().doc(`${COL.SPACE}/${stake.space}`); - const space = (await spaceDocRef.get())!; + const spaceDocRef = build5Db().doc(COL.SPACE, stake.space); + const space = (await spaceDocRef.get())!; const stakedValue = getStakeForType(distribution, stake.type) - stake.value; if (!space.tokenBased || stakedValue >= (space.minStakedValue || 0)) { return; } - const guardianDocRef = spaceDocRef.collection(SUB_COL.GUARDIANS).doc(stake.member); + const guardianDocRef = build5Db().doc(COL.SPACE, stake.space, SUB_COL.GUARDIANS, stake.member); const isGuardian = (await spaceDocRef.get()) !== undefined; if (isGuardian && space.totalGuardians > 1) { - transaction.delete(guardianDocRef); + await transaction.delete(guardianDocRef); } if (space.totalMembers > 1) { - const memberDocRef = spaceDocRef.collection(SUB_COL.MEMBERS).doc(stake.member); - transaction.delete(memberDocRef); + const memberDocRef = build5Db().doc(COL.SPACE, stake.space, SUB_COL.MEMBERS, stake.member); + await transaction.delete(memberDocRef); } - transaction.update(spaceDocRef, { + await transaction.update(spaceDocRef, { totalGuardians: build5Db().inc(isGuardian && space.totalGuardians > 1 ? -1 : 0), totalMembers: build5Db().inc(space.totalMembers > 1 ? -1 : 0), }); diff --git a/packages/functions/src/services/validators/access.ts b/packages/functions/src/services/validators/access.ts index a310b1f533..5017e211ad 100644 --- a/packages/functions/src/services/validators/access.ts +++ b/packages/functions/src/services/validators/access.ts @@ -1,5 +1,5 @@ -import { build5Db } from '@build-5/database'; -import { Access, COL, Nft, SUB_COL, TransactionPayloadType, WenError } from '@build-5/interfaces'; +import { PgTransactionPayloadType, build5Db } from '@build-5/database'; +import { Access, COL, SUB_COL, WenError } from '@build-5/interfaces'; import { invalidArgument } from '../../utils/error.utils'; export const assertHasAccess = async ( @@ -14,13 +14,13 @@ export const assertHasAccess = async ( } if (access === Access.MEMBERS_ONLY) { - if (!(await build5Db().doc(`${COL.SPACE}/${spaceId}/${SUB_COL.MEMBERS}/${member}`).get())) { + if (!(await build5Db().doc(COL.SPACE, spaceId, SUB_COL.MEMBERS, member).get())) { throw invalidArgument(WenError.you_are_not_part_of_space); } } if (access === Access.GUARDIANS_ONLY) { - if (!(await build5Db().doc(`${COL.SPACE}/${spaceId}/${SUB_COL.GUARDIANS}/${member}`).get())) { + if (!(await build5Db().doc(COL.SPACE, spaceId, SUB_COL.GUARDIANS, member).get())) { throw invalidArgument(WenError.you_are_not_guardian_of_space); } } @@ -29,9 +29,9 @@ export const assertHasAccess = async ( for (const award of accessAwards) { const snapshot = await build5Db() .collection(COL.TRANSACTION) - .where('payload.type', '==', TransactionPayloadType.BADGE) + .where('payload_type', '==', PgTransactionPayloadType.BADGE) .where('member', '==', member) - .where('payload.award', '==', award) + .where('payload_award', '==', award) .limit(1) .get(); if (!snapshot.length) { @@ -42,7 +42,7 @@ export const assertHasAccess = async ( if (access === Access.MEMBERS_WITH_NFT_FROM_COLLECTION) { const includedCollections: string[] = []; - const snapshot = await build5Db().collection(COL.NFT).where('owner', '==', member).get(); + const snapshot = await build5Db().collection(COL.NFT).where('owner', '==', member).get(); if (snapshot.length > 0 && accessCollections?.length) { for (const data of snapshot) { if ( diff --git a/packages/functions/src/services/wallet/NativeTokenWallet.ts b/packages/functions/src/services/wallet/NativeTokenWallet.ts index f2bafdf382..753caa14ff 100644 --- a/packages/functions/src/services/wallet/NativeTokenWallet.ts +++ b/packages/functions/src/services/wallet/NativeTokenWallet.ts @@ -1,5 +1,5 @@ import { build5Db } from '@build-5/database'; -import { COL, Member, Token, Transaction } from '@build-5/interfaces'; +import { COL, Member, SUB_COL, Token, Transaction } from '@build-5/interfaces'; import { AliasOutputBuilderParams, Client, @@ -18,8 +18,6 @@ import { getVaultAndGuardianOutput, tokenToFoundryMetadata, } from '../../utils/token-minting-utils/foundry.utils'; -import { getOwnedTokenTotal } from '../../utils/token-minting-utils/member.utils'; -import { getUnclaimedAirdropTotalValue } from '../../utils/token.utils'; import { AliasWallet } from './AliasWallet'; import { MnemonicService } from './mnemonic'; import { Wallet, WalletParams } from './wallet'; @@ -53,7 +51,7 @@ export class NativeTokenWallet { nextAliasOutput.stateIndex!++; nextAliasOutput.foundryCounter!++; - const token = await build5Db().doc(`${COL.TOKEN}/${transaction.payload.token}`).get(); + const token = await build5Db().doc(COL.TOKEN, transaction.payload.token!).get(); const metadata = await tokenToFoundryMetadata(token); const foundryOutput = await createFoundryOutput( @@ -63,9 +61,15 @@ export class NativeTokenWallet { JSON.stringify(metadata), ); - const totalDistributed = - (await getOwnedTokenTotal(token.uid)) + (await getUnclaimedAirdropTotalValue(token.uid)); - const member = await build5Db().doc(`${COL.MEMBER}/${transaction.member}`).get(); + const totalOwned = await build5Db() + .collection(COL.TOKEN, token.uid, SUB_COL.DISTRIBUTION) + .getTotalOwned(); + const airdropTotal = await build5Db() + .collection(COL.AIRDROP) + .getUnclaimedAirdropTotalValue(token.uid); + const totalDistributed = totalOwned + airdropTotal; + + const member = await build5Db().doc(COL.MEMBER, transaction.member!).get(); const tokenId = Utils.computeFoundryId( nextAliasOutput.aliasId, foundryOutput.serialNumber, diff --git a/packages/functions/src/services/wallet/NftWallet.ts b/packages/functions/src/services/wallet/NftWallet.ts index c69d56f389..8b5d7198b8 100644 --- a/packages/functions/src/services/wallet/NftWallet.ts +++ b/packages/functions/src/services/wallet/NftWallet.ts @@ -1,4 +1,4 @@ -import { build5Db } from '@build-5/database'; +import { PgNftStatus, build5Db } from '@build-5/database'; import { Award, COL, @@ -7,7 +7,6 @@ import { Network, NetworkAddress, Nft, - NftStatus, Space, Stamp, Transaction, @@ -105,7 +104,7 @@ export class NftWallet { } nextAliasOutput.stateIndex!++; - const collectionDocRef = build5Db().doc(`${COL.COLLECTION}/${transaction.payload.collection}`); + const collectionDocRef = build5Db().doc(COL.COLLECTION, transaction.payload.collection!); const collection = await collectionDocRef.get(); const collectionMetadata = await this.getCollectionMetadata(transaction.network!, collection); @@ -154,10 +153,8 @@ export class NftWallet { if (collection.type === CollectionType.METADATA) { return { immutableMetadata: '', mutableMetadata: '' }; } - const royaltySpaceDocRef = build5Db().doc( - `${COL.SPACE}/${collection.royaltiesSpace || undefined}`, - ); - const royaltySpace = await royaltySpaceDocRef.get(); + const royaltySpaceDocRef = build5Db().doc(COL.SPACE, collection.royaltiesSpace || ''); + const royaltySpace = await royaltySpaceDocRef.get(); const royaltySpaceAddress = getAddress(royaltySpace, network); const collectionMetadata = await collectionToMetadata(collection, royaltySpaceAddress); return { immutableMetadata: JSON.stringify(collectionMetadata), mutableMetadata: '' }; @@ -184,11 +181,11 @@ export class NftWallet { nextAliasOutput.aliasId = Utils.computeAliasId(aliasOutputId); nextAliasOutput.stateIndex!++; - const awardDocRef = build5Db().doc(`${COL.AWARD}/${transaction.payload.award}`); + const awardDocRef = build5Db().doc(COL.AWARD, transaction.payload.award!); const award = await awardDocRef.get(); const issuerAddress = new AliasAddress(Utils.computeAliasId(aliasOutputId)); - const spaceDocRef = build5Db().doc(`${COL.SPACE}/${award.space}`); + const spaceDocRef = build5Db().doc(COL.SPACE, award.space); const space = await spaceDocRef.get(); const metadata = await awardToCollectionMetadata(award, space); const collectionOutput = await createNftOutput( @@ -250,12 +247,10 @@ export class NftWallet { : collectionOutput.nftId; const collection = ( - await build5Db().doc(`${COL.COLLECTION}/${transaction.payload.collection}`).get() - ); - const royaltySpaceDocRef = build5Db().doc( - `${COL.SPACE}/${collection.royaltiesSpace || undefined}`, + await build5Db().doc(COL.COLLECTION, transaction.payload.collection!).get() ); - const royaltySpace = await royaltySpaceDocRef.get(); + const royaltySpaceDocRef = build5Db().doc(COL.SPACE, collection.royaltiesSpace || ''); + const royaltySpace = await royaltySpaceDocRef.get(); const royaltySpaceAddress = getAddress(royaltySpace, transaction.network!); const nfts = await getPreMintedNfts(transaction.payload.collection as string); @@ -293,17 +288,17 @@ export class NftWallet { ); blockId = await submitBlock(this.wallet, essence, unlocks); const batch = build5Db().batch(); - nftOutputsToMint.forEach((output, i) => { - batch.update(build5Db().doc(`${COL.NFT}/${nfts[i].uid}`), { - 'mintingData.address': nftMintAddresses[i].bech32, - 'mintingData.storageDeposit': Number(output.amount), + for (let i = 0; i < nftOutputsToMint.length; ++i) { + batch.update(build5Db().doc(COL.NFT, nfts[i].uid), { + mintingData_address: nftMintAddresses[i].bech32, + mintingData_storageDeposit: Number(nftOutputsToMint[i].amount), }); - }); + } - const transactionDocRef = build5Db().doc(`${COL.TRANSACTION}/${transaction.uid}`); + const transactionDocRef = build5Db().doc(COL.TRANSACTION, transaction.uid); batch.update(transactionDocRef, { - 'payload.amount': nftOutputsToMint.reduce((acc, act) => acc + Number(act.amount), 0), - 'payload.nfts': nfts.slice(0, nftsToMint).map((nft) => nft.uid), + payload_amount: nftOutputsToMint.reduce((acc, act) => acc + Number(act.amount), 0), + payload_nfts: nfts.slice(0, nftsToMint).map((nft) => nft.uid), }); await batch.commit(); @@ -354,7 +349,7 @@ export class NftWallet { ? Utils.computeNftId(collectionOutputId) : collectionOutput.nftId; - const awardDocRef = build5Db().doc(`${COL.AWARD}/${transaction.payload.award}`); + const awardDocRef = build5Db().doc(COL.AWARD, transaction.payload.award!); const award = await awardDocRef.get(); const issuerAddress = new NftAddress(collectionNftId); @@ -365,7 +360,7 @@ export class NftWallet { collectionNftId, transaction.uid, dayjs(get(transaction, 'payload.participatedOn')!.toDate()), - get(transaction, 'payload.edition', 0), + transaction.payload.edition || 0, ); const ntt = await createNftOutput( this.wallet, @@ -439,9 +434,7 @@ export class NftWallet { nextCollectionOutput.nftId = Utils.computeNftId(collectionOutputId); } - const order = await build5Db() - .doc(`${COL.TRANSACTION}/${transaction.payload.orderId}`) - .get(); + const order = await build5Db().doc(COL.TRANSACTION, transaction.payload.orderId!).get(); const issuerAddress = new NftAddress(transaction.payload.collectionId!); const ownerAddress = Utils.parseBech32Address(transaction.payload.targetAddress!); const mutableMetadata = JSON.stringify(get(order, 'payload.metadata', {})); @@ -519,7 +512,7 @@ export class NftWallet { } nextAliasOutput.stateIndex!++; - const stampDocRef = build5Db().doc(`${COL.STAMP}/${transaction.payload.stamp}`); + const stampDocRef = build5Db().doc(COL.STAMP, transaction.payload.stamp!); const stamp = await stampDocRef.get(); const issuerAddress = new AliasAddress(nextAliasOutput.aliasId); @@ -592,7 +585,7 @@ export class NftWallet { const collectionOutputId = await this.client.nftOutputId(transaction.payload.collectionId!); const collectionOutput = (await this.client.getOutput(collectionOutputId)).output as NftOutput; - const nft = await build5Db().doc(`${COL.NFT}/${transaction.payload.nft}`).get(); + const nft = await build5Db().doc(COL.NFT, transaction.payload.nft!).get(); const nftOwnerAddressBech = nft.mintingData?.address || nft.depositData?.address!; const nftOwnerAddress = await this.wallet.getAddressDetails(nftOwnerAddressBech); const nftOutputId = await this.client.nftOutputId(nft.mintingData?.nftId!); @@ -614,9 +607,7 @@ export class NftWallet { nextCollectionOutput.nftId = Utils.computeNftId(collectionOutputId); } - const order = await build5Db() - .doc(`${COL.TRANSACTION}/${transaction.payload.orderId}`) - .get(); + const order = await build5Db().doc(COL.TRANSACTION, transaction.payload.orderId!).get(); const mutableMetadata = JSON.stringify(get(order, 'payload.metadata', {})); const nextNftOutput: NftOutputBuilderParams = cloneDeep(nftOutput); if (nextNftOutput.nftId === EMPTY_NFT_ID) { @@ -855,7 +846,7 @@ const getPreMintedNfts = (collection: string, limit = 100) => build5Db() .collection(COL.NFT) .where('collection', '==', collection) - .where('status', '==', NftStatus.PRE_MINTED) + .where('status', '==', PgNftStatus.PRE_MINTED) .where('placeholderNft', '==', false) .limit(limit) - .get(); + .get(); diff --git a/packages/functions/src/services/wallet/mnemonic.ts b/packages/functions/src/services/wallet/mnemonic.ts index 1fe0b74a47..d76aef25c5 100644 --- a/packages/functions/src/services/wallet/mnemonic.ts +++ b/packages/functions/src/services/wallet/mnemonic.ts @@ -1,5 +1,5 @@ -import { build5Db } from '@build-5/database'; -import { COL, DEFAULT_NETWORK, Mnemonic, NetworkAddress } from '@build-5/interfaces'; +import { PgNetwork, build5Db, convertEnum } from '@build-5/database'; +import { COL, DEFAULT_NETWORK, Mnemonic, Network, NetworkAddress } from '@build-5/interfaces'; import { AES, enc } from 'crypto-js'; export class MnemonicService { @@ -11,9 +11,12 @@ export class MnemonicService { await build5Db() .collection(COL.MNEMONIC) .doc(address) - .set({ + .upsert({ mnemonic: AES.encrypt(mnemonic, process.env.ENCRYPTION_SALT || '').toString(), - network, + network: convertEnum(network, Network, PgNetwork), + consumedOutputIds: [], + consumedNftOutputIds: [], + consumedAliasOutputIds: [], }); } @@ -24,8 +27,9 @@ export class MnemonicService { public static async getData(address: NetworkAddress | undefined): Promise { if (!address) { - return {}; + return {} as Mnemonic; } - return (await build5Db().collection(COL.MNEMONIC).doc(address).get()) || {}; + const docRef = build5Db().doc(COL.MNEMONIC, address); + return (await docRef.get()) || ({} as Mnemonic); } } diff --git a/packages/functions/src/services/wallet/wallet.service.ts b/packages/functions/src/services/wallet/wallet.service.ts index 709be20eb0..21f8a929ee 100644 --- a/packages/functions/src/services/wallet/wallet.service.ts +++ b/packages/functions/src/services/wallet/wallet.service.ts @@ -24,15 +24,20 @@ const NODES = { [Network.ATOI]: ['https://rms1.svrs.io/'], }; +export const tangleClients: { [key: string]: Client } = {}; + const getClient = async (network: Network, nodeIndexToExclude?: number) => { let nodeUrl = ''; for (let i = 0; i < 5; ++i) { const nodeIndex = getRandomIndex(NODES[network], nodeIndexToExclude); nodeUrl = NODES[network][nodeIndex]; try { - const client = new Client({ nodes: [nodeUrl] }); + const client = tangleClients[nodeUrl] || new Client({ nodes: [nodeUrl] }); const info = await client.getInfo(); if (info.nodeInfo.status.isHealthy) { + if (!tangleClients[nodeUrl]) { + tangleClients[nodeUrl] = client; + } return { client, info: info.nodeInfo, nodeIndex, nodeUrl }; } } catch (error) { @@ -64,5 +69,5 @@ export const setConsumedOutputIds = ( consumedAliasOutputIds: string[] = [], ) => build5Db() - .doc(`${COL.MNEMONIC}/${address}`) + .doc(COL.MNEMONIC, address) .update({ consumedOutputIds, consumedNftOutputIds, consumedAliasOutputIds }); diff --git a/packages/functions/src/triggers/algolia/algolia.trigger.ts b/packages/functions/src/triggers/algolia/algolia.trigger.ts index 8a8bd9ba96..6f413a486b 100644 --- a/packages/functions/src/triggers/algolia/algolia.trigger.ts +++ b/packages/functions/src/triggers/algolia/algolia.trigger.ts @@ -1,8 +1,9 @@ +import { BaseRecord } from '@build-5/database'; import { COL, SOON_PROJECT_ID } from '@build-5/interfaces'; import algoliasearch from 'algoliasearch'; import { algoliaAppId, algoliaKey } from '../../utils/config.utils'; -import { FirestoreDocEvent } from '../common'; -import { docToAlgoliaData } from './firestore.to.algolia'; +import { PgDocEvent } from '../common'; + const client = algoliasearch(algoliaAppId(), algoliaKey()); const deleteObject = async (col: COL, objectID: string) => { @@ -13,8 +14,8 @@ const deleteObject = async (col: COL, objectID: string) => { } }; -const upsertObject = async (rawData: Record, col: COL, objectID: string) => { - const data = docToAlgoliaData({ ...rawData, objectID, id: objectID }); +const upsertObject = async (rawData: BaseRecord, col: COL, objectID: string) => { + const data = docToAlgoliaData({ ...rawData, objectID, id: objectID } as BaseRecord); try { await client.initIndex(col).saveObject(data).wait(); } catch (error) { @@ -22,7 +23,7 @@ const upsertObject = async (rawData: Record, col: COL, objectID } }; -export const algoliaTrigger = async (event: FirestoreDocEvent>) => { +export const algoliaTrigger = async (event: PgDocEvent) => { const { prev, curr, col } = event; if (col !== COL.MEMBER && curr?.project !== SOON_PROJECT_ID) { @@ -41,3 +42,26 @@ export const algoliaTrigger = async (event: FirestoreDocEvent processObject(data); + +const processObject = (data: BaseRecord) => + Object.entries(data).reduce((acc, [key, val]) => { + const value = processValue(val); + return isValid(value) ? { ...acc, [key]: value } : acc; + }, {} as BaseRecord); + +const processValue = (value: unknown): unknown => { + if (value instanceof Date) { + return value.getTime(); + } + if (value instanceof Array) { + return value.map(processValue); + } + if (value instanceof Object) { + return processObject({ ...value } as BaseRecord); + } + return value; +}; + +const isValid = (value: unknown) => typeof value !== 'undefined' && value !== null; diff --git a/packages/functions/src/triggers/algolia/firestore.to.algolia.ts b/packages/functions/src/triggers/algolia/firestore.to.algolia.ts deleted file mode 100644 index 1401c41f0c..0000000000 --- a/packages/functions/src/triggers/algolia/firestore.to.algolia.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { firestore } from 'firebase-admin'; - -export const docToAlgoliaData = (data: Record) => processObject(data); - -const processObject = (data: Record) => - Object.entries(data).reduce( - (acc, [key, val]) => { - const value = processValue(val); - return isValid(value) ? { ...acc, [key]: value } : acc; - }, - {} as Record, - ); - -const processValue = (value: unknown): unknown => { - if (value instanceof firestore.Timestamp) { - return value.toDate().getTime(); - } - if (value instanceof Array) { - return value.map(processValue); - } - if (value instanceof Object) { - return processObject({ ...value }); - } - return value; -}; - -const isValid = (value: unknown) => typeof value !== 'undefined' && value !== null; diff --git a/packages/functions/src/triggers/award.trigger.ts b/packages/functions/src/triggers/award.trigger.ts index 0c7b49b378..0d4f2f178b 100644 --- a/packages/functions/src/triggers/award.trigger.ts +++ b/packages/functions/src/triggers/award.trigger.ts @@ -1,9 +1,14 @@ -import { build5Db } from '@build-5/database'; import { - Award, - AwardBadgeType, + PgAward, + PgAwardBadgeType, + PgNetwork, + PgTransactionType, + build5Db, + convertEnum, +} from '@build-5/database'; +import { COL, - Token, + Network, Transaction, TransactionPayloadType, TransactionType, @@ -11,9 +16,9 @@ import { import { head } from 'lodash'; import { getProject } from '../utils/common.utils'; import { getRandomEthAddress } from '../utils/wallet.utils'; -import { FirestoreDocEvent } from './common'; +import { PgDocEvent } from './common'; -export const onAwardUpdated = async (event: FirestoreDocEvent) => { +export const onAwardUpdated = async (event: PgDocEvent) => { const { prev, curr } = event; if (!prev || !curr || !curr.funded) { return; @@ -26,13 +31,13 @@ export const onAwardUpdated = async (event: FirestoreDocEvent) => { ) { const targetAddress = await getReturnAddress(curr); - const burnAlias = { + const burnAlias: Transaction = { project: getProject(curr), type: TransactionType.AWARD, uid: getRandomEthAddress(), space: curr.space, member: curr.fundedBy, - network: curr.network, + network: convertEnum(curr.network, PgNetwork, Network)!, payload: { type: TransactionPayloadType.BURN_ALIAS, sourceAddress: curr.address, @@ -42,22 +47,22 @@ export const onAwardUpdated = async (event: FirestoreDocEvent) => { award: curr.uid, }, }; - await build5Db().doc(`${COL.TRANSACTION}/${burnAlias.uid}`).create(burnAlias); + await build5Db().doc(COL.TRANSACTION, burnAlias.uid).create(burnAlias); - const remainingBadges = curr.badge.total - curr.issued; - if (curr.badge.type === AwardBadgeType.BASE && remainingBadges) { - const tokenDocRef = build5Db().doc(`${COL.TOKEN}/${curr.badge.tokenUid}`); - const token = (await tokenDocRef.get())!; - const baseTokenCredit = { + const remainingBadges = curr.badge_total! - curr.issued!; + if (curr.badge_type === PgAwardBadgeType.BASE && remainingBadges) { + const tokenDocRef = build5Db().doc(COL.TOKEN, curr.badge_tokenUid!); + const token = (await tokenDocRef.get())!; + const baseTokenCredit: Transaction = { project: getProject(curr), type: TransactionType.CREDIT, uid: getRandomEthAddress(), space: curr.space, member: curr.fundedBy, - network: curr.network, + network: convertEnum(curr.network, PgNetwork, Network)!, payload: { type: TransactionPayloadType.AWARD_COMPLETED, - amount: remainingBadges * curr.badge.tokenReward, + amount: remainingBadges * curr.badge_tokenReward!, sourceAddress: curr.address, targetAddress, reconciled: false, @@ -67,21 +72,21 @@ export const onAwardUpdated = async (event: FirestoreDocEvent) => { tokenSymbol: token.symbol, }, }; - await build5Db().doc(`${COL.TRANSACTION}/${baseTokenCredit.uid}`).create(baseTokenCredit); + await build5Db().doc(COL.TRANSACTION, baseTokenCredit.uid).create(baseTokenCredit); } } if ( - curr.badge.type === AwardBadgeType.NATIVE && + curr.badge_type === PgAwardBadgeType.NATIVE && (prev.completed !== curr.completed || prev.airdropClaimed !== curr.airdropClaimed) && curr.completed && curr.airdropClaimed === curr.issued ) { const targetAddress = await getReturnAddress(curr); - const remainingBadges = curr.badge.total - curr.issued; + const remainingBadges = curr.badge_total! - curr.issued!; - const tokenDocRef = build5Db().doc(`${COL.TOKEN}/${curr.badge.tokenUid}`); - const token = (await tokenDocRef.get())!; + const tokenDocRef = build5Db().doc(COL.TOKEN, curr.badge_tokenUid!); + const token = (await tokenDocRef.get())!; const nativeTokensCredit: Transaction = { project: getProject(curr), @@ -89,15 +94,15 @@ export const onAwardUpdated = async (event: FirestoreDocEvent) => { uid: getRandomEthAddress(), space: curr.space, member: curr.fundedBy, - network: curr.network, + network: convertEnum(curr.network, PgNetwork, Network)!, payload: { type: TransactionPayloadType.AWARD_COMPLETED, amount: curr.nativeTokenStorageDeposit, nativeTokens: remainingBadges ? [ { - id: curr.badge.tokenId!, - amount: BigInt(remainingBadges * curr.badge.tokenReward), + id: curr.badge_tokenId!, + amount: BigInt(remainingBadges * curr.badge_tokenReward!), }, ] : [], @@ -110,20 +115,20 @@ export const onAwardUpdated = async (event: FirestoreDocEvent) => { tokenSymbol: token.symbol, }, }; - await build5Db().doc(`${COL.TRANSACTION}/${nativeTokensCredit.uid}`).create(nativeTokensCredit); + await build5Db().doc(COL.TRANSACTION, nativeTokensCredit.uid).create(nativeTokensCredit); } }; -const getReturnAddress = async (award: Award) => { +const getReturnAddress = async (award: PgAward) => { if (award.fundingAddress) { return award.fundingAddress; } const snap = await build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.PAYMENT) - .where('payload.targetAddress', '==', award.address) - .where('payload.invalidPayment', '==', false) + .where('type', '==', PgTransactionType.PAYMENT) + .where('payload_targetAddress', '==', award.address) + .where('payload_invalidPayment', '==', false) .limit(1) - .get(); + .get(); return head(snap)?.payload.sourceAddress || ''; }; diff --git a/packages/functions/src/triggers/collection.stats.trigger.ts b/packages/functions/src/triggers/collection.stats.trigger.ts index 580d654072..835f0c90a1 100644 --- a/packages/functions/src/triggers/collection.stats.trigger.ts +++ b/packages/functions/src/triggers/collection.stats.trigger.ts @@ -1,35 +1,28 @@ -import { build5Db } from '@build-5/database'; -import { COL, CollectionStats } from '@build-5/interfaces'; +import { PgCollectionStats, build5Db } from '@build-5/database'; +import { COL } from '@build-5/interfaces'; import { getRankingThreshold } from '../utils/config.utils'; -import { FirestoreDocEvent } from './common'; +import { PgDocEvent } from './common'; -export const onCollectionStatsWrite = async (event: FirestoreDocEvent) => { +export const onCollectionStatsWrite = async (event: PgDocEvent) => { const { prev, curr } = event; if (!curr) { return; } if (rankingThresholdReached(prev, curr)) { - await onRankingThresholdReached(event.docId); + await build5Db().doc(COL.COLLECTION, event.uid).update({ approved: false, rejected: true }); } }; const rankingThresholdReached = ( - prev: CollectionStats | undefined, - curr: CollectionStats | undefined, + prev: PgCollectionStats | undefined, + curr: PgCollectionStats | undefined, ) => { const rankingThreshold = getRankingThreshold(); return ( - prev?.ranks && - curr?.ranks && - curr.ranks.sum < rankingThreshold && - prev.ranks.sum >= rankingThreshold + prev?.ranks_sum && + curr?.ranks_sum && + curr.ranks_sum < rankingThreshold && + prev.ranks_sum >= rankingThreshold ); }; - -const onRankingThresholdReached = async (collectionId: string) => { - await build5Db().doc(`${COL.COLLECTION}/${collectionId}`).update({ - approved: false, - rejected: true, - }); -}; diff --git a/packages/functions/src/triggers/collection.trigger.ts b/packages/functions/src/triggers/collection.trigger.ts index e4c781bd8e..016366a017 100644 --- a/packages/functions/src/triggers/collection.trigger.ts +++ b/packages/functions/src/triggers/collection.trigger.ts @@ -1,49 +1,55 @@ -import { build5Db, getSnapshot } from '@build-5/database'; +import { + PgCollection, + PgCollectionStatus, + PgMediaStatus, + PgNetwork, + PgNftUpdate, + PgTransactionType, + PgUnsoldMintingOptions, + build5Db, + convertEnum, +} from '@build-5/database'; import { COL, - Collection, - CollectionStatus, DEFAULT_NETWORK, MediaStatus, - Member, - Nft, + Network, Transaction, TransactionPayloadType, TransactionType, - UnsoldMintingOptions, } from '@build-5/interfaces'; import { last } from 'lodash'; import { getAddress } from '../utils/address.utils'; import { collectionToIpfsMetadata, downloadMediaAndPackCar } from '../utils/car.utils'; import { getProject } from '../utils/common.utils'; import { getRandomEthAddress } from '../utils/wallet.utils'; -import { FirestoreDocEvent } from './common'; +import { PgDocEvent } from './common'; -export const onCollectionUpdated = async (event: FirestoreDocEvent) => { +export const onCollectionUpdated = async (event: PgDocEvent) => { const { prev, curr } = event; if (!prev || !curr) { return; } try { if (prev && (curr.approved !== prev.approved || curr.rejected !== prev.rejected)) { - return await updateNftApprovalState(curr.uid); + return await updateNftApprovalState(curr.uid, curr.approved || false, curr.rejected || false); } if (curr.placeholderNft && prev.availableNfts !== curr.availableNfts) { return await hidePlaceholderNft(curr); } - if (prev.mintingData?.nftsToMint !== 0 && curr.mintingData?.nftsToMint === 0) { + if (prev.mintingData_nftsToMint !== 0 && curr.mintingData_nftsToMint === 0) { return await onCollectionMinted(curr); } - if (prev.status !== curr.status && curr.status === CollectionStatus.MINTING) { + if (prev.status !== curr.status && curr.status === PgCollectionStatus.MINTING) { return await onCollectionMinting(curr); } if ( - curr.status === CollectionStatus.MINTING && - prev.mintingData?.nftMediaToPrepare && - curr.mintingData?.nftMediaToPrepare === 0 + curr.status === PgCollectionStatus.MINTING && + prev.mintingData_nftMediaToPrepare && + curr.mintingData_nftMediaToPrepare === 0 ) { return await onNftMediaPrepared(curr); } @@ -52,148 +58,130 @@ export const onCollectionUpdated = async (event: FirestoreDocEvent) } }; -const updateNftApprovalState = async (collectionId: string) => { - let lastDocId = ''; - do { - const lastDoc = await getSnapshot(COL.NFT, lastDocId); - const snap = await build5Db() - .collection(COL.NFT) - .where('collection', '==', collectionId) - .startAfter(lastDoc) - .limit(500) - .get(); - lastDocId = last(snap)?.uid || ''; - - await build5Db().runTransaction(async (transaction) => { - const collectionDocRef = build5Db().doc(`${COL.COLLECTION}/${collectionId}`); - const collection = await transaction.get(collectionDocRef); - - snap.forEach((nft) => { - const nftDocRef = build5Db().doc(`${COL.NFT}/${nft.uid}`); - transaction.update(nftDocRef, { - approved: collection?.approved || false, - rejected: collection?.rejected || false, - }); - }); - }); - } while (lastDocId); -}; +const updateNftApprovalState = (collectionId: string, approved: boolean, rejected: boolean) => + build5Db().collection(COL.NFT).update({ approved, rejected }, { collection: collectionId }); -const hidePlaceholderNft = async (collection: Collection) => { - const nftDocRef = build5Db().doc(`${COL.NFT}/${collection.placeholderNft}`); +const hidePlaceholderNft = async (collection: PgCollection) => { + const nftDocRef = build5Db().doc(COL.NFT, collection.placeholderNft!); await nftDocRef.update({ hidden: collection.availableNfts === 0 }); }; -const onCollectionMinted = async (collection: Collection) => { +const onCollectionMinted = async (collection: PgCollection) => { + const network = convertEnum(collection.mintingData_network!, PgNetwork, Network)!; if (collection.limitedEdition) { const order: Transaction = { project: getProject(collection), type: TransactionType.MINT_COLLECTION, uid: getRandomEthAddress(), - member: collection.mintingData?.mintedBy, + member: collection.mintingData_mintedBy, space: collection.space, - network: collection.mintingData?.network!, + network, payload: { type: TransactionPayloadType.LOCK_COLLECTION, amount: 0, - sourceAddress: collection.mintingData?.address, + sourceAddress: collection.mintingData_address, collection: collection.uid, - aliasStorageDeposit: collection.mintingData?.aliasStorageDeposit || 0, + aliasStorageDeposit: collection.mintingData_aliasStorageDeposit || 0, }, }; - await build5Db().doc(`${COL.TRANSACTION}/${order.uid}`).create(order); + await build5Db().doc(COL.TRANSACTION, order.uid).create(order); return; } - const memberDocRef = build5Db().doc(`${COL.MEMBER}/${collection.mintingData?.mintedBy}`); - const member = (await memberDocRef.get())!; + const memberDocRef = build5Db().doc(COL.MEMBER, collection.mintingData_mintedBy!); + const member = (await memberDocRef.get())!; const order: Transaction = { project: getProject(collection), type: TransactionType.MINT_COLLECTION, uid: getRandomEthAddress(), - member: collection.mintingData?.mintedBy, + member: collection.mintingData_mintedBy, space: collection.space, - network: collection.mintingData?.network!, + network, payload: { type: TransactionPayloadType.SEND_ALIAS_TO_GUARDIAN, - amount: collection.mintingData?.aliasStorageDeposit, - sourceAddress: collection.mintingData?.address, - targetAddress: getAddress(member, collection.mintingData?.network!), + amount: collection.mintingData_aliasStorageDeposit, + sourceAddress: collection.mintingData_address, + targetAddress: getAddress(member, network), collection: collection.uid, lockCollectionNft: collection.limitedEdition || false, }, }; - await build5Db().doc(`${COL.TRANSACTION}/${order.uid}`).create(order); + await build5Db().doc(COL.TRANSACTION, order.uid).create(order); }; -const onCollectionMinting = async (collection: Collection) => { - await build5Db().doc(`${COL.COLLECTION}/${collection.uid}`).update({ - 'mintingData.nftsToMint': build5Db().deleteField(), - 'mintingData.nftMediaToUpload': build5Db().deleteField(), - 'mintingData.nftMediaToPrepare': build5Db().deleteField(), +const onCollectionMinting = async (collection: PgCollection) => { + await build5Db().doc(COL.COLLECTION, collection.uid).update({ + mintingData_nftsToMint: null, + mintingData_nftMediaToUpload: null, + mintingData_nftMediaToPrepare: null, }); const metadata = collectionToIpfsMetadata(collection); - const ipfs = await downloadMediaAndPackCar(collection.uid, collection.bannerUrl, metadata); + const ipfs = await downloadMediaAndPackCar(collection.uid, collection.bannerUrl!, metadata); await updateNftsForMinting(collection); - await build5Db().doc(`${COL.COLLECTION}/${collection.uid}`).update({ - mediaStatus: MediaStatus.PENDING_UPLOAD, + await build5Db().doc(COL.COLLECTION, collection.uid).update({ + mediaStatus: PgMediaStatus.PENDING_UPLOAD, ipfsMedia: ipfs.ipfsMedia, ipfsMetadata: ipfs.ipfsMetadata, ipfsRoot: ipfs.ipfsRoot, }); }; -const onNftMediaPrepared = async (collection: Collection) => { +const onNftMediaPrepared = async (collection: PgCollection) => { const order: Transaction = { project: getProject(collection), type: TransactionType.MINT_COLLECTION, uid: getRandomEthAddress(), - member: collection.mintingData?.mintedBy!, + member: collection.mintingData_mintedBy!, space: collection.space, - network: collection.mintingData?.network!, + network: convertEnum(collection.mintingData_network!, PgNetwork, Network)!, payload: { type: TransactionPayloadType.MINT_ALIAS, - amount: collection.mintingData?.aliasStorageDeposit || 0, - sourceAddress: collection.mintingData?.address, + amount: collection.mintingData_aliasStorageDeposit || 0, + sourceAddress: collection.mintingData_address, collection: collection.uid, - collectionStorageDeposit: collection.mintingData?.storageDeposit, + collectionStorageDeposit: collection.mintingData_storageDeposit, }, }; - await build5Db().doc(`${COL.TRANSACTION}/${order.uid}`).create(order); + await build5Db().doc(COL.TRANSACTION, order.uid).create(order); }; const BATCH_SIZE = 1000; -const updateNftsForMinting = async (collection: Collection) => { - const collectionDocRef = build5Db().doc(`${COL.COLLECTION}/${collection.uid}`); - const unsoldMintingOptions = collection.mintingData?.unsoldMintingOptions; - let lastDocId = ''; +const updateNftsForMinting = async (collection: PgCollection) => { + const collectionDocRef = build5Db().doc(COL.COLLECTION, collection.uid); + const unsoldMintingOptions = collection.mintingData_unsoldMintingOptions; let unsoldCount = 0; let nftsToMintCount = 0; let nftMediaToUploadCount = 0; let nftMediaToPrepareCount = 0; + if (unsoldMintingOptions === PgUnsoldMintingOptions.BURN_UNSOLD) { + const deleted = await build5Db() + .collection(COL.NFT) + .delete({ collection: collection.uid, sold: false, placeholderNft: false }); + if (deleted) { + await build5Db() + .doc(COL.COLLECTION, collection.uid) + .update({ total: build5Db().inc(-deleted) }); + } + } + + let lastUid = ''; do { - const lastDoc = await getSnapshot(COL.NFT, lastDocId); const allNfts = await build5Db() .collection(COL.NFT) .where('collection', '==', collection.uid) .where('placeholderNft', '==', false) - .startAfter(lastDoc) + .where('uid', '>', lastUid) + .orderBy('uid') .limit(BATCH_SIZE) - .get(); - lastDocId = last(allNfts)?.uid || ''; + .get(); + lastUid = last(allNfts)?.uid || ''; const unsold = allNfts.filter((nft) => !nft.sold); - if (unsoldMintingOptions === UnsoldMintingOptions.BURN_UNSOLD) { - const promises = unsold.map((nft) => build5Db().doc(`${COL.NFT}/${nft.uid}`).delete()); - await Promise.all(promises); - await build5Db() - .doc(`${COL.COLLECTION}/${collection.uid}`) - .update({ total: build5Db().inc(-unsold.length) }); - } + const nftsToMint = - unsoldMintingOptions === UnsoldMintingOptions.BURN_UNSOLD + unsoldMintingOptions === PgUnsoldMintingOptions.BURN_UNSOLD ? allNfts.filter((nft) => nft.sold) : allNfts; @@ -214,33 +202,32 @@ const updateNftsForMinting = async (collection: Collection) => { nftMediaToPrepareCount -= nftMediaAlreadyPrepared; unsoldCount += unsold.length; - } while (lastDocId); + } while (lastUid); await collectionDocRef.update({ - 'mintingData.nftsToMint': build5Db().inc(nftsToMintCount), - 'mintingData.nftMediaToUpload': build5Db().inc(nftMediaToUploadCount), - 'mintingData.nftMediaToPrepare': build5Db().inc(nftMediaToPrepareCount), + mintingData_nftsToMint: build5Db().inc(nftsToMintCount), + mintingData_nftMediaToUpload: build5Db().inc(nftMediaToUploadCount), + mintingData_nftMediaToPrepare: build5Db().inc(nftMediaToPrepareCount), }); if ( !unsoldCount || - [UnsoldMintingOptions.BURN_UNSOLD, UnsoldMintingOptions.TAKE_OWNERSHIP].includes( - unsoldMintingOptions!, - ) + PgUnsoldMintingOptions.BURN_UNSOLD === unsoldMintingOptions || + PgUnsoldMintingOptions.TAKE_OWNERSHIP === unsoldMintingOptions ) { const promises = ( await build5Db() .collection(COL.NFT) .where('collection', '==', collection.uid) .where('placeholderNft', '==', true) - .get() - ).map((nft) => { - const docRef = build5Db().doc(`${COL.NFT}/${nft.uid}`); - docRef.update({ hidden: true }); + .get() + ).map(async (nft) => { + const docRef = build5Db().doc(COL.NFT, nft.uid); + await docRef.update({ hidden: true }); }); await Promise.all(promises); } - if (unsoldCount && unsoldMintingOptions === UnsoldMintingOptions.TAKE_OWNERSHIP) { + if (unsoldCount && unsoldMintingOptions === PgUnsoldMintingOptions.TAKE_OWNERSHIP) { await collectionDocRef.update({ sold: build5Db().inc(unsoldCount) }); } @@ -248,28 +235,27 @@ const updateNftsForMinting = async (collection: Collection) => { if ( unsoldCount && collection.placeholderNft && - collection.mintingData?.unsoldMintingOptions === UnsoldMintingOptions.SET_NEW_PRICE + collection.mintingData_unsoldMintingOptions === PgUnsoldMintingOptions.SET_NEW_PRICE ) { await build5Db() - .doc(`${COL.NFT}/${collection.placeholderNft}`) + .doc(COL.NFT, collection.placeholderNft) .update({ - availablePrice: collection.mintingData?.newPrice || collection.price, - price: collection.mintingData?.newPrice || collection.price, + availablePrice: collection.mintingData_newPrice || collection.price, + price: collection.mintingData_newPrice || collection.price, }); } }; -const setNftForMinting = async (nftId: string, collection: Collection): Promise => { - const nftDocRef = build5Db().doc(`${COL.NFT}/${nftId}`); - +const setNftForMinting = async (nftId: string, collection: PgCollection): Promise => { const nft = await build5Db().runTransaction(async (transaction) => { - const nft = (await transaction.get(nftDocRef))!; + const nftDocRef = build5Db().doc(COL.NFT, nftId); + const nft = (await transaction.get(nftDocRef))!; if (nft.mediaStatus === MediaStatus.PREPARE_IPFS) { - transaction.update(nftDocRef, { mediaStatus: MediaStatus.ERROR }); + await transaction.update(nftDocRef, { mediaStatus: PgMediaStatus.ERROR }); } - const nftUpdateData = { + const nftUpdateData = { auctionFrom: null, auctionTo: null, extendedAuctionTo: null, @@ -279,22 +265,25 @@ const setNftForMinting = async (nftId: string, collection: Collection): Promise< auctionHighestBid: null, auctionHighestBidder: null, auction: null, - mediaStatus: + mediaStatus: convertEnum( nft.mediaStatus === MediaStatus.PREPARE_IPFS ? MediaStatus.ERROR : nft.mediaStatus || MediaStatus.PREPARE_IPFS, + MediaStatus, + PgMediaStatus, + ), }; if (nft.auction) { - const auctionDocRef = build5Db().doc(`${COL.AUCTION}/${nft.auction}`); - transaction.update(auctionDocRef, { active: false }); + const auctionDocRef = build5Db().doc(COL.AUCTION, nft.auction); + await transaction.update(auctionDocRef, { active: false }); const payments = await build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.PAYMENT) - .where('payload.invalidPayment', '==', false) - .where('payload.auction', '==', nft.auction) - .get(); + .where('type', '==', PgTransactionType.PAYMENT) + .where('payload_invalidPayment', '==', false) + .where('payload_auction', '==', nft.auction) + .get(); for (const payment of payments) { const credit: Transaction = { project: getProject(payment), @@ -312,15 +301,14 @@ const setNftForMinting = async (nftId: string, collection: Collection): Promise< collection: nft.collection, }, }; - const creditDocRef = build5Db().doc(`${COL.TRANSACTION}/${credit.uid}`); - transaction.create(creditDocRef, credit); + const creditDocRef = build5Db().doc(COL.TRANSACTION, credit.uid); + await transaction.create(creditDocRef, credit); } } if (nft.locked) { - transaction.update(build5Db().doc(`${COL.TRANSACTION}/${nft.lockedBy}`), { - 'payload.void': true, - }); + const docRef = build5Db().doc(COL.TRANSACTION, nft.lockedBy!); + await transaction.update(docRef, { payload_void: true }); nftUpdateData.locked = false; nftUpdateData.lockedBy = null; } @@ -330,13 +318,13 @@ const setNftForMinting = async (nftId: string, collection: Collection): Promise< nftUpdateData.availablePrice = null; nftUpdateData.price = 0; } else { - if (collection.mintingData?.unsoldMintingOptions === UnsoldMintingOptions.SET_NEW_PRICE) { + if (collection.mintingData_unsoldMintingOptions === PgUnsoldMintingOptions.SET_NEW_PRICE) { nftUpdateData.availablePrice = - collection.mintingData?.newPrice || nftUpdateData.availablePrice; - nftUpdateData.price = collection.mintingData?.newPrice || nftUpdateData.price; + collection.mintingData_newPrice || nftUpdateData.availablePrice; + nftUpdateData.price = collection.mintingData_newPrice || nftUpdateData.price; } - if (collection.mintingData?.unsoldMintingOptions === UnsoldMintingOptions.TAKE_OWNERSHIP) { - nftUpdateData.owner = collection.mintingData?.mintedBy!; + if (collection.mintingData_unsoldMintingOptions === PgUnsoldMintingOptions.TAKE_OWNERSHIP) { + nftUpdateData.owner = collection.mintingData_mintedBy!; nftUpdateData.isOwned = true; nftUpdateData.sold = true; nftUpdateData.availableFrom = null; @@ -344,14 +332,15 @@ const setNftForMinting = async (nftId: string, collection: Collection): Promise< nftUpdateData.price = 0; } } - transaction.update(nftDocRef, nftUpdateData); + await transaction.update(nftDocRef, nftUpdateData); return nftUpdateData; }); - if (nft.mediaStatus === MediaStatus.ERROR) { - await nftDocRef.update({ mediaStatus: MediaStatus.PREPARE_IPFS }); + if (nft.mediaStatus === PgMediaStatus.ERROR) { + const nftDocRef = build5Db().doc(COL.NFT, nftId); + await nftDocRef.update({ mediaStatus: PgMediaStatus.PREPARE_IPFS }); } - return nft.mediaStatus!; + return convertEnum(nft.mediaStatus, PgMediaStatus, MediaStatus)!; }; diff --git a/packages/functions/src/triggers/common.ts b/packages/functions/src/triggers/common.ts index aacc45044c..33fd6907d5 100644 --- a/packages/functions/src/triggers/common.ts +++ b/packages/functions/src/triggers/common.ts @@ -1,11 +1,11 @@ +import { BaseRecord } from '@build-5/database'; import { COL, SUB_COL } from '@build-5/interfaces'; -export interface FirestoreDocEvent { - prev?: T; +export interface PgDocEvent { + prev: T; curr?: T; - path: string; col: COL; - docId: string; + uid: string; subCol?: SUB_COL; - subDocId?: string; + subColId?: string; } diff --git a/packages/functions/src/triggers/milestone-transactions-triggers/MilestoneTransactionAdapter.ts b/packages/functions/src/triggers/milestone-transactions-triggers/MilestoneTransactionAdapter.ts index 9b3bc3a214..831dde3c64 100644 --- a/packages/functions/src/triggers/milestone-transactions-triggers/MilestoneTransactionAdapter.ts +++ b/packages/functions/src/triggers/milestone-transactions-triggers/MilestoneTransactionAdapter.ts @@ -1,9 +1,5 @@ -import { - MilestoneTransaction, - MilestoneTransactionEntry, - Network, - Timestamp, -} from '@build-5/interfaces'; +import { MilestoneTransactions } from '@build-5/database'; +import { MilestoneTransaction, MilestoneTransactionEntry, Network } from '@build-5/interfaces'; import { BasicOutput, FeatureType, @@ -27,10 +23,10 @@ export class MilestoneTransactionAdapter { constructor(private readonly network: Network) {} public toMilestoneTransaction = async ( - data: Record, + data: MilestoneTransactions, ): Promise => { const wallet = await WalletService.newWallet(this.network); - const payload = data.payload as TransactionPayload; + const payload = data.payload as unknown as TransactionPayload; const essence = payload.essence as RegularTransactionEssence; const outputs = essence.outputs .filter((o) => VALID_OUTPUTS_TYPES.includes(o.type)) @@ -72,7 +68,7 @@ export class MilestoneTransactionAdapter { fromAddresses.push(senderBech32); } - const build5TransactionId = await getMilestoneTransactionId(data); + const build5TransactionId = getMilestoneTransactionId(data); const consumedOutputIds = essence.inputs.map((i) => { const { transactionId, transactionOutputIndex } = i as UTXOInput; @@ -81,9 +77,9 @@ export class MilestoneTransactionAdapter { return { uid: data.uid as string, - createdOn: data.createdOn as Timestamp, + createdOn: data.createdOn!, messageId: data.blockId as string, - milestone: data.milestone as number, + milestone: data.milestone!, consumedOutputIds, fromAddresses, outputs: entries, diff --git a/packages/functions/src/triggers/milestone-transactions-triggers/common.ts b/packages/functions/src/triggers/milestone-transactions-triggers/common.ts index 45ff1f6d0f..94399f6762 100644 --- a/packages/functions/src/triggers/milestone-transactions-triggers/common.ts +++ b/packages/functions/src/triggers/milestone-transactions-triggers/common.ts @@ -1,5 +1,5 @@ -import { build5Db } from '@build-5/database'; -import { COL, NetworkAddress, Transaction } from '@build-5/interfaces'; +import { MilestoneTransactions, build5Db } from '@build-5/database'; +import { COL, NetworkAddress } from '@build-5/interfaces'; import { RegularTransactionEssence, TaggedDataPayload, @@ -11,23 +11,23 @@ import { isEmpty } from 'lodash'; export const confirmTransaction = async ( milestoneTransactionPath: string, - milestoneTransaction: Record, + milestoneTransaction: MilestoneTransactions, ) => { - const transactionId = await getMilestoneTransactionId(milestoneTransaction); + const transactionId = getMilestoneTransactionId(milestoneTransaction); if (isEmpty(transactionId)) { return; } - const docRef = build5Db().doc(`${COL.TRANSACTION}/${transactionId}`); - const transaction = await docRef.get(); + const docRef = build5Db().doc(COL.TRANSACTION, transactionId); + const transaction = await docRef.get(); if (!transaction) { return; } await docRef.update({ - 'payload.walletReference.confirmed': true, - 'payload.walletReference.confirmedOn': dayjs().toDate(), - 'payload.walletReference.inProgress': false, - 'payload.walletReference.milestoneTransactionPath': milestoneTransactionPath, + payload_walletReference_confirmed: true, + payload_walletReference_confirmedOn: dayjs().toDate(), + payload_walletReference_inProgress: false, + payload_walletReference_milestoneTransactionPath: milestoneTransactionPath, }); await unclockMnemonic(transaction.payload.sourceAddress); @@ -39,7 +39,7 @@ export const unclockMnemonic = async (address: NetworkAddress | undefined) => { if (isEmpty(address)) { return; } - await build5Db().doc(`${COL.MNEMONIC}/${address}`).update({ + await build5Db().doc(COL.MNEMONIC, address!).update({ lockedBy: '', consumedOutputIds: [], consumedNftOutputIds: [], @@ -47,9 +47,9 @@ export const unclockMnemonic = async (address: NetworkAddress | undefined) => { }); }; -export const getMilestoneTransactionId = async (milestoneTransaction: Record) => { +export const getMilestoneTransactionId = (milestoneTransaction: MilestoneTransactions) => { try { - const payload = milestoneTransaction.payload; + const payload = milestoneTransaction.payload as unknown as TransactionPayload; const essence = payload.essence as RegularTransactionEssence; const hexData = (essence?.payload as TaggedDataPayload)?.data || ''; const metadata = JSON.parse(hexToUtf8(hexData)); diff --git a/packages/functions/src/triggers/milestone-transactions-triggers/consumed.vote.outputs.ts b/packages/functions/src/triggers/milestone-transactions-triggers/consumed.vote.outputs.ts index b91fc716df..08d2627602 100644 --- a/packages/functions/src/triggers/milestone-transactions-triggers/consumed.vote.outputs.ts +++ b/packages/functions/src/triggers/milestone-transactions-triggers/consumed.vote.outputs.ts @@ -1,39 +1,35 @@ -import { build5Db } from '@build-5/database'; -import { COL, Proposal, SUB_COL, Transaction, TransactionType } from '@build-5/interfaces'; +import { PgProposalUpdate, PgTransactionType, build5Db } from '@build-5/database'; +import { COL, Proposal, SUB_COL } from '@build-5/interfaces'; import dayjs from 'dayjs'; import { getTokenVoteMultiplier } from '../../services/payment/voting-service'; -import { serverTime } from '../../utils/dateTime.utils'; export const processConsumedVoteOutputs = async (consumedOutputIds: string[]) => { const batch = build5Db().batch(); for (const consumedOutput of consumedOutputIds) { const voteTransactionSnap = await build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.VOTE) - .where('payload.outputId', '==', consumedOutput) - .where('payload.outputConsumed', '==', false) + .where('type', '==', PgTransactionType.VOTE) + .where('payload_outputId', '==', consumedOutput) + .where('payload_outputConsumed', '==', false) .limit(1) - .get(); + .get(); if (!voteTransactionSnap.length) { continue; } - const voteTransactionDocRef = build5Db().doc( - `${COL.TRANSACTION}/${voteTransactionSnap[0].uid}`, - ); + const voteTransactionDocRef = build5Db().doc(COL.TRANSACTION, voteTransactionSnap[0].uid); const voteTransaction = voteTransactionSnap[0]; - const proposalDocRef = build5Db().doc(`${COL.PROPOSAL}/${voteTransaction.payload.proposalId}`); + const proposalDocRef = build5Db().doc(COL.PROPOSAL, voteTransaction.payload.proposalId!); const proposal = await proposalDocRef.get(); + if (dayjs().isAfter(proposal.settings.endDate.toDate())) { batch.update(voteTransactionDocRef, { - 'payload.outputConsumed': true, - 'payload.outputConsumedOn': serverTime(), + payload_outputConsumed: true, + payload_outputConsumedOn: dayjs().toDate(), }); continue; } - const prevWeight = voteTransaction.payload.weight!; - const currWeightMultiplier = getTokenVoteMultiplier( proposal, dayjs(voteTransaction.createdOn?.toDate()), @@ -42,42 +38,31 @@ export const processConsumedVoteOutputs = async (consumedOutputIds: string[]) => const currWeight = voteTransaction.payload.tokenAmount! * currWeightMultiplier; const value = voteTransaction.payload.values![0]; - const data = { + const data: PgProposalUpdate = { results: { total: build5Db().inc(-prevWeight + currWeight), voted: build5Db().inc(-prevWeight + currWeight), - answers: { [value]: build5Db().inc(-prevWeight + currWeight) }, + answers: { [value.toString()]: build5Db().inc(-prevWeight + currWeight) }, }, }; - batch.set(proposalDocRef, data, true); + batch.update(proposalDocRef, data); - batch.update(voteTransactionDocRef, { - 'payload.weight': currWeight, - 'payload.weightMultiplier': currWeightMultiplier, - 'payload.outputConsumed': true, - 'payload.outputConsumedOn': serverTime(), - }); - - const proposalMemberDocRef = proposalDocRef - .collection(SUB_COL.MEMBERS) - .doc(voteTransaction.member!); - batch.set( - proposalMemberDocRef, - { - values: build5Db().arrayRemove({ - [value]: prevWeight, - voteTransaction: voteTransaction.uid, - }), - voteTransactions: build5Db().inc(-1), - weightPerAnswer: { [value]: build5Db().inc(-prevWeight + currWeight) }, - }, - true, + const proposalMemberDocRef = build5Db().doc( + COL.PROPOSAL, + voteTransaction.payload.proposalId!, + SUB_COL.MEMBERS, + voteTransaction.member!, ); batch.update(proposalMemberDocRef, { - values: build5Db().arrayUnion({ - [value]: currWeight, - voteTransaction: voteTransaction.uid, - }), + weight: build5Db().inc(-prevWeight + currWeight), + values: { [voteTransaction.uid]: { weight: build5Db().inc(-prevWeight + currWeight) } }, + }); + + batch.update(voteTransactionDocRef, { + payload_weight: currWeight, + payload_weightMultiplier: currWeightMultiplier, + payload_outputConsumed: true, + payload_outputConsumedOn: dayjs().toDate(), }); } await batch.commit(); diff --git a/packages/functions/src/triggers/milestone-transactions-triggers/milestone-transaction.trigger.ts b/packages/functions/src/triggers/milestone-transactions-triggers/milestone-transaction.trigger.ts index 733216b642..f50906a59b 100644 --- a/packages/functions/src/triggers/milestone-transactions-triggers/milestone-transaction.trigger.ts +++ b/packages/functions/src/triggers/milestone-transactions-triggers/milestone-transaction.trigger.ts @@ -1,42 +1,47 @@ -import { build5Db } from '@build-5/database'; -import { Network } from '@build-5/interfaces'; +import { PgMilestoneTransactions, build5Db } from '@build-5/database'; +import { COL, Network, SUB_COL } from '@build-5/interfaces'; import dayjs from 'dayjs'; import { ProcessingService } from '../../services/payment/payment-processing'; -import { FirestoreDocEvent } from '../common'; +import { PgDocEvent } from '../common'; import { MilestoneTransactionAdapter } from './MilestoneTransactionAdapter'; import { confirmTransaction } from './common'; import { processConsumedVoteOutputs } from './consumed.vote.outputs'; import { updateTokenSupplyData } from './token.foundry'; export const handleMilestoneTransactionWrite = - (network: Network) => async (event: FirestoreDocEvent>) => { + // eslint-disable-next-line require-await + (network: Network) => async (event: PgDocEvent) => { const { curr } = event; if (!curr) { return; } + const path = `${event.col}/${event.subColId}/${event.subCol!}/${event.uid}`; try { return build5Db().runTransaction(async (transaction) => { - const docRef = build5Db().doc(event.path); - const data = await transaction.get>(docRef); - if (!data || data.processed) { + const docRef = build5Db().doc( + event.col as COL.MILESTONE, + event.subColId!, + event.subCol! as SUB_COL.TRANSACTIONS, + event.uid, + ); + const milestoneTran = await transaction.get(docRef); + if (!milestoneTran || milestoneTran.processed) { return; } - await confirmTransaction(event.path, data); - await updateTokenSupplyData(data); + await confirmTransaction(path, milestoneTran); + await updateTokenSupplyData(milestoneTran); const adapter = new MilestoneTransactionAdapter(network); - const milestoneTransaction = await adapter.toMilestoneTransaction({ - ...data, - uid: event.subDocId, - }); + const milestoneTransaction = await adapter.toMilestoneTransaction(milestoneTran); const service = new ProcessingService(transaction); await service.processMilestoneTransactions(milestoneTransaction); - service.submit(); + await service.submit(); await processConsumedVoteOutputs(milestoneTransaction.consumedOutputIds); return transaction.update(docRef, { processed: true, processedOn: dayjs().toDate() }); }); } catch (error) { - console.error(`${network} transaction error`, event.path, error); + console.error(`${network} transaction error`, path, error); + return; } }; diff --git a/packages/functions/src/triggers/milestone-transactions-triggers/token.foundry.ts b/packages/functions/src/triggers/milestone-transactions-triggers/token.foundry.ts index a5638a4d4b..cffe591b5d 100644 --- a/packages/functions/src/triggers/milestone-transactions-triggers/token.foundry.ts +++ b/packages/functions/src/triggers/milestone-transactions-triggers/token.foundry.ts @@ -1,4 +1,4 @@ -import { build5Db } from '@build-5/database'; +import { MilestoneTransactions, build5Db } from '@build-5/database'; import { COL } from '@build-5/interfaces'; import { AddressUnlockCondition, @@ -13,9 +13,9 @@ import { } from '@iota/sdk'; import { getTokenByMintId } from '../../utils/token.utils'; -export const updateTokenSupplyData = async (data: Record) => { +export const updateTokenSupplyData = async (data: MilestoneTransactions) => { const foundryOutputs = ( - (data.payload as TransactionPayload).essence as RegularTransactionEssence + (data.payload as unknown as TransactionPayload).essence as RegularTransactionEssence ).outputs .filter((o) => o.type === OutputType.Foundry) .map((o) => o); @@ -32,10 +32,10 @@ export const updateTokenSupplyData = async (data: Record) => { const tokenScheme = foundryOutput.tokenScheme as SimpleTokenScheme; const meltedTokens = Number(tokenScheme.meltedTokens); const totalSupply = Number(tokenScheme.maximumSupply); - const tokendDocRef = build5Db().doc(`${COL.TOKEN}/${token.uid}`); + const tokendDocRef = build5Db().doc(COL.TOKEN, token.uid); await tokendDocRef.update({ - 'mintingData.meltedTokens': meltedTokens, - 'mintingData.circulatingSupply': totalSupply - meltedTokens, + mintingData_meltedTokens: meltedTokens, + mintingData_circulatingSupply: totalSupply - meltedTokens, }); } }; diff --git a/packages/functions/src/triggers/mnemonic.trigger.ts b/packages/functions/src/triggers/mnemonic.trigger.ts index 52ba987170..3499de1177 100644 --- a/packages/functions/src/triggers/mnemonic.trigger.ts +++ b/packages/functions/src/triggers/mnemonic.trigger.ts @@ -1,31 +1,25 @@ -import { build5Db } from '@build-5/database'; -import { COL, MAX_WALLET_RETRY, Mnemonic, NetworkAddress, Transaction } from '@build-5/interfaces'; +import { PgMnemonic, PgTransactionType, build5Db, convertEnum } from '@build-5/database'; +import { COL, MAX_WALLET_RETRY, NetworkAddress, TransactionType } from '@build-5/interfaces'; import { chunk, isEmpty } from 'lodash'; -import { FirestoreDocEvent } from './common'; +import { PgDocEvent } from './common'; import { CREDIT_EXECUTABLE_TRANSACTIONS, DEFAULT_EXECUTABLE_TRANSACTIONS, } from './transaction-trigger/transaction.trigger'; -enum FieldNameType { - SOURCE_ADDRESS = 'payload.sourceAddress', - STORAGE_DEP_ADDRESS = 'payload.storageDepositSourceAddress', - ALIAS_GOV_ADDRESS = 'payload.aliasGovAddress', -} - -export const onMnemonicUpdated = async (event: FirestoreDocEvent) => { +export const onMnemonicUpdated = async (event: PgDocEvent) => { const { prev, curr } = event; if (!prev || !curr || isEmpty(prev?.lockedBy) || !isEmpty(curr?.lockedBy)) { return; } - const address = event.docId; + const address = event.uid; const tranId = await getUncofirmedTransactionsId(address); if (!isEmpty(tranId)) { await build5Db() - .doc(`${COL.TRANSACTION}/${tranId}`) - .update({ shouldRetry: true, 'payload.walletReference.inProgress': false }); + .doc(COL.TRANSACTION, tranId!) + .update({ shouldRetry: true, payload_walletReference_inProgress: false }); } }; @@ -37,12 +31,19 @@ const getUncofirmedTransactionsId = async (address: NetworkAddress) => { for (const types of TYPE_CHUNKS) { const transactions = await build5Db() .collection(COL.TRANSACTION) - .or(Object.values(FieldNameType).map((fieldPath) => ({ fieldPath, value: address }))) - .where('type', 'in', types) - .where('payload.walletReference.confirmed', '==', false) - .where('payload.walletReference.count', '<', MAX_WALLET_RETRY) + .where('payload_walletReference_confirmed', '==', false) + .whereIn( + 'type', + types.map((t) => convertEnum(t, TransactionType, PgTransactionType)!), + ) + .whereOr({ + payload_sourceAddress: address, + payload_storageDepositSourceAddress: address, + payload_aliasGovAddress: address, + }) + .where('payload_walletReference_count', '<', MAX_WALLET_RETRY) .limit(1) - .get(); + .get(); if (transactions.length) { return transactions[0].uid; } diff --git a/packages/functions/src/triggers/nft.trigger.ts b/packages/functions/src/triggers/nft.trigger.ts index 8b2c45b475..a07bd3c46b 100644 --- a/packages/functions/src/triggers/nft.trigger.ts +++ b/packages/functions/src/triggers/nft.trigger.ts @@ -1,9 +1,9 @@ -import { build5Db } from '@build-5/database'; -import { COL, Collection, MediaStatus, Nft, NftAvailable } from '@build-5/interfaces'; +import { PgMediaStatus, PgNft, PgNftAvailable, build5Db, convertEnum } from '@build-5/database'; +import { COL, NftAvailable } from '@build-5/interfaces'; import { downloadMediaAndPackCar, nftToIpfsMetadata } from '../utils/car.utils'; -import { FirestoreDocEvent } from './common'; +import { PgDocEvent } from './common'; -const getNftAvailability = (nft: Nft | undefined) => { +const getNftAvailability = (nft: PgNft | undefined) => { if (!nft || nft.placeholderNft) { return NftAvailable.UNAVAILABLE; } @@ -19,7 +19,7 @@ const getNftAvailability = (nft: Nft | undefined) => { return NftAvailable.UNAVAILABLE; }; -export const onNftWrite = async (event: FirestoreDocEvent) => { +export const onNftWrite = async (event: PgDocEvent) => { const { prev, curr } = event; if (!curr) { return; @@ -35,42 +35,42 @@ export const onNftWrite = async (event: FirestoreDocEvent) => { ); const availableNfts = getAvailableNftsChange(prevAvailability, currAvailability, prev?.owner); - const collectionDocRef = build5Db().doc(`${COL.COLLECTION}/${curr.collection}`); + const collectionDocRef = build5Db().doc(COL.COLLECTION, curr.collection!); await collectionDocRef.update({ nftsOnSale: build5Db().inc(nftsOnSale), nftsOnAuction: build5Db().inc(nftsOnAuction), availableNfts: build5Db().inc(availableNfts), }); - const docRef = build5Db().doc(event.path); - await docRef.update({ available: currAvailability }); + const docRef = build5Db().doc(COL.NFT, curr.uid); + await docRef.update({ available: convertEnum(currAvailability, NftAvailable, PgNftAvailable) }); } - if (prev?.mediaStatus !== curr.mediaStatus && curr.mediaStatus === MediaStatus.PREPARE_IPFS) { + if (prev?.mediaStatus !== curr.mediaStatus && curr.mediaStatus === PgMediaStatus.PREPARE_IPFS) { await prepareNftMedia(curr); } }; -const prepareNftMedia = async (nft: Nft) => { - const collectionDocRef = build5Db().doc(`${COL.COLLECTION}/${nft.collection}`); - const nftDocRef = build5Db().doc(`${COL.NFT}/${nft.uid}`); +const prepareNftMedia = async (nft: PgNft) => { + const collectionDocRef = build5Db().doc(COL.COLLECTION, nft.collection!); + const nftDocRef = build5Db().doc(COL.NFT, nft.uid); const batch = build5Db().batch(); if (nft.ipfsRoot) { - batch.update(nftDocRef, { mediaStatus: MediaStatus.PENDING_UPLOAD }); + batch.update(nftDocRef, { mediaStatus: PgMediaStatus.PENDING_UPLOAD }); } else { - const collection = (await collectionDocRef.get())!; + const collection = (await collectionDocRef.get())!; const metadata = nftToIpfsMetadata(collection, nft); - const ipfs = await downloadMediaAndPackCar(nft.uid, nft.media, metadata); + const ipfs = await downloadMediaAndPackCar(nft.uid, nft.media!, metadata); batch.update(nftDocRef, { - mediaStatus: MediaStatus.PENDING_UPLOAD, + mediaStatus: PgMediaStatus.PENDING_UPLOAD, ipfsMedia: ipfs.ipfsMedia, ipfsMetadata: ipfs.ipfsMetadata, ipfsRoot: ipfs.ipfsRoot, }); } - batch.update(collectionDocRef, { 'mintingData.nftMediaToPrepare': build5Db().inc(-1) }); + batch.update(collectionDocRef, { mintingData_nftMediaToPrepare: build5Db().inc(-1) }); await batch.commit(); }; diff --git a/packages/functions/src/triggers/proposal.trigger.ts b/packages/functions/src/triggers/proposal.trigger.ts index abd9a9e7a6..a1df053bbf 100644 --- a/packages/functions/src/triggers/proposal.trigger.ts +++ b/packages/functions/src/triggers/proposal.trigger.ts @@ -1,33 +1,31 @@ -import { build5Db } from '@build-5/database'; +import { + build5Db, + PgProposal, + PgProposalType, + PgStakeRewardStatus, + removeNulls, +} from '@build-5/database'; import { ADD_REMOVE_GUARDIAN_THRESHOLD_PERCENTAGE, BaseProposalAnswerValue, COL, MediaStatus, - Member, - Proposal, - ProposalType, REMOVE_STAKE_REWARDS_THRESHOLD_PERCENTAGE, - Space, - SpaceGuardian, - SpaceMember, - StakeRewardStatus, StakeType, SUB_COL, - TokenDistribution, UPDATE_SPACE_THRESHOLD_PERCENTAGE, } from '@build-5/interfaces'; import dayjs from 'dayjs'; -import { get, set } from 'lodash'; +import { get, head, set } from 'lodash'; import { getStakeForType } from '../services/stake.service'; import { downloadMediaAndPackCar } from '../utils/car.utils'; -import { dateToTimestamp } from '../utils/dateTime.utils'; import { spaceToIpfsMetadata } from '../utils/space.utils'; import { getTokenForSpace } from '../utils/token.utils'; -import { FirestoreDocEvent } from './common'; +import { PgDocEvent } from './common'; -export const onProposalWrite = async (event: FirestoreDocEvent) => { +export const onProposalWrite = async (event: PgDocEvent) => { const { prev, curr } = event; + if (!curr) { return; } @@ -40,64 +38,72 @@ export const onProposalWrite = async (event: FirestoreDocEvent) => { } if ( - curr.type === ProposalType.EDIT_SPACE && + curr.type === PgProposalType.EDIT_SPACE && voteThresholdReached(prev, curr, UPDATE_SPACE_THRESHOLD_PERCENTAGE) ) { return await onEditSpaceProposalApproved(curr); } if ( - curr.type === ProposalType.REMOVE_STAKE_REWARD && + curr.type === PgProposalType.REMOVE_STAKE_REWARD && voteThresholdReached(prev, curr, REMOVE_STAKE_REWARDS_THRESHOLD_PERCENTAGE) ) { return await onRemoveStakeRewardApporved(curr); } }; -const isAddRemoveGuardianVote = (curr: Proposal) => - [ProposalType.ADD_GUARDIAN, ProposalType.REMOVE_GUARDIAN].includes(curr.type); +const isAddRemoveGuardianVote = (curr: PgProposal) => + [PgProposalType.ADD_GUARDIAN, PgProposalType.REMOVE_GUARDIAN].includes(curr.type!); -const voteThresholdReached = (prev: Proposal | undefined, curr: Proposal, threshold: number) => { +const voteThresholdReached = ( + prev: PgProposal | undefined, + curr: PgProposal, + threshold: number, +) => { + const prevAnswers = prev?.results?.answers as Record | undefined; const prevAnsweredPercentage = - ((prev?.results?.answers[BaseProposalAnswerValue.YES] || 0) * 100) / - (prev?.results?.total || 1); + ((prevAnswers?.[BaseProposalAnswerValue.YES] || 0) * 100) / Number(prev?.results?.total || 1); + + const currAnswers = curr.results?.answers as Record | undefined; const currAnsweredPercentage = - ((curr.results?.answers[BaseProposalAnswerValue.YES] || 0) * 100) / (curr.results?.total || 1); + ((currAnswers?.[BaseProposalAnswerValue.YES] || 0) * 100) / Number(curr.results?.total || 1); return prevAnsweredPercentage <= threshold && currAnsweredPercentage > threshold; }; -const onAddRemoveGuardianProposalApproved = async (proposal: Proposal) => { - const spaceDocRef = build5Db().doc(`${COL.SPACE}/${proposal.space}`); - const guardianDocRef = spaceDocRef - .collection(SUB_COL.GUARDIANS) - .doc(proposal.settings.addRemoveGuardian!); - const isAddGuardian = proposal.type === ProposalType.ADD_GUARDIAN; +const onAddRemoveGuardianProposalApproved = async (proposal: PgProposal) => { + const spaceDocRef = build5Db().doc(COL.SPACE, proposal.space!); + const guardianDocRef = build5Db().doc( + COL.SPACE, + proposal.space!, + SUB_COL.GUARDIANS, + proposal.settings_addRemoveGuardian!, + ); + const isAddGuardian = proposal.type === PgProposalType.ADD_GUARDIAN; const batch = build5Db().batch(); if (isAddGuardian) { - batch.set(guardianDocRef, { - uid: proposal.settings.addRemoveGuardian, + batch.upsert(guardianDocRef, { parentId: proposal.space, - parentCol: COL.SPACE, }); } else { batch.delete(guardianDocRef); } batch.update(spaceDocRef, { totalGuardians: build5Db().inc(isAddGuardian ? 1 : -1) }); - const proposalDocRef = build5Db().doc(`${COL.PROPOSAL}/${proposal.uid}`); + const proposalDocRef = build5Db().doc(COL.PROPOSAL, proposal.uid); batch.update(proposalDocRef, { - 'settings.endDate': dateToTimestamp(dayjs().subtract(1, 's')), + settings_endDate: dayjs().subtract(1, 's').toDate(), completed: true, }); await batch.commit(); }; -const onEditSpaceProposalApproved = async (proposal: Proposal) => { - const spaceUpdateData = proposal.settings.spaceUpdateData!; - const spaceDocRef = build5Db().doc(`${COL.SPACE}/${spaceUpdateData.uid}`); +const onEditSpaceProposalApproved = async (proposal: PgProposal) => { + const spaceUpdateData = proposal.settings_spaceUpdateData!; + const spaceId = spaceUpdateData.uid! as string; + const spaceDocRef = build5Db().doc(COL.SPACE, spaceId); if (spaceUpdateData.bannerUrl) { - const space = (await spaceDocRef.get())!; + const space = (await spaceDocRef.get())!; const metadata = spaceToIpfsMetadata({ ...space, ...spaceUpdateData }); const ipfs = await downloadMediaAndPackCar( space.uid, @@ -111,36 +117,43 @@ const onEditSpaceProposalApproved = async (proposal: Proposal) => { } if (spaceUpdateData.open) { - const knockingMembersSnap = await spaceDocRef - .collection(SUB_COL.KNOCKING_MEMBERS) - .get(); + const knockingMembersSnap = await build5Db() + .collection(COL.SPACE, spaceId, SUB_COL.KNOCKING_MEMBERS) + .get(); const deleteKnockingMemberPromise = knockingMembersSnap.map((kMember) => - spaceDocRef.collection(SUB_COL.KNOCKING_MEMBERS).doc(kMember.uid).delete(), + build5Db().doc(COL.SPACE, spaceId, SUB_COL.KNOCKING_MEMBERS, kMember.uid).delete(), ); await Promise.all(deleteKnockingMemberPromise); } const { removedMembers, removedGuardians } = await removeMembersAndGuardiansThatDontHaveEnoughStakes(spaceUpdateData); - const updateData = spaceUpdateData.open - ? { ...spaceUpdateData, totalPendingMembers: 0 } - : spaceUpdateData; - const prevValidatedAddresses = get(updateData, 'prevValidatedAddresses'); - if (prevValidatedAddresses) { - set(updateData, 'prevValidatedAddresses', build5Db().arrayUnion(prevValidatedAddresses)); - } - await spaceDocRef.set( - { - ...updateData, - totalMembers: build5Db().inc(-removedMembers), - totalGuardians: build5Db().inc(-removedGuardians), - }, - true, + + const updateData = removeNulls( + spaceDocRef.converter.toPg( + spaceUpdateData.open + ? { ...spaceUpdateData, totalPendingMembers: 0 } + : // eslint-disable-next-line @typescript-eslint/no-explicit-any + (spaceUpdateData as any), + ), ); + const prevValidatedAddress = head(get(updateData, 'prevValidatedAddresses', [])); + if (prevValidatedAddress) { + set(updateData, 'prevValidatedAddresses', build5Db().arrayUnion(prevValidatedAddress)); + } else { + delete updateData.prevValidatedAddresses; + } + + await spaceDocRef.upsert({ + ...updateData, + totalMembers: build5Db().inc(-removedMembers), + totalGuardians: build5Db().inc(-removedGuardians), + }); + await build5Db() - .doc(`${COL.PROPOSAL}/${proposal.uid}`) + .doc(COL.PROPOSAL, proposal.uid) .update({ - 'settings.endDate': dateToTimestamp(dayjs().subtract(1, 's')), + settings_endDate: dayjs().subtract(1, 's').toDate(), completed: true, }); }; @@ -151,14 +164,16 @@ const removeMembersAndGuardiansThatDontHaveEnoughStakes = async ( if (!updateData.tokenBased) { return { removedMembers: 0, removedGuardians: 0 }; } - const spaceDocRef = build5Db().doc(`${COL.SPACE}/${updateData.uid}`); - const space = (await spaceDocRef.get())!; + const spaceDocRef = build5Db().doc(COL.SPACE, updateData.uid! as string); + const space = (await spaceDocRef.get())!; const token = await getTokenForSpace(space.uid); let removedMembers = 0; let removedGuardians = 0; - const membersSnap = await spaceDocRef.collection(SUB_COL.MEMBERS).get(); + const membersSnap = await build5Db() + .collection(COL.SPACE, updateData.uid! as string, SUB_COL.MEMBERS) + .get(); for (const member of membersSnap) { if (space.totalMembers - removedMembers === 1) { @@ -171,9 +186,16 @@ const removeMembersAndGuardiansThatDontHaveEnoughStakes = async ( ); if (!hasEnoughStaked) { removedMembers++; - await spaceDocRef.collection(SUB_COL.MEMBERS).doc(member.uid).delete(); - const guardianDocRef = spaceDocRef.collection(SUB_COL.GUARDIANS).doc(member.uid); - const guardian = await guardianDocRef.get(); + await build5Db() + .doc(COL.SPACE, updateData.uid! as string, SUB_COL.MEMBERS, member.uid) + .delete(); + const guardianDocRef = build5Db().doc( + COL.SPACE, + updateData.uid! as string, + SUB_COL.GUARDIANS, + member.uid, + ); + const guardian = await guardianDocRef.get(); if (guardian) { await guardianDocRef.delete(); removedGuardians++; @@ -185,26 +207,24 @@ const removeMembersAndGuardiansThatDontHaveEnoughStakes = async ( }; const memberHasEnoughStakedValues = async (token: string, member: string, minStaked: number) => { - const distributionDocRef = build5Db().doc( - `${COL.TOKEN}/${token}/${SUB_COL.DISTRIBUTION}/${member}`, - ); - const distribution = await distributionDocRef.get(); + const distributionDocRef = build5Db().doc(COL.TOKEN, token, SUB_COL.DISTRIBUTION, member); + const distribution = await distributionDocRef.get(); const stakedValue = getStakeForType(distribution, StakeType.DYNAMIC); return stakedValue > minStaked; }; -const onRemoveStakeRewardApporved = async (proposal: Proposal) => { +const onRemoveStakeRewardApporved = async (proposal: PgProposal) => { const batch = build5Db().batch(); - const stakeRewardIds = proposal.settings.stakeRewardIds || []; - stakeRewardIds.forEach((rewardId) => { - const docRef = build5Db().doc(`${COL.STAKE_REWARD}/${rewardId}`); - batch.update(docRef, { status: StakeRewardStatus.DELETED }); - }); + const stakeRewardIds = proposal.settings_stakeRewardIds || []; + for (const rewardId of stakeRewardIds) { + const docRef = build5Db().doc(COL.STAKE_REWARD, rewardId); + batch.update(docRef, { status: PgStakeRewardStatus.DELETED }); + } - const proposalDocRef = build5Db().doc(`${COL.PROPOSAL}/${proposal.uid}`); + const proposalDocRef = build5Db().doc(COL.PROPOSAL, proposal.uid); batch.update(proposalDocRef, { - 'settings.endDate': dateToTimestamp(dayjs().subtract(1, 's')), + settings_endDate: dayjs().subtract(1, 's').toDate(), completed: true, }); 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 5f2d0a8f16..48ff1fcb98 100644 --- a/packages/functions/src/triggers/token-trading/match-base-token.ts +++ b/packages/functions/src/triggers/token-trading/match-base-token.ts @@ -3,7 +3,6 @@ import { COL, Entity, Member, - Space, Token, TokenPurchaseAge, TokenTradeOrder, @@ -39,9 +38,7 @@ const createIotaPayments = async ( if (balance !== 0 && balance < Number(remainder.amount)) { return []; } - const sellOrder = await build5Db() - .doc(`${COL.TRANSACTION}/${sell.orderTransactionId}`) - .get(); + const sellOrder = await build5Db().doc(COL.TRANSACTION, sell.orderTransactionId!).get(); const billPayment: Transaction = { project: getProject(sell), type: TransactionType.BILL_PAYMENT, @@ -105,7 +102,7 @@ const createRoyaltyPayment = async ( spaceId: string, fee: number, ) => { - const space = (await build5Db().doc(`${COL.SPACE}/${spaceId}`).get())!; + const space = (await build5Db().doc(COL.SPACE, spaceId).get())!; const spaceAddress = getAddress(space, buy.sourceNetwork!); const sellerAddress = getAddress(seller, buy.sourceNetwork!); const output = await packBasicOutput(wallet, spaceAddress, 0, { @@ -151,9 +148,7 @@ const createSmrPayments = async ( ): Promise => { const wallet = await WalletService.newWallet(buy.sourceNetwork!); const tmpAddress = await wallet.getNewIotaAddressDetails(false); - const buyOrder = await build5Db() - .doc(`${COL.TRANSACTION}/${buy.orderTransactionId}`) - .get(); + const buyOrder = await build5Db().doc(COL.TRANSACTION, buy.orderTransactionId!).get(); let salePrice = Number(bigDecimal.floor(bigDecimal.multiply(price, tokensToTrade))); let balanceLeft = buy.balance - salePrice; @@ -256,8 +251,8 @@ export const matchBaseToken = async ( buy.count - buy.fulfilled, Math.floor(buy.balance / price), ); - const seller = await build5Db().doc(`${COL.MEMBER}/${sell.owner}`).get(); - const buyer = await build5Db().doc(`${COL.MEMBER}/${buy.owner}`).get(); + 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, buy, seller!, buyer!, tokensToTrade); const smrPayments = await createSmrPayments( @@ -272,14 +267,14 @@ export const matchBaseToken = async ( if (isEmpty(iotaPayments) || isEmpty(smrPayments)) { return { sellerCreditId: undefined, buyerCreditId: undefined, purchase: undefined }; } - iotaPayments.forEach((payment) => { - const docRef = build5Db().doc(`${COL.TRANSACTION}/${payment.uid}`); - transaction.create(docRef, payment); - }); - smrPayments.forEach((payment) => { - const docRef = build5Db().doc(`${COL.TRANSACTION}/${payment.uid}`); - transaction.create(docRef, payment); - }); + for (const payment of iotaPayments) { + const docRef = build5Db().doc(COL.TRANSACTION, payment.uid); + await transaction.create(docRef, payment); + } + for (const payment of smrPayments) { + const docRef = build5Db().doc(COL.TRANSACTION, payment.uid); + await transaction.create(docRef, payment); + } return { sellerCreditId: iotaPayments.find((o) => o.type === TransactionType.CREDIT)?.uid, buyerCreditId: smrPayments.find((o) => o.type === TransactionType.CREDIT)?.uid, 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 50f80fdf14..b4856ca6fe 100644 --- a/packages/functions/src/triggers/token-trading/match-minted-token.ts +++ b/packages/functions/src/triggers/token-trading/match-minted-token.ts @@ -3,7 +3,6 @@ import { COL, Entity, Member, - Space, Token, TokenPurchaseAge, TokenTradeOrder, @@ -39,7 +38,7 @@ const createRoyaltyBillPayments = async ( const promises = Object.entries(royaltyFees) .filter((entry) => entry[1] > 0) .map(async ([spaceId, fee]): Promise => { - const space = await build5Db().doc(`${COL.SPACE}/${spaceId}`).get(); + 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 = await packBasicOutput(wallet, spaceAddress, 0, { @@ -238,15 +237,11 @@ export const matchMintedToken = async ( ): Promise => { const wallet = await WalletService.newWallet(token.mintingData?.network!); - const seller = (await build5Db().doc(`${COL.MEMBER}/${sell.owner}`).get())!; - const buyer = (await build5Db().doc(`${COL.MEMBER}/${buy.owner}`).get())!; + const seller = (await build5Db().doc(COL.MEMBER, sell.owner).get())!; + const buyer = (await build5Db().doc(COL.MEMBER, buy.owner).get())!; - const buyOrderTran = (await build5Db() - .doc(`${COL.TRANSACTION}/${buy.orderTransactionId}`) - .get())!; - const sellOrderTran = (await build5Db() - .doc(`${COL.TRANSACTION}/${sell.orderTransactionId}`) - .get())!; + const buyOrderTran = (await build5Db().doc(COL.TRANSACTION, buy.orderTransactionId!).get())!; + const sellOrderTran = (await build5Db().doc(COL.TRANSACTION, sell.orderTransactionId!).get())!; const tokensToTrade = Math.min( sell.count - sell.fulfilled, @@ -326,18 +321,17 @@ export const matchMintedToken = async ( ? createCreditToBuyer(token, buyer, buy, buyOrderTran, balanceLeft) : undefined; - [ + const payments = [ ...royaltyBillPayments, billPaymentToSeller, billPaymentWithNativeTokens, creditToSeller, creditToBuyer, - ] - .filter((t) => t !== undefined) - .forEach((data) => { - const docRef = build5Db().doc(`${COL.TRANSACTION}/${data!.uid}`); - transaction.create(docRef, data!); - }); + ].filter((t) => t !== undefined); + for (const data of payments) { + const docRef = build5Db().doc(COL.TRANSACTION, data!.uid); + await transaction.create(docRef, data!); + } return { purchase: { 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 cf095a8b24..a68cd89d2d 100644 --- a/packages/functions/src/triggers/token-trading/match-simple-token.ts +++ b/packages/functions/src/triggers/token-trading/match-simple-token.ts @@ -6,7 +6,6 @@ import { MIN_IOTA_AMOUNT, Member, SUB_COL, - Space, Token, TokenPurchaseAge, TokenTradeOrder, @@ -35,9 +34,7 @@ const createBuyPayments = async ( ) => { let salePrice = Number(bigDecimal.floor(bigDecimal.multiply(tokensToTrade, price))); const fulfilled = buy.fulfilled + tokensToTrade === buy.count; - const buyOrder = (await build5Db() - .doc(`${COL.TRANSACTION}/${buy.orderTransactionId}`) - .get())!; + const buyOrder = (await build5Db().doc(COL.TRANSACTION, buy.orderTransactionId!).get())!; const royaltyFees = await getRoyaltyFees(salePrice, seller.tokenTradingFeePercentage); let balanceLeft = buy.balance - salePrice; @@ -57,7 +54,7 @@ const createBuyPayments = async ( const royaltyPaymentPromises = Object.entries(royaltyFees) .filter((entry) => entry[1] > 0) .map(async ([space, fee]): Promise => { - const spaceData = await build5Db().doc(`${COL.SPACE}/${space}`).get(); + const spaceData = await build5Db().doc(COL.SPACE, space).get(); return { project: getProject(buy), type: TransactionType.BILL_PAYMENT, @@ -145,33 +142,33 @@ const createBuyPayments = async ( return [billPayment, ...royaltyPayments, credit]; }; -const updateSaleLock = ( +const updateSaleLock = async ( transaction: ITransaction, prev: TokenTradeOrder, sell: TokenTradeOrder, ) => { const diff = sell.fulfilled - prev.fulfilled; - const docRef = build5Db().doc(`${COL.TOKEN}/${sell.token}/${SUB_COL.DISTRIBUTION}/${sell.owner}`); + const docRef = build5Db().doc(COL.TOKEN, sell.token, SUB_COL.DISTRIBUTION, sell.owner); const data = { lockedForSale: build5Db().inc(-diff), sold: build5Db().inc(diff), tokenOwned: build5Db().inc(-diff), }; - transaction.set(docRef, data, true); + await transaction.upsert(docRef, data); }; -const updateBuyerDistribution = ( +const updateBuyerDistribution = async ( transaction: ITransaction, prev: TokenTradeOrder, buy: TokenTradeOrder, ) => { const diff = buy.fulfilled - prev.fulfilled; - const docRef = build5Db().doc(`${COL.TOKEN}/${buy.token}/${SUB_COL.DISTRIBUTION}/${buy.owner}`); + const docRef = build5Db().doc(COL.TOKEN, buy.token, SUB_COL.DISTRIBUTION, buy.owner); const data = { totalPurchased: build5Db().inc(diff), tokenOwned: build5Db().inc(diff), }; - transaction.set(docRef, data, true); + await transaction.upsert(docRef, data); }; export const matchSimpleToken = async ( @@ -184,8 +181,8 @@ export const matchSimpleToken = async ( ): Promise => { const tokensToTrade = Math.min(sell.count - sell.fulfilled, buy.count - buy.fulfilled); - const seller = (await build5Db().doc(`${COL.MEMBER}/${sell.owner}`).get())!; - const buyer = (await build5Db().doc(`${COL.MEMBER}/${buy.owner}`).get())!; + const seller = (await build5Db().doc(COL.MEMBER, sell.owner).get())!; + const buyer = (await build5Db().doc(COL.MEMBER, buy.owner).get())!; const buyerPayments = await createBuyPayments( token, buy, @@ -200,7 +197,7 @@ export const matchSimpleToken = async ( return { purchase: undefined, buyerCreditId: undefined, sellerCreditId: undefined }; } buyerPayments.forEach((p) => { - const docRef = build5Db().doc(`${COL.TRANSACTION}/${p.uid}`); + const docRef = build5Db().doc(COL.TRANSACTION, p.uid); return transaction.create(docRef, p); }); @@ -229,13 +226,13 @@ export const matchSimpleToken = async ( }; }; -export const updateSellLockAndDistribution = ( +export const updateSellLockAndDistribution = async ( transaction: ITransaction, prevBuy: TokenTradeOrder, buy: TokenTradeOrder, prevSell: TokenTradeOrder, sell: TokenTradeOrder, ) => { - updateSaleLock(transaction, prevSell, sell); - updateBuyerDistribution(transaction, prevBuy, buy); + await updateSaleLock(transaction, prevSell, sell); + await updateBuyerDistribution(transaction, prevBuy, buy); }; diff --git a/packages/functions/src/triggers/token-trading/match-token.ts b/packages/functions/src/triggers/token-trading/match-token.ts index ea0df2664a..1a698ea76e 100644 --- a/packages/functions/src/triggers/token-trading/match-token.ts +++ b/packages/functions/src/triggers/token-trading/match-token.ts @@ -1,6 +1,17 @@ -import { IQuery, ITransaction, build5Db, getSnapshot } from '@build-5/database'; +import { + IQuery, + ITransaction, + PgNetwork, + PgTokenMarket, + PgTokenStatus, + PgTokenTradeOrderStatus, + PgTokenTradeOrderType, + build5Db, + convertEnum, +} from '@build-5/database'; import { COL, + Network, Token, TokenPurchase, TokenStatus, @@ -10,7 +21,7 @@ import { } from '@build-5/interfaces'; import dayjs from 'dayjs'; import bigDecimal from 'js-big-decimal'; -import { cloneDeep, last } from 'lodash'; +import { cloneDeep } from 'lodash'; import { matchBaseToken } from './match-base-token'; import { matchMintedToken } from './match-minted-token'; import { matchSimpleToken, updateSellLockAndDistribution } from './match-simple-token'; @@ -21,7 +32,7 @@ export interface Match { readonly buyerCreditId: string | undefined; } -type Query = (trade: TokenTradeOrder, startAfter: string) => Promise; +type Query = (trade: TokenTradeOrder) => IQuery; type Matcher = ( transaction: ITransaction, token: Token, @@ -36,60 +47,39 @@ type PostMatchAction = ( buy: TokenTradeOrder, prevSell: TokenTradeOrder, sell: TokenTradeOrder, -) => void; +) => Promise; export const TOKEN_TRADE_ORDER_FETCH_LIMIT = 20; -export const matchTradeOrder = async (tradeOrder: TokenTradeOrder) => { - const token = (await build5Db().doc(`${COL.TOKEN}/${tradeOrder.token}`).get())!; +export const matchTradeOrder = async (tradeOrder: PgTokenMarket) => { + const token = (await build5Db().doc(COL.TOKEN, tradeOrder.token!).get())!; const query = getQuery(token); const matcher = getMatcher(token); const postMatchActions = getPostMatchActions(token); - let lastDocId = ''; - do { - lastDocId = await runTradeOrderMatching( - query, - matcher, - postMatchActions, - lastDocId, - token, - tradeOrder.uid, - ); - } while (lastDocId); - - if (tradeOrder.type === TokenTradeOrderType.BUY) { - do { - lastDocId = await runTradeOrderMatching( - query, - matcher, - postMatchActions, - lastDocId, - token, - tradeOrder.uid, - false, - ); - } while (lastDocId); + await runTradeOrderMatching(query, matcher, postMatchActions, token, tradeOrder.uid); + + if (tradeOrder.type === PgTokenTradeOrderType.BUY) { + await runTradeOrderMatching(query, matcher, postMatchActions, token, tradeOrder.uid, false); } }; -const runTradeOrderMatching = async ( +const runTradeOrderMatching = ( query: Query, matcher: Matcher, postMatchActions: PostMatchAction | undefined, - lastDocId: string, token: Token, tradeOrderId: string, invertedPrice = true, ) => build5Db().runTransaction(async (transaction) => { - const tradeOrderDocRef = build5Db().doc(`${COL.TOKEN_MARKET}/${tradeOrderId}`); - const tradeOrder = (await transaction.get(tradeOrderDocRef))!; + const tradeOrderDocRef = build5Db().doc(COL.TOKEN_MARKET, tradeOrderId); + const tradeOrder = (await transaction.get(tradeOrderDocRef))!; if (tradeOrder.status !== TokenTradeOrderStatus.ACTIVE) { - return ''; + return 0; } - const docs = await (await query(tradeOrder, lastDocId)).get(); + const docs = await query(tradeOrder).get(); const trades = await getTradesSorted(transaction, docs); let update = cloneDeep(tradeOrder); @@ -122,21 +112,33 @@ const runTradeOrderMatching = async ( } const sell = updateTrade(prevSell, purchase); const buy = updateTrade(prevBuy, purchase, buyerCreditId); - const docRef = build5Db().doc(`${COL.TOKEN_MARKET}/${trade!.uid}`); - transaction.update(docRef, isSell ? buy : sell); + const docRef = build5Db().doc(COL.TOKEN_MARKET, trade!.uid); + await transaction.update(docRef, toPgTrade(isSell ? buy : sell)); if (postMatchActions) { - postMatchActions(transaction, prevBuy, buy, prevSell, sell); + await postMatchActions(transaction, prevBuy, buy, prevSell, sell); } - const purchaseDocRef = build5Db().doc(`${COL.TOKEN_PURCHASE}/${purchase.uid}`); - transaction.create(purchaseDocRef, purchase); + const purchaseDocRef = build5Db().doc(COL.TOKEN_PURCHASE, purchase.uid); + await transaction.create(purchaseDocRef, purchase); update = isSell ? sell : buy; } - transaction.update(build5Db().doc(`${COL.TOKEN_MARKET}/${tradeOrder.uid}`), update); - return update.status === TokenTradeOrderStatus.SETTLED ? '' : last(docs)?.uid || ''; + await transaction.update(build5Db().doc(COL.TOKEN_MARKET, tradeOrder.uid), toPgTrade(update)); + return update.status === TokenTradeOrderStatus.SETTLED ? 0 : docs.length; }); +const toPgTrade = (trade: TokenTradeOrder): PgTokenMarket => ({ + ...trade, + createdOn: trade.createdOn?.toDate(), + updatedOn: trade.updatedOn?.toDate(), + tokenStatus: convertEnum(trade.tokenStatus, TokenStatus, PgTokenStatus), + type: convertEnum(trade.type, TokenTradeOrderType, PgTokenTradeOrderType), + status: convertEnum(trade.status, TokenTradeOrderStatus, PgTokenTradeOrderStatus), + expiresAt: trade.expiresAt.toDate(), + sourceNetwork: convertEnum(trade.sourceNetwork, Network, PgNetwork), + targetNetwork: convertEnum(trade.targetNetwork, Network, PgNetwork), +}); + const updateTrade = (trade: TokenTradeOrder, purchase: TokenPurchase, creditTransactionId = '') => { const fulfilled = trade.fulfilled + purchase.count; const salePrice = bigDecimal.floor(bigDecimal.multiply(purchase.count, purchase.price)); @@ -178,41 +180,32 @@ const getPostMatchActions = (token: Token) => { } }; -const getSimpleTokenQuery = async (trade: TokenTradeOrder, startAfter = '') => { - const lastDoc = await getSnapshot(COL.TOKEN_MARKET, startAfter); +const getSimpleTokenQuery = (trade: TokenTradeOrder) => { const type = - trade.type === TokenTradeOrderType.BUY ? TokenTradeOrderType.SELL : TokenTradeOrderType.BUY; + trade.type === TokenTradeOrderType.BUY ? PgTokenTradeOrderType.SELL : PgTokenTradeOrderType.BUY; return build5Db() .collection(COL.TOKEN_MARKET) .where('type', '==', type) .where('token', '==', trade.token) .where('price', trade.type === TokenTradeOrderType.BUY ? '<=' : '>=', trade.price) - .where('status', '==', TokenTradeOrderStatus.ACTIVE) + .where('status', '==', PgTokenTradeOrderStatus.ACTIVE) .orderBy('price', trade.type === TokenTradeOrderType.BUY ? 'asc' : 'desc') - .orderBy('createdOn') - .startAfter(lastDoc) - .limit(TOKEN_TRADE_ORDER_FETCH_LIMIT); + .orderBy('createdOn'); }; -const getBaseTokenTradeQuery = async (trade: TokenTradeOrder, startAfter = '') => { - const lastDoc = await getSnapshot(COL.TOKEN_MARKET, startAfter); - return build5Db() +const getBaseTokenTradeQuery = (trade: TokenTradeOrder) => + build5Db() .collection(COL.TOKEN_MARKET) - .where('sourceNetwork', '==', trade.targetNetwork) + .where('sourceNetwork', '==', convertEnum(trade.targetNetwork, Network, PgNetwork)) .where('token', '==', trade.token) .where('price', trade.type === TokenTradeOrderType.BUY ? '<=' : '>=', trade.price) - .where('status', '==', TokenTradeOrderStatus.ACTIVE) + .where('status', '==', PgTokenTradeOrderStatus.ACTIVE) .orderBy('price', trade.type === TokenTradeOrderType.BUY ? 'asc' : 'desc') - .orderBy('createdOn') - .startAfter(lastDoc) - .limit(TOKEN_TRADE_ORDER_FETCH_LIMIT); -}; + .orderBy('createdOn'); const getTradesSorted = async (transaction: ITransaction, unsortedTrades: TokenTradeOrder[]) => { - const unsortedTradesDocs = unsortedTrades.map((ut) => - build5Db().doc(`${COL.TOKEN_MARKET}/${ut.uid}`), - ); - const trades = await transaction.getAll(...unsortedTradesDocs); + const unsortedTradesDocs = unsortedTrades.map((ut) => build5Db().doc(COL.TOKEN_MARKET, ut.uid)); + const trades = await transaction.getAll(...unsortedTradesDocs); return trades.sort((a, b) => { const price = a?.type === TokenTradeOrderType.SELL ? a.price - b!.price : b!.price - a!.price; const createdOn = dayjs(a!.createdOn?.toDate()).isBefore(dayjs(b!.createdOn?.toDate())) diff --git a/packages/functions/src/triggers/token-trading/token-purchase.trigger.ts b/packages/functions/src/triggers/token-trading/token-purchase.trigger.ts index 3e0da6d1c5..b0d7aa3ae6 100644 --- a/packages/functions/src/triggers/token-trading/token-purchase.trigger.ts +++ b/packages/functions/src/triggers/token-trading/token-purchase.trigger.ts @@ -1,24 +1,20 @@ -import { build5Db } from '@build-5/database'; -import { COL, SUB_COL, TokenPurchase, TokenPurchaseAge } from '@build-5/interfaces'; -import { FirestoreDocEvent } from '../common'; +import { PgTokenPurchase, PgTokenStatsUpdate, build5Db } from '@build-5/database'; +import { COL, SUB_COL } from '@build-5/interfaces'; +import { PgDocEvent } from '../common'; -export const onTokenPurchaseCreated = async (event: FirestoreDocEvent) => { +export const onTokenPurchaseCreated = async (event: PgDocEvent) => { const { curr } = event; if (!curr || !curr.token) { return; } - const tokenDocRef = build5Db().doc(`${COL.TOKEN}/${curr.token}`); - const statsDocRef = tokenDocRef.collection(SUB_COL.STATS).doc(curr.token); - const volume = Object.values(TokenPurchaseAge).reduce( - (acc, act) => ({ ...acc, [act]: build5Db().inc(curr.count) }), - {}, - ); - const statsData = { + const statsDocRef = build5Db().doc(COL.TOKEN, curr.token, SUB_COL.STATS, curr.token); + const statsData: PgTokenStatsUpdate = { parentId: curr.token, - parentCol: COL.TOKEN, - volumeTotal: build5Db().inc(curr.count), - volume, + volumeTotal: build5Db().inc(curr.count!), + volume_in24h: build5Db().inc(curr.count!), + volume_in48h: build5Db().inc(curr.count!), + volume_in7d: build5Db().inc(curr.count!), }; - statsDocRef.set(statsData, true); + await statsDocRef.upsert(statsData); }; diff --git a/packages/functions/src/triggers/token-trading/token-trade-order.trigger.ts b/packages/functions/src/triggers/token-trading/token-trade-order.trigger.ts index eeb4f6a2db..06cb3285b7 100644 --- a/packages/functions/src/triggers/token-trading/token-trade-order.trigger.ts +++ b/packages/functions/src/triggers/token-trading/token-trade-order.trigger.ts @@ -1,19 +1,10 @@ -import { build5Db } from '@build-5/database'; -import { - COL, - Member, - Project, - ProjectBilling, - StakeType, - SUB_COL, - TokenDistribution, - TokenTradeOrder, -} from '@build-5/interfaces'; +import { build5Db, PgTokenMarket } from '@build-5/database'; +import { COL, Member, ProjectBilling, StakeType, SUB_COL } from '@build-5/interfaces'; import { getStakeForType, getTier } from '../../services/stake.service'; -import { FirestoreDocEvent } from '../common'; +import { PgDocEvent } from '../common'; import { matchTradeOrder } from './match-token'; -export const onTokenTradeOrderWrite = async (event: FirestoreDocEvent) => { +export const onTokenTradeOrderWrite = async (event: PgDocEvent) => { const { prev, curr } = event; if (!curr) { return; @@ -25,13 +16,17 @@ export const onTokenTradeOrderWrite = async (event: FirestoreDocEvent { - const project = await build5Db().get(COL.PROJECT, projectId); - if (project?.config?.billing !== ProjectBilling.TOKEN_BASE) { + const project = await build5Db().doc(COL.PROJECT, projectId).get(); + if (project?.config?.billing !== ProjectBilling.TOKEN_BASED) { return 0; } - const tokenDocRef = build5Db().doc(`${COL.TOKEN}/${project.config.nativeTokenUid}`); - const distributionDocRef = tokenDocRef.collection(SUB_COL.DISTRIBUTION).doc(member.uid); - const distribution = await distributionDocRef.get(); + const distributionDocRef = build5Db().doc( + COL.TOKEN, + project.config.nativeTokenUid!, + SUB_COL.DISTRIBUTION, + member.uid, + ); + const distribution = await distributionDocRef.get(); const stakeValue = getStakeForType(distribution, StakeType.DYNAMIC); return getTier(project.config.tiers || [], stakeValue); }; diff --git a/packages/functions/src/triggers/token.trigger.ts b/packages/functions/src/triggers/token.trigger.ts index 02dbd9d4c7..81e6891f2b 100644 --- a/packages/functions/src/triggers/token.trigger.ts +++ b/packages/functions/src/triggers/token.trigger.ts @@ -1,17 +1,24 @@ -import { IBatch, build5Db } from '@build-5/database'; +import { + IBatch, + PgMediaStatus, + PgNetwork, + PgToken, + PgTokenStatus, + PgTokenTradeOrderStatus, + PgTransactionType, + build5Db, + convertEnum, +} from '@build-5/database'; import { COL, DEFAULT_NETWORK, Entity, MIN_IOTA_AMOUNT, - MediaStatus, Member, + Network, SUB_COL, Space, - Token, TokenDistribution, - TokenStatus, - TokenTradeOrder, TokenTradeOrderStatus, Transaction, TransactionPayloadType, @@ -33,32 +40,32 @@ import { orderDocRef, } from '../utils/token.utils'; import { getRandomEthAddress } from '../utils/wallet.utils'; -import { FirestoreDocEvent } from './common'; +import { PgDocEvent } from './common'; -export const onTokenStatusUpdated = async (event: FirestoreDocEvent) => { +export const onTokenStatusUpdated = async (event: PgDocEvent) => { const { prev, curr } = event; - if (prev?.status === TokenStatus.AVAILABLE && curr?.status === TokenStatus.PROCESSING) { + if (prev?.status === PgTokenStatus.AVAILABLE && curr?.status === PgTokenStatus.PROCESSING) { return await processTokenDistribution(curr!); } - if (prev?.status !== curr?.status && curr?.status === TokenStatus.CANCEL_SALE) { + if (prev?.status !== curr?.status && curr?.status === PgTokenStatus.CANCEL_SALE) { return await cancelPublicSale(curr!); } - if (prev?.status !== curr?.status && curr?.status === TokenStatus.MINTING) { + if (prev?.status !== curr?.status && curr?.status === PgTokenStatus.MINTING) { return await mintToken(curr); } - if (prev?.mintingData?.tokensInVault && curr?.mintingData?.tokensInVault === 0) { + if (prev?.mintingData_tokensInVault && curr?.mintingData_tokensInVault === 0) { await onTokenVaultEmptied(curr); } }; -const getTokenCount = (token: Token, amount: number) => Math.floor(amount / token.pricePerToken); +const getTokenCount = (token: PgToken, amount: number) => Math.floor(amount / token.pricePerToken!); const getBoughtByMember = ( - token: Token, + token: PgToken, totalDeposit: number, totalSupply: number, totalBought: number, @@ -88,13 +95,13 @@ const getTotalPaid = (pricePerToken: number, boughtByMember: number) => { const getMemberDistribution = ( distribution: TokenDistribution, - token: Token, + token: PgToken, totalSupply: number, totalBought: number, ): TokenDistribution => { const totalDeposit = distribution.totalDeposit || 0; const boughtByMember = getBoughtByMember(token, totalDeposit, totalSupply, totalBought); - const totalPaid = getTotalPaid(token.pricePerToken, boughtByMember); + const totalPaid = getTotalPaid(token.pricePerToken!, boughtByMember); const refundedAmount = Number(bigDecimal.subtract(totalDeposit, totalPaid)); return { uid: distribution.uid, @@ -113,7 +120,7 @@ const getFlooredDistribution = (distribution: TokenDistribution): TokenDistribut }; const createBillAndRoyaltyPayment = async ( - token: Token, + token: PgToken, distribution: TokenDistribution, payments: Transaction[], order: Transaction, @@ -126,14 +133,14 @@ const createBillAndRoyaltyPayment = async ( let balance = distribution.totalPaid + (distribution.refundedAmount! < MIN_IOTA_AMOUNT ? distribution.refundedAmount! : 0); - const member = await memberDocRef(distribution.uid!).get(); + const member = await build5Db().doc(COL.MEMBER, distribution.uid!).get(); const [royaltySpaceId, fee] = Object.entries( await getRoyaltyFees(balance, member.tokenPurchaseFeePercentage, true), )[0]; let royaltyPayment: Transaction | undefined = undefined; if (fee >= MIN_IOTA_AMOUNT && balance - fee >= MIN_IOTA_AMOUNT) { - const royaltySpace = await build5Db().doc(`${COL.SPACE}/${royaltySpaceId}`).get(); + const royaltySpace = await build5Db().doc(COL.SPACE, royaltySpaceId).get(); const network = order.network || DEFAULT_NETWORK; royaltyPayment = { project: getProject(order), @@ -159,7 +166,7 @@ const createBillAndRoyaltyPayment = async ( tokenSymbol: token.symbol, }, }; - const royaltyPaymentDocRef = build5Db().doc(`${COL.TRANSACTION}/${royaltyPayment.uid}`); + const royaltyPaymentDocRef = build5Db().doc(COL.TRANSACTION, royaltyPayment.uid); batch.create(royaltyPaymentDocRef, royaltyPayment); balance -= fee; } @@ -189,13 +196,13 @@ const createBillAndRoyaltyPayment = async ( tokenSymbol: token.symbol, }, }; - const billPaymentDocRef = build5Db().doc(`${COL.TRANSACTION}/${billPayment.uid}`); + const billPaymentDocRef = build5Db().doc(COL.TRANSACTION, billPayment.uid); batch.create(billPaymentDocRef, billPayment); return { billPaymentId: billPayment.uid, royaltyBillPaymentId: royaltyPayment?.uid || '' }; }; const createCredit = async ( - token: Token, + token: PgToken, distribution: TokenDistribution, payments: Transaction[], order: Transaction, @@ -206,7 +213,7 @@ const createCredit = async ( } const member = await memberDocRef(distribution.uid!).get(); const tranId = getRandomEthAddress(); - const docRef = build5Db().doc(`${COL.TRANSACTION}/${tranId}`); + const docRef = build5Db().doc(COL.TRANSACTION, tranId); const network = order.network || DEFAULT_NETWORK; const data: Transaction = { project: getProject(order), @@ -234,16 +241,20 @@ const createCredit = async ( return tranId; }; -const reconcileBuyer = (token: Token) => async (distribution: TokenDistribution) => { +const reconcileBuyer = (token: PgToken) => async (distribution: TokenDistribution) => { const batch = build5Db().batch(); - const tokenDocRef = build5Db().doc(`${COL.TOKEN}/${token.uid}`); - const distributionDoc = tokenDocRef.collection(SUB_COL.DISTRIBUTION).doc(distribution.uid!); + const distributionDoc = build5Db().doc( + COL.TOKEN, + token.uid, + SUB_COL.DISTRIBUTION, + distribution.uid!, + ); - const spaceDocRef = build5Db().doc(`${COL.SPACE}/${token.space}`); - const space = (await spaceDocRef.get())!; + const spaceDocRef = build5Db().doc(COL.SPACE, token.space!); + const space = (await spaceDocRef.get())!; const order = await orderDocRef(distribution.uid!, token).get(); - const payments = await allPaymentsQuery(distribution.uid!, token.uid).get(); + const payments = await allPaymentsQuery(distribution.uid!, token.uid).get(); const { billPaymentId, royaltyBillPaymentId } = await createBillAndRoyaltyPayment( token, @@ -261,13 +272,17 @@ const reconcileBuyer = (token: Token) => async (distribution: TokenDistribution) batch, ); + // eslint-disable-next-line @typescript-eslint/no-unused-vars + const { stakeExpiry, ...rest } = distribution; batch.update(distributionDoc, { - ...distribution, + ...rest, tokenOwned: build5Db().inc(distribution.totalBought || 0), reconciled: true, billPaymentId, royaltyBillPaymentId, creditPaymentId, + mintedClaimedOn: distribution.mintedClaimedOn?.toDate(), + createdOn: distribution.createdOn?.toDate(), }); await batch.commit(); }; @@ -275,14 +290,14 @@ const reconcileBuyer = (token: Token) => async (distribution: TokenDistribution) const distributeLeftoverTokens = ( distributions: TokenDistribution[], totalPublicSupply: number, - token: Token, + token: PgToken, ) => { let tokensLeft = totalPublicSupply - distributions.reduce((sum, p) => sum + p.totalBought!, 0); let i = 0; let sell = false; while (tokensLeft) { const distribution = { ...distributions[i] }; - if (distribution.refundedAmount! >= token.pricePerToken) { + if (distribution.refundedAmount! >= token.pricePerToken!) { sell = true; tokensLeft--; distribution.refundedAmount = Number( @@ -299,18 +314,17 @@ const distributeLeftoverTokens = ( } }; -const cancelPublicSale = async (token: Token) => { - const tokenDocRef = build5Db().doc(`${COL.TOKEN}/${token.uid}`); - const distributions = await tokenDocRef - .collection(SUB_COL.DISTRIBUTION) +const cancelPublicSale = async (token: PgToken) => { + const distributions = await build5Db() + .collection(COL.TOKEN, token.uid, SUB_COL.DISTRIBUTION) .where('totalDeposit', '>', 0) - .get(); + .get(); const promises = distributions.map(async (distribution) => { const batch = build5Db().batch(); const order = await orderDocRef(distribution.uid!, token).get(); - const payments = await allPaymentsQuery(distribution.uid!, token.uid).get(); + const payments = await allPaymentsQuery(distribution.uid!, token.uid).get(); const creditPaymentId = await createCredit( token, { ...distribution, refundedAmount: distribution?.totalDeposit }, @@ -319,7 +333,12 @@ const cancelPublicSale = async (token: Token) => { batch, ); - const distributionDocRef = tokenDocRef.collection(SUB_COL.DISTRIBUTION).doc(distribution.uid!); + const distributionDocRef = build5Db().doc( + COL.TOKEN, + token.uid, + SUB_COL.DISTRIBUTION, + distribution.uid!, + ); batch.update(distributionDocRef, { creditPaymentId, totalDeposit: 0 }); await batch.commit(); @@ -329,20 +348,19 @@ const cancelPublicSale = async (token: Token) => { const errors = results .filter((r) => r.status === 'rejected') .map((r) => String((r).reason)); - const status = isEmpty(errors) ? TokenStatus.AVAILABLE : TokenStatus.ERROR; - await build5Db().doc(`${COL.TOKEN}/${token.uid}`).update({ status }); + const status = isEmpty(errors) ? PgTokenStatus.AVAILABLE : PgTokenStatus.ERROR; + await build5Db().doc(COL.TOKEN, token.uid).update({ status }); - if (status === TokenStatus.ERROR) { + if (status === PgTokenStatus.ERROR) { console.error('Token processing error', token.uid, errors); } }; -const processTokenDistribution = async (token: Token) => { - const tokenDocRef = build5Db().doc(`${COL.TOKEN}/${token.uid}`); - const distributionsSnap = await tokenDocRef - .collection(SUB_COL.DISTRIBUTION) +const processTokenDistribution = async (token: PgToken) => { + const distributionsSnap = await build5Db() + .collection(COL.TOKEN, token.uid, SUB_COL.DISTRIBUTION) .where('totalDeposit', '>', 0) - .get(); + .get(); const totalBought = distributionsSnap.reduce( (sum, doc) => sum + getTokenCount(token, doc.totalDeposit || 0), 0, @@ -352,7 +370,7 @@ const processTokenDistribution = async (token: Token) => { const distributions = distributionsSnap .sort((a, b) => (b.totalDeposit || 0) - (a.totalDeposit || 0)) - .map((d) => getMemberDistribution(d, token, totalPublicSupply, totalBought)); + .map((d) => getMemberDistribution(d, token, totalPublicSupply, totalBought)); if (totalBought > totalPublicSupply) { distributeLeftoverTokens(distributions, totalPublicSupply, token); @@ -363,93 +381,96 @@ const processTokenDistribution = async (token: Token) => { const errors = results .filter((r) => r.status === 'rejected') .map((r) => String((r).reason)); - const status = isEmpty(errors) ? TokenStatus.PRE_MINTED : TokenStatus.ERROR; - await build5Db().doc(`${COL.TOKEN}/${token.uid}`).update({ status }); + const status = isEmpty(errors) ? PgTokenStatus.PRE_MINTED : PgTokenStatus.ERROR; + await build5Db().doc(COL.TOKEN, token.uid).update({ status }); - if (status === TokenStatus.ERROR) { + if (status === PgTokenStatus.ERROR) { console.error('Token processing error', token.uid, errors); } }; -const mintToken = async (token: Token) => { +const mintToken = async (token: PgToken) => { await cancelAllActiveSales(token!.uid); await setIpfsData(token); + const network = convertEnum(token.mintingData_network, PgNetwork, Network)!; const order: Transaction = { project: getProject(token), type: TransactionType.MINT_TOKEN, uid: getRandomEthAddress(), - member: token.mintingData?.mintedBy, + member: token.mintingData_mintedBy!, space: token!.space, - network: token.mintingData?.network!, + network, payload: { type: TransactionPayloadType.MINT_ALIAS, - amount: token.mintingData?.aliasStorageDeposit, - sourceAddress: token.mintingData?.vaultAddress, + amount: token.mintingData_aliasStorageDeposit, + sourceAddress: token.mintingData_vaultAddress, token: token.uid, }, }; - await build5Db().doc(`${COL.TRANSACTION}/${order.uid}`).create(order); + await build5Db().doc(COL.TRANSACTION, order.uid).create(order); }; const cancelAllActiveSales = async (token: string) => { - const runTransaction = () => + const runTransactions = () => build5Db().runTransaction(async (transaction) => { const snap = build5Db() .collection(COL.TOKEN_MARKET) - .where('status', '==', TokenTradeOrderStatus.ACTIVE) + .where('status', '==', PgTokenTradeOrderStatus.ACTIVE) .where('token', '==', token) .limit(150) - .get(); - const docRefs = (await snap).map((to) => build5Db().doc(`${COL.TOKEN_MARKET}/${to.uid}`)); - const promises = (await transaction.getAll(...docRefs)) + .get(); + const docRefs = (await snap).map((to) => build5Db().doc(COL.TOKEN_MARKET, to.uid)); + const promises = (await transaction.getAll(...docRefs)) .filter((d) => d && d.status === TokenTradeOrderStatus.ACTIVE) .map((d) => cancelTradeOrderUtil(transaction, d!, TokenTradeOrderStatus.CANCELLED_MINTING_TOKEN), ); return (await Promise.all(promises)).length; }); - await guardedRerun(async () => (await runTransaction()) !== 0); + await guardedRerun(async () => (await runTransactions()) !== 0); }; -const setIpfsData = async (token: Token) => { +const setIpfsData = async (token: PgToken) => { const metadata = tokenToIpfsMetadata(token); const ipfs = await downloadMediaAndPackCar(token.uid, token.icon!, metadata); - await build5Db().doc(`${COL.TOKEN}/${token.uid}`).update({ - mediaStatus: MediaStatus.PENDING_UPLOAD, + await build5Db().doc(COL.TOKEN, token.uid).update({ + mediaStatus: PgMediaStatus.PENDING_UPLOAD, ipfsMedia: ipfs.ipfsMedia, ipfsMetadata: ipfs.ipfsMetadata, ipfsRoot: ipfs.ipfsRoot, }); }; -const onTokenVaultEmptied = async (token: Token) => { - const wallet = await WalletService.newWallet(token.mintingData?.network); - const { amount: vaultBalance } = await wallet.getBalance(token.mintingData?.vaultAddress!); - const minter = await build5Db().doc(`${COL.MEMBER}/${token.mintingData?.mintedBy}`).get(); +const onTokenVaultEmptied = async (token: PgToken) => { + const network = convertEnum(token.mintingData_network, PgNetwork, Network)!; + const wallet = await WalletService.newWallet(network); + const { amount: vaultBalance } = await wallet.getBalance(token.mintingData_vaultAddress!); + const minter = await build5Db().doc(COL.MEMBER, token.mintingData_mintedBy!).get(); const paymentsSnap = await build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.PAYMENT) - .where('payload.sourceTransaction', 'array-contains', token.mintingData?.vaultAddress!) - .get(); + .where('type', '==', PgTransactionType.PAYMENT) + // eslint-disable-next-line @typescript-eslint/no-explicit-any + .where('payload_sourceTransaction', 'array-contains', token.mintingData_vaultAddress! as any) + .get(); const credit: Transaction = { project: getProject(token), type: TransactionType.CREDIT, uid: getRandomEthAddress(), space: token.space, member: minter!.uid, - network: token.mintingData?.network!, + network, payload: { type: TransactionPayloadType.TOKEN_VAULT_EMPTIED, dependsOnBillPayment: true, amount: Number(vaultBalance), - sourceAddress: token.mintingData?.vaultAddress!, - targetAddress: getAddress(minter, token.mintingData?.network!), + sourceAddress: token.mintingData_vaultAddress!, + targetAddress: getAddress(minter, network), sourceTransaction: paymentsSnap.map((p) => p.uid), token: token.uid, tokenSymbol: token.symbol, }, }; - await build5Db().doc(`${COL.TRANSACTION}/${credit.uid}`).create(credit); + await build5Db().doc(COL.TRANSACTION, credit.uid).create(credit); }; diff --git a/packages/functions/src/triggers/transaction-trigger/airdrop.claim.ts b/packages/functions/src/triggers/transaction-trigger/airdrop.claim.ts index 224679b315..dfcdcda03c 100644 --- a/packages/functions/src/triggers/transaction-trigger/airdrop.claim.ts +++ b/packages/functions/src/triggers/transaction-trigger/airdrop.claim.ts @@ -1,14 +1,23 @@ -import { ITransaction, build5Db } from '@build-5/database'; +import { + ITransaction, + PgNetwork, + PgTokenDropStatus, + PgTransaction, + PgTransactionPayloadType, + PgTransactionType, + build5Db, + convertEnum, +} from '@build-5/database'; import { COL, Entity, IgnoreWalletReason, Member, + Network, SUB_COL, Stake, StakeType, Token, - TokenDistribution, TokenDrop, TokenDropStatus, TokenStatus, @@ -29,17 +38,17 @@ import { getRandomEthAddress } from '../../utils/wallet.utils'; const LOOP_SIZE = 10000; -export const onAirdropClaim = async (order: Transaction) => { - const tokenDocRef = build5Db().doc(`${COL.TOKEN}/${order.payload.token}`); - const token = (await tokenDocRef.get())!; +export const onAirdropClaim = async (order: PgTransaction) => { + const tokenDocRef = build5Db().doc(COL.TOKEN, order.payload_token!); + const token = (await tokenDocRef.get())!; - if (order.payload.type === TransactionPayloadType.TOKEN_AIRDROP) { + if (order.payload_type === PgTransactionPayloadType.TOKEN_AIRDROP) { return await onPreMintedAirdropClaim(order, token); } return await onMintedAirdropClaim(order, token); }; -const onPreMintedAirdropClaim = async (order: Transaction, token: Token) => { +const onPreMintedAirdropClaim = async (order: PgTransaction, token: Token) => { if (![TokenStatus.AVAILABLE, TokenStatus.PRE_MINTED].includes(token.status)) { return; } @@ -48,7 +57,7 @@ const onPreMintedAirdropClaim = async (order: Transaction, token: Token) => { token, true, )(async (transaction, airdrop) => { - const airdropDocRef = build5Db().doc(`${COL.AIRDROP}/${airdrop.uid}`); + const airdropDocRef = build5Db().doc(COL.AIRDROP, airdrop.uid); const billPayment: Transaction = { project: getProject(order), @@ -56,56 +65,54 @@ const onPreMintedAirdropClaim = async (order: Transaction, token: Token) => { uid: getRandomEthAddress(), space: order.space, member: order.member, - network: order.network, + network: convertEnum(order.network, PgNetwork, Network)!, ignoreWallet: true, ignoreWalletReason: IgnoreWalletReason.PRE_MINTED_AIRDROP_CLAIM, payload: { type: TransactionPayloadType.PRE_MINTED_AIRDROP_CLAIM, amount: 0, sourceTransaction: [order.uid], - quantity: order.payload.quantity || 0, + quantity: order.payload_quantity || 0, airdropId: airdrop.uid, token: token.uid, tokenSymbol: token.symbol, }, }; - const billPaymentDocRef = build5Db().doc(`${COL.TRANSACTION}/${billPayment.uid}`); - transaction.create(billPaymentDocRef, billPayment); + const billPaymentDocRef = build5Db().doc(COL.TRANSACTION, billPayment.uid); + await transaction.create(billPaymentDocRef, billPayment); - transaction.update(airdropDocRef, { - status: TokenDropStatus.CLAIMED, + await transaction.update(airdropDocRef, { + status: PgTokenDropStatus.CLAIMED, billPaymentId: billPayment.uid, }); const distributionDocRef = build5Db().doc( - `${COL.TOKEN}/${order.payload.token}/${SUB_COL.DISTRIBUTION}/${order.member}`, - ); - transaction.set( - distributionDocRef, - { - parentId: order.payload.token, - parentCol: COL.TOKEN, - uid: order.member, - tokenClaimed: build5Db().inc(airdrop.count), - tokenOwned: build5Db().inc(airdrop.count), - totalUnclaimedAirdrop: build5Db().inc(-airdrop.count), - }, - true, + COL.TOKEN, + order.payload_token!, + SUB_COL.DISTRIBUTION, + order.member, ); + await transaction.upsert(distributionDocRef, { + parentId: order.payload_token, + tokenClaimed: build5Db().inc(airdrop.count), + tokenOwned: build5Db().inc(airdrop.count), + totalUnclaimedAirdrop: build5Db().inc(-airdrop.count), + }); return billPayment.payload.amount!; }); }; -const onMintedAirdropClaim = async (order: Transaction, token: Token) => { +const onMintedAirdropClaim = async (order: PgTransaction, token: Token) => { const paymentsSnap = await build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.PAYMENT) - .where('payload.sourceTransaction', 'array-contains', order.uid) - .get(); + .where('type', '==', PgTransactionType.PAYMENT) + // eslint-disable-next-line @typescript-eslint/no-explicit-any + .where('payload_sourceTransaction', 'array-contains', order.uid as any) + .get(); const paymentsId = paymentsSnap.map((d) => d.uid); - const memberDocRef = build5Db().doc(`${COL.MEMBER}/${order.member}`); - const member = (await memberDocRef.get())!; + const memberDocRef = build5Db().doc(COL.MEMBER, order.member!); + const member = (await memberDocRef.get())!; const wallet = await WalletService.newWallet(token.mintingData?.network!); let storageDepositUsed = await claimOwnedMintedTokens(order, paymentsId, token, member, wallet); @@ -114,7 +121,7 @@ const onMintedAirdropClaim = async (order: Transaction, token: Token) => { order, token, )(async (transaction, airdrop) => { - const airdropDocRef = build5Db().doc(`${COL.AIRDROP}/${airdrop.uid}`); + const airdropDocRef = build5Db().doc(COL.AIRDROP, airdrop.uid); const billPayment = await mintedDropToBillPayment( order, @@ -124,84 +131,89 @@ const onMintedAirdropClaim = async (order: Transaction, token: Token) => { member, wallet, ); - const billPaymentDocRef = build5Db().doc(`${COL.TRANSACTION}/${billPayment.uid}`); - transaction.create(billPaymentDocRef, billPayment); const stake = mintedDropToStake(order, airdrop, billPayment); if (stake) { - const stakeDocRef = build5Db().doc(`${COL.STAKE}/${stake.uid}`); - transaction.create(stakeDocRef, stake); + const stakeDocRef = build5Db().doc(COL.STAKE, stake.uid); + await transaction.create(stakeDocRef, stake); } - const tokenDocRef = build5Db().doc(`${COL.TOKEN}/${token.uid}`); + const billPaymentDocRef = build5Db().doc(COL.TRANSACTION, billPayment.uid); + await transaction.create(billPaymentDocRef, billPayment); + + const tokenDocRef = build5Db().doc(COL.TOKEN, token.uid); if (!airdrop.sourceAddress) { - transaction.update(tokenDocRef, { - 'mintingData.tokensInVault': build5Db().inc(-airdrop.count), + await transaction.update(tokenDocRef, { + mintingData_tokensInVault: build5Db().inc(-airdrop.count), }); } if (airdrop.orderId) { - const orderDocRef = build5Db().doc(`${COL.TRANSACTION}/${airdrop.orderId}`); - transaction.update(orderDocRef, { 'payload.unclaimedAirdrops': build5Db().inc(-1) }); + const orderDocRef = build5Db().doc(COL.TRANSACTION, airdrop.orderId); + await transaction.update(orderDocRef, { payload_unclaimedAirdrops: build5Db().inc(-1) }); } - const distributionDocRef = tokenDocRef.collection(SUB_COL.DISTRIBUTION).doc(member.uid); - transaction.set( - distributionDocRef, - { - parentId: token.uid, - parentCol: COL.TOKEN, - uid: member.uid, - tokenClaimed: build5Db().inc(airdrop.count), - tokenOwned: build5Db().inc(airdrop.count), - totalUnclaimedAirdrop: build5Db().inc(-airdrop.count), - mintedClaimedOn: dayjs().toDate(), - }, - true, + const distributionDocRef = build5Db().doc( + COL.TOKEN, + token.uid, + SUB_COL.DISTRIBUTION, + member.uid, ); + await transaction.upsert(distributionDocRef, { + parentId: token.uid, + tokenClaimed: build5Db().inc(airdrop.count), + tokenOwned: build5Db().inc(airdrop.count), + totalUnclaimedAirdrop: build5Db().inc(-airdrop.count), + mintedClaimedOn: dayjs().toDate(), + }); - transaction.update(airdropDocRef, { - status: TokenDropStatus.CLAIMED, + await transaction.update(airdropDocRef, { + status: PgTokenDropStatus.CLAIMED, billPaymentId: billPayment.uid, }); return airdrop.isBaseToken ? 0 : billPayment.payload.amount!; }); - if (storageDepositUsed < order.payload.amount!) { - console.info('onMintedAirdropClaim', order.uid, storageDepositUsed, order.payload.amount); + if (storageDepositUsed < order.payload_amount!) { + console.info('onMintedAirdropClaim', order.uid, storageDepositUsed, order.payload_amount); + const network = convertEnum(order.network, PgNetwork, Network)!; const credit: Transaction = { project: getProject(order), type: TransactionType.CREDIT, uid: getRandomEthAddress(), space: token.space, member: member.uid, - network: order.network, + network, payload: { type: TransactionPayloadType.CLAIM_MINTED_TOKEN, - amount: order.payload.amount! - storageDepositUsed, - sourceAddress: order.payload.targetAddress, - targetAddress: getAddress(member, order.network!), + amount: order.payload_amount! - storageDepositUsed, + sourceAddress: order.payload_targetAddress, + targetAddress: getAddress(member, network), sourceTransaction: paymentsId, token: token.uid, reconciled: true, void: false, }, }; - await build5Db().doc(`${COL.TRANSACTION}/${credit.uid}`).create(credit); + await build5Db().doc(COL.TRANSACTION, credit.uid).create(credit); } }; const claimOwnedMintedTokens = ( - order: Transaction, + order: PgTransaction, sourceTransaction: string[], token: Token, member: Member, wallet: Wallet, ) => build5Db().runTransaction(async (transaction) => { - const tokenDocRef = build5Db().doc(`${COL.TOKEN}/${token.uid}`); - const distributionDocRef = tokenDocRef.collection(SUB_COL.DISTRIBUTION).doc(order.member!); - const distribution = (await transaction.get(distributionDocRef))!; + const distributionDocRef = build5Db().doc( + COL.TOKEN, + token.uid, + SUB_COL.DISTRIBUTION, + order.member!, + ); + const distribution = (await transaction.get(distributionDocRef))!; if (distribution?.mintedClaimedOn || !distribution?.tokenOwned) { return 0; } @@ -225,23 +237,26 @@ const claimOwnedMintedTokens = ( member, wallet, ); - const billPaymentDocRef = build5Db().doc(`${COL.TRANSACTION}/${billPayment.uid}`); - transaction.create(billPaymentDocRef, billPayment); const stake = mintedDropToStake(order, airdrop, billPayment); if (stake) { - const stakeDocRef = build5Db().doc(`${COL.STAKE}/${stake.uid}`); - transaction.create(stakeDocRef, stake); + const stakeDocRef = build5Db().doc(COL.STAKE, stake.uid); + await transaction.create(stakeDocRef, stake); } - transaction.update(distributionDocRef, { mintedClaimedOn: dayjs().toDate() }); - transaction.update(tokenDocRef, { - 'mintingData.tokensInVault': build5Db().inc(-airdrop.count), + + const billPaymentDocRef = build5Db().doc(COL.TRANSACTION, billPayment.uid); + await transaction.create(billPaymentDocRef, billPayment); + + await transaction.update(distributionDocRef, { mintedClaimedOn: dayjs().toDate() }); + const tokenDocRef = build5Db().doc(COL.TOKEN, token.uid); + await transaction.update(tokenDocRef, { + mintingData_tokensInVault: build5Db().inc(-airdrop.count), }); return billPayment.payload.amount!; }); const mintedDropToBillPayment = async ( - order: Transaction, + order: PgTransaction, sourceTransaction: string[], token: Token, drop: TokenDrop, @@ -257,7 +272,7 @@ const mintedDropToBillPayment = async ( uid: getRandomEthAddress(), space: token.space, member: order.member, - network: order.network, + network: convertEnum(order.network, PgNetwork, Network)!, payload: { type: drop.isBaseToken ? TransactionPayloadType.BASE_AIRDROP_CLAIM @@ -268,7 +283,7 @@ const mintedDropToBillPayment = async ( previousOwner: token.space, ownerEntity: Entity.MEMBER, owner: order.member!, - storageDepositSourceAddress: drop.isBaseToken ? '' : order.payload.targetAddress, + storageDepositSourceAddress: drop.isBaseToken ? '' : order.payload_targetAddress, vestingAt: dayjs(drop.vestingAt.toDate()).isAfter(dayjs()) ? drop.vestingAt : null, sourceAddress: drop.sourceAddress || token.mintingData?.vaultAddress!, targetAddress: memberAddress, @@ -281,7 +296,7 @@ const mintedDropToBillPayment = async ( }; }; -const mintedDropToStake = (order: Transaction, drop: TokenDrop, billPayment: Transaction) => { +const mintedDropToStake = (order: PgTransaction, drop: TokenDrop, billPayment: Transaction) => { const vestingAt = dayjs(drop.vestingAt.toDate()); const weeks = vestingAt.diff(dayjs(), 'w'); if (weeks < 1 || drop.isBaseToken) { @@ -291,7 +306,7 @@ const mintedDropToStake = (order: Transaction, drop: TokenDrop, billPayment: Tra project: getProject(order), uid: getRandomEthAddress(), member: order.member!, - token: order.payload.token!, + token: order.payload_token!, type: drop.stakeType || StakeType.DYNAMIC, space: order.space!, amount: drop.count, @@ -307,7 +322,7 @@ const mintedDropToStake = (order: Transaction, drop: TokenDrop, billPayment: Tra }; const airdropsQuery = ( - order: Transaction, + order: PgTransaction, token: Token, member: string, isPreMintedClaim?: boolean, @@ -316,9 +331,9 @@ const airdropsQuery = ( .collection(COL.AIRDROP) .where('token', '==', token.uid) .where('member', '==', member) - .where('status', '==', TokenDropStatus.UNCLAIMED); + .where('status', '==', PgTokenDropStatus.UNCLAIMED); if (isPreMintedClaim) { - query = query.where('vestingAt', '<=', serverTime()); + query = query.where('vestingAt', '<=', dayjs().toDate()); } else { query = query.where('createdOn', '<=', order.createdOn).orderBy('createdOn'); } @@ -327,23 +342,18 @@ const airdropsQuery = ( }; const runInAirdropLoop = - (order: Transaction, token: Token, isPreMintedClaim?: boolean) => + (order: PgTransaction, token: Token, isPreMintedClaim?: boolean) => async (func: (transaction: ITransaction, airdrop: TokenDrop) => Promise) => { let storageDeposit = 0; for (let i = 0; i < LOOP_SIZE; ++i) { - const snap = await airdropsQuery( - order, - token, - order.member!, - isPreMintedClaim, - ).get(); + const snap = await airdropsQuery(order, token, order.member!, isPreMintedClaim).get(); if (!snap.length) { return storageDeposit; } - const refs = snap.map((airdrop) => build5Db().doc(`${COL.AIRDROP}/${airdrop.uid}`)); storageDeposit += await build5Db().runTransaction(async (transaction) => { + const refs = snap.map((airdrop) => build5Db().doc(COL.AIRDROP, airdrop.uid)); let actStorageDeposit = 0; - const airdrops = (await transaction.getAll(...refs)).filter( + const airdrops = (await transaction.getAll(...refs)).filter( (drop) => drop!.status === TokenDropStatus.UNCLAIMED, ); for (const airdrop of airdrops) { 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 88df0144af..f99d44e131 100644 --- a/packages/functions/src/triggers/transaction-trigger/award.transaction.update.ts +++ b/packages/functions/src/triggers/transaction-trigger/award.transaction.update.ts @@ -1,37 +1,52 @@ -import { build5Db } from '@build-5/database'; -import { COL, Transaction, TransactionPayloadType, TransactionType } from '@build-5/interfaces'; +import { + PgNetwork, + PgTransaction, + PgTransactionPayloadType, + build5Db, + convertEnum, +} from '@build-5/database'; +import { + COL, + Network, + Transaction, + TransactionPayloadType, + TransactionType, +} from '@build-5/interfaces'; import { TransactionPayload, Utils } from '@iota/sdk'; import { getProject } from '../../utils/common.utils'; +import { getPathParts } from '../../utils/milestone'; import { getRandomEthAddress } from '../../utils/wallet.utils'; -export const onAwardUpdate = async (transaction: Transaction) => { - switch (transaction.payload.type) { - case TransactionPayloadType.MINT_ALIAS: { +export const onAwardUpdate = async (transaction: PgTransaction) => { + switch (transaction.payload_type) { + case PgTransactionPayloadType.MINT_ALIAS: { await onAliasMinted(transaction); break; } - case TransactionPayloadType.MINT_COLLECTION: { + case PgTransactionPayloadType.MINT_COLLECTION: { await onCollectionMinted(transaction); break; } - case TransactionPayloadType.BADGE: { + case PgTransactionPayloadType.BADGE: { await onBadgeMinted(transaction); break; } } }; -const onAliasMinted = async (transaction: Transaction) => { - const path = transaction.payload.walletReference?.milestoneTransactionPath!; - const milestoneTransaction = (await build5Db().doc(path).get>())!; +const onAliasMinted = async (transaction: PgTransaction) => { + const { col, colId, subCol, subColId } = getPathParts( + transaction.payload_walletReference_milestoneTransactionPath!, + ); + const milestoneTransaction = (await build5Db().doc(col, colId, subCol, subColId).get())!; const aliasOutputId = Utils.computeOutputId( - Utils.transactionId(milestoneTransaction.payload as TransactionPayload), + Utils.transactionId(milestoneTransaction.payload as unknown as TransactionPayload), 0, ); - const awardDocRef = build5Db().doc(`${COL.AWARD}/${transaction.payload.award}`); + const awardDocRef = build5Db().doc(COL.AWARD, transaction.payload_award!); await awardDocRef.update({ - aliasBlockId: milestoneTransaction.blockId, + aliasBlockId: milestoneTransaction.blockId as string, aliasId: Utils.computeAliasId(aliasOutputId), }); @@ -41,35 +56,37 @@ const onAliasMinted = async (transaction: Transaction) => { uid: getRandomEthAddress(), member: transaction.member, space: transaction.space, - network: transaction.network, + network: convertEnum(transaction.network, PgNetwork, Network)!, payload: { type: TransactionPayloadType.MINT_COLLECTION, - sourceAddress: transaction.payload.sourceAddress, - award: transaction.payload.award, + sourceAddress: transaction.payload_sourceAddress, + award: transaction.payload_award, }, }; - await build5Db().doc(`${COL.TRANSACTION}/${order.uid}`).create(order); + await build5Db().doc(COL.TRANSACTION, order.uid).create(order); }; -const onCollectionMinted = async (transaction: Transaction) => { - const path = transaction.payload.walletReference?.milestoneTransactionPath!; - const milestoneTransaction = (await build5Db().doc(path).get>())!; +const onCollectionMinted = async (transaction: PgTransaction) => { + const { col, colId, subCol, subColId } = getPathParts( + transaction.payload_walletReference_milestoneTransactionPath!, + ); + const milestoneTransaction = (await build5Db().doc(col, colId, subCol, subColId).get())!; const collectionOutputId = Utils.computeOutputId( - Utils.transactionId(milestoneTransaction.payload as TransactionPayload), + Utils.transactionId(milestoneTransaction.payload as unknown as TransactionPayload), 1, ); await build5Db() - .doc(`${COL.AWARD}/${transaction.payload.award}`) + .doc(COL.AWARD, transaction.payload_award!) .update({ - collectionBlockId: milestoneTransaction.blockId, + collectionBlockId: milestoneTransaction.blockId as string, collectionId: Utils.computeNftId(collectionOutputId), approved: true, rejected: false, }); }; -const onBadgeMinted = async (transaction: Transaction) => +const onBadgeMinted = (transaction: PgTransaction) => build5Db() - .doc(`${COL.AWARD}/${transaction.payload.award}`) + .doc(COL.AWARD, transaction.payload_award!) .update({ badgesMinted: build5Db().inc(1) }); diff --git a/packages/functions/src/triggers/transaction-trigger/collection-minting.ts b/packages/functions/src/triggers/transaction-trigger/collection-minting.ts index cf7015348f..b3d9ba20d0 100644 --- a/packages/functions/src/triggers/transaction-trigger/collection-minting.ts +++ b/packages/functions/src/triggers/transaction-trigger/collection-minting.ts @@ -1,40 +1,46 @@ -import { build5Db } from '@build-5/database'; +import { + PgCollectionStatus, + PgNetwork, + PgNftStatus, + PgTransaction, + PgTransactionPayloadType, + build5Db, + convertEnum, +} from '@build-5/database'; import { COL, Collection, - CollectionStatus, - Member, - NftStatus, + Network, Transaction, TransactionPayloadType, TransactionType, } from '@build-5/interfaces'; import { TransactionPayload, Utils } from '@iota/sdk'; import dayjs from 'dayjs'; -import { get } from 'lodash'; import { getAddress } from '../../utils/address.utils'; import { getProject } from '../../utils/common.utils'; +import { getPathParts } from '../../utils/milestone'; import { getRandomEthAddress } from '../../utils/wallet.utils'; -export const onCollectionMintingUpdate = async (transaction: Transaction) => { - switch (transaction.payload.type) { - case TransactionPayloadType.MINT_ALIAS: { +export const onCollectionMintingUpdate = async (transaction: PgTransaction) => { + switch (transaction.payload_type) { + case PgTransactionPayloadType.MINT_ALIAS: { await onCollectionAliasMinted(transaction); break; } - case TransactionPayloadType.MINT_COLLECTION: { + case PgTransactionPayloadType.MINT_COLLECTION: { await onCollectionMinted(transaction); break; } - case TransactionPayloadType.MINT_NFTS: { + case PgTransactionPayloadType.MINT_NFTS: { await onNftMintSuccess(transaction); break; } - case TransactionPayloadType.LOCK_COLLECTION: { + case PgTransactionPayloadType.LOCK_COLLECTION: { await onCollectionLocked(transaction); break; } - case TransactionPayloadType.SEND_ALIAS_TO_GUARDIAN: { + case PgTransactionPayloadType.SEND_ALIAS_TO_GUARDIAN: { await onCollectionAliasTransfered(transaction); break; } @@ -45,20 +51,22 @@ export const onCollectionMintingUpdate = async (transaction: Transaction) => { } }; -const onCollectionAliasMinted = async (transaction: Transaction) => { - const path = transaction.payload.walletReference?.milestoneTransactionPath!; - const milestoneTransaction = (await build5Db().doc(path).get>())!; +const onCollectionAliasMinted = async (transaction: PgTransaction) => { + const { col, colId, subCol, subColId } = getPathParts( + transaction.payload_walletReference_milestoneTransactionPath!, + ); + const milestoneTransaction = (await build5Db().doc(col, colId, subCol, subColId).get())!; const aliasOutputId = Utils.computeOutputId( - Utils.transactionId(milestoneTransaction.payload as TransactionPayload), + Utils.transactionId(milestoneTransaction.payload as unknown as TransactionPayload), 0, ); await build5Db() - .doc(`${COL.COLLECTION}/${transaction.payload.collection}`) + .doc(COL.COLLECTION, transaction.payload_collection!) .update({ - 'mintingData.aliasBlockId': milestoneTransaction.blockId, - 'mintingData.aliasId': Utils.computeAliasId(aliasOutputId), - 'mintingData.aliasStorageDeposit': transaction.payload.amount, + mintingData_aliasBlockId: milestoneTransaction.blockId as string, + mintingData_aliasId: Utils.computeAliasId(aliasOutputId), + mintingData_aliasStorageDeposit: transaction.payload_amount, }); const order: Transaction = { @@ -67,26 +75,28 @@ const onCollectionAliasMinted = async (transaction: Transaction) => { uid: getRandomEthAddress(), member: transaction.member, space: transaction.space, - network: transaction.network, + network: convertEnum(transaction.network, PgNetwork, Network)!, payload: { type: TransactionPayloadType.MINT_COLLECTION, - amount: get(transaction, 'payload.collectionStorageDeposit', 0), - sourceAddress: transaction.payload.sourceAddress, - collection: transaction.payload.collection, + amount: transaction.payload_collectionStorageDeposit || 0, + sourceAddress: transaction.payload_sourceAddress, + collection: transaction.payload_collection, }, }; - await build5Db().doc(`${COL.TRANSACTION}/${order.uid}`).create(order); + await build5Db().doc(COL.TRANSACTION, order.uid).create(order); }; -const onCollectionMinted = async (transaction: Transaction) => { - const path = transaction.payload.walletReference?.milestoneTransactionPath!; - const milestoneTransaction = (await build5Db().doc(path).get>())!; +const onCollectionMinted = async (transaction: PgTransaction) => { + const { col, colId, subCol, subColId } = getPathParts( + transaction.payload_walletReference_milestoneTransactionPath!, + ); + const milestoneTransaction = (await build5Db().doc(col, colId, subCol, subColId).get())!; const collectionOutputId = Utils.computeOutputId( - Utils.transactionId(milestoneTransaction.payload as TransactionPayload), + Utils.transactionId(milestoneTransaction.payload as unknown as TransactionPayload), 1, ); - const collectionDocRef = build5Db().doc(`${COL.COLLECTION}/${transaction.payload.collection}`); - const collection = (await collectionDocRef.get())!; + const collectionDocRef = build5Db().doc(COL.COLLECTION, transaction.payload_collection!); + const collection = (await collectionDocRef.get())!; await saveCollectionMintingData( transaction, milestoneTransaction.blockId as string, @@ -94,97 +104,100 @@ const onCollectionMinted = async (transaction: Transaction) => { ); if (collection.mintingData?.nftsToMint) { const order = createMintNftsTransaction(transaction); - await build5Db().doc(`${COL.TRANSACTION}/${order.uid}`).create(order); + await build5Db().doc(COL.TRANSACTION, order.uid).create(order); } }; const saveCollectionMintingData = ( - transaction: Transaction, + transaction: PgTransaction, blockId: string, collectionOutputId: string, ) => build5Db() - .doc(`${COL.COLLECTION}/${transaction.payload.collection}`) + .doc(COL.COLLECTION, transaction.payload_collection!) .update({ - 'mintingData.blockId': blockId, - 'mintingData.nftId': Utils.computeNftId(collectionOutputId), - 'mintingData.mintedOn': dayjs().toDate(), + mintingData_blockId: blockId, + mintingData_nftId: Utils.computeNftId(collectionOutputId), + mintingData_mintedOn: dayjs().toDate(), }); -const onNftMintSuccess = async (transaction: Transaction) => { +const onNftMintSuccess = async (transaction: PgTransaction) => { const batch = build5Db().batch(); - const collectionDocRef = build5Db().doc(`${COL.COLLECTION}/${transaction.payload.collection}`); + const collectionDocRef = build5Db().doc(COL.COLLECTION, transaction.payload_collection!); const collection = await collectionDocRef.get(); batch.update(collectionDocRef, { - 'mintingData.nftsToMint': build5Db().inc(-transaction.payload.nfts!.length), + mintingData_nftsToMint: build5Db().inc(-transaction.payload_nfts!.length), }); - const milestoneTransaction = (await build5Db() - .doc(transaction.payload.walletReference?.milestoneTransactionPath!) - .get>())!; - transaction.payload.nfts!.forEach((nftId, i) => { + const { col, colId, subCol, subColId } = getPathParts( + transaction.payload_walletReference_milestoneTransactionPath!, + ); + const milestoneTransaction = (await build5Db().doc(col, colId, subCol, subColId).get())!; + for (let i = 0; i < transaction.payload_nfts!.length; ++i) { + const nftId = transaction.payload_nfts![i]; const outputId = Utils.computeOutputId( - Utils.transactionId(milestoneTransaction.payload as TransactionPayload), + Utils.transactionId(milestoneTransaction.payload as unknown as TransactionPayload), i + 2, ); - const docRef = build5Db().doc(`${COL.NFT}/${nftId}`); + const docRef = build5Db().doc(COL.NFT, nftId); batch.update(docRef, { - 'mintingData.network': transaction.network, - 'mintingData.mintedOn': dayjs().toDate(), - 'mintingData.mintedBy': transaction.member, - 'mintingData.blockId': milestoneTransaction.blockId, - 'mintingData.nftId': Utils.computeNftId(outputId), - status: NftStatus.MINTED, + mintingData_network: transaction.network, + mintingData_mintedOn: dayjs().toDate(), + mintingData_mintedBy: transaction.member, + mintingData_blockId: milestoneTransaction.blockId as string, + mintingData_nftId: Utils.computeNftId(outputId), + status: PgNftStatus.MINTED, }); - }); + } - if (collection.mintingData?.nftsToMint! - transaction.payload.nfts!.length > 0) { + if (collection.mintingData?.nftsToMint! - transaction.payload_nfts!.length > 0) { const order = createMintNftsTransaction(transaction); - const docRef = build5Db().doc(`${COL.TRANSACTION}/${order.uid}`); + const docRef = build5Db().doc(COL.TRANSACTION, order.uid); batch.create(docRef, order); } await batch.commit(); }; -const createMintNftsTransaction = (transaction: Transaction): Transaction => ({ +const createMintNftsTransaction = (transaction: PgTransaction): Transaction => ({ project: getProject(transaction), type: TransactionType.MINT_COLLECTION, uid: getRandomEthAddress(), member: transaction.member, space: transaction.space, - network: transaction.network, + network: convertEnum(transaction.network, PgNetwork, Network)!, payload: { type: TransactionPayloadType.MINT_NFTS, - sourceAddress: transaction.payload.sourceAddress, - collection: transaction.payload.collection, + sourceAddress: transaction.payload_sourceAddress, + collection: transaction.payload_collection, }, }); -const onCollectionLocked = async (transaction: Transaction) => { - const member = (await build5Db().doc(`${COL.MEMBER}/${transaction.member}`).get())!; +const onCollectionLocked = async (transaction: PgTransaction) => { + const member = (await build5Db().doc(COL.MEMBER, transaction.member!).get())!; + const network = convertEnum(transaction.network, PgNetwork, Network)!; const order: Transaction = { project: getProject(transaction), type: TransactionType.MINT_COLLECTION, uid: getRandomEthAddress(), member: transaction.member, space: transaction.space, - network: transaction.network, + network, payload: { type: TransactionPayloadType.SEND_ALIAS_TO_GUARDIAN, - amount: transaction.payload.aliasStorageDeposit, - sourceAddress: transaction.payload.sourceAddress, - targetAddress: getAddress(member, transaction.network!), - collection: transaction.payload.collection, + amount: transaction.payload_aliasStorageDeposit, + sourceAddress: transaction.payload_sourceAddress, + targetAddress: getAddress(member, network), + collection: transaction.payload_collection, }, }; - await build5Db().doc(`${COL.TRANSACTION}/${order.uid}`).create(order); + await build5Db().doc(COL.TRANSACTION, order.uid).create(order); }; -const onCollectionAliasTransfered = async (transaction: Transaction) => +const onCollectionAliasTransfered = (transaction: PgTransaction) => build5Db() - .doc(`${COL.COLLECTION}/${transaction.payload.collection}`) - .update({ status: CollectionStatus.MINTED, approved: true }); + .doc(COL.COLLECTION, transaction.payload_collection!) + .update({ status: PgCollectionStatus.MINTED, approved: true }); diff --git a/packages/functions/src/triggers/transaction-trigger/matadatNft-minting.ts b/packages/functions/src/triggers/transaction-trigger/matadatNft-minting.ts index 663e81cc18..4929544bc2 100644 --- a/packages/functions/src/triggers/transaction-trigger/matadatNft-minting.ts +++ b/packages/functions/src/triggers/transaction-trigger/matadatNft-minting.ts @@ -1,19 +1,22 @@ -import { build5Db } from '@build-5/database'; +import { + PgNetwork, + PgNftStatus, + PgTransaction, + PgTransactionPayloadType, + build5Db, + convertEnum, +} from '@build-5/database'; import { COL, Collection, DEFAULT_NETWORK, - Member, - Nft, - NftStatus, - Space, + Network, Transaction, TransactionPayloadType, TransactionType, } from '@build-5/interfaces'; import { TransactionPayload, Utils } from '@iota/sdk'; import dayjs from 'dayjs'; -import { get } from 'lodash'; import { createMetadataCollection, createMetadataNft, @@ -23,162 +26,160 @@ import { import { WalletService } from '../../services/wallet/wallet.service'; import { getAddress } from '../../utils/address.utils'; import { getProject } from '../../utils/common.utils'; -import { dateToTimestamp } from '../../utils/dateTime.utils'; +import { getPathParts } from '../../utils/milestone'; import { getRandomEthAddress } from '../../utils/wallet.utils'; -export const onMetadataNftMintUpdate = async (transaction: Transaction) => { - switch (transaction.payload.type) { - case TransactionPayloadType.MINT_ALIAS: { +export const onMetadataNftMintUpdate = async (transaction: PgTransaction) => { + switch (transaction.payload_type) { + case PgTransactionPayloadType.MINT_ALIAS: { await onAliasMinted(transaction); break; } - case TransactionPayloadType.MINT_COLLECTION: { + case PgTransactionPayloadType.MINT_COLLECTION: { await onCollectionMinted(transaction); break; } - case TransactionPayloadType.MINT_NFT: { + case PgTransactionPayloadType.MINT_NFT: { await onNftMinted(transaction); break; } - case TransactionPayloadType.UPDATE_MINTED_NFT: { + case PgTransactionPayloadType.UPDATE_MINTED_NFT: { await onNftUpdated(transaction); break; } } }; -const onAliasMinted = async (transaction: Transaction) => { - const path = transaction.payload.walletReference?.milestoneTransactionPath!; - const milestoneTransaction = (await build5Db().doc(path).get>())!; +const onAliasMinted = async (transaction: PgTransaction) => { + const { col, colId, subCol, subColId } = getPathParts( + transaction.payload_walletReference_milestoneTransactionPath!, + ); + const milestoneTransaction = (await build5Db().doc(col, colId, subCol, subColId).get())!; const aliasOutputId = Utils.computeOutputId( - Utils.transactionId(milestoneTransaction.payload as TransactionPayload), + Utils.transactionId(milestoneTransaction.payload as unknown as TransactionPayload), 0, ); const aliasId = Utils.computeAliasId(aliasOutputId); const batch = build5Db().batch(); - const spaceDocRef = build5Db().doc(`${COL.SPACE}/${transaction.space}`); + const spaceDocRef = build5Db().doc(COL.SPACE, transaction.space!); batch.update(spaceDocRef, { name: `Space of alias: ${aliasId}`, - alias: { - address: transaction.payload.targetAddress, - aliasId, - blockId: milestoneTransaction.blockId, - mintedOn: dateToTimestamp(dayjs()), - mintedBy: transaction.member, - }, + alias_address: transaction.payload_targetAddress, + alias_aliasId: aliasId, + alias_blockId: milestoneTransaction.blockId as string, + alias_mintedOn: dayjs().toDate(), + alias_mintedBy: transaction.member, }); const collection = createMetadataCollection(getProject(transaction), transaction.space!); - const collectionDocRef = build5Db().doc(`${COL.COLLECTION}/${collection.uid}`); - batch.create(collectionDocRef, collection); + const collectionDocRef = build5Db().doc(COL.COLLECTION, collection.uid); + batch.create(collectionDocRef, collection as Collection); const order = createMintMetadataCollectionOrder( transaction, collection.uid, aliasId, - get(transaction, 'payload.orderId', ''), - transaction.payload.targetAddress!, + transaction.payload_orderId!, + transaction.payload_targetAddress!, milestoneTransaction.blockId as string, ); - const orderDocRef = build5Db().doc(`${COL.TRANSACTION}/${order.uid}`); + const orderDocRef = build5Db().doc(COL.TRANSACTION, order.uid); batch.create(orderDocRef, order); await batch.commit(); }; -const onCollectionMinted = async (transaction: Transaction) => { - const path = transaction.payload.walletReference?.milestoneTransactionPath!; - const milestoneTransaction = (await build5Db().doc(path).get>())!; +const onCollectionMinted = async (transaction: PgTransaction) => { + const { col, colId, subCol, subColId } = getPathParts( + transaction.payload_walletReference_milestoneTransactionPath!, + ); + const milestoneTransaction = (await build5Db().doc(col, colId, subCol, subColId).get())!; const collectionOutputId = Utils.computeOutputId( - Utils.transactionId(milestoneTransaction.payload as TransactionPayload), + Utils.transactionId(milestoneTransaction.payload as unknown as TransactionPayload), 1, ); const collectionId = Utils.computeNftId(collectionOutputId); const batch = build5Db().batch(); - const collectionDocRef = build5Db().doc(`${COL.COLLECTION}/${transaction.payload.collection}`); + const collectionDocRef = build5Db().doc(COL.COLLECTION, transaction.payload_collection!); batch.update(collectionDocRef, { - mintingData: { - address: transaction.payload.targetAddress, - network: transaction.network, - mintedOn: dateToTimestamp(dayjs()), - mintedBy: transaction.member, - blockId: milestoneTransaction.blockId, - nftId: collectionId, - storageDeposit: get(transaction, 'payload.collectionOutputAmount', 0), - aliasBlockId: get(transaction, 'payload.aliasBlockId', ''), - aliasId: get(transaction, 'payload.aliasId', ''), - }, + mintingData_address: transaction.payload_targetAddress, + mintingData_network: transaction.network, + mintingData_mintedOn: dayjs().toDate(), + mintingData_mintedBy: transaction.member, + mintingData_blockId: milestoneTransaction.blockId as string, + mintingData_nftId: collectionId, + mintingData_storageDeposit: transaction.payload_collectionOutputAmount, + mintingData_aliasBlockId: transaction.payload_aliasBlockId, + mintingData_aliasId: transaction.payload_aliasId, }); - const order = await build5Db() - .doc(`${COL.TRANSACTION}/${transaction.payload.orderId}`) - .get(); + const order = (await build5Db().doc(COL.TRANSACTION, transaction.payload_orderId!).get())!; const nft = createMetadataNft( getProject(transaction), transaction.member!, transaction.space!, - transaction.payload.collection!, - get(order, 'payload.metadata', {}), + transaction.payload_collection!, + order.payload.metadata || {}, ); - const nftDocRef = build5Db().doc(`${COL.NFT}/${nft.uid}`); + const nftDocRef = build5Db().doc(COL.NFT, nft.uid); batch.create(nftDocRef, nft); - const space = await build5Db().doc(`${COL.SPACE}/${transaction.space}`).get(); + const space = await build5Db().doc(COL.SPACE, transaction.space!).get(); const nftMintOrder = createMintMetadataNftOrder( transaction, nft, space?.alias?.address!, collectionId, - get(transaction, 'payload.orderId', ''), + transaction.payload_orderId!, ); - const nftMintOrderDocRef = build5Db().doc(`${COL.TRANSACTION}/${nftMintOrder.uid}`); + const nftMintOrderDocRef = build5Db().doc(COL.TRANSACTION, nftMintOrder.uid); batch.create(nftMintOrderDocRef, nftMintOrder); await batch.commit(); }; -const onNftMinted = async (transaction: Transaction) => { - const path = transaction.payload.walletReference?.milestoneTransactionPath!; - const milestoneTransaction = (await build5Db().doc(path).get>())!; +const onNftMinted = async (transaction: PgTransaction) => { + const { col, colId, subCol, subColId } = getPathParts( + transaction.payload_walletReference_milestoneTransactionPath!, + ); + const milestoneTransaction = (await build5Db().doc(col, colId, subCol, subColId).get())!; const nftOutputId = Utils.computeOutputId( - Utils.transactionId(milestoneTransaction.payload as TransactionPayload), + Utils.transactionId(milestoneTransaction.payload as unknown as TransactionPayload), 2, ); const nftId = Utils.computeNftId(nftOutputId); const batch = build5Db().batch(); - const nftDocRef = build5Db().doc(`${COL.NFT}/${transaction.payload.nft}`); - const nft = await nftDocRef.get(); + const nftDocRef = build5Db().doc(COL.NFT, transaction.payload_nft!); + const nft = await nftDocRef.get(); batch.update(nftDocRef, { - status: NftStatus.MINTED, - mintingData: { - address: transaction.payload.targetAddress, - network: transaction.network, - mintedOn: dateToTimestamp(dayjs()), - mintedBy: transaction.member, - blockId: milestoneTransaction.blockId, - nftId, - }, + status: PgNftStatus.MINTED, + mintingData_address: transaction.payload_targetAddress, + mintingData_network: transaction.network, + mintingData_mintedOn: dayjs().toDate(), + mintingData_mintedBy: transaction.member, + mintingData_blockId: milestoneTransaction.blockId as string, + mintingData_nftId: nftId, }); - const orderDocRef = build5Db().doc(`${COL.TRANSACTION}/${transaction.payload.orderId}`); + const orderDocRef = build5Db().doc(COL.TRANSACTION, transaction.payload_orderId!); const order = await orderDocRef.get(); const storageDepositTotal = - get(order, 'payload.aliasOutputAmount', 0) + - get(order, 'payload.collectionOutputAmount', 0) + - get(order, 'payload.nftOutputAmount', 0); + (order.payload.aliasOutputAmount || 0) + + (order.payload.collectionOutputAmount || 0) + + (order.payload.nftOutputAmount || 0); - const member = await build5Db().doc(`${COL.MEMBER}/${transaction.member}`).get(); - const collection = await build5Db().doc(`${COL.COLLECTION}/${nft?.collection}`).get(); - const space = await build5Db().doc(`${COL.SPACE}/${collection?.space}`).get(); + const member = await build5Db().doc(COL.MEMBER, transaction.member!).get(); + const collection = await build5Db().doc(COL.COLLECTION, nft?.collection!).get(); + const space = await build5Db().doc(COL.SPACE, collection?.space!).get(); const remainder = order.payload.amount! - storageDepositTotal; @@ -205,31 +206,30 @@ const onNftMinted = async (transaction: Transaction) => { tag: order.payload.tag || '', }, }; - const creditDocRef = build5Db().doc(`${COL.TRANSACTION}/${creditTransaction.uid}`); + const creditDocRef = build5Db().doc(COL.TRANSACTION, creditTransaction.uid); batch.create(creditDocRef, creditTransaction); } await batch.commit(); }; -const onNftUpdated = async (transaction: Transaction) => { +const onNftUpdated = async (transaction: PgTransaction) => { const batch = build5Db().batch(); - const orderDocRef = build5Db().doc(`${COL.TRANSACTION}/${transaction.payload.orderId}`); + const orderDocRef = build5Db().doc(COL.TRANSACTION, transaction.payload_orderId!); const order = await orderDocRef.get(); - const nftDocRef = build5Db().doc(`${COL.NFT}/${transaction.payload.nft}`); - const nft = await nftDocRef.get(); - batch.update(nftDocRef, { - properties: order.payload.metadata, - }); + const nftDocRef = build5Db().doc(COL.NFT, transaction.payload_nft!); + const nft = await nftDocRef.get(); + batch.update(nftDocRef, { properties: JSON.stringify(order.payload.metadata) }); - const wallet = await WalletService.newWallet(transaction.network!); + const network = convertEnum(transaction.network!, PgNetwork, Network); + const wallet = await WalletService.newWallet(network!); const { amount: balance } = await wallet.getBalance(order.payload.targetAddress!); - const member = await build5Db().doc(`${COL.MEMBER}/${transaction.member}`).get(); - const collection = await build5Db().doc(`${COL.COLLECTION}/${nft?.collection}`).get(); - const space = await build5Db().doc(`${COL.SPACE}/${collection?.space}`).get(); + const member = await build5Db().doc(COL.MEMBER, transaction.member!).get(); + const collection = await build5Db().doc(COL.COLLECTION, nft?.collection!).get(); + const space = await build5Db().doc(COL.SPACE, collection?.space!).get(); if (Number(balance)) { const creditTransaction: Transaction = { @@ -254,7 +254,7 @@ const onNftUpdated = async (transaction: Transaction) => { tag: order.payload.tag || '', }, }; - const creditDocRef = build5Db().doc(`${COL.TRANSACTION}/${creditTransaction.uid}`); + const creditDocRef = build5Db().doc(COL.TRANSACTION, creditTransaction.uid); batch.create(creditDocRef, creditTransaction); } diff --git a/packages/functions/src/triggers/transaction-trigger/nft-staked.ts b/packages/functions/src/triggers/transaction-trigger/nft-staked.ts index 48b6916bb7..85d2aee419 100644 --- a/packages/functions/src/triggers/transaction-trigger/nft-staked.ts +++ b/packages/functions/src/triggers/transaction-trigger/nft-staked.ts @@ -1,31 +1,32 @@ -import { build5Db } from '@build-5/database'; -import { COL, Nft, Transaction } from '@build-5/interfaces'; +import { PgStakeType, PgTransaction, build5Db, convertEnum } from '@build-5/database'; +import { COL, StakeType } from '@build-5/interfaces'; import { getProject } from '../../utils/common.utils'; +import { dateToTimestamp } from '../../utils/dateTime.utils'; import { getRandomEthAddress } from '../../utils/wallet.utils'; -export const onNftStaked = async (transaction: Transaction) => { - const nftDocRef = build5Db().doc(`${COL.NFT}/${transaction.payload.nft}`); - const nft = (await nftDocRef.get())!; +export const onNftStaked = async (transaction: PgTransaction) => { + const nftDocRef = build5Db().doc(COL.NFT, transaction.payload_nft!); + const nft = (await nftDocRef.get())!; const nftStake = { project: getProject(transaction), uid: getRandomEthAddress(), - member: transaction.member, + member: transaction.member!, space: nft.space, nft: nft.uid, collection: nft.collection, - weeks: transaction.payload.weeks, - expiresAt: transaction.payload.vestingAt, + weeks: transaction.payload_weeks!, + expiresAt: dateToTimestamp(transaction.payload_vestingAt!), expirationProcessed: false, - type: transaction.payload.stakeType, + type: convertEnum(transaction.payload_stakeType!, PgStakeType, StakeType)!, }; const batch = build5Db().batch(); - const nftStakeDocRef = build5Db().doc(`${COL.NFT_STAKE}/${nftStake.uid}`); + const nftStakeDocRef = build5Db().doc(COL.NFT_STAKE, nftStake.uid); batch.create(nftStakeDocRef, nftStake); - const collectionDocRef = build5Db().doc(`${COL.COLLECTION}/${nft.collection}`); + const collectionDocRef = build5Db().doc(COL.COLLECTION, nft.collection); batch.update(collectionDocRef, { stakedNft: build5Db().inc(1) }); await batch.commit(); diff --git a/packages/functions/src/triggers/transaction-trigger/proposal.vote.ts b/packages/functions/src/triggers/transaction-trigger/proposal.vote.ts index 4b37aedd2d..a1c7d240e1 100644 --- a/packages/functions/src/triggers/transaction-trigger/proposal.vote.ts +++ b/packages/functions/src/triggers/transaction-trigger/proposal.vote.ts @@ -1,19 +1,28 @@ -import { build5Db } from '@build-5/database'; -import { COL, Transaction, TransactionType } from '@build-5/interfaces'; +import { + PgNetwork, + PgTransaction, + PgTransactionType, + build5Db, + convertEnum, +} from '@build-5/database'; +import { COL, Network } from '@build-5/interfaces'; +import { getPathParts } from '../../utils/milestone'; import { MilestoneTransactionAdapter } from '../milestone-transactions-triggers/MilestoneTransactionAdapter'; -export const onProposalVoteCreditConfirmed = async (transaction: Transaction) => { - const milestoneDoc = (await build5Db() - .doc(transaction.payload.walletReference?.milestoneTransactionPath!) - .get>())!; - const adapter = new MilestoneTransactionAdapter(transaction.network!); - const milestoneTransaction = await adapter.toMilestoneTransaction(milestoneDoc); +export const onProposalVoteCreditConfirmed = async (transaction: PgTransaction) => { + const { col, colId, subCol, subColId } = getPathParts( + transaction.payload_walletReference_milestoneTransactionPath!, + ); + const milestone = (await build5Db().doc(col, colId, subCol, subColId).get())!; + const network = convertEnum(transaction.network!, PgNetwork, Network)!; + const adapter = new MilestoneTransactionAdapter(network); + const milestoneTransaction = await adapter.toMilestoneTransaction(milestone); const outputId = milestoneTransaction.outputs[0].outputId!; const voteTransactionSnap = await build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.VOTE) - .where('payload.creditId', '==', transaction.uid) - .get(); - const voteTransactionDoc = build5Db().doc(`${COL.TRANSACTION}/${voteTransactionSnap[0].uid}`); - await voteTransactionDoc.update({ 'payload.outputId': outputId }); + .where('type', '==', PgTransactionType.VOTE) + .where('payload_creditId', '==', transaction.uid) + .get(); + const voteTransactionDoc = build5Db().doc(COL.TRANSACTION, voteTransactionSnap[0].uid); + await voteTransactionDoc.update({ payload_outputId: outputId }); }; diff --git a/packages/functions/src/triggers/transaction-trigger/staking.ts b/packages/functions/src/triggers/transaction-trigger/staking.ts index f5f9504fa6..19aeeba173 100644 --- a/packages/functions/src/triggers/transaction-trigger/staking.ts +++ b/packages/functions/src/triggers/transaction-trigger/staking.ts @@ -1,48 +1,36 @@ -import { build5Db } from '@build-5/database'; -import { COL, Stake, SUB_COL, Transaction } from '@build-5/interfaces'; +import { PgTokenStatsUpdate, PgTransaction, build5Db } from '@build-5/database'; +import { COL, SUB_COL } from '@build-5/interfaces'; import { onStakeCreated } from '../../services/stake.service'; -export const onStakingConfirmed = async (billPayment: Transaction) => { - const stakeDocRef = build5Db().doc(`${COL.STAKE}/${billPayment.payload.stake}`); - const stake = (await stakeDocRef.get())!; +export const onStakingConfirmed = async (billPayment: PgTransaction) => { + const stakeDocRef = build5Db().doc(COL.STAKE, billPayment.payload_stake!); + const stake = (await stakeDocRef.get())!; await build5Db().runTransaction((transaction) => onStakeCreated(transaction, stake)); + const tokenUid = billPayment.payload_token; + const batch = build5Db().batch(); - const updateData = { - stakes: { - [stake.type]: { - amount: build5Db().inc(stake.amount), - totalAmount: build5Db().inc(stake.amount), - value: build5Db().inc(stake.value), - totalValue: build5Db().inc(stake.value), - }, - }, - stakeExpiry: { - [stake.type]: { - [stake.expiresAt.toMillis()]: stake.value, - }, - }, + const updateData: PgTokenStatsUpdate = { + [`stakes_${stake.type}_amount`]: build5Db().inc(stake.amount), + [`stakes_${stake.type}_totalAmount`]: build5Db().inc(stake.amount), + [`stakes_${stake.type}_value`]: build5Db().inc(stake.value), + [`stakes_${stake.type}_totalValue`]: build5Db().inc(stake.value), + stakeExpiry: { [stake.type]: { [stake.expiresAt.toMillis()]: stake.value } }, + parentId: tokenUid!, }; - const tokenUid = billPayment.payload.token; - const tokenDocRef = build5Db().doc(`${COL.TOKEN}/${tokenUid}/${SUB_COL.STATS}/${tokenUid}`); - batch.set(tokenDocRef, { stakes: updateData.stakes }, true); + const tokenDocRef = build5Db().doc(COL.TOKEN, tokenUid!, SUB_COL.STATS, tokenUid); + batch.upsert(tokenDocRef, updateData); const distirbutionDocRef = build5Db().doc( - `${COL.TOKEN}/${tokenUid}/${SUB_COL.DISTRIBUTION}/${billPayment.member}`, - ); - batch.set( - distirbutionDocRef, - { - parentId: tokenUid, - parentCol: COL.TOKEN, - uid: billPayment.member, - ...updateData, - }, - true, + COL.TOKEN, + tokenUid!, + SUB_COL.DISTRIBUTION, + billPayment.member, ); + batch.upsert(distirbutionDocRef, updateData); await batch.commit(); }; diff --git a/packages/functions/src/triggers/transaction-trigger/stamp-minting.ts b/packages/functions/src/triggers/transaction-trigger/stamp-minting.ts index b405efdd3f..393c3546cb 100644 --- a/packages/functions/src/triggers/transaction-trigger/stamp-minting.ts +++ b/packages/functions/src/triggers/transaction-trigger/stamp-minting.ts @@ -1,48 +1,59 @@ -import { build5Db } from '@build-5/database'; -import { COL, Transaction, TransactionPayloadType, TransactionType } from '@build-5/interfaces'; +import { + PgNetwork, + PgTransaction, + PgTransactionPayloadType, + build5Db, + convertEnum, +} from '@build-5/database'; +import { + COL, + Network, + Transaction, + TransactionPayloadType, + TransactionType, +} from '@build-5/interfaces'; import { TransactionPayload, Utils } from '@iota/sdk'; import dayjs from 'dayjs'; import { getProject } from '../../utils/common.utils'; -import { dateToTimestamp } from '../../utils/dateTime.utils'; +import { getPathParts } from '../../utils/milestone'; import { getRandomEthAddress } from '../../utils/wallet.utils'; -export const onStampMintUpdate = async (transaction: Transaction) => { - switch (transaction.payload.type) { - case TransactionPayloadType.MINT_ALIAS: { +export const onStampMintUpdate = async (transaction: PgTransaction) => { + switch (transaction.payload_type) { + case PgTransactionPayloadType.MINT_ALIAS: { await onAliasMinted(transaction); break; } - case TransactionPayloadType.MINT_NFT: { + case PgTransactionPayloadType.MINT_NFT: { await onNftMinted(transaction); break; } } }; -const onAliasMinted = async (transaction: Transaction) => { - const path = transaction.payload.walletReference?.milestoneTransactionPath!; - const milestoneTransaction = (await build5Db().doc(path).get>())!; +const onAliasMinted = async (transaction: PgTransaction) => { + const path = transaction.payload_walletReference_milestoneTransactionPath!; + const { col, colId, subCol, subColId } = getPathParts(path); + const milestoneTransaction = (await build5Db().doc(col, colId, subCol, subColId).get())!; const aliasOutputId = Utils.computeOutputId( - Utils.transactionId(milestoneTransaction.payload as TransactionPayload), + Utils.transactionId(milestoneTransaction.payload as unknown as TransactionPayload), 0, ); const aliasId = Utils.computeAliasId(aliasOutputId); const batch = build5Db().batch(); - const stampDocRef = build5Db().doc(`${COL.STAMP}/${transaction.payload.stamp}`); + const stampDocRef = build5Db().doc(COL.STAMP, transaction.payload_stamp!); batch.update(stampDocRef, { aliasId }); - const spaceDocRef = build5Db().doc(`${COL.SPACE}/${transaction.space}`); + const spaceDocRef = build5Db().doc(COL.SPACE, transaction.space!); batch.update(spaceDocRef, { name: `Space of alias: ${aliasId}`, - alias: { - address: transaction.payload.targetAddress, - aliasId, - blockId: milestoneTransaction.blockId, - mintedOn: dateToTimestamp(dayjs()), - mintedBy: transaction.member, - }, + alias_address: transaction.payload_targetAddress, + alias_aliasId: aliasId, + alias_blockId: milestoneTransaction.blockId as string, + alias_mintedOn: dayjs().toDate(), + alias_mintedBy: transaction.member, }); const mintNftOrder: Transaction = { @@ -51,30 +62,31 @@ const onAliasMinted = async (transaction: Transaction) => { uid: getRandomEthAddress(), member: transaction.member, space: transaction.space, - network: transaction.network, + network: convertEnum(transaction.network, PgNetwork, Network)!, payload: { type: TransactionPayloadType.MINT_NFT, - sourceAddress: transaction.payload.targetAddress, - aliasGovAddress: transaction.payload.targetAddress, - targetAddress: transaction.payload.targetAddress, + sourceAddress: transaction.payload_targetAddress, + aliasGovAddress: transaction.payload_targetAddress, + targetAddress: transaction.payload_targetAddress, aliasId, - stamp: transaction.payload.stamp, + stamp: transaction.payload_stamp, }, }; - const orderDocRef = build5Db().doc(`${COL.TRANSACTION}/${mintNftOrder.uid}`); + const orderDocRef = build5Db().doc(COL.TRANSACTION, mintNftOrder.uid); batch.create(orderDocRef, mintNftOrder); await batch.commit(); }; -const onNftMinted = async (transaction: Transaction) => { - const path = transaction.payload.walletReference?.milestoneTransactionPath!; - const milestoneTransaction = (await build5Db().doc(path).get>())!; +const onNftMinted = async (transaction: PgTransaction) => { + const path = transaction.payload_walletReference_milestoneTransactionPath!; + const { col, colId, subCol, subColId } = getPathParts(path); + const milestoneTransaction = (await build5Db().doc(col, colId, subCol, subColId).get())!; const nftOutputId = Utils.computeOutputId( - Utils.transactionId(milestoneTransaction.payload as TransactionPayload), + Utils.transactionId(milestoneTransaction.payload as unknown as TransactionPayload), 1, ); const nftId = Utils.computeNftId(nftOutputId); - const stampDocRef = build5Db().doc(`${COL.STAMP}/${transaction.payload.stamp}`); + const stampDocRef = build5Db().doc(COL.STAMP, transaction.payload_stamp!); await stampDocRef.update({ nftId }); }; diff --git a/packages/functions/src/triggers/transaction-trigger/token-minting.ts b/packages/functions/src/triggers/transaction-trigger/token-minting.ts index 247f06ce53..81bb941eb1 100644 --- a/packages/functions/src/triggers/transaction-trigger/token-minting.ts +++ b/packages/functions/src/triggers/transaction-trigger/token-minting.ts @@ -1,9 +1,16 @@ -import { build5Db } from '@build-5/database'; +import { + PgNetwork, + PgTokenStatus, + PgTransaction, + PgTransactionPayloadType, + build5Db, + convertEnum, +} from '@build-5/database'; import { COL, Member, + Network, Token, - TokenStatus, Transaction, TransactionPayloadType, TransactionType, @@ -20,19 +27,20 @@ import { import dayjs from 'dayjs'; import { getAddress } from '../../utils/address.utils'; import { getProject } from '../../utils/common.utils'; +import { getPathParts } from '../../utils/milestone'; import { getRandomEthAddress } from '../../utils/wallet.utils'; -export const onTokenMintingUpdate = async (transaction: Transaction) => { - switch (transaction.payload.type) { - case TransactionPayloadType.MINT_ALIAS: { +export const onTokenMintingUpdate = async (transaction: PgTransaction) => { + switch (transaction.payload_type) { + case PgTransactionPayloadType.MINT_ALIAS: { await onAliasMinted(transaction); break; } - case TransactionPayloadType.MINT_FOUNDRY: { + case PgTransactionPayloadType.MINT_FOUNDRY: { await onFoundryMinted(transaction); break; } - case TransactionPayloadType.SEND_ALIAS_TO_GUARDIAN: { + case PgTransactionPayloadType.SEND_ALIAS_TO_GUARDIAN: { await onAliasSendToGuardian(transaction); break; } @@ -43,47 +51,49 @@ export const onTokenMintingUpdate = async (transaction: Transaction) => { } }; -const onAliasMinted = async (transaction: Transaction) => { - const path = transaction.payload.walletReference?.milestoneTransactionPath!; - const milestoneTransaction = (await build5Db().doc(path).get>())!; +const onAliasMinted = async (transaction: PgTransaction) => { + const path = transaction.payload_walletReference_milestoneTransactionPath!; + const { col, colId, subCol, subColId } = getPathParts(path); + const milestoneTransaction = (await build5Db().doc(col, colId, subCol, subColId).get())!; const aliasOutputId = Utils.computeOutputId( - Utils.transactionId(milestoneTransaction.payload as TransactionPayload), + Utils.transactionId(milestoneTransaction.payload as unknown as TransactionPayload), 0, ); await build5Db() - .doc(`${COL.TOKEN}/${transaction.payload.token}`) + .doc(COL.TOKEN, transaction.payload_token!) .update({ - 'mintingData.aliasBlockId': milestoneTransaction.blockId, - 'mintingData.aliasId': Utils.computeAliasId(aliasOutputId), + mintingData_aliasBlockId: milestoneTransaction.blockId as string, + mintingData_aliasId: Utils.computeAliasId(aliasOutputId), }); - const token = await build5Db().doc(`${COL.TOKEN}/${transaction.payload.token}`).get(); + const token = await build5Db().doc(COL.TOKEN, transaction.payload_token!).get(); const order: Transaction = { project: getProject(transaction), type: TransactionType.MINT_TOKEN, uid: getRandomEthAddress(), member: transaction.member, space: transaction.space, - network: transaction.network, + network: convertEnum(transaction.network, PgNetwork, Network)!, payload: { type: TransactionPayloadType.MINT_FOUNDRY, amount: token.mintingData?.foundryStorageDeposit! + token.mintingData?.vaultStorageDeposit! + token.mintingData?.guardianStorageDeposit!, - sourceAddress: transaction.payload.sourceAddress, - token: transaction.payload.token, + sourceAddress: transaction.payload_sourceAddress, + token: transaction.payload_token, }, }; - await build5Db().doc(`${COL.TRANSACTION}/${order.uid}`).create(order); + await build5Db().doc(COL.TRANSACTION, order.uid).create(order); }; -const onFoundryMinted = async (transaction: Transaction) => { - const path = transaction.payload.walletReference?.milestoneTransactionPath!; - const milestoneTransaction = (await build5Db().doc(path).get>())!; +const onFoundryMinted = async (transaction: PgTransaction) => { + const path = transaction.payload_walletReference_milestoneTransactionPath!; + const { col, colId, subCol, subColId } = getPathParts(path); + const milestoneTransaction = (await build5Db().doc(col, colId, subCol, subColId).get())!; - const payload = milestoneTransaction.payload as TransactionPayload; + const payload = milestoneTransaction.payload as unknown as TransactionPayload; const essence = payload.essence as RegularTransactionEssence; const aliasOutput = essence.outputs.find((o) => o.type === OutputType.Alias); const foundryOutput = essence.outputs.find((o) => o.type === OutputType.Foundry); @@ -98,40 +108,40 @@ const onFoundryMinted = async (transaction: Transaction) => { const totalSupply = Number(tokenScheme.maximumSupply); await build5Db() - .doc(`${COL.TOKEN}/${transaction.payload.token}`) + .doc(COL.TOKEN, transaction.payload_token!) .update({ - 'mintingData.blockId': milestoneTransaction.blockId, - 'mintingData.tokenId': foundryId, - 'mintingData.meltedTokens': meltedTokens, - 'mintingData.circulatingSupply': totalSupply - meltedTokens, + mintingData_blockId: milestoneTransaction.blockId as string, + mintingData_tokenId: foundryId, + mintingData_meltedTokens: meltedTokens, + mintingData_circulatingSupply: totalSupply - meltedTokens, }); - const token = await build5Db().doc(`${COL.TOKEN}/${transaction.payload.token}`).get(); - const member = await build5Db().doc(`${COL.MEMBER}/${token.mintingData?.mintedBy}`).get(); + const token = await build5Db().doc(COL.TOKEN, transaction.payload_token!).get(); + const member = await build5Db().doc(COL.MEMBER, token.mintingData?.mintedBy!).get(); const order: Transaction = { project: getProject(transaction), type: TransactionType.MINT_TOKEN, uid: getRandomEthAddress(), member: transaction.member, space: transaction.space, - network: transaction.network, + network: convertEnum(transaction.network, PgNetwork, Network)!, payload: { type: TransactionPayloadType.SEND_ALIAS_TO_GUARDIAN, amount: token.mintingData?.aliasStorageDeposit!, - sourceAddress: transaction.payload.sourceAddress, + sourceAddress: transaction.payload_sourceAddress, targetAddress: getAddress(member, token.mintingData?.network!), - token: transaction.payload.token, + token: transaction.payload_token, }, }; - await build5Db().doc(`${COL.TRANSACTION}/${order.uid}`).create(order); + await build5Db().doc(COL.TRANSACTION, order.uid).create(order); }; -const onAliasSendToGuardian = async (transaction: Transaction) => { - const tokenDocRef = build5Db().doc(`${COL.TOKEN}/${transaction.payload.token}`); +const onAliasSendToGuardian = async (transaction: PgTransaction) => { + const tokenDocRef = build5Db().doc(COL.TOKEN, transaction.payload_token!); const token = await tokenDocRef.get(); await tokenDocRef.update({ - 'mintingData.mintedOn': dayjs().toDate(), - status: TokenStatus.MINTED, + mintingData_mintedOn: dayjs().toDate(), + status: PgTokenStatus.MINTED, approved: true, tradingDisabled: !token.public || token.tradingDisabled || false, }); diff --git a/packages/functions/src/triggers/transaction-trigger/transaction.trigger.ts b/packages/functions/src/triggers/transaction-trigger/transaction.trigger.ts index 02f2bf3566..5d2e3a9100 100644 --- a/packages/functions/src/triggers/transaction-trigger/transaction.trigger.ts +++ b/packages/functions/src/triggers/transaction-trigger/transaction.trigger.ts @@ -1,4 +1,12 @@ -import { ITransaction, build5Db } from '@build-5/database'; +import { + ITransaction, + PgNetwork, + PgTransaction, + PgTransactionPayloadType, + PgTransactionType, + build5Db, + convertEnum, +} from '@build-5/database'; import { COL, DEFAULT_NETWORK, @@ -25,7 +33,7 @@ import { getProject } from '../../utils/common.utils'; import { isEmulatorEnv } from '../../utils/config.utils'; import { serverTime } from '../../utils/dateTime.utils'; import { getRandomEthAddress } from '../../utils/wallet.utils'; -import { FirestoreDocEvent } from '../common'; +import { PgDocEvent } from '../common'; import { unclockMnemonic } from '../milestone-transactions-triggers/common'; import { onAirdropClaim } from './airdrop.claim'; import { onAwardUpdate } from './award.transaction.update'; @@ -61,19 +69,20 @@ export const EXECUTABLE_TRANSACTIONS = [ ...CREDIT_EXECUTABLE_TRANSACTIONS, ]; -export const onTransactionWrite = async (event: FirestoreDocEvent) => { +export const onTransactionWrite = async (event: PgDocEvent) => { const { prev, curr } = event; if (!curr) { return; } - const isExecutableType = EXECUTABLE_TRANSACTIONS.includes(curr.type); + const type = convertEnum(curr.type, PgTransactionType, TransactionType)!; + const isExecutableType = EXECUTABLE_TRANSACTIONS.includes(type); const isCreate = prev === undefined; const shouldRetry = !prev?.shouldRetry && curr?.shouldRetry; if (isCreate) { - const docRef = build5Db().doc(`${COL.TRANSACTION}/${curr.uid}`); - await docRef.update({ isOrderType: curr.type === TransactionType.ORDER }); + const docRef = build5Db().doc(COL.TRANSACTION, curr.uid); + await docRef.update({ isOrderType: type === TransactionType.ORDER }); } if (isExecutableType && !curr?.ignoreWallet && (isCreate || shouldRetry)) { @@ -81,101 +90,99 @@ export const onTransactionWrite = async (event: FirestoreDocEvent) } if ( - curr.payload.type === TransactionPayloadType.AIRDROP_MINTED_TOKEN && - prev?.payload?.unclaimedAirdrops && - curr.payload.unclaimedAirdrops === 0 + curr.payload_type === PgTransactionPayloadType.AIRDROP_MINTED_TOKEN && + prev?.payload_unclaimedAirdrops && + curr.payload_unclaimedAirdrops === 0 ) { await onMintedAirdropCleared(curr); return; } - if (curr.type === TransactionType.MINT_COLLECTION && isConfirmed(prev, curr)) { + if (type === TransactionType.MINT_COLLECTION && isConfirmed(prev, curr)) { await onCollectionMintingUpdate(curr); return; } - if (curr.type === TransactionType.MINT_TOKEN && isConfirmed(prev, curr)) { + if (type === TransactionType.MINT_TOKEN && isConfirmed(prev, curr)) { await onTokenMintingUpdate(curr); return; } - if (curr.type === TransactionType.CREDIT_STORAGE_DEPOSIT_LOCKED && isConfirmed(prev, curr)) { + if (type === TransactionType.CREDIT_STORAGE_DEPOSIT_LOCKED && isConfirmed(prev, curr)) { await build5Db() - .doc(`${COL.TRANSACTION}/${curr.payload.transaction}`) + .doc(COL.TRANSACTION, curr.payload_transaction!) .update({ - 'payload.walletReference.confirmed': true, - 'payload.walletReference.inProgress': false, - 'payload.walletReference.count': build5Db().inc(1), - 'payload.walletReference.processedOn': dayjs().toDate(), - 'payload.walletReference.chainReference': - curr.payload?.walletReference?.chainReference || '', - 'payload.walletReference.chainReferences': build5Db().arrayUnion( - curr.payload?.walletReference?.chainReference || '', + payload_walletReference_confirmed: true, + payload_walletReference_inProgress: false, + payload_walletReference_count: build5Db().inc(1), + payload_walletReference_processedOn: dayjs().toDate(), + payload_walletReference_chainReference: curr.payload_walletReference_chainReference || '', + payload_walletReference_chainReferences: build5Db().arrayUnion( + curr.payload_walletReference_chainReference || '', ), }); return; } if ( - curr.type === TransactionType.BILL_PAYMENT && + type === TransactionType.BILL_PAYMENT && isConfirmed(prev, curr) && - !isEmpty(curr.payload.stake) + !isEmpty(curr.payload_stake) ) { await onStakingConfirmed(curr); return; } const airdropOrderTypes = [ - TransactionPayloadType.TOKEN_AIRDROP, - TransactionPayloadType.CLAIM_MINTED_TOKEN, - TransactionPayloadType.CLAIM_BASE_TOKEN, + PgTransactionPayloadType.TOKEN_AIRDROP, + PgTransactionPayloadType.CLAIM_MINTED_TOKEN, + PgTransactionPayloadType.CLAIM_BASE_TOKEN, ]; if ( - airdropOrderTypes.includes(curr.payload.type!) && - !prev?.payload.reconciled && - curr.payload.reconciled + airdropOrderTypes.includes(curr.payload_type!) && + !prev?.payload_reconciled && + curr.payload_reconciled ) { - console.info('onAirdropClaim', JSON.stringify(prev), JSON.stringify(curr)); await onAirdropClaim(curr); return; } - if (isConfirmed(prev, curr) && curr.payload.proposalId && curr.type === TransactionType.CREDIT) { + if (isConfirmed(prev, curr) && curr.payload_proposalId && type === TransactionType.CREDIT) { await onProposalVoteCreditConfirmed(curr); return; } - if (isConfirmed(prev, curr) && curr.payload.weeks && curr.type === TransactionType.WITHDRAW_NFT) { + if (isConfirmed(prev, curr) && curr.payload_weeks && type === TransactionType.WITHDRAW_NFT) { await onNftStaked(curr); return; } - if (isConfirmed(prev, curr) && curr.type === TransactionType.AWARD) { + if (isConfirmed(prev, curr) && type === TransactionType.AWARD) { await onAwardUpdate(curr); return; } - if (isConfirmed(prev, curr) && curr.type === TransactionType.METADATA_NFT) { + if (isConfirmed(prev, curr) && type === TransactionType.METADATA_NFT) { await onMetadataNftMintUpdate(curr); return; } - if (isConfirmed(prev, curr) && curr.type === TransactionType.METADATA_NFT) { + if (isConfirmed(prev, curr) && type === TransactionType.METADATA_NFT) { await onMetadataNftMintUpdate(curr); return; } - if (isConfirmed(prev, curr) && curr.type === TransactionType.STAMP) { + if (isConfirmed(prev, curr) && type === TransactionType.STAMP) { await onStampMintUpdate(curr); return; } if ( isConfirmed(prev, curr) && - curr.payload.award && - curr.payload.type === TransactionPayloadType.MINTED_AIRDROP_CLAIM + curr.payload_award && + curr.payload_type === PgTransactionPayloadType.MINTED_AIRDROP_CLAIM ) { - const awardDocRef = build5Db().doc(`${COL.AWARD}/${curr.payload.award}`); + const awardDocRef = build5Db().doc(COL.AWARD, curr.payload_award); await awardDocRef.update({ airdropClaimed: build5Db().inc(1) }); } }; @@ -186,8 +193,8 @@ const executeTransaction = async (transactionId: string) => { return; } - const docRef = build5Db().doc(`${COL.TRANSACTION}/${transactionId}`); - const transaction = (await docRef.get())!; + const docRef = build5Db().doc(COL.TRANSACTION, transactionId); + const transaction = (await docRef.get())!; const payload = transaction.payload; const params = await getWalletParams(transaction); @@ -248,18 +255,18 @@ const executeTransaction = async (transactionId: string) => { const chainReference = await submit(); await docRef.update({ - 'payload.walletReference.processedOn': dayjs().toDate(), - 'payload.walletReference.chainReference': chainReference, - 'payload.walletReference.chainReferences': build5Db().arrayUnion(chainReference), - 'payload.walletReference.nodeIndex': wallet.nodeIndex, + payload_walletReference_processedOn: dayjs().toDate(), + payload_walletReference_chainReference: chainReference, + payload_walletReference_chainReferences: build5Db().arrayUnion(chainReference), + payload_walletReference_nodeIndex: wallet.nodeIndex, }); } catch (error) { console.error('onTransactionWrite-error', transaction.uid, wallet.nodeUrl, error); await docRef.update({ - 'payload.walletReference.chainReference': null, - 'payload.walletReference.processedOn': dayjs().toDate(), - 'payload.walletReference.error': JSON.stringify(error), - 'payload.walletReference.nodeIndex': wallet.nodeIndex, + payload_walletReference_chainReference: null, + payload_walletReference_processedOn: dayjs().toDate(), + payload_walletReference_error: JSON.stringify(error), + payload_walletReference_nodeIndex: wallet.nodeIndex, }); await unclockMnemonic(payload.sourceAddress!); } @@ -355,7 +362,7 @@ const submitCreateAwardTransaction = ( } }; -const submitMintMetadataTransaction = async ( +const submitMintMetadataTransaction = ( transaction: Transaction, wallet: Wallet, params: WalletParams, @@ -387,7 +394,7 @@ const submitMintMetadataTransaction = async ( } }; -const submitMintStampTransaction = async ( +const submitMintStampTransaction = ( transaction: Transaction, wallet: Wallet, params: WalletParams, @@ -445,8 +452,8 @@ const submitUnlockTransaction = async ( const prepareTransaction = (transactionId: string) => build5Db().runTransaction(async (transaction) => { - const docRef = build5Db().doc(`${COL.TRANSACTION}/${transactionId}`); - const tranData = await transaction.get(docRef); + const docRef = build5Db().doc(COL.TRANSACTION, transactionId); + const tranData = await transaction.get(docRef); if ( isEmulatorEnv() && [Network.SMR, Network.IOTA].includes(tranData?.network || DEFAULT_NETWORK) @@ -459,7 +466,7 @@ const prepareTransaction = (transactionId: string) => !isEmpty(walletResponse.chainReference) || walletResponse.count > MAX_WALLET_RETRY ) { - transaction.update(docRef, { shouldRetry: false }); + await transaction.update(docRef, { shouldRetry: false }); return false; } @@ -468,10 +475,20 @@ const prepareTransaction = (transactionId: string) => tranData.payload.dependsOnBillPayment ) { walletResponse.chainReference = null; - transaction.update(docRef, { + await transaction.update(docRef, { shouldRetry: false, - 'payload.walletReference': walletResponse, - 'payload.dependsOnBillPayment': false, + payload_walletReference_createdOn: walletResponse.createdOn?.toDate(), + payload_walletReference_processedOn: walletResponse.processedOn?.toDate(), + payload_walletReference_chainReference: walletResponse.chainReference || undefined, + payload_walletReference_chainReferences: walletResponse.chainReferences, + payload_walletReference_error: walletResponse.error as string, + payload_walletReference_confirmed: walletResponse.confirmed, + payload_walletReference_confirmedOn: walletResponse.confirmedOn?.toDate(), + payload_walletReference_milestoneTransactionPath: walletResponse.milestoneTransactionPath, + payload_walletReference_count: walletResponse.count, + payload_walletReference_inProgress: walletResponse.inProgress, + payload_walletReference_nodeIndex: walletResponse.nodeIndex, + payload_dependsOnBillPayment: false, }); return false; } @@ -482,12 +499,25 @@ const prepareTransaction = (transactionId: string) => walletResponse.processedOn = serverTime(); walletResponse.inProgress = true; - transaction.update(docRef, { shouldRetry: false, 'payload.walletReference': walletResponse }); + await transaction.update(docRef, { + shouldRetry: false, + payload_walletReference_createdOn: walletResponse.createdOn?.toDate(), + payload_walletReference_processedOn: walletResponse.processedOn?.toDate(), + payload_walletReference_chainReference: walletResponse.chainReference || undefined, + payload_walletReference_chainReferences: walletResponse.chainReferences, + payload_walletReference_error: walletResponse.error as string, + payload_walletReference_confirmed: walletResponse.confirmed, + payload_walletReference_confirmedOn: walletResponse.confirmedOn?.toDate(), + payload_walletReference_milestoneTransactionPath: walletResponse.milestoneTransactionPath, + payload_walletReference_count: walletResponse.count, + payload_walletReference_inProgress: walletResponse.inProgress, + payload_walletReference_nodeIndex: walletResponse.nodeIndex, + }); if (!tranData.payload.outputToConsume) { - lockMnemonic(transaction, transactionId, tranData.payload.sourceAddress); - lockMnemonic(transaction, transactionId, tranData.payload.storageDepositSourceAddress); - lockMnemonic(transaction, transactionId, tranData.payload.aliasGovAddress); + await lockMnemonic(transaction, transactionId, tranData.payload.sourceAddress); + await lockMnemonic(transaction, transactionId, tranData.payload.storageDepositSourceAddress); + await lockMnemonic(transaction, transactionId, tranData.payload.aliasGovAddress); } return true; @@ -506,13 +536,13 @@ const getMnemonic = async ( address: NetworkAddress | undefined, ): Promise => { if (isEmpty(address)) { - return {}; + return {} as Mnemonic; } - const docRef = build5Db().doc(`${COL.MNEMONIC}/${address}`); - return (await transaction.get(docRef)) || {}; + const docRef = build5Db().doc(COL.MNEMONIC, address!); + return (await transaction.get(docRef)) || ({} as Mnemonic); }; -const lockMnemonic = ( +const lockMnemonic = async ( transaction: ITransaction, lockedBy: string, address: NetworkAddress | undefined, @@ -520,8 +550,8 @@ const lockMnemonic = ( if (isEmpty(address)) { return; } - const docRef = build5Db().doc(`${COL.MNEMONIC}/${address}`); - transaction.update(docRef, { + const docRef = build5Db().doc(COL.MNEMONIC, address!); + await transaction.update(docRef, { lockedBy, consumedOutputIds: [], consumedNftOutputIds: [], @@ -543,28 +573,29 @@ const mnemonicsAreLocked = async (transaction: ITransaction, tran: Transaction) ); }; -const isConfirmed = (prev: Transaction | undefined, curr: Transaction | undefined) => - !prev?.payload?.walletReference?.confirmed && curr?.payload?.walletReference?.confirmed; +const isConfirmed = (prev: PgTransaction | undefined, curr: PgTransaction | undefined) => + !prev?.payload_walletReference_confirmed && curr?.payload_walletReference_confirmed; -const onMintedAirdropCleared = async (curr: Transaction) => { - const member = await build5Db().doc(`${COL.MEMBER}/${curr.member}`).get(); +const onMintedAirdropCleared = async (curr: PgTransaction) => { + const network = convertEnum(curr.network, PgNetwork, Network) || DEFAULT_NETWORK; + const member = await build5Db().doc(COL.MEMBER, curr.member!).get(); const credit: Transaction = { project: getProject(curr), type: TransactionType.CREDIT, uid: getRandomEthAddress(), space: curr.space, member: curr.member, - network: curr.network || DEFAULT_NETWORK, + network, payload: { type: TransactionPayloadType.AIRDROP_MINTED_TOKEN, - amount: curr.payload.amount, - sourceAddress: curr.payload.targetAddress, - targetAddress: getAddress(member, curr.network || DEFAULT_NETWORK), + amount: curr.payload_amount, + sourceAddress: curr.payload_targetAddress, + targetAddress: getAddress(member, network), sourceTransaction: [curr.uid], reconciled: true, void: false, - token: curr.payload.token, + token: curr.payload_token, }, }; - await build5Db().doc(`${COL.TRANSACTION}/${credit.uid}`).create(credit); + await build5Db().doc(COL.TRANSACTION, credit.uid).create(credit); }; diff --git a/packages/functions/src/triggers/transaction-trigger/wallet-params.ts b/packages/functions/src/triggers/transaction-trigger/wallet-params.ts index 34143f1857..58cf00693b 100644 --- a/packages/functions/src/triggers/transaction-trigger/wallet-params.ts +++ b/packages/functions/src/triggers/transaction-trigger/wallet-params.ts @@ -3,7 +3,6 @@ import { COL, IOTATangleTransaction, NativeToken, - Nft, Transaction, TransactionType, } from '@build-5/interfaces'; @@ -44,7 +43,7 @@ const getParams = async (transaction: Transaction) => { } if (payload.nft) { details.nft = payload.nft; - const nft = await build5Db().doc(`${COL.NFT}/${payload.nft}`).get(); + const nft = await build5Db().doc(COL.NFT, payload.nft).get(); if (nft && nft.ipfsMedia) { details.ipfsMedia = 'ipfs://' + nft.ipfsMedia; } diff --git a/packages/functions/src/utils/car.utils.ts b/packages/functions/src/utils/car.utils.ts index a410adbd27..1c8e65af19 100644 --- a/packages/functions/src/utils/car.utils.ts +++ b/packages/functions/src/utils/car.utils.ts @@ -1,3 +1,4 @@ +import { PgCollection, PgNft, PgToken } from '@build-5/database'; import { Collection, KEY_NAME_TANGLE, Nft, Token } from '@build-5/interfaces'; import { CarReader } from '@ipld/car'; import * as dagPb from '@ipld/dag-pb'; @@ -87,7 +88,7 @@ const toImportCandidate = (file: FileLike) => ({ }, }); -export const collectionToIpfsMetadata = (collection: Collection) => ({ +export const collectionToIpfsMetadata = (collection: Collection | PgCollection) => ({ name: collection.name, description: collection.description, author: collection.createdBy, @@ -97,7 +98,7 @@ export const collectionToIpfsMetadata = (collection: Collection) => ({ uid: collection.uid, }); -export const nftToIpfsMetadata = (collection: Collection, nft: Nft) => { +export const nftToIpfsMetadata = (collection: Collection, nft: Nft | PgNft) => { const props = propsToAttributes(nft.properties); const stats = propsToAttributes(nft.stats); return { @@ -113,11 +114,11 @@ export const nftToIpfsMetadata = (collection: Collection, nft: Nft) => { }; }; -export const tokenToIpfsMetadata = (token: Token) => ({ +export const tokenToIpfsMetadata = (token: Token | PgToken) => ({ name: token.name, description: token.description || '', space: token.space, platform: KEY_NAME_TANGLE, uid: token.uid, - symbol: token.symbol.toUpperCase(), + symbol: token.symbol!.toUpperCase(), }); diff --git a/packages/functions/src/utils/collection-minting-utils/nft.prop.utils.ts b/packages/functions/src/utils/collection-minting-utils/nft.prop.utils.ts index 3a325eaa5c..81ea52427e 100644 --- a/packages/functions/src/utils/collection-minting-utils/nft.prop.utils.ts +++ b/packages/functions/src/utils/collection-minting-utils/nft.prop.utils.ts @@ -1,6 +1,7 @@ import { PropStats } from '@build-5/interfaces'; -export const propsToAttributes = (props: PropStats | undefined) => +// eslint-disable-next-line @typescript-eslint/no-explicit-any +export const propsToAttributes = (props: PropStats | Record | undefined) => Object.entries(props || {}).map(([key, value]) => ({ trait_type: key, value: value.value, diff --git a/packages/functions/src/utils/collection-minting-utils/nft.utils.ts b/packages/functions/src/utils/collection-minting-utils/nft.utils.ts index e6a3abf083..eb8b8cc12e 100644 --- a/packages/functions/src/utils/collection-minting-utils/nft.utils.ts +++ b/packages/functions/src/utils/collection-minting-utils/nft.utils.ts @@ -96,17 +96,14 @@ export const collectionToMetadata = async ( }; export const getNftByMintingId = async (nftId: string) => { - const snap = await build5Db() - .collection(COL.NFT) - .where('mintingData.nftId', '==', nftId) - .get(); + const snap = await build5Db().collection(COL.NFT).where('mintingData_nftId', '==', nftId).get(); return head(snap); }; export const getCollectionByMintingId = async (collectionId: string) => { const snap = await build5Db() .collection(COL.COLLECTION) - .where('mintingData.nftId', '==', collectionId) - .get(); + .where('mintingData_nftId', '==', collectionId) + .get(); return head(snap); }; diff --git a/packages/functions/src/utils/common.utils.ts b/packages/functions/src/utils/common.utils.ts index 8a76b044ee..f2bf469c75 100644 --- a/packages/functions/src/utils/common.utils.ts +++ b/packages/functions/src/utils/common.utils.ts @@ -1,4 +1,4 @@ -import { build5Db } from '@build-5/database'; +import { BaseRecord as PgBaseRecord, build5Db } from '@build-5/database'; import { Access, BaseRecord, @@ -6,7 +6,6 @@ import { Collection, MIN_AMOUNT_TO_TRANSFER, Nft, - ProjectAdmin, Restrictions, SOON_PROJECT_ID, SUB_COL, @@ -69,11 +68,11 @@ export const getRestrictions = (collection?: Collection, nft?: Nft): Restriction }; export const assertIsProjectAdmin = async (project: string, member: string) => { - const projectDocRef = build5Db().doc(`${COL.PROJECT}/${project}`); - const admin = await projectDocRef.collection(SUB_COL.ADMINS).doc(member).get(); + const admin = await build5Db().doc(COL.PROJECT, project, SUB_COL.ADMINS, member).get(); if (!admin) { throw invalidArgument(WenError.you_are_not_admin_of_project); } }; -export const getProject = (data: BaseRecord | undefined) => data?.project || SOON_PROJECT_ID; +export const getProject = (data: BaseRecord | PgBaseRecord | undefined) => + data?.project || SOON_PROJECT_ID; diff --git a/packages/functions/src/utils/dateTime.utils.ts b/packages/functions/src/utils/dateTime.utils.ts index 9722ec8093..bb604dba13 100644 --- a/packages/functions/src/utils/dateTime.utils.ts +++ b/packages/functions/src/utils/dateTime.utils.ts @@ -1,10 +1,9 @@ import { Timestamp as ITimestamp } from '@build-5/interfaces'; import dayjs from 'dayjs'; -import { Timestamp } from 'firebase-admin/firestore'; export const dateToTimestamp = (d: dayjs.ConfigType, onlyDownToMinutes = false) => { const date = onlyDownToMinutes ? dayjs(d).second(0).millisecond(0) : dayjs(d); - return Timestamp.fromDate(date.toDate()) as ITimestamp; + return ITimestamp.fromDate(date.toDate()) as ITimestamp; }; export const serverTime = () => dateToTimestamp(dayjs()); diff --git a/packages/functions/src/utils/error.utils.ts b/packages/functions/src/utils/error.utils.ts index 282cfc6d7f..ec285d3c15 100644 --- a/packages/functions/src/utils/error.utils.ts +++ b/packages/functions/src/utils/error.utils.ts @@ -1,14 +1,14 @@ -import { FunctionsErrorCode } from 'firebase-functions/v1/https'; -import * as functions from 'firebase-functions/v2'; - interface Error { - readonly key?: string; + key: string; + code: number; } -const throwArgument = (type: FunctionsErrorCode, err: Error, append = '') => - new functions.https.HttpsError(type, err.key + '. ' + append, err); - -export const invalidArgument = (err: Error, append = '') => - throwArgument('invalid-argument', err, append); +export const invalidArgument = (err: Error, eMessage = '') => { + // eslint-disable-next-line no-throw-literal + throw { eCode: err.code, eKey: err.key, eMessage, status: 400 }; +}; -export const unAuthenticated = (err: Error) => throwArgument('unauthenticated', err); +export const unAuthenticated = (err: Error) => { + // eslint-disable-next-line no-throw-literal + throw { eCode: err.code, eKey: err.key, status: 401 }; +}; diff --git a/packages/functions/src/utils/media.utils.ts b/packages/functions/src/utils/media.utils.ts index 41f135e6da..8889ddc088 100644 --- a/packages/functions/src/utils/media.utils.ts +++ b/packages/functions/src/utils/media.utils.ts @@ -16,7 +16,7 @@ import mime from 'mime-types'; import os from 'os'; import path from 'path'; import { BUCKET_BASE_URLS } from '../services/joi/common'; -import { getBucket, isEmulatorEnv } from './config.utils'; +import { getBucket } from './config.utils'; export const migrateUriToSotrage = async ( col: COL, @@ -88,13 +88,13 @@ export const uriToUrl = (uri: string) => { export const getRandomBuild5Url = (owner: string, uid: string, extension: string) => { const bucket = build5Storage().bucket(getBucket()); - const baseUrl = isEmulatorEnv() ? BUCKET_BASE_URLS['local'] : BUCKET_BASE_URLS[bucket.getName()]; + const baseUrl = BUCKET_BASE_URLS[bucket.getName()]; - const isEmulatorOrDev = isEmulatorEnv() || bucket.getName() === Bucket.DEV; + const isDev = bucket.getName() === Bucket.DEV; const destination = `${owner}/${uid}/${generateRandomFileName()}.${extension}`; - const url = `${baseUrl}${isEmulatorOrDev ? encodeURIComponent(destination) : destination}`; + const url = `${baseUrl}${isDev ? encodeURIComponent(destination) : destination}`; - return isEmulatorOrDev ? url + '?generation=1695968595134&alt=media' : url; + return isDev ? url + '?alt=media' : url; }; export const downloadFile = async (url: string, workDir: string, fileName: string) => { @@ -117,26 +117,22 @@ export const downloadFile = async (url: string, workDir: string, fileName: strin const extension = mime.extension(contentType); return new Promise<{ extension: string; size: number; hash: string }>((resolve, reject) => { - let size = 0; - const chunks: any = []; - response.data.on('data', (chunk: any) => { - chunks.push(chunk); - size += chunk.length; - }); - - response.data.on('end', () => { - if (size > MAX_FILE_SIZE_BYTES) { + stream.on('finish', () => { + const stats = fs.statSync(destination); + if (stats.size > MAX_FILE_SIZE_BYTES) { reject(WenError.max_size); return; } + const content = fs.readFileSync(destination); resolve({ extension, - size, + size: stats.size, hash: createHash('sha1') - .update('' + chunks.join()) + .update('' + content) .digest('hex'), }); }); - response.data.on('error', reject); + + stream.on('error', reject); }); }; diff --git a/packages/functions/src/utils/milestone.ts b/packages/functions/src/utils/milestone.ts new file mode 100644 index 0000000000..036f2dd8c5 --- /dev/null +++ b/packages/functions/src/utils/milestone.ts @@ -0,0 +1,6 @@ +import { COL, SUB_COL } from '@build-5/interfaces'; + +export const getPathParts = (path: string) => { + const [col, colId, subCol, subColId] = path.split('/'); + return { col: col as COL.MILESTONE, colId, subCol: subCol as SUB_COL.TRANSACTIONS, subColId }; +}; diff --git a/packages/functions/src/utils/royalty.utils.ts b/packages/functions/src/utils/royalty.utils.ts index 225ba496e3..769e493a45 100644 --- a/packages/functions/src/utils/royalty.utils.ts +++ b/packages/functions/src/utils/royalty.utils.ts @@ -1,5 +1,5 @@ import { build5Db } from '@build-5/database'; -import { COL, SYSTEM_CONFIG_DOC_ID, SystemConfig } from '@build-5/interfaces'; +import { COL, SYSTEM_CONFIG_DOC_ID } from '@build-5/interfaces'; import bigDecimal from 'js-big-decimal'; import { getRoyaltyPercentage, @@ -38,9 +38,7 @@ const getTokenPurchaseFeePercentage = async ( if (memberFeePercentage !== undefined) { return memberFeePercentage; } - const systemConfig = await build5Db() - .doc(`${COL.SYSTEM}/${SYSTEM_CONFIG_DOC_ID}`) - .get(); + const systemConfig = await build5Db().doc(COL.SYSTEM, SYSTEM_CONFIG_DOC_ID).get(); const systemPercentage = isTokenPurchase ? systemConfig?.tokenPurchaseFeePercentage : systemConfig?.tokenTradingFeePercentage; diff --git a/packages/functions/src/utils/schema.utils.ts b/packages/functions/src/utils/schema.utils.ts index 6af062fff4..0f63e95268 100644 --- a/packages/functions/src/utils/schema.utils.ts +++ b/packages/functions/src/utils/schema.utils.ts @@ -34,5 +34,8 @@ export const assertValidationAsync = async ( return validationResult.value! as T; }; -export const cleanupParams = (obj: Record) => - Object.entries(obj).reduce((acc, act) => ({ ...acc, [act[0]]: act[1] || null }), {}); +export const cleanupParams = (obj: T): T => + Object.entries(obj as Record).reduce( + (acc, act) => ({ ...acc, [act[0]]: act[1] || null }), + {}, + ) as T; diff --git a/packages/functions/src/utils/space.utils.ts b/packages/functions/src/utils/space.utils.ts index 9f715df08d..4ef85c3104 100644 --- a/packages/functions/src/utils/space.utils.ts +++ b/packages/functions/src/utils/space.utils.ts @@ -4,16 +4,15 @@ import { head } from 'lodash'; import { invalidArgument } from './error.utils'; export const assertSpaceExists = async (spaceId: string) => { - const spaceDocRef = build5Db().doc(`${COL.SPACE}/${spaceId}`); - const space = await spaceDocRef.get(); + const spaceDocRef = build5Db().doc(COL.SPACE, spaceId); + const space = await spaceDocRef.get(); if (!space) { throw invalidArgument(WenError.space_does_not_exists); } }; export const assertIsSpaceMember = async (space: string, member: string) => { - const spaceDocRef = build5Db().doc(`${COL.SPACE}/${space}`); - const spaceMemberDocRef = spaceDocRef.collection(SUB_COL.MEMBERS).doc(member); + const spaceMemberDocRef = build5Db().doc(COL.SPACE, space, SUB_COL.MEMBERS, member); const spaceMember = await spaceMemberDocRef.get(); if (!spaceMember) { throw invalidArgument(WenError.you_are_not_part_of_space); @@ -30,13 +29,13 @@ export const getSpace = async (space: string | undefined) => { return undefined; } const docRef = build5Db().collection(COL.SPACE).doc(space); - return await docRef.get(); + return await docRef.get(); }; export const hasActiveEditProposal = async (space: string) => { const ongoingProposalSnap = await build5Db() .collection(COL.PROPOSAL) - .where('settings.spaceUpdateData.uid', '==', space) + .where('space', '==', space) .where('completed', '==', false) .get(); return ongoingProposalSnap.length > 0; @@ -45,8 +44,8 @@ export const hasActiveEditProposal = async (space: string) => { export const getSpaceByAliasId = async (aliasId: string) => { const spaces = await build5Db() .collection(COL.SPACE) - .where('alias.aliasId', '==', aliasId) + .where('alias_aliasId', '==', aliasId) .limit(1) - .get(); + .get(); return head(spaces); }; diff --git a/packages/functions/src/utils/token-minting-utils/member.utils.ts b/packages/functions/src/utils/token-minting-utils/member.utils.ts index 8d36a11877..b672977626 100644 --- a/packages/functions/src/utils/token-minting-utils/member.utils.ts +++ b/packages/functions/src/utils/token-minting-utils/member.utils.ts @@ -1,30 +1,8 @@ -import { build5Db, getSnapshot } from '@build-5/database'; -import { COL, SUB_COL, Token, TokenDistribution, TokenDrop } from '@build-5/interfaces'; +import { Token, TokenDrop } from '@build-5/interfaces'; import dayjs from 'dayjs'; -import { last } from 'lodash'; import { Wallet } from '../../services/wallet/wallet'; import { packBasicOutput } from '../basic-output.utils'; -export const getOwnedTokenTotal = async (token: string) => { - let count = 0; - let lastDocId = ''; - const tokenDocRef = build5Db().doc(`${COL.TOKEN}/${token}`); - do { - const lastDoc = lastDocId - ? await getSnapshot(COL.TOKEN, token, SUB_COL.DISTRIBUTION, lastDocId) - : undefined; - const snap = await tokenDocRef - .collection(SUB_COL.DISTRIBUTION) - .startAfter(lastDoc) - .limit(1000) - .get(); - lastDocId = last(snap)?.uid || ''; - - count += snap.reduce((acc, act) => acc + (act.tokenOwned || 0), 0); - } while (lastDocId); - return count; -}; - export const dropToOutput = ( wallet: Wallet, token: Token, diff --git a/packages/functions/src/utils/token-trade.utils.ts b/packages/functions/src/utils/token-trade.utils.ts index a43291e1f2..d1cb57ea24 100644 --- a/packages/functions/src/utils/token-trade.utils.ts +++ b/packages/functions/src/utils/token-trade.utils.ts @@ -1,9 +1,8 @@ -import { ITransaction, build5Db } from '@build-5/database'; +import { ITransaction, PgTokenTradeOrderStatus, build5Db, convertEnum } from '@build-5/database'; import { COL, CreditPaymentReason, DEFAULT_NETWORK, - Member, SUB_COL, Token, TokenStatus, @@ -20,14 +19,14 @@ import { getProject } from './common.utils'; import { getRandomEthAddress } from './wallet.utils'; export const creditBuyer = async (transaction: ITransaction, buy: TokenTradeOrder) => { - const memberDocRef = build5Db().doc(`${COL.MEMBER}/${buy.owner}`); - const member = (await memberDocRef.get())!; + const memberDocRef = build5Db().doc(COL.MEMBER, buy.owner); + const member = (await memberDocRef.get())!; - const tokenDocRef = build5Db().doc(`${COL.TOKEN}/${buy.token}`); - const token = (await tokenDocRef.get())!; + const tokenDocRef = build5Db().doc(COL.TOKEN, buy.token); + const token = (await tokenDocRef.get())!; - const orderDocRef = build5Db().doc(`${COL.TRANSACTION}/${buy.orderTransactionId}`); - const order = (await orderDocRef.get())!; + const orderDocRef = build5Db().doc(COL.TRANSACTION, buy.orderTransactionId!); + const order = (await orderDocRef.get())!; const network = order.network || DEFAULT_NETWORK; const credit: Transaction = { @@ -50,11 +49,11 @@ export const creditBuyer = async (transaction: ITransaction, buy: TokenTradeOrde tokenSymbol: token.symbol, }, }; - const creditDocRef = build5Db().doc(`${COL.TRANSACTION}/${credit.uid}`); - transaction.create(creditDocRef, credit); + const creditDocRef = build5Db().doc(COL.TRANSACTION, credit.uid); + await transaction.create(creditDocRef, credit); - const tradeOrderDocRef = build5Db().doc(`${COL.TOKEN_MARKET}/${buy.uid}`); - transaction.update(tradeOrderDocRef, { creditTransactionId: credit.uid }); + const tradeOrderDocRef = build5Db().doc(COL.TOKEN_MARKET, buy.uid); + await transaction.update(tradeOrderDocRef, { creditTransactionId: credit.uid }); }; const creditBaseTokenSale = async ( @@ -62,11 +61,11 @@ const creditBaseTokenSale = async ( token: Token, sale: TokenTradeOrder, ) => { - const orderDocRef = build5Db().doc(`${COL.TRANSACTION}/${sale.orderTransactionId}`); - const order = (await orderDocRef.get())!; + const orderDocRef = build5Db().doc(COL.TRANSACTION, sale.orderTransactionId!); + const order = (await orderDocRef.get())!; - const memberDocRef = build5Db().doc(`${COL.MEMBER}/${sale.owner}`); - const member = await memberDocRef.get(); + const memberDocRef = build5Db().doc(COL.MEMBER, sale.owner); + const member = await memberDocRef.get(); const network = order.network || DEFAULT_NETWORK; const data: Transaction = { project: getProject(sale), @@ -88,11 +87,11 @@ const creditBaseTokenSale = async ( tokenSymbol: token.symbol, }, }; - const creditDocRef = build5Db().doc(`${COL.TRANSACTION}/${data.uid}`); - transaction.create(creditDocRef, data); + const creditDocRef = build5Db().doc(COL.TRANSACTION, data.uid); + await transaction.create(creditDocRef, data); - const tradeDocRef = build5Db().doc(`${COL.TOKEN_MARKET}/${sale.uid}`); - transaction.update(tradeDocRef, { + const tradeDocRef = build5Db().doc(COL.TOKEN_MARKET, sale.uid); + await transaction.update(tradeDocRef, { creditTransactionId: data.uid, balance: 0, }); @@ -103,14 +102,14 @@ export const cancelTradeOrderUtil = async ( tradeOrder: TokenTradeOrder, forcedStatus?: TokenTradeOrderStatus, ) => { - const saleDocRef = build5Db().doc(`${COL.TOKEN_MARKET}/${tradeOrder.uid}`); + const saleDocRef = build5Db().doc(COL.TOKEN_MARKET, tradeOrder.uid); const status = forcedStatus || (tradeOrder.fulfilled === 0 ? TokenTradeOrderStatus.CANCELLED : TokenTradeOrderStatus.PARTIALLY_SETTLED_AND_CANCELLED); - const tokenDocRef = build5Db().doc(`${COL.TOKEN}/${tradeOrder.token}`); - const token = (await tokenDocRef.get())!; + const tokenDocRef = build5Db().doc(COL.TOKEN, tradeOrder.token); + const token = (await tokenDocRef.get())!; if (token.status === TokenStatus.BASE) { await creditBaseTokenSale(transaction, token, tradeOrder); @@ -118,25 +117,32 @@ export const cancelTradeOrderUtil = async ( if (token.status === TokenStatus.MINTED) { await cancelMintedSell(transaction, tradeOrder, token); } else { - const distributionDocRef = tokenDocRef.collection(SUB_COL.DISTRIBUTION).doc(tradeOrder.owner); + const distributionDocRef = build5Db().doc( + COL.TOKEN, + tradeOrder.token, + SUB_COL.DISTRIBUTION, + tradeOrder.owner, + ); const leftForSale = bigDecimal.subtract(tradeOrder.count, tradeOrder.fulfilled); - transaction.update(distributionDocRef, { + await transaction.update(distributionDocRef, { lockedForSale: build5Db().inc(-Number(leftForSale)), }); } } else { await creditBuyer(transaction, tradeOrder); } - transaction.update(saleDocRef, { status }); + await transaction.update(saleDocRef, { + status: convertEnum(status, TokenTradeOrderStatus, PgTokenTradeOrderStatus), + }); return { ...tradeOrder, status }; }; const cancelMintedSell = async (transaction: ITransaction, sell: TokenTradeOrder, token: Token) => { - const orderDocRef = build5Db().doc(`${COL.TRANSACTION}/${sell.orderTransactionId}`); - const order = (await orderDocRef.get())!; + const orderDocRef = build5Db().doc(COL.TRANSACTION, sell.orderTransactionId!); + const order = (await orderDocRef.get())!; - const sellerDocRef = build5Db().doc(`${COL.MEMBER}/${sell.owner}`); - const seller = await sellerDocRef.get(); + const sellerDocRef = build5Db().doc(COL.MEMBER, sell.owner); + const seller = await sellerDocRef.get(); const tokensLeft = sell.count - sell.fulfilled; const network = order.network || DEFAULT_NETWORK; @@ -161,9 +167,9 @@ const cancelMintedSell = async (transaction: ITransaction, sell: TokenTradeOrder tokenSymbol: token.symbol, }, }; - const creditDocRef = build5Db().doc(`${COL.TRANSACTION}/${data.uid}`); - transaction.create(creditDocRef, data); + const creditDocRef = build5Db().doc(COL.TRANSACTION, data.uid); + await transaction.create(creditDocRef, data); - const tradeOrderDocRef = build5Db().doc(`${COL.TOKEN_MARKET}/${sell.uid}`); - transaction.update(tradeOrderDocRef, { creditTransactionId: data.uid }); + const tradeOrderDocRef = build5Db().doc(COL.TOKEN_MARKET, sell.uid); + await transaction.update(tradeOrderDocRef, { creditTransactionId: data.uid }); }; diff --git a/packages/functions/src/utils/token.utils.ts b/packages/functions/src/utils/token.utils.ts index de5ebfb47b..958e030e23 100644 --- a/packages/functions/src/utils/token.utils.ts +++ b/packages/functions/src/utils/token.utils.ts @@ -1,39 +1,36 @@ -import { build5Db, getSnapshot } from '@build-5/database'; +import { build5Db, PgToken, PgTokenDropStatus } from '@build-5/database'; import { COL, Collection, SUB_COL, Token, - TokenDrop, - TokenDropStatus, + TokenAllocation, TokenStatus, WenError, } from '@build-5/interfaces'; import dayjs from 'dayjs'; import bigDecimal from 'js-big-decimal'; -import { last } from 'lodash'; +import { head } from 'lodash'; import { invalidArgument } from './error.utils'; export const BIG_DECIMAL_PRECISION = 1000; -export const tokenOrderTransactionDocId = (member: string, token: Token) => - member + '_' + token.uid; +export const tokenOrderTransactionDocId = (member: string, token: Token | PgToken) => + member + token.uid; export const allPaymentsQuery = (member: string, token: string) => build5Db() .collection(COL.TRANSACTION) .where('member', '==', member) - .where('payload.token', '==', token); + .where('payload_token', '==', token); -export const orderDocRef = (member: string, token: Token) => - build5Db().doc(`${COL.TRANSACTION}/${tokenOrderTransactionDocId(member, token)}`); +export const orderDocRef = (member: string, token: Token | PgToken) => + build5Db().doc(COL.TRANSACTION, tokenOrderTransactionDocId(member, token)); -export const memberDocRef = (member: string) => build5Db().doc(`${COL.MEMBER}/${member}`); +export const memberDocRef = (member: string) => build5Db().doc(COL.MEMBER, member); export const assertIsGuardian = async (space: string, member: string) => { - const guardianDoc = await build5Db() - .doc(`${COL.SPACE}/${space}/${SUB_COL.GUARDIANS}/${member}`) - .get(); + const guardianDoc = await build5Db().doc(COL.SPACE, space, SUB_COL.GUARDIANS, member).get(); if (!guardianDoc) { throw invalidArgument(WenError.you_are_not_guardian_of_space); } @@ -78,8 +75,9 @@ export const getBoughtByMemberDiff = ( return Number(bigDecimal.subtract(currentOrderCount, prevOrderCount)); }; -export const getTotalPublicSupply = (token: Token) => { - const publicPercentage = token.allocations.find((a) => a.isPublicSale)?.percentage || 0; +export const getTotalPublicSupply = (token: Token | PgToken) => { + const publicPercentage = + (token.allocations! as TokenAllocation[]).find((a) => a.isPublicSale)?.percentage || 0; return Number(bigDecimal.floor(bigDecimal.multiply(token.totalSupply, publicPercentage / 100))); }; @@ -121,55 +119,35 @@ export const getTokenForSpace = async (space: string) => { return snap[0]; }; -export const getUnclaimedDrops = async (token: string, member: string) => +export const getUnclaimedDrops = (token: string, member: string) => build5Db() .collection(COL.AIRDROP) .where('token', '==', token) .where('member', '==', member) - .where('status', '==', TokenDropStatus.UNCLAIMED) - .get(); - -export const getUnclaimedAirdropTotalValue = async (token: string) => { - let count = 0; - let lastDocId = ''; - do { - const lastDoc = await getSnapshot(COL.AIRDROP, lastDocId); - const snap = await build5Db() - .collection(COL.AIRDROP) - .where('token', '==', token) - .where('status', '==', TokenDropStatus.UNCLAIMED) - .startAfter(lastDoc) - .get(); - lastDocId = last(snap)?.uid || ''; - - count += snap.reduce((acc, act) => acc + act.count, 0); - } while (lastDocId); - return count; -}; + .where('status', '==', PgTokenDropStatus.UNCLAIMED) + .get(); export const getTokenBySymbol = async (symbol: string) => { let snap = await build5Db() .collection(COL.TOKEN) .where('symbol', '==', symbol.toUpperCase()) .where('approved', '==', true) - .limit(1) .get(); if (snap.length) { - return snap[0]; + return head(snap); } snap = await build5Db() .collection(COL.TOKEN) .where('symbol', '==', symbol.toUpperCase()) .where('public', '==', true) - .limit(1) .get(); - return snap[0]; + return head(snap); }; export const getTokenByMintId = async (tokenId: string) => { const snap = await build5Db() .collection(COL.TOKEN) - .where('mintingData.tokenId', '==', tokenId) + .where('mintingData_tokenId', '==', tokenId) .get(); return snap[0]; }; diff --git a/packages/functions/src/utils/wallet.utils.ts b/packages/functions/src/utils/wallet.utils.ts index 720b7bd528..e60bbba47a 100644 --- a/packages/functions/src/utils/wallet.utils.ts +++ b/packages/functions/src/utils/wallet.utils.ts @@ -1,9 +1,8 @@ -import { build5Db } from '@build-5/database'; +import { PgMemberUpdate, build5Db } from '@build-5/database'; import { Build5Request, COL, DecodedToken, - Member, Network, NetworkAddress, WEN_FUNC, @@ -63,7 +62,7 @@ export const decodeAuth = async ( } if (req.customToken) { - await validateWithIdToken(req, func); + validateWithIdToken(req, func); return { address: req.address, project, body: req.body }; } @@ -82,7 +81,7 @@ const validateWithSignature = async (req: Build5Request) => { throw unAuthenticated(WenError.invalid_signature); } - const memberDocRef = build5Db().doc(`${COL.MEMBER}/${req.address}`); + const memberDocRef = build5Db().doc(COL.MEMBER, req.address); await memberDocRef.update({ nonce: getRandomNonce() }); }; @@ -98,10 +97,10 @@ const validateLegacyPubKey = async (req: Build5Request) => { const validatedAddress = (member.validatedAddress || {})[network] || address; const updateData = { nonce: getRandomNonce(), - validatedAddress: { [network]: validatedAddress }, + [`${network}Address`]: validatedAddress, }; - const memberDocRef = build5Db().doc(`${COL.MEMBER}/${address}`); - await memberDocRef.set(updateData, true); + const memberDocRef = build5Db().doc(COL.MEMBER, address); + await memberDocRef.upsert(updateData); return address; }; @@ -171,12 +170,12 @@ const validateWithPublicKey = async (req: Build5Request) => { } const validatedAddress = (member.validatedAddress || {})[network] || address; - const updateData = { + const updateData: PgMemberUpdate = { nonce: getRandomNonce(), - validatedAddress: { [network]: validatedAddress }, + [`${network}Address`]: validatedAddress, }; - const memberDocRef = build5Db().doc(`${COL.MEMBER}/${address}`); - await memberDocRef.set(updateData, true); + const memberDocRef = build5Db().doc(COL.MEMBER, address); + await memberDocRef.upsert(updateData); return address; }; @@ -201,8 +200,8 @@ const validatePubKey = async (info: INodeInfo, req: Build5Request) => { }; const getMember = async (address: NetworkAddress) => { - const memberDocRef = build5Db().doc(`${COL.MEMBER}/${address}`); - const member = await memberDocRef.get(); + const memberDocRef = build5Db().doc(COL.MEMBER, address); + const member = await memberDocRef.get(); if (!member) { throw unAuthenticated(WenError.failed_to_decode_token); } @@ -212,7 +211,7 @@ const getMember = async (address: NetworkAddress) => { return member; }; -const validateWithIdToken = async (req: Build5Request, func: WEN_FUNC) => { +const validateWithIdToken = (req: Build5Request, func: WEN_FUNC) => { const decoded = jwt.verify(req.customToken!, getJwtSecretKey()); if (get(decoded, 'uid', '') !== req.address) { diff --git a/packages/functions/test-tangle/address.spec.ts b/packages/functions/test-tangle/address.spec.ts index 39d69c5c33..57fef4fb20 100644 --- a/packages/functions/test-tangle/address.spec.ts +++ b/packages/functions/test-tangle/address.spec.ts @@ -1,6 +1,6 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ -import { build5Db } from '@build-5/database'; +import { PgTransactionPayloadType, PgTransactionType, build5Db } from '@build-5/database'; import { COL, MIN_IOTA_AMOUNT, @@ -12,27 +12,19 @@ import { Transaction, TransactionPayloadType, TransactionType, + WEN_FUNC, } from '@build-5/interfaces'; import dayjs from 'dayjs'; import { isEmpty, set } from 'lodash'; import { getAddress } from '../src/utils/address.utils'; import { dateToTimestamp } from '../src/utils/dateTime.utils'; -import * as wallet from '../src/utils/wallet.utils'; -import { - createMember, - createSpace, - validateMemberAddressFunc, - validateSpaceAddressFunc, - wait, -} from '../test/controls/common'; -import { getWallet } from '../test/set-up'; +import { validateMemberAddressFunc, wait } from '../test/controls/common'; +import { getWallet, mockWalletReturnValue, testEnv } from '../test/set-up'; import { getTangleOrder } from './common'; import { requestFundsFromFaucet } from './faucet'; -let walletSpy: any; - const awaitMemberAddressValidation = async (memberId: string, network: Network) => { - const memberDocRef = build5Db().doc(`${COL.MEMBER}/${memberId}`); + const memberDocRef = build5Db().doc(COL.MEMBER, memberId); await wait(async () => { const member = await memberDocRef.get(); return !isEmpty(getAddress(member, network)); @@ -40,7 +32,7 @@ const awaitMemberAddressValidation = async (memberId: string, network: Network) }; const awaitSpaceAddressValidation = async (space: string, network: Network) => { - const spaceDocRef = build5Db().doc(`${COL.SPACE}/${space}`); + const spaceDocRef = build5Db().doc(COL.SPACE, space); await wait(async () => { const space = await spaceDocRef.get(); return !isEmpty(getAddress(space, network)); @@ -53,13 +45,14 @@ describe('Address validation', () => { let tangleOrder: Transaction; beforeEach(async () => { - walletSpy = jest.spyOn(wallet, 'decodeAuth'); - member = await createMember(walletSpy); - await build5Db().doc(`${COL.MEMBER}/${member}`).update({ validatedAddress: {} }); + member = await testEnv.createMember(); + await build5Db() + .doc(COL.MEMBER, member) + .update({ smrAddress: '', rmsAddress: '', iotaAddress: '', atoiAddress: '' }); }); const validateMemberAddress = async (network: Network, expiresAt?: Timestamp) => { - const order = await validateMemberAddressFunc(walletSpy, member, network); + const order = await validateMemberAddressFunc(member, network); const { faucetAddress } = await requestFundsFromFaucet( network, order.payload.targetAddress!, @@ -69,11 +62,19 @@ describe('Address validation', () => { await awaitMemberAddressValidation(member, network); - const memberDocRef = build5Db().doc(`${COL.MEMBER}/${member}`); + const memberDocRef = build5Db().doc(COL.MEMBER, member); const data = await memberDocRef.get(); expect(data.validatedAddress![network]).toBe(faucetAddress.bech32); }; + const validateSpaceAddressFunc = async (adr: string, space: string, network?: Network) => { + mockWalletReturnValue(adr, network ? { space, network } : { space }); + const order = await testEnv.wrap(WEN_FUNC.validateAddress); + expect(order?.type).toBe(TransactionType.ORDER); + expect(order?.payload.type).toBe(TransactionPayloadType.SPACE_ADDRESS_VALIDATION); + return order; + }; + it.each([Network.ATOI, Network.RMS])( 'Should validate member address with network', async (network: Network) => { @@ -87,7 +88,7 @@ describe('Address validation', () => { }); const validateSpace = async (network: Network) => { - const order = await validateSpaceAddressFunc(walletSpy, member, space, network); + const order = await validateSpaceAddressFunc(member, space, network); const { faucetAddress } = await requestFundsFromFaucet( network, order.payload.targetAddress!, @@ -96,7 +97,7 @@ describe('Address validation', () => { await awaitSpaceAddressValidation(space, network); - const spaceDocRef = build5Db().doc(`${COL.SPACE}/${space}`); + const spaceDocRef = build5Db().doc(COL.SPACE, space); const spaceData = await spaceDocRef.get(); expect(spaceData.validatedAddress![network]).toBe(faucetAddress.bech32); }; @@ -104,15 +105,19 @@ describe('Address validation', () => { it.each([Network.ATOI, Network.RMS])( 'Should validate space address with network', async (network: Network) => { - space = (await createSpace(walletSpy, member)).uid; - await build5Db().doc(`${COL.SPACE}/${space}`).update({ validatedAddress: {} }); + space = (await testEnv.createSpace(member)).uid; + await build5Db() + .doc(COL.SPACE, space) + .update({ smrAddress: '', rmsAddress: '', iotaAddress: '', atoiAddress: '' }); await validateSpace(network); }, ); it('Should validate space address with both network', async () => { - space = (await createSpace(walletSpy, member)).uid; - await build5Db().doc(`${COL.SPACE}/${space}`).update({ validatedAddress: {} }); + space = (await testEnv.createSpace(member)).uid; + await build5Db() + .doc(COL.SPACE, space) + .update({ smrAddress: '', rmsAddress: '', iotaAddress: '', atoiAddress: '' }); await validateSpace(Network.ATOI); await validateSpace(Network.RMS); }); @@ -125,8 +130,8 @@ describe('Address validation', () => { const walletService = await getWallet(network); const tmpAddress = await walletService.getNewIotaAddressDetails(); - const order = await validateMemberAddressFunc(walletSpy, member, network); - const memberDocRef = build5Db().doc(`${COL.MEMBER}/${member}`); + const order = await validateMemberAddressFunc(member, network); + const memberDocRef = build5Db().doc(COL.MEMBER, member); let memberData = await memberDocRef.get(); await requestFundsFromFaucet(network, tmpAddress.bech32, order.payload.amount!); @@ -142,7 +147,7 @@ describe('Address validation', () => { const unlock = ( await build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.UNLOCK) + .where('type', '==', PgTransactionType.UNLOCK) .where('member', '==', member) .get() )[0] as Transaction; @@ -151,9 +156,9 @@ describe('Address validation', () => { await wait(async () => { const snap = await build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.CREDIT) + .where('type', '==', PgTransactionType.CREDIT) .where('member', '==', member) - .get(); + .get(); return snap.length === 1 && snap[0].payload?.walletReference?.confirmed; }); @@ -172,12 +177,14 @@ describe('Address validation', () => { const tmp = await wallet.getNewIotaAddressDetails(); await build5Db() - .doc(`${COL.MEMBER}/${member}`) - .set({ validatedAddress: { [network]: tmp.bech32 } }, true); + .doc(COL.MEMBER, member) + .upsert({ [`${network}Address`]: tmp.bech32 }); if (validateSpace) { - space = (await createSpace(walletSpy, member)).uid; - await build5Db().doc(`${COL.SPACE}/${space}`).update({ validatedAddress: {} }); + space = (await testEnv.createSpace(member)).uid; + await build5Db() + .doc(COL.SPACE, space) + .update({ smrAddress: '', rmsAddress: '', iotaAddress: '', atoiAddress: '' }); } await requestFundsFromFaucet(network, tmp.bech32, 5 * MIN_IOTA_AMOUNT); @@ -191,19 +198,19 @@ describe('Address validation', () => { const query = build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.CREDIT) + .where('type', '==', PgTransactionType.CREDIT) .where('member', '==', member); await wait(async () => { - const snap = await query.get(); + const snap = await query.get(); return snap.length > 0 && snap[0]?.payload?.walletReference?.confirmed; }); if (validateSpace) { - const spaceData = await build5Db().doc(`${COL.SPACE}/${space}`).get(); + const spaceData = await build5Db().doc(COL.SPACE, space).get(); expect(spaceData.validatedAddress![network]).toBe(tmp.bech32); } else { - const memberData = await build5Db().doc(`${COL.MEMBER}/${member}`).get(); + const memberData = await build5Db().doc(COL.MEMBER, member).get(); expect(memberData.validatedAddress![network]).toBe(tmp.bech32); expect(memberData.prevValidatedAddresses).toEqual([tmp.bech32]); } @@ -211,7 +218,7 @@ describe('Address validation', () => { const snap = await build5Db() .collection(COL.TRANSACTION) .where('member', '==', member) - .where('payload.type', '==', TransactionPayloadType.TANGLE_TRANSFER) + .where('payload_type', '==', PgTransactionPayloadType.TANGLE_TRANSFER) .get(); expect(snap.length).toBe(1); }); diff --git a/packages/functions/test-tangle/auction-tangle/auction.bit.tangle.spec.ts b/packages/functions/test-tangle/auction-tangle/auction.bit.tangle.spec.ts index 1143897aeb..18d86ca911 100644 --- a/packages/functions/test-tangle/auction-tangle/auction.bit.tangle.spec.ts +++ b/packages/functions/test-tangle/auction-tangle/auction.bit.tangle.spec.ts @@ -1,51 +1,45 @@ -import { IDocument, build5Db } from '@build-5/database'; +import { IDocument, PgTransactionType, Update, build5Db } from '@build-5/database'; import { Auction, AuctionType, COL, MIN_IOTA_AMOUNT, - Member, Network, Space, TangleRequestType, Transaction, - TransactionType, } from '@build-5/interfaces'; import dayjs from 'dayjs'; import { MnemonicService } from '../../src/services/wallet/mnemonic'; import { Wallet } from '../../src/services/wallet/wallet'; import { AddressDetails } from '../../src/services/wallet/wallet.service'; import { getAddress } from '../../src/utils/address.utils'; -import * as wallet from '../../src/utils/wallet.utils'; -import { createMember, createSpace, wait } from '../../test/controls/common'; -import { getWallet } from '../../test/set-up'; +import { wait } from '../../test/controls/common'; +import { getWallet, testEnv } from '../../test/set-up'; import { getTangleOrder } from '../common'; import { requestFundsFromFaucet } from '../faucet'; -let walletSpy: any; - describe('Auction tangle test', () => { let member: string; let space: Space; let memberAddress: AddressDetails; let w: Wallet; let tangleOrder: Transaction; - let auctionDocRef: IDocument; + let auctionDocRef: IDocument; const now = dayjs(); let auction: Auction; beforeAll(async () => { - walletSpy = jest.spyOn(wallet, 'decodeAuth'); w = await getWallet(Network.RMS); tangleOrder = await getTangleOrder(Network.RMS); }); beforeEach(async () => { - member = await createMember(walletSpy); - space = await createSpace(walletSpy, member); + member = await testEnv.createMember(); + space = await testEnv.createSpace(member); - const memberDocRef = build5Db().doc(`${COL.MEMBER}/${member}`); - const memberData = await memberDocRef.get(); + const memberDocRef = build5Db().doc(COL.MEMBER, member); + const memberData = await memberDocRef.get(); const bech32 = getAddress(memberData, Network.RMS); memberAddress = await w.getAddressDetails(bech32); @@ -63,16 +57,16 @@ describe('Auction tangle test', () => { const creaditQuery = build5Db() .collection(COL.TRANSACTION) .where('member', '==', member) - .where('type', '==', TransactionType.CREDIT_TANGLE_REQUEST); + .where('type', '==', PgTransactionType.CREDIT_TANGLE_REQUEST); await wait(async () => { - const credits = await creaditQuery.get(); + const credits = await creaditQuery.get(); return credits.length === 1 && credits[0].payload.walletReference?.confirmed; }); - const credits = await creaditQuery.get(); + const credits = await creaditQuery.get(); expect(credits[0].payload.response?.auction).toBeDefined(); - auctionDocRef = build5Db().doc(`${COL.AUCTION}/${credits[0].payload.response?.auction}`); + auctionDocRef = build5Db().doc(COL.AUCTION, credits[0].payload.response?.auction! as string); auction = await auctionDocRef.get(); }); diff --git a/packages/functions/test-tangle/award-tangle/award-tangle_1.spec.ts b/packages/functions/test-tangle/award-tangle/award-tangle_1.spec.ts index 2b9ba0e2ad..f2e3eb2c0e 100644 --- a/packages/functions/test-tangle/award-tangle/award-tangle_1.spec.ts +++ b/packages/functions/test-tangle/award-tangle/award-tangle_1.spec.ts @@ -1,29 +1,26 @@ -import { build5Db } from '@build-5/database'; +import { PgTransactionType, build5Db } from '@build-5/database'; import { Award, COL, - Member, MIN_IOTA_AMOUNT, + Member, Network, Space, TangleRequestType, Token, Transaction, - TransactionType, } from '@build-5/interfaces'; import dayjs from 'dayjs'; import { Wallet } from '../../src/services/wallet/wallet'; import { AddressDetails } from '../../src/services/wallet/wallet.service'; import { getAddress } from '../../src/utils/address.utils'; -import * as wallet from '../../src/utils/wallet.utils'; -import { createMember, createSpace, wait } from '../../test/controls/common'; -import { getWallet, MEDIA } from '../../test/set-up'; +import { wait } from '../../test/controls/common'; +import { MEDIA, getWallet, testEnv } from '../../test/set-up'; import { getTangleOrder } from '../common'; import { requestFundsFromFaucet } from '../faucet'; import { saveBaseToken } from './common'; const network = Network.RMS; -let walletSpy: any; const CUSTOM_MEDIA = 'https://ipfs.io/ipfs/bafkreiapx7kczhfukx34ldh3pxhdip5kgvh237dlhp55koefjo6tyupnj4'; @@ -37,18 +34,17 @@ describe('Award tangle request', () => { let tangleOrder: Transaction; beforeAll(async () => { - walletSpy = jest.spyOn(wallet, 'decodeAuth'); walletService = await getWallet(network); tangleOrder = await getTangleOrder(Network.RMS); }); beforeEach(async () => { - guardian = await createMember(walletSpy); - space = await createSpace(walletSpy, guardian); + guardian = await testEnv.createMember(); + space = await testEnv.createSpace(guardian); token = await saveBaseToken(space.uid, guardian, Network.RMS); - const guardianDocRef = build5Db().doc(`${COL.MEMBER}/${guardian}`); + const guardianDocRef = build5Db().doc(COL.MEMBER, guardian); const guardianData = await guardianDocRef.get(); const guardianBech32 = getAddress(guardianData, network); guardianAddress = await walletService.getAddressDetails(guardianBech32); @@ -73,7 +69,7 @@ describe('Award tangle request', () => { const creditQuery = build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.CREDIT_TANGLE_REQUEST) + .where('type', '==', PgTransactionType.CREDIT_TANGLE_REQUEST) .where('member', '==', guardian); await wait(async () => { const snap = await creditQuery.get(); @@ -83,7 +79,7 @@ describe('Award tangle request', () => { const credit = snap[0] as Transaction; expect(credit.payload.amount).toBe(5 * MIN_IOTA_AMOUNT); - const awardDocRef = build5Db().doc(`${COL.AWARD}/${credit.payload.response!.award}`); + const awardDocRef = build5Db().doc(COL.AWARD, credit.payload.response!.award! as string); const award = (await awardDocRef.get()) as Award; expect(award.uid).toBe(credit.payload.response!.award); expect(award.name).toBe(newAward.name); diff --git a/packages/functions/test-tangle/award-tangle/award-tangle_2.spec.ts b/packages/functions/test-tangle/award-tangle/award-tangle_2.spec.ts index 2a99bfb02a..8e71dcedf1 100644 --- a/packages/functions/test-tangle/award-tangle/award-tangle_2.spec.ts +++ b/packages/functions/test-tangle/award-tangle/award-tangle_2.spec.ts @@ -1,30 +1,26 @@ -import { build5Db } from '@build-5/database'; +import { PgTransactionType, build5Db } from '@build-5/database'; import { Award, COL, - Member, MIN_IOTA_AMOUNT, + Member, Network, Space, TangleRequestType, Token, Transaction, - TransactionType, } from '@build-5/interfaces'; import dayjs from 'dayjs'; import { MnemonicService } from '../../src/services/wallet/mnemonic'; import { Wallet } from '../../src/services/wallet/wallet'; import { AddressDetails } from '../../src/services/wallet/wallet.service'; import { getAddress } from '../../src/utils/address.utils'; -import * as wallet from '../../src/utils/wallet.utils'; -import { createMember, createSpace, wait } from '../../test/controls/common'; -import { getWallet, MEDIA } from '../../test/set-up'; +import { wait } from '../../test/controls/common'; +import { MEDIA, getWallet, testEnv } from '../../test/set-up'; import { getTangleOrder } from '../common'; import { requestFundsFromFaucet } from '../faucet'; import { saveBaseToken } from './common'; -let walletSpy: any; - describe('Award tangle request', () => { let guardian: string; let space: Space; @@ -36,14 +32,13 @@ describe('Award tangle request', () => { const beforeEach = async (network: Network) => { tangleOrder = await getTangleOrder(network); - walletSpy = jest.spyOn(wallet, 'decodeAuth'); walletService = await getWallet(network); - guardian = await createMember(walletSpy); - space = await createSpace(walletSpy, guardian); + guardian = await testEnv.createMember(); + space = await testEnv.createSpace(guardian); token = await saveBaseToken(space.uid, guardian, network); - const guardianDocRef = build5Db().doc(`${COL.MEMBER}/${guardian}`); + const guardianDocRef = build5Db().doc(COL.MEMBER, guardian); const guardianData = await guardianDocRef.get(); const guardianBech32 = getAddress(guardianData, network); guardianAddress = await walletService.getAddressDetails(guardianBech32); @@ -71,7 +66,7 @@ describe('Award tangle request', () => { const creditQuery = build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.CREDIT_TANGLE_REQUEST) + .where('type', '==', PgTransactionType.CREDIT_TANGLE_REQUEST) .where('member', '==', guardian); await wait(async () => { const snap = await creditQuery.get(); @@ -87,7 +82,7 @@ describe('Award tangle request', () => { credit.payload.response!.amount as number, ); - const awardDocRef = build5Db().doc(`${COL.AWARD}/${credit.payload.response!.award}`); + const awardDocRef = build5Db().doc(COL.AWARD, credit.payload.response!.award! as string); await wait(async () => { const award = (await awardDocRef.get()) as Award; return award.funded; @@ -111,16 +106,16 @@ describe('Award tangle request', () => { const creditQuery = build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.CREDIT_TANGLE_REQUEST) + .where('type', '==', PgTransactionType.CREDIT_TANGLE_REQUEST) .where('member', '==', guardian); await wait(async () => { const snap = await creditQuery.get(); return snap.length === 1; }); - let snap = await creditQuery.get(); + let snap = await creditQuery.get(); let credit = snap[0] as Transaction; expect(credit.payload.amount).toBe(MIN_IOTA_AMOUNT); - const awardDocRef = build5Db().doc(`${COL.AWARD}/${credit.payload.response!.award}`); + const awardDocRef = build5Db().doc(COL.AWARD, credit.payload.response!.award as string); await walletService.send(guardianAddress, tangleOrder.payload.targetAddress!, MIN_IOTA_AMOUNT, { customMetadata: { @@ -134,7 +129,7 @@ describe('Award tangle request', () => { const snap = await creditQuery.get(); return snap.length === 2; }); - snap = await creditQuery.get(); + snap = await creditQuery.get(); credit = snap.find((doc) => doc?.payload?.response?.award === undefined)!; await requestFundsFromFaucet( Network.RMS, diff --git a/packages/functions/test-tangle/award-tangle/award-tangle_3.spec.ts b/packages/functions/test-tangle/award-tangle/award-tangle_3.spec.ts index 33f1ce3844..a5efc47d06 100644 --- a/packages/functions/test-tangle/award-tangle/award-tangle_3.spec.ts +++ b/packages/functions/test-tangle/award-tangle/award-tangle_3.spec.ts @@ -1,9 +1,9 @@ -import { build5Db } from '@build-5/database'; +import { PgTransactionType, build5Db } from '@build-5/database'; import { Award, COL, - Member, MIN_IOTA_AMOUNT, + Member, NativeToken, Network, SOON_PROJECT_ID, @@ -12,7 +12,6 @@ import { Token, TokenStatus, Transaction, - TransactionType, } from '@build-5/interfaces'; import dayjs from 'dayjs'; import { MnemonicService } from '../../src/services/wallet/mnemonic'; @@ -21,13 +20,11 @@ import { AddressDetails } from '../../src/services/wallet/wallet.service'; import { getAddress } from '../../src/utils/address.utils'; import { serverTime } from '../../src/utils/dateTime.utils'; import * as wallet from '../../src/utils/wallet.utils'; -import { createMember, createSpace, getRandomSymbol, wait } from '../../test/controls/common'; -import { getWallet, MEDIA } from '../../test/set-up'; +import { getRandomSymbol, wait } from '../../test/controls/common'; +import { MEDIA, getWallet, testEnv } from '../../test/set-up'; import { getTangleOrder } from '../common'; import { requestFundsFromFaucet, requestMintedTokenFromFaucet } from '../faucet'; -let walletSpy: any; - describe('Award tangle request', () => { let guardian: string; let space: Space; @@ -39,14 +36,13 @@ describe('Award tangle request', () => { const beforeEach = async (network: Network) => { tangleOrder = await getTangleOrder(network); - walletSpy = jest.spyOn(wallet, 'decodeAuth'); walletService = await getWallet(network); - guardian = await createMember(walletSpy); - space = await createSpace(walletSpy, guardian); + guardian = await testEnv.createMember(); + space = await testEnv.createSpace(guardian); token = await saveToken(space.uid, guardian, network); - const guardianDocRef = build5Db().doc(`${COL.MEMBER}/${guardian}`); + const guardianDocRef = build5Db().doc(COL.MEMBER, guardian); const guardianData = await guardianDocRef.get(); const guardianBech32 = getAddress(guardianData, network); guardianAddress = await walletService.getAddressDetails(guardianBech32); @@ -71,7 +67,7 @@ describe('Award tangle request', () => { const creditQuery = build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.CREDIT_TANGLE_REQUEST) + .where('type', '==', PgTransactionType.CREDIT_TANGLE_REQUEST) .where('member', '==', guardian); await wait(async () => { const snap = await creditQuery.get(); @@ -80,7 +76,7 @@ describe('Award tangle request', () => { let snap = await creditQuery.get(); let credit = snap[0] as Transaction; expect(credit.payload.amount).toBe(MIN_IOTA_AMOUNT); - const awardDocRef = build5Db().doc(`${COL.AWARD}/${credit.payload.response!.award}`); + const awardDocRef = build5Db().doc(COL.AWARD, credit.payload.response!.award as string); await requestMintedTokenFromFaucet( walletService, @@ -144,9 +140,9 @@ const saveToken = async (space: string, guardian: string, network: Network) => { network, tokenId: MINTED_TOKEN_ID, }, - }; - await build5Db().doc(`${COL.TOKEN}/${token.uid}`).set(token); - return token as Token; + } as Token; + await build5Db().doc(COL.TOKEN, token.uid).create(token); + return token; }; export const VAULT_MNEMONIC = diff --git a/packages/functions/test-tangle/award-tangle/award-tangle_4.spec.ts b/packages/functions/test-tangle/award-tangle/award-tangle_4.spec.ts index f6262cc434..749be86bf5 100644 --- a/packages/functions/test-tangle/award-tangle/award-tangle_4.spec.ts +++ b/packages/functions/test-tangle/award-tangle/award-tangle_4.spec.ts @@ -1,15 +1,14 @@ -import { build5Db } from '@build-5/database'; +import { PgTransactionType, build5Db } from '@build-5/database'; import { Award, COL, - Member, MIN_IOTA_AMOUNT, + Member, Network, Space, TangleRequestType, Token, Transaction, - TransactionType, } from '@build-5/interfaces'; import dayjs from 'dayjs'; import { isEmpty } from 'lodash'; @@ -17,15 +16,13 @@ import { MnemonicService } from '../../src/services/wallet/mnemonic'; import { Wallet } from '../../src/services/wallet/wallet'; import { AddressDetails } from '../../src/services/wallet/wallet.service'; import { getAddress } from '../../src/utils/address.utils'; -import * as wallet from '../../src/utils/wallet.utils'; -import { createMember, createSpace, wait } from '../../test/controls/common'; -import { getWallet, MEDIA } from '../../test/set-up'; +import { wait } from '../../test/controls/common'; +import { MEDIA, getWallet, testEnv } from '../../test/set-up'; import { getTangleOrder } from '../common'; import { requestFundsFromFaucet } from '../faucet'; import { saveBaseToken } from './common'; const network = Network.RMS; -let walletSpy: any; describe('Award tangle request', () => { let guardian: string; @@ -38,15 +35,14 @@ describe('Award tangle request', () => { const beforeEach = async (network: Network) => { tangleOrder = await getTangleOrder(network); - walletSpy = jest.spyOn(wallet, 'decodeAuth'); walletService = await getWallet(network); - guardian = await createMember(walletSpy); - space = await createSpace(walletSpy, guardian); + guardian = await testEnv.createMember(); + space = await testEnv.createSpace(guardian); token = await saveBaseToken(space.uid, guardian, network); - const guardianDocRef = build5Db().doc(`${COL.MEMBER}/${guardian}`); + const guardianDocRef = build5Db().doc(COL.MEMBER, guardian); const guardianData = await guardianDocRef.get(); const guardianBech32 = getAddress(guardianData, network); guardianAddress = await walletService.getAddressDetails(guardianBech32); @@ -63,13 +59,13 @@ describe('Award tangle request', () => { const creditQuery = build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.CREDIT_TANGLE_REQUEST) + .where('type', '==', PgTransactionType.CREDIT_TANGLE_REQUEST) .where('member', '==', guardian); await wait(async () => { const snap = await creditQuery.get(); return snap.length === 1; }); - let snap = await creditQuery.get(); + let snap = await creditQuery.get(); let credit = snap[0] as Transaction; await requestFundsFromFaucet( network, @@ -77,7 +73,7 @@ describe('Award tangle request', () => { credit.payload.response!.amount as number, ); - const awardDocRef = build5Db().doc(`${COL.AWARD}/${credit.payload.response!.award}`); + const awardDocRef = build5Db().doc(COL.AWARD, credit.payload.response!.award as string); await wait(async () => { const award = (await awardDocRef.get()) as Award; return award.approved; @@ -94,13 +90,13 @@ describe('Award tangle request', () => { }); await wait(async () => { - const snap = await creditQuery.get(); + const snap = await creditQuery.get(); return ( snap.length === 2 && snap.reduce((acc, act) => acc && (act?.payload?.walletReference?.confirmed || false), true) ); }); - snap = await creditQuery.get(); + snap = await creditQuery.get(); credit = snap.find((d) => !isEmpty(d?.payload?.response?.badges))!; expect(Object.keys(credit.payload.response!.badges as any).length).toBe(150); diff --git a/packages/functions/test-tangle/award-tangle/award-tangle_5.spec.ts b/packages/functions/test-tangle/award-tangle/award-tangle_5.spec.ts index 1a65b11fa9..97e10748c7 100644 --- a/packages/functions/test-tangle/award-tangle/award-tangle_5.spec.ts +++ b/packages/functions/test-tangle/award-tangle/award-tangle_5.spec.ts @@ -1,32 +1,28 @@ -import { build5Db } from '@build-5/database'; +import { PgTransactionPayloadType, PgTransactionType, build5Db } from '@build-5/database'; import { Award, COL, - Member, MIN_IOTA_AMOUNT, + Member, Network, NetworkAddress, Space, TangleRequestType, Token, Transaction, - TransactionPayloadType, - TransactionType, } from '@build-5/interfaces'; import dayjs from 'dayjs'; import { MnemonicService } from '../../src/services/wallet/mnemonic'; import { Wallet } from '../../src/services/wallet/wallet'; import { AddressDetails } from '../../src/services/wallet/wallet.service'; import { getAddress } from '../../src/utils/address.utils'; -import * as wallet from '../../src/utils/wallet.utils'; -import { createMember, createSpace, wait } from '../../test/controls/common'; -import { getWallet, MEDIA } from '../../test/set-up'; +import { wait } from '../../test/controls/common'; +import { MEDIA, getWallet, testEnv } from '../../test/set-up'; import { getTangleOrder } from '../common'; import { requestFundsFromFaucet } from '../faucet'; import { saveBaseToken } from './common'; const network = Network.RMS; -let walletSpy: any; describe('Award tangle request', () => { let guardian: string; @@ -37,18 +33,17 @@ describe('Award tangle request', () => { let tangleOrder: Transaction; beforeAll(async () => { - walletSpy = jest.spyOn(wallet, 'decodeAuth'); walletService = await getWallet(network); tangleOrder = await getTangleOrder(Network.RMS); }); beforeEach(async () => { - guardian = await createMember(walletSpy); - space = await createSpace(walletSpy, guardian); + guardian = await testEnv.createMember(); + space = await testEnv.createSpace(guardian); token = await saveBaseToken(space.uid, guardian, Network.RMS); - const guardianDocRef = build5Db().doc(`${COL.MEMBER}/${guardian}`); + const guardianDocRef = build5Db().doc(COL.MEMBER, guardian); const guardianData = await guardianDocRef.get(); const guardianBech32 = getAddress(guardianData, network); guardianAddress = await walletService.getAddressDetails(guardianBech32); @@ -64,7 +59,7 @@ describe('Award tangle request', () => { const creditQuery = build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.CREDIT_TANGLE_REQUEST) + .where('type', '==', PgTransactionType.CREDIT_TANGLE_REQUEST) .where('member', '==', guardian); await wait(async () => { const snap = await creditQuery.get(); @@ -78,7 +73,7 @@ describe('Award tangle request', () => { credit.payload.response!.amount as number, ); - const awardDocRef = build5Db().doc(`${COL.AWARD}/${credit.payload.response!.award}`); + const awardDocRef = build5Db().doc(COL.AWARD, credit.payload.response!.award as string); await wait(async () => { const award = (await awardDocRef.get()) as Award; return award.approved; @@ -96,7 +91,7 @@ describe('Award tangle request', () => { }); await wait(async () => { - const snap = await badgeQuery(tmp.bech32).get(); + const snap = await badgeQuery(tmp.bech32).get(); return snap.length === 1 && snap[0]?.payload?.walletReference?.confirmed; }); @@ -113,7 +108,7 @@ describe('Award tangle request', () => { const badgeQuery = (targetAddress: NetworkAddress) => build5Db() .collection(COL.TRANSACTION) - .where('payload.type', '==', TransactionPayloadType.BADGE) + .where('payload_type', '==', PgTransactionPayloadType.BADGE) .where('member', '==', targetAddress); const awardRequest = (space: string, tokenSymbol: string) => ({ diff --git a/packages/functions/test-tangle/award-tangle/award-tangle_6.spec.ts b/packages/functions/test-tangle/award-tangle/award-tangle_6.spec.ts index fc62400256..ee2c95b541 100644 --- a/packages/functions/test-tangle/award-tangle/award-tangle_6.spec.ts +++ b/packages/functions/test-tangle/award-tangle/award-tangle_6.spec.ts @@ -1,15 +1,14 @@ -import { build5Db } from '@build-5/database'; +import { PgTransactionType, build5Db } from '@build-5/database'; import { Award, COL, - Member, MIN_IOTA_AMOUNT, + Member, Network, Space, TangleRequestType, Token, Transaction, - TransactionType, } from '@build-5/interfaces'; import dayjs from 'dayjs'; import { isEmpty } from 'lodash'; @@ -17,15 +16,13 @@ import { MnemonicService } from '../../src/services/wallet/mnemonic'; import { Wallet } from '../../src/services/wallet/wallet'; import { AddressDetails } from '../../src/services/wallet/wallet.service'; import { getAddress } from '../../src/utils/address.utils'; -import * as wallet from '../../src/utils/wallet.utils'; -import { createMember, createSpace, wait } from '../../test/controls/common'; -import { getWallet, MEDIA } from '../../test/set-up'; +import { wait } from '../../test/controls/common'; +import { MEDIA, getWallet, testEnv } from '../../test/set-up'; import { getTangleOrder } from '../common'; import { requestFundsFromFaucet } from '../faucet'; import { saveBaseToken } from './common'; const network = Network.RMS; -let walletSpy: any; describe('Award tangle request', () => { let guardian: string; @@ -36,18 +33,17 @@ describe('Award tangle request', () => { let tangleOrder: Transaction; beforeAll(async () => { - walletSpy = jest.spyOn(wallet, 'decodeAuth'); walletService = await getWallet(network); tangleOrder = await getTangleOrder(Network.RMS); }); beforeEach(async () => { - guardian = await createMember(walletSpy); - space = await createSpace(walletSpy, guardian); + guardian = await testEnv.createMember(); + space = await testEnv.createSpace(guardian); token = await saveBaseToken(space.uid, guardian, Network.RMS); - const guardianDocRef = build5Db().doc(`${COL.MEMBER}/${guardian}`); + const guardianDocRef = build5Db().doc(COL.MEMBER, guardian); const guardianData = await guardianDocRef.get(); const guardianBech32 = getAddress(guardianData, network); guardianAddress = await walletService.getAddressDetails(guardianBech32); @@ -63,13 +59,13 @@ describe('Award tangle request', () => { const creditQuery = build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.CREDIT_TANGLE_REQUEST) + .where('type', '==', PgTransactionType.CREDIT_TANGLE_REQUEST) .where('member', '==', guardian); await wait(async () => { const snap = await creditQuery.get(); return snap.length === 1; }); - let snap = await creditQuery.get(); + let snap = await creditQuery.get(); let credit = snap[0]; await requestFundsFromFaucet( Network.RMS, @@ -77,7 +73,7 @@ describe('Award tangle request', () => { credit.payload.response!.amount as number, ); - const awardDocRef = build5Db().doc(`${COL.AWARD}/${credit.payload.response!.award}`); + const awardDocRef = build5Db().doc(COL.AWARD, credit.payload.response!.award as string); await wait(async () => { const award = await awardDocRef.get(); return award.approved; @@ -94,10 +90,10 @@ describe('Award tangle request', () => { }); await wait(async () => { - const snap = await creditQuery.get(); + const snap = await creditQuery.get(); return snap.length === 2; }); - snap = await creditQuery.get(); + snap = await creditQuery.get(); credit = snap.find((d) => !isEmpty(d.payload?.response?.badges))!; expect(Object.keys(credit.payload.response!.badges as any).length).toBe(150); diff --git a/packages/functions/test-tangle/award-tangle/award-tangle_7.spec.ts b/packages/functions/test-tangle/award-tangle/award-tangle_7.spec.ts index fc43984c69..42abd55233 100644 --- a/packages/functions/test-tangle/award-tangle/award-tangle_7.spec.ts +++ b/packages/functions/test-tangle/award-tangle/award-tangle_7.spec.ts @@ -1,29 +1,25 @@ -import { build5Db } from '@build-5/database'; +import { PgTransactionType, build5Db } from '@build-5/database'; import { Award, COL, - Member, MIN_IOTA_AMOUNT, + Member, Network, Space, TangleRequestType, Token, Transaction, - TransactionType, } from '@build-5/interfaces'; import dayjs from 'dayjs'; import { Wallet } from '../../src/services/wallet/wallet'; import { AddressDetails } from '../../src/services/wallet/wallet.service'; import { getAddress } from '../../src/utils/address.utils'; -import * as wallet from '../../src/utils/wallet.utils'; -import { createMember, createSpace, wait } from '../../test/controls/common'; -import { getWallet, MEDIA } from '../../test/set-up'; +import { wait } from '../../test/controls/common'; +import { MEDIA, getWallet, testEnv } from '../../test/set-up'; import { getTangleOrder } from '../common'; import { requestFundsFromFaucet } from '../faucet'; import { saveBaseToken } from './common'; -let walletSpy: any; - describe('Award tangle request', () => { let guardian: string; let space: Space; @@ -36,14 +32,14 @@ describe('Award tangle request', () => { const beforeEach = async (network: Network) => { tangleOrder = await getTangleOrder(network); - walletSpy = jest.spyOn(wallet, 'decodeAuth'); + walletService = await getWallet(network); - guardian = await createMember(walletSpy); - space = await createSpace(walletSpy, guardian); + guardian = await testEnv.createMember(); + space = await testEnv.createSpace(guardian); token = await saveBaseToken(space.uid, guardian, network); - const guardianDocRef = build5Db().doc(`${COL.MEMBER}/${guardian}`); + const guardianDocRef = build5Db().doc(COL.MEMBER, guardian); const guardianData = await guardianDocRef.get(); const guardianBech32 = getAddress(guardianData, network); guardianAddress = await walletService.getAddressDetails(guardianBech32); @@ -71,7 +67,7 @@ describe('Award tangle request', () => { const creditQuery = build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.CREDIT_TANGLE_REQUEST) + .where('type', '==', PgTransactionType.CREDIT_TANGLE_REQUEST) .where('member', '==', guardian); await wait(async () => { const snap = await creditQuery.get(); @@ -81,7 +77,7 @@ describe('Award tangle request', () => { const credit = snap[0] as Transaction; expect(credit.payload.amount).toBe(5 * MIN_IOTA_AMOUNT); - const awardDocRef = build5Db().doc(`${COL.AWARD}/${credit.payload.response!.award}`); + const awardDocRef = build5Db().doc(COL.AWARD, credit.payload.response!.award as string); const award = (await awardDocRef.get()) as Award; expect(award.uid).toBe(credit.payload.response!.award); expect(award.name).toBe(newAward.name); diff --git a/packages/functions/test-tangle/award-tangle/common.ts b/packages/functions/test-tangle/award-tangle/common.ts index f98ed354d0..8c907fd5a0 100644 --- a/packages/functions/test-tangle/award-tangle/common.ts +++ b/packages/functions/test-tangle/award-tangle/common.ts @@ -1,13 +1,5 @@ -import { IQuery, build5Db } from '@build-5/database'; -import { - COL, - Network, - SOON_PROJECT_ID, - Token, - TokenStatus, - TransactionPayloadType, - TransactionType, -} from '@build-5/interfaces'; +import { IQuery, PgTransactionPayloadType, PgTransactionType, build5Db } from '@build-5/database'; +import { COL, Network, SOON_PROJECT_ID, Token, TokenStatus } from '@build-5/interfaces'; import { serverTime } from '../../src/utils/dateTime.utils'; import { getRandomEthAddress } from '../../src/utils/wallet.utils'; import { getRandomSymbol, wait } from '../../test/controls/common'; @@ -16,20 +8,20 @@ import { MEDIA } from '../../test/set-up'; export const awaitAllTransactionsForAward = async (awardId: string) => { const baseTransQuery = build5Db() .collection(COL.TRANSACTION) - .where('payload.award', '==', awardId) - .where('type', 'in', [TransactionType.BILL_PAYMENT, TransactionType.CREDIT]); + .where('payload_award', '==', awardId) + .whereIn('type', [PgTransactionType.BILL_PAYMENT, PgTransactionType.CREDIT]); await allConfirmed(baseTransQuery); const nttQuery = build5Db() .collection(COL.TRANSACTION) - .where('payload.award', '==', awardId) - .where('payload.type', '==', TransactionPayloadType.BADGE); + .where('payload_award', '==', awardId) + .where('payload_type', '==', PgTransactionPayloadType.BADGE); await allConfirmed(nttQuery); }; -const allConfirmed = (query: IQuery) => +const allConfirmed = (query: IQuery) => wait(async () => { - const snap = await query.get(); + const snap = await query.get(); const allConfirmed = snap.reduce( (acc, doc) => acc && doc?.payload?.walletReference?.confirmed, true, @@ -54,7 +46,7 @@ export const saveBaseToken = async (space: string, guardian: string, network: Ne mintingData: { network, }, - }; - await build5Db().doc(`${COL.TOKEN}/${token.uid}`).set(token); - return token as Token; + } as Token; + await build5Db().doc(COL.TOKEN, token.uid).create(token); + return token; }; diff --git a/packages/functions/test-tangle/award/award_1.spec.ts b/packages/functions/test-tangle/award/award_1.spec.ts index 936d74da5f..6c8b4cc59d 100644 --- a/packages/functions/test-tangle/award/award_1.spec.ts +++ b/packages/functions/test-tangle/award/award_1.spec.ts @@ -1,37 +1,26 @@ -import { build5Db } from '@build-5/database'; +import { PgTransactionPayloadType, PgTransactionType, build5Db } from '@build-5/database'; import { Award, COL, - Member, MIN_IOTA_AMOUNT, + Member, Network, - Space, SUB_COL, + Space, Token, TokenDistribution, Transaction, - TransactionPayloadType, - TransactionType, + WEN_FUNC, } from '@build-5/interfaces'; import { NftOutput, TimelockUnlockCondition, UnlockConditionType } from '@iota/sdk'; import dayjs from 'dayjs'; -import { - approveAwardParticipant, - awardParticipate, - createAward, - fundAward, -} from '../../src/runtime/firebase/award'; -import { claimMintedTokenOrder } from '../../src/runtime/firebase/token/minting'; import { Wallet } from '../../src/services/wallet/wallet'; import { getAddress } from '../../src/utils/address.utils'; -import * as wallet from '../../src/utils/wallet.utils'; -import { createMember, createSpace, mockWalletReturnValue, wait } from '../../test/controls/common'; -import { getWallet, MEDIA, testEnv } from '../../test/set-up'; +import { wait } from '../../test/controls/common'; +import { MEDIA, getWallet, mockWalletReturnValue, testEnv } from '../../test/set-up'; import { requestFundsFromFaucet } from '../faucet'; import { awaitAllTransactionsForAward, saveBaseToken } from './common'; -let walletSpy: any; - describe('Create award, base', () => { let guardian: string; let member: string; @@ -41,35 +30,31 @@ describe('Create award, base', () => { let now: dayjs.Dayjs; let token: Token; - beforeAll(async () => { - walletSpy = jest.spyOn(wallet, 'decodeAuth'); - }); - const setup = async (network: Network) => { now = dayjs(); walletService = await getWallet(network); - guardian = await createMember(walletSpy); - member = await createMember(walletSpy); - space = await createSpace(walletSpy, guardian); + guardian = await testEnv.createMember(); + member = await testEnv.createMember(); + space = await testEnv.createSpace(guardian); token = await saveBaseToken(space.uid, guardian, network); - mockWalletReturnValue(walletSpy, guardian, awardRequest(network, space.uid, token.symbol)); - award = await testEnv.wrap(createAward)({}); + mockWalletReturnValue(guardian, awardRequest(network, space.uid, token.symbol)); + award = await testEnv.wrap(WEN_FUNC.createAward); }; it.each([Network.ATOI, Network.RMS])( 'Should create, fund and participate in award', async (network: Network) => { await setup(network); - mockWalletReturnValue(walletSpy, guardian, { uid: award.uid }); - const order = await testEnv.wrap(fundAward)({}); + mockWalletReturnValue(guardian, { uid: award.uid }); + const order = await testEnv.wrap(WEN_FUNC.fundAward); const address = await walletService.getNewIotaAddressDetails(); - await requestFundsFromFaucet(network, address.bech32, order.payload.amount); - await walletService.send(address, order.payload.targetAddress, order.payload.amount, {}); + await requestFundsFromFaucet(network, address.bech32, order.payload.amount!); + await walletService.send(address, order.payload.targetAddress!, order.payload.amount!, {}); - const awardDocRef = build5Db().doc(`${COL.AWARD}/${award.uid}`); + const awardDocRef = build5Db().doc(COL.AWARD, award.uid); await wait(async () => { const award = await awardDocRef.get(); return award.approved && award.funded; @@ -80,42 +65,41 @@ describe('Create award, base', () => { expect(awardData.collectionBlockId).toBeDefined(); expect(awardData.collectionId).toBeDefined(); - mockWalletReturnValue(walletSpy, member, { uid: award.uid }); - await testEnv.wrap(awardParticipate)({}); + mockWalletReturnValue(member, { uid: award.uid }); + await testEnv.wrap(WEN_FUNC.participateAward); - mockWalletReturnValue(walletSpy, guardian, { award: award.uid, members: [member, member] }); - await testEnv.wrap(approveAwardParticipant)({}); + mockWalletReturnValue(guardian, { award: award.uid, members: [member, member] }); + await testEnv.wrap(WEN_FUNC.approveParticipantAward); - const memberDocRef = build5Db().doc(`${COL.MEMBER}/${member}`); + const memberDocRef = build5Db().doc(COL.MEMBER, member); const memberData = await memberDocRef.get(); const memberBech32 = getAddress(memberData, network); - const tokenDocRef = build5Db().doc(`${COL.TOKEN}/${token.uid}`); - const distributionDocRef = tokenDocRef.collection(SUB_COL.DISTRIBUTION).doc(member); - let distribution = await distributionDocRef.get(); - expect(distribution.totalUnclaimedAirdrop).toBe(2 * MIN_IOTA_AMOUNT); + const distributionDocRef = build5Db().doc(COL.TOKEN, token.uid, SUB_COL.DISTRIBUTION, member); + let distribution = await distributionDocRef.get(); + expect(distribution?.totalUnclaimedAirdrop).toBe(2 * MIN_IOTA_AMOUNT); const nttQuery = build5Db() .collection(COL.TRANSACTION) .where('member', '==', member) - .where('payload.type', '==', TransactionPayloadType.BADGE); + .where('payload_type', '==', PgTransactionPayloadType.BADGE); await wait(async () => { const snap = await nttQuery.get(); return snap.length === 2; }); - mockWalletReturnValue(walletSpy, member, { symbol: token.symbol }); - const claimOrder = await testEnv.wrap(claimMintedTokenOrder)({}); + mockWalletReturnValue(member, { symbol: token.symbol }); + const claimOrder = await testEnv.wrap(WEN_FUNC.claimMintedTokenOrder); await requestFundsFromFaucet( network, - claimOrder.payload.targetAddress, - claimOrder.payload.amount, + claimOrder.payload.targetAddress!, + claimOrder.payload.amount!, ); const billPaymentQuery = build5Db() .collection(COL.TRANSACTION) .where('member', '==', member) - .where('type', '==', TransactionType.BILL_PAYMENT); + .where('type', '==', PgTransactionType.BILL_PAYMENT); await wait(async () => { const snap = await billPaymentQuery.get(); return snap.length === 2; @@ -128,7 +112,7 @@ describe('Create award, base', () => { await wait(async () => { let { amount } = await walletService.getBalance(memberBech32); - return amount === 2 * MIN_IOTA_AMOUNT + claimOrder.payload.amount; + return amount === 2 * MIN_IOTA_AMOUNT + claimOrder.payload.amount!; }); await wait(async () => { @@ -150,10 +134,10 @@ describe('Create award, base', () => { const burnAliasQuery = build5Db() .collection(COL.TRANSACTION) - .where('payload.type', '==', TransactionPayloadType.BURN_ALIAS) + .where('payload_type', '==', PgTransactionPayloadType.BURN_ALIAS) .where('member', '==', guardian); await wait(async () => { - const snap = await burnAliasQuery.get(); + const snap = await burnAliasQuery.get(); return snap.length === 1 && snap[0]?.payload?.walletReference?.confirmed; }); diff --git a/packages/functions/test-tangle/award/award_10.spec.ts b/packages/functions/test-tangle/award/award_10.spec.ts index 239db273ae..7e19e886b4 100644 --- a/packages/functions/test-tangle/award/award_10.spec.ts +++ b/packages/functions/test-tangle/award/award_10.spec.ts @@ -2,34 +2,26 @@ import { build5Db } from '@build-5/database'; import { Award, COL, - Member, Network, SOON_PROJECT_ID, Space, Token, TokenStatus, + Transaction, + WEN_FUNC, } from '@build-5/interfaces'; import dayjs from 'dayjs'; -import { approveAwardParticipant, createAward, fundAward } from '../../src/runtime/firebase/award'; -import { joinSpace } from '../../src/runtime/firebase/space'; import { MnemonicService } from '../../src/services/wallet/mnemonic'; import { Wallet } from '../../src/services/wallet/wallet'; import { AddressDetails } from '../../src/services/wallet/wallet.service'; import { getAddress } from '../../src/utils/address.utils'; import { serverTime } from '../../src/utils/dateTime.utils'; import * as wallet from '../../src/utils/wallet.utils'; -import { - createMember, - createSpace, - getRandomSymbol, - mockWalletReturnValue, - wait, -} from '../../test/controls/common'; -import { MEDIA, getWallet, testEnv } from '../../test/set-up'; +import { getRandomSymbol, wait } from '../../test/controls/common'; +import { MEDIA, getWallet, mockWalletReturnValue, testEnv } from '../../test/set-up'; import { requestFundsFromFaucet, requestMintedTokenFromFaucet } from '../faucet'; const network = Network.RMS; -let walletSpy: any; describe('Create award, native', () => { let guardian: string; @@ -41,32 +33,31 @@ describe('Create award, native', () => { let token: Token; beforeAll(async () => { - walletSpy = jest.spyOn(wallet, 'decodeAuth'); walletService = await getWallet(network); }); beforeEach(async () => { - guardian = await createMember(walletSpy); - member = await createMember(walletSpy); - space = await createSpace(walletSpy, guardian); + guardian = await testEnv.createMember(); + member = await testEnv.createMember(); + space = await testEnv.createSpace(guardian); - mockWalletReturnValue(walletSpy, member, { uid: space?.uid }); - await testEnv.wrap(joinSpace)({}); + mockWalletReturnValue(member, { uid: space?.uid }); + await testEnv.wrap(WEN_FUNC.joinSpace); token = await saveToken(space.uid, guardian); - mockWalletReturnValue(walletSpy, member, awardRequest(space.uid, token.symbol)); - award = await testEnv.wrap(createAward)({}); + mockWalletReturnValue(member, awardRequest(space.uid, token.symbol)); + award = await testEnv.wrap(WEN_FUNC.createAward); - const guardianDocRef = build5Db().doc(`${COL.MEMBER}/${guardian}`); - const guardianData = await guardianDocRef.get(); + const guardianDocRef = build5Db().doc(COL.MEMBER, guardian); + const guardianData = await guardianDocRef.get(); const guardianBech32 = getAddress(guardianData, network); guardianAddress = await walletService.getAddressDetails(guardianBech32); }); it('Should create and issue to upper case address', async () => { - mockWalletReturnValue(walletSpy, guardian, { uid: award.uid }); - const order = await testEnv.wrap(fundAward)({}); + mockWalletReturnValue(guardian, { uid: award.uid }); + const order = await testEnv.wrap(WEN_FUNC.fundAward); await requestFundsFromFaucet(network, guardianAddress.bech32, order.payload.amount); await requestMintedTokenFromFaucet( @@ -76,22 +67,22 @@ describe('Create award, native', () => { VAULT_MNEMONIC, 15, ); - await walletService.send(guardianAddress, order.payload.targetAddress, order.payload.amount, { + await walletService.send(guardianAddress, order.payload.targetAddress!, order.payload.amount!, { nativeTokens: [{ id: MINTED_TOKEN_ID, amount: BigInt(15) }], }); await MnemonicService.store(guardianAddress.bech32, guardianAddress.mnemonic); - const awardDocRef = build5Db().doc(`${COL.AWARD}/${award.uid}`); + const awardDocRef = build5Db().doc(COL.AWARD, award.uid); await wait(async () => { const award = await awardDocRef.get(); return award.approved && award.funded; }); - mockWalletReturnValue(walletSpy, guardian, { + mockWalletReturnValue(guardian, { award: award.uid, members: [member.toUpperCase()], }); - await testEnv.wrap(approveAwardParticipant)({}); + await testEnv.wrap(WEN_FUNC.approveParticipantAward); const snap = await build5Db().collection(COL.AIRDROP).where('member', '==', member).get(); expect(snap.length).toBe(1); @@ -133,9 +124,9 @@ const saveToken = async (space: string, guardian: string) => { network: Network.RMS, tokenId: MINTED_TOKEN_ID, }, - }; - await build5Db().doc(`${COL.TOKEN}/${token.uid}`).set(token); - return token as Token; + } as Token; + await build5Db().doc(COL.TOKEN, token.uid).create(token); + return token; }; export const VAULT_MNEMONIC = diff --git a/packages/functions/test-tangle/award/award_11.spec.ts b/packages/functions/test-tangle/award/award_11.spec.ts index d854fc1d95..96fcc2abe2 100644 --- a/packages/functions/test-tangle/award/award_11.spec.ts +++ b/packages/functions/test-tangle/award/award_11.spec.ts @@ -1,37 +1,26 @@ -import { build5Db } from '@build-5/database'; +import { PgTransactionPayloadType, PgTransactionType, build5Db } from '@build-5/database'; import { Award, COL, - Member, MIN_IOTA_AMOUNT, + Member, Network, - Space, SUB_COL, + Space, Token, TokenDistribution, Transaction, - TransactionPayloadType, - TransactionType, + WEN_FUNC, } from '@build-5/interfaces'; import { NftOutput, TimelockUnlockCondition, UnlockConditionType } from '@iota/sdk'; import dayjs from 'dayjs'; -import { - approveAwardParticipant, - awardParticipate, - createAward, - fundAward, -} from '../../src/runtime/firebase/award'; -import { claimMintedTokenOrder } from '../../src/runtime/firebase/token/minting'; import { Wallet } from '../../src/services/wallet/wallet'; import { getAddress } from '../../src/utils/address.utils'; -import * as wallet from '../../src/utils/wallet.utils'; -import { createMember, createSpace, mockWalletReturnValue, wait } from '../../test/controls/common'; -import { getWallet, MEDIA, testEnv } from '../../test/set-up'; +import { wait } from '../../test/controls/common'; +import { MEDIA, getWallet, mockWalletReturnValue, testEnv } from '../../test/set-up'; import { requestFundsFromFaucet } from '../faucet'; import { awaitAllTransactionsForAward, saveBaseToken } from './common'; -let walletSpy: any; - describe('Create award, base', () => { let guardian: string; let member: string; @@ -41,34 +30,32 @@ describe('Create award, base', () => { let now: dayjs.Dayjs; let token: Token; - beforeAll(async () => { - walletSpy = jest.spyOn(wallet, 'decodeAuth'); - }); + beforeAll(async () => {}); const setup = async (network: Network) => { now = dayjs(); walletService = await getWallet(network); - guardian = await createMember(walletSpy); - member = await createMember(walletSpy); - space = await createSpace(walletSpy, guardian); + guardian = await testEnv.createMember(); + member = await testEnv.createMember(); + space = await testEnv.createSpace(guardian); token = await saveBaseToken(space.uid, guardian, network); - mockWalletReturnValue(walletSpy, guardian, awardRequest(network, space.uid, token.symbol)); - award = await testEnv.wrap(createAward)({}); + mockWalletReturnValue(guardian, awardRequest(network, space.uid, token.symbol)); + award = await testEnv.wrap(WEN_FUNC.createAward); }; it('Should create, fund and participate in award, return to sender address', async () => { const network = Network.RMS; await setup(network); - mockWalletReturnValue(walletSpy, guardian, { uid: award.uid }); - const order = await testEnv.wrap(fundAward)({}); + mockWalletReturnValue(guardian, { uid: award.uid }); + const order = await testEnv.wrap(WEN_FUNC.fundAward); const address = await walletService.getNewIotaAddressDetails(); await requestFundsFromFaucet(network, address.bech32, order.payload.amount); - await walletService.send(address, order.payload.targetAddress, order.payload.amount, {}); + await walletService.send(address, order.payload.targetAddress!, order.payload.amount!, {}); - const awardDocRef = build5Db().doc(`${COL.AWARD}/${award.uid}`); + const awardDocRef = build5Db().doc(COL.AWARD, award.uid); await wait(async () => { const award = await awardDocRef.get(); return award.approved && award.funded; @@ -80,32 +67,31 @@ describe('Create award, base', () => { expect(awardData.collectionId).toBeDefined(); expect(awardData.fundingAddress).toBe(address.bech32); - mockWalletReturnValue(walletSpy, member, { uid: award.uid }); - await testEnv.wrap(awardParticipate)({}); + mockWalletReturnValue(member, { uid: award.uid }); + await testEnv.wrap(WEN_FUNC.participateAward); - mockWalletReturnValue(walletSpy, guardian, { award: award.uid, members: [member, member] }); - await testEnv.wrap(approveAwardParticipant)({}); + mockWalletReturnValue(guardian, { award: award.uid, members: [member, member] }); + await testEnv.wrap(WEN_FUNC.approveParticipantAward); - const memberDocRef = build5Db().doc(`${COL.MEMBER}/${member}`); + const memberDocRef = build5Db().doc(COL.MEMBER, member); const memberData = await memberDocRef.get(); const memberBech32 = getAddress(memberData, network); - const tokenDocRef = build5Db().doc(`${COL.TOKEN}/${token.uid}`); - const distributionDocRef = tokenDocRef.collection(SUB_COL.DISTRIBUTION).doc(member); + const distributionDocRef = build5Db().doc(COL.TOKEN, token.uid, SUB_COL.DISTRIBUTION, member); let distribution = await distributionDocRef.get(); expect(distribution.totalUnclaimedAirdrop).toBe(2 * MIN_IOTA_AMOUNT); const nttQuery = build5Db() .collection(COL.TRANSACTION) .where('member', '==', member) - .where('payload.type', '==', TransactionPayloadType.BADGE); + .where('payload_type', '==', PgTransactionPayloadType.BADGE); await wait(async () => { const snap = await nttQuery.get(); return snap.length === 2; }); - mockWalletReturnValue(walletSpy, member, { symbol: token.symbol }); - const claimOrder = await testEnv.wrap(claimMintedTokenOrder)({}); + mockWalletReturnValue(member, { symbol: token.symbol }); + const claimOrder = await testEnv.wrap(WEN_FUNC.claimMintedTokenOrder); await requestFundsFromFaucet( network, claimOrder.payload.targetAddress, @@ -115,7 +101,7 @@ describe('Create award, base', () => { const billPaymentQuery = build5Db() .collection(COL.TRANSACTION) .where('member', '==', member) - .where('type', '==', TransactionType.BILL_PAYMENT); + .where('type', '==', PgTransactionType.BILL_PAYMENT); await wait(async () => { const snap = await billPaymentQuery.get(); return snap.length === 2; @@ -128,7 +114,7 @@ describe('Create award, base', () => { await wait(async () => { let { amount } = await walletService.getBalance(memberBech32); - return amount === 2 * MIN_IOTA_AMOUNT + claimOrder.payload.amount; + return amount === 2 * MIN_IOTA_AMOUNT + claimOrder.payload.amount!; }); await wait(async () => { @@ -150,13 +136,13 @@ describe('Create award, base', () => { const burnAliasQuery = build5Db() .collection(COL.TRANSACTION) - .where('payload.type', '==', TransactionPayloadType.BURN_ALIAS) + .where('payload_type', '==', PgTransactionPayloadType.BURN_ALIAS) .where('member', '==', guardian); await wait(async () => { - const snap = await burnAliasQuery.get(); + const snap = await burnAliasQuery.get(); return snap.length === 1 && snap[0]?.payload?.walletReference?.confirmed; }); - const snap = await burnAliasQuery.get(); + const snap = await burnAliasQuery.get(); expect(snap[0].payload.targetAddress).toBe(address.bech32); await wait(async () => { diff --git a/packages/functions/test-tangle/award/award_12.spec.ts b/packages/functions/test-tangle/award/award_12.spec.ts index e1a89a0947..cf735de8b7 100644 --- a/packages/functions/test-tangle/award/award_12.spec.ts +++ b/packages/functions/test-tangle/award/award_12.spec.ts @@ -1,37 +1,26 @@ -import { build5Db } from '@build-5/database'; +import { PgTransactionPayloadType, PgTransactionType, build5Db } from '@build-5/database'; import { Award, COL, - Member, MIN_IOTA_AMOUNT, + Member, Network, - Space, SUB_COL, + Space, Token, TokenDistribution, Transaction, - TransactionPayloadType, - TransactionType, + WEN_FUNC, } from '@build-5/interfaces'; import { NftOutput, TimelockUnlockCondition, UnlockConditionType } from '@iota/sdk'; import dayjs from 'dayjs'; -import { - approveAwardParticipant, - awardParticipate, - createAward, - fundAward, -} from '../../src/runtime/firebase/award'; -import { claimMintedTokenOrder } from '../../src/runtime/firebase/token/minting'; import { Wallet } from '../../src/services/wallet/wallet'; import { getAddress } from '../../src/utils/address.utils'; -import * as wallet from '../../src/utils/wallet.utils'; -import { createMember, createSpace, mockWalletReturnValue, wait } from '../../test/controls/common'; -import { getWallet, MEDIA, testEnv } from '../../test/set-up'; +import { wait } from '../../test/controls/common'; +import { MEDIA, getWallet, mockWalletReturnValue, testEnv } from '../../test/set-up'; import { requestFundsFromFaucet } from '../faucet'; import { awaitAllTransactionsForAward, saveBaseToken } from './common'; -let walletSpy: any; - describe('Create award, base', () => { let guardian: string; let member: string; @@ -41,34 +30,32 @@ describe('Create award, base', () => { let now: dayjs.Dayjs; let token: Token; - beforeAll(async () => { - walletSpy = jest.spyOn(wallet, 'decodeAuth'); - }); + beforeAll(async () => {}); const setup = async (network: Network) => { now = dayjs(); walletService = await getWallet(network); - guardian = await createMember(walletSpy); - member = await createMember(walletSpy); - space = await createSpace(walletSpy, guardian); + guardian = await testEnv.createMember(); + member = await testEnv.createMember(); + space = await testEnv.createSpace(guardian); token = await saveBaseToken(space.uid, guardian, network); - mockWalletReturnValue(walletSpy, guardian, awardRequest(network, space.uid, token.symbol)); - award = await testEnv.wrap(createAward)({}); + mockWalletReturnValue(guardian, awardRequest(network, space.uid, token.symbol)); + award = await testEnv.wrap(WEN_FUNC.createAward); }; it('Should create, fund and participate in award, return to sender address when funding address is missing', async () => { const network = Network.RMS; await setup(network); - mockWalletReturnValue(walletSpy, guardian, { uid: award.uid }); - const order = await testEnv.wrap(fundAward)({}); + mockWalletReturnValue(guardian, { uid: award.uid }); + const order = await testEnv.wrap(WEN_FUNC.fundAward); const address = await walletService.getNewIotaAddressDetails(); await requestFundsFromFaucet(network, address.bech32, order.payload.amount); - await walletService.send(address, order.payload.targetAddress, order.payload.amount, {}); + await walletService.send(address, order.payload.targetAddress!, order.payload.amount!, {}); - const awardDocRef = build5Db().doc(`${COL.AWARD}/${award.uid}`); + const awardDocRef = build5Db().doc(COL.AWARD, award.uid); await wait(async () => { const award = await awardDocRef.get(); return award.approved && award.funded; @@ -79,34 +66,33 @@ describe('Create award, base', () => { expect(awardData.collectionBlockId).toBeDefined(); expect(awardData.collectionId).toBeDefined(); expect(awardData.fundingAddress).toBe(address.bech32); - await awardDocRef.update({ fundingAddress: build5Db().deleteField() }); + await awardDocRef.update({ fundingAddress: undefined }); - mockWalletReturnValue(walletSpy, member, { uid: award.uid }); - await testEnv.wrap(awardParticipate)({}); + mockWalletReturnValue(member, { uid: award.uid }); + await testEnv.wrap(WEN_FUNC.participateAward); - mockWalletReturnValue(walletSpy, guardian, { award: award.uid, members: [member, member] }); - await testEnv.wrap(approveAwardParticipant)({}); + mockWalletReturnValue(guardian, { award: award.uid, members: [member, member] }); + await testEnv.wrap(WEN_FUNC.approveParticipantAward); - const memberDocRef = build5Db().doc(`${COL.MEMBER}/${member}`); + const memberDocRef = build5Db().doc(COL.MEMBER, member); const memberData = await memberDocRef.get(); const memberBech32 = getAddress(memberData, network); - const tokenDocRef = build5Db().doc(`${COL.TOKEN}/${token.uid}`); - const distributionDocRef = tokenDocRef.collection(SUB_COL.DISTRIBUTION).doc(member); + const distributionDocRef = build5Db().doc(COL.TOKEN, token.uid, SUB_COL.DISTRIBUTION, member); let distribution = await distributionDocRef.get(); expect(distribution.totalUnclaimedAirdrop).toBe(2 * MIN_IOTA_AMOUNT); const nttQuery = build5Db() .collection(COL.TRANSACTION) .where('member', '==', member) - .where('payload.type', '==', TransactionPayloadType.BADGE); + .where('payload_type', '==', PgTransactionPayloadType.BADGE); await wait(async () => { const snap = await nttQuery.get(); return snap.length === 2; }); - mockWalletReturnValue(walletSpy, member, { symbol: token.symbol }); - const claimOrder = await testEnv.wrap(claimMintedTokenOrder)({}); + mockWalletReturnValue(member, { symbol: token.symbol }); + const claimOrder = await testEnv.wrap(WEN_FUNC.claimMintedTokenOrder); await requestFundsFromFaucet( network, claimOrder.payload.targetAddress, @@ -116,7 +102,7 @@ describe('Create award, base', () => { const billPaymentQuery = build5Db() .collection(COL.TRANSACTION) .where('member', '==', member) - .where('type', '==', TransactionType.BILL_PAYMENT); + .where('type', '==', PgTransactionType.BILL_PAYMENT); await wait(async () => { const snap = await billPaymentQuery.get(); return snap.length === 2; @@ -129,7 +115,7 @@ describe('Create award, base', () => { await wait(async () => { let { amount } = await walletService.getBalance(memberBech32); - return amount === 2 * MIN_IOTA_AMOUNT + claimOrder.payload.amount; + return amount === 2 * MIN_IOTA_AMOUNT + claimOrder.payload.amount!; }); await wait(async () => { @@ -151,13 +137,13 @@ describe('Create award, base', () => { const burnAliasQuery = build5Db() .collection(COL.TRANSACTION) - .where('payload.type', '==', TransactionPayloadType.BURN_ALIAS) + .where('payload_type', '==', PgTransactionPayloadType.BURN_ALIAS) .where('member', '==', guardian); await wait(async () => { - const snap = await burnAliasQuery.get(); + const snap = await burnAliasQuery.get(); return snap.length === 1 && snap[0]?.payload?.walletReference?.confirmed; }); - const snap = await burnAliasQuery.get(); + const snap = await burnAliasQuery.get(); expect(snap[0].payload.targetAddress).toBe(address.bech32); await wait(async () => { diff --git a/packages/functions/test-tangle/award/award_1_b.spec.ts b/packages/functions/test-tangle/award/award_1_b.spec.ts index 04080d9da4..3464b38e04 100644 --- a/packages/functions/test-tangle/award/award_1_b.spec.ts +++ b/packages/functions/test-tangle/award/award_1_b.spec.ts @@ -1,32 +1,19 @@ -import { MIN_IOTA_AMOUNT, Network, Token, WenError } from '@build-5/interfaces'; +import { MIN_IOTA_AMOUNT, Network, Token, WEN_FUNC, WenError } from '@build-5/interfaces'; import dayjs from 'dayjs'; -import { createAward } from '../../src/runtime/firebase/award'; -import * as wallet from '../../src/utils/wallet.utils'; -import { - createMember, - createSpace, - expectThrow, - mockWalletReturnValue, -} from '../../test/controls/common'; -import { MEDIA, testEnv } from '../../test/set-up'; +import { expectThrow } from '../../test/controls/common'; +import { MEDIA, mockWalletReturnValue, testEnv } from '../../test/set-up'; import { saveBaseToken } from './common'; -let walletSpy: any; - describe('Create award, base', () => { let token: Token; - beforeAll(async () => { - walletSpy = jest.spyOn(wallet, 'decodeAuth'); - }); - it('Should throw, max lockTime', async () => { const network = Network.RMS; - const guardian = await createMember(walletSpy); - const space = await createSpace(walletSpy, guardian); + const guardian = await testEnv.createMember(); + const space = await testEnv.createSpace(guardian); token = await saveBaseToken(space.uid, guardian, network); - mockWalletReturnValue(walletSpy, guardian, awardRequest(network, space.uid, token.symbol)); - await expectThrow(testEnv.wrap(createAward)({}), WenError.invalid_params.key); + mockWalletReturnValue(guardian, awardRequest(network, space.uid, token.symbol)); + await expectThrow(testEnv.wrap(WEN_FUNC.createAward), WenError.invalid_params.key); }); }); @@ -41,7 +28,7 @@ const awardRequest = (network: Network, space: string, tokenSymbol: string) => ( total: 2, image: MEDIA, tokenReward: MIN_IOTA_AMOUNT, - lockTime: (Math.pow(2, 32) - dayjs().unix() + 100) * 1000, + lockTime: (Math.pow(2, 32) - dayjs().unix() + 1000) * 1000, tokenSymbol, }, network, diff --git a/packages/functions/test-tangle/award/award_2.spec.ts b/packages/functions/test-tangle/award/award_2.spec.ts index 48097e5ca4..577c6323ec 100644 --- a/packages/functions/test-tangle/award/award_2.spec.ts +++ b/packages/functions/test-tangle/award/award_2.spec.ts @@ -1,31 +1,21 @@ -import { build5Db } from '@build-5/database'; +import { PgTransactionPayloadType, PgTransactionType, build5Db } from '@build-5/database'; import { Award, COL, Member, Network, SOON_PROJECT_ID, - Space, SUB_COL, + Space, Token, TokenDistribution, - TokenDrop, TokenDropStatus, TokenStatus, Transaction, - TransactionPayloadType, - TransactionType, + WEN_FUNC, } from '@build-5/interfaces'; import { NftOutput, TimelockUnlockCondition, UnlockConditionType } from '@iota/sdk'; import dayjs from 'dayjs'; -import { - approveAwardParticipant, - awardParticipate, - createAward, - fundAward, -} from '../../src/runtime/firebase/award'; -import { joinSpace } from '../../src/runtime/firebase/space'; -import { claimMintedTokenOrder } from '../../src/runtime/firebase/token/minting'; import { MnemonicService } from '../../src/services/wallet/mnemonic'; import { Wallet } from '../../src/services/wallet/wallet'; import { AddressDetails } from '../../src/services/wallet/wallet.service'; @@ -33,20 +23,13 @@ import { getAddress } from '../../src/utils/address.utils'; import { mergeOutputs } from '../../src/utils/basic-output.utils'; import { serverTime } from '../../src/utils/dateTime.utils'; import * as wallet from '../../src/utils/wallet.utils'; -import { - createMember, - createSpace, - getRandomSymbol, - mockWalletReturnValue, - wait, -} from '../../test/controls/common'; -import { getWallet, MEDIA, testEnv } from '../../test/set-up'; +import { getRandomSymbol, wait } from '../../test/controls/common'; +import { MEDIA, getWallet, mockWalletReturnValue, testEnv } from '../../test/set-up'; import { awaitTransactionConfirmationsForToken } from '../common'; import { requestFundsFromFaucet, requestMintedTokenFromFaucet } from '../faucet'; import { awaitAllTransactionsForAward } from './common'; const network = Network.RMS; -let walletSpy: any; describe('Create award, native', () => { let guardian: string; @@ -59,35 +42,34 @@ describe('Create award, native', () => { let now: dayjs.Dayjs; beforeAll(async () => { - walletSpy = jest.spyOn(wallet, 'decodeAuth'); walletService = await getWallet(network); }); beforeEach(async () => { now = dayjs(); - guardian = await createMember(walletSpy); - member = await createMember(walletSpy); - space = await createSpace(walletSpy, guardian); + guardian = await testEnv.createMember(); + member = await testEnv.createMember(); + space = await testEnv.createSpace(guardian); - mockWalletReturnValue(walletSpy, member, { uid: space?.uid }); - await testEnv.wrap(joinSpace)({}); + mockWalletReturnValue(member, { uid: space?.uid }); + await testEnv.wrap(WEN_FUNC.joinSpace); token = await saveToken(space.uid, guardian); - mockWalletReturnValue(walletSpy, member, awardRequest(space.uid, token.symbol)); - award = await testEnv.wrap(createAward)({}); + mockWalletReturnValue(member, awardRequest(space.uid, token.symbol)); + award = await testEnv.wrap(WEN_FUNC.createAward); - const guardianDocRef = build5Db().doc(`${COL.MEMBER}/${guardian}`); + const guardianDocRef = build5Db().doc(COL.MEMBER, guardian); const guardianData = await guardianDocRef.get(); const guardianBech32 = getAddress(guardianData, network); guardianAddress = await walletService.getAddressDetails(guardianBech32); }); it('Should create and fund award', async () => { - mockWalletReturnValue(walletSpy, guardian, { uid: award.uid }); - const order = await testEnv.wrap(fundAward)({}); + mockWalletReturnValue(guardian, { uid: award.uid }); + const order = await testEnv.wrap(WEN_FUNC.fundAward); - await requestFundsFromFaucet(network, guardianAddress.bech32, order.payload.amount); + await requestFundsFromFaucet(network, guardianAddress.bech32, order.payload.amount!); await requestMintedTokenFromFaucet( walletService, guardianAddress, @@ -95,12 +77,12 @@ describe('Create award, native', () => { VAULT_MNEMONIC, 10, ); - await walletService.send(guardianAddress, order.payload.targetAddress, order.payload.amount, { + await walletService.send(guardianAddress, order.payload.targetAddress!, order.payload.amount!, { nativeTokens: [{ id: MINTED_TOKEN_ID, amount: BigInt('0xA') }], }); await MnemonicService.store(guardianAddress.bech32, guardianAddress.mnemonic); - const awardDocRef = build5Db().doc(`${COL.AWARD}/${award.uid}`); + const awardDocRef = build5Db().doc(COL.AWARD, award.uid); await wait(async () => { const award = await awardDocRef.get(); return award.approved && award.funded; @@ -111,21 +93,20 @@ describe('Create award, native', () => { expect(awardData.collectionBlockId).toBeDefined(); expect(awardData.collectionId).toBeDefined(); - mockWalletReturnValue(walletSpy, member, { uid: award.uid }); - await testEnv.wrap(awardParticipate)({}); + mockWalletReturnValue(member, { uid: award.uid }); + await testEnv.wrap(WEN_FUNC.participateAward); - mockWalletReturnValue(walletSpy, guardian, { award: award.uid, members: [member, member] }); - await testEnv.wrap(approveAwardParticipant)({}); + mockWalletReturnValue(guardian, { award: award.uid, members: [member, member] }); + await testEnv.wrap(WEN_FUNC.approveParticipantAward); - const tokenDocRef = build5Db().doc(`${COL.TOKEN}/${token.uid}`); - const distributionDocRef = tokenDocRef.collection(SUB_COL.DISTRIBUTION).doc(member); + const distributionDocRef = build5Db().doc(COL.TOKEN, token.uid, SUB_COL.DISTRIBUTION, member); let distribution = await distributionDocRef.get(); expect(distribution.totalUnclaimedAirdrop).toBe(10); const nttQuery = build5Db() .collection(COL.TRANSACTION) .where('member', '==', member) - .where('payload.type', '==', TransactionPayloadType.BADGE); + .where('payload_type', '==', PgTransactionPayloadType.BADGE); await wait(async () => { const snap = await nttQuery.get(); return snap.length === 2; @@ -133,7 +114,7 @@ describe('Create award, native', () => { await awaitAllTransactionsForAward(award.uid); - const memberDocRef = build5Db().doc(`${COL.MEMBER}/${member}`); + const memberDocRef = build5Db().doc(COL.MEMBER, member); const memberData = await memberDocRef.get(); const memberBech32 = getAddress(memberData, network); await wait(async () => { @@ -154,19 +135,19 @@ describe('Create award, native', () => { } const airdropQuery = build5Db().collection(COL.AIRDROP).where('member', '==', member); - let airdropSnap = await airdropQuery.get(); + let airdropSnap = await airdropQuery.get(); expect(airdropSnap.length).toBe(2); - mockWalletReturnValue(walletSpy, member, { symbol: token.symbol }); - const claimOrder = await testEnv.wrap(claimMintedTokenOrder)({}); + mockWalletReturnValue(member, { symbol: token.symbol }); + const claimOrder = await testEnv.wrap(WEN_FUNC.claimMintedTokenOrder); await requestFundsFromFaucet( network, - claimOrder.payload.targetAddress, - claimOrder.payload.amount, + claimOrder.payload.targetAddress!, + claimOrder.payload.amount!, ); await wait(async () => { - airdropSnap = await airdropQuery.get(); + airdropSnap = await airdropQuery.get(); const allClaimed = airdropSnap.reduce( (acc, doc) => acc && doc.status === TokenDropStatus.CLAIMED, true, @@ -186,19 +167,19 @@ describe('Create award, native', () => { const creditQuery = build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.CREDIT) + .where('type', '==', PgTransactionType.CREDIT) .where('member', '==', guardian); await wait(async () => { - const snap = await creditQuery.get(); + const snap = await creditQuery.get(); return snap.length === 1 && snap[0]?.payload?.walletReference?.confirmed; }); const burnAliasQuery = build5Db() .collection(COL.TRANSACTION) - .where('payload.type', '==', TransactionPayloadType.BURN_ALIAS) + .where('payload_type', '==', PgTransactionPayloadType.BURN_ALIAS) .where('member', '==', guardian); await wait(async () => { - const snap = await burnAliasQuery.get(); + const snap = await burnAliasQuery.get(); return snap.length === 1 && snap[0]?.payload?.walletReference?.confirmed; }); const { amount } = await walletService.getBalance(guardianAddress.bech32); @@ -241,9 +222,10 @@ const saveToken = async (space: string, guardian: string) => { network: Network.RMS, tokenId: MINTED_TOKEN_ID, }, - }; - await build5Db().doc(`${COL.TOKEN}/${token.uid}`).set(token); - return token as Token; + links: [] as URL[], + } as Token; + await build5Db().doc(COL.TOKEN, token.uid).create(token); + return token; }; export const VAULT_MNEMONIC = diff --git a/packages/functions/test-tangle/award/award_3.spec.ts b/packages/functions/test-tangle/award/award_3.spec.ts index f21fb6ea6e..4f2459f395 100644 --- a/packages/functions/test-tangle/award/award_3.spec.ts +++ b/packages/functions/test-tangle/award/award_3.spec.ts @@ -2,24 +2,22 @@ import { build5Db } from '@build-5/database'; import { Award, COL, - MediaStatus, MIN_IOTA_AMOUNT, + MediaStatus, Network, Space, Token, + Transaction, + WEN_FUNC, } from '@build-5/interfaces'; import dayjs from 'dayjs'; import { uploadMediaToWeb3 } from '../../src/cron/media.cron'; -import { createAward, fundAward } from '../../src/runtime/firebase/award'; -import { joinSpace } from '../../src/runtime/firebase/space'; -import * as wallet from '../../src/utils/wallet.utils'; -import { createMember, createSpace, mockWalletReturnValue, wait } from '../../test/controls/common'; -import { MEDIA, testEnv } from '../../test/set-up'; +import { wait } from '../../test/controls/common'; +import { MEDIA, mockWalletReturnValue, testEnv } from '../../test/set-up'; import { requestFundsFromFaucet } from '../faucet'; import { saveBaseToken } from './common'; const network = Network.RMS; -let walletSpy: any; describe('Create award, base', () => { let guardian: string; @@ -28,30 +26,26 @@ describe('Create award, base', () => { let award: Award; let token: Token; - beforeAll(async () => { - walletSpy = jest.spyOn(wallet, 'decodeAuth'); - }); - beforeEach(async () => { - guardian = await createMember(walletSpy); - member = await createMember(walletSpy); - space = await createSpace(walletSpy, guardian); + guardian = await testEnv.createMember(); + member = await testEnv.createMember(); + space = await testEnv.createSpace(guardian); - mockWalletReturnValue(walletSpy, member, { uid: space?.uid }); - await testEnv.wrap(joinSpace)({}); + mockWalletReturnValue(member, { uid: space?.uid }); + await testEnv.wrap(WEN_FUNC.joinSpace); token = await saveBaseToken(space.uid, guardian, network); - mockWalletReturnValue(walletSpy, guardian, awardRequest(space.uid, token.symbol)); - award = await testEnv.wrap(createAward)({}); + mockWalletReturnValue(guardian, awardRequest(space.uid, token.symbol)); + award = await testEnv.wrap(WEN_FUNC.createAward); }); it('Should upload award media', async () => { - mockWalletReturnValue(walletSpy, guardian, { uid: award.uid }); - const order = await testEnv.wrap(fundAward)({}); + mockWalletReturnValue(guardian, { uid: award.uid }); + const order = await testEnv.wrap(WEN_FUNC.fundAward); await requestFundsFromFaucet(network, order.payload.targetAddress, order.payload.amount); - const awardDocRef = build5Db().doc(`${COL.AWARD}/${award.uid}`); + const awardDocRef = build5Db().doc(COL.AWARD, award.uid); await wait(async () => { const award = await awardDocRef.get(); return award.approved && award.funded; diff --git a/packages/functions/test-tangle/award/award_4.spec.ts b/packages/functions/test-tangle/award/award_4.spec.ts index 065c204faf..5221dcbe63 100644 --- a/packages/functions/test-tangle/award/award_4.spec.ts +++ b/packages/functions/test-tangle/award/award_4.spec.ts @@ -1,4 +1,4 @@ -import { build5Db } from '@build-5/database'; +import { PgTransactionPayloadType, PgTransactionType, build5Db } from '@build-5/database'; import { Award, COL, @@ -8,29 +8,17 @@ import { Token, Transaction, TransactionPayloadType, - TransactionType, + WEN_FUNC, } from '@build-5/interfaces'; import dayjs from 'dayjs'; import { processExpiredAwards } from '../../src/cron/award.cron'; -import { - approveAwardParticipant, - awardParticipate, - cancelAward, - createAward, - fundAward, -} from '../../src/runtime/firebase/award'; -import { joinSpace } from '../../src/runtime/firebase/space'; -import { claimMintedTokenOrder } from '../../src/runtime/firebase/token/minting'; import { Wallet } from '../../src/services/wallet/wallet'; -import { dateToTimestamp } from '../../src/utils/dateTime.utils'; -import * as wallet from '../../src/utils/wallet.utils'; -import { createMember, createSpace, mockWalletReturnValue, wait } from '../../test/controls/common'; -import { MEDIA, getWallet, testEnv } from '../../test/set-up'; +import { wait } from '../../test/controls/common'; +import { MEDIA, getWallet, mockWalletReturnValue, testEnv } from '../../test/set-up'; import { requestFundsFromFaucet } from '../faucet'; import { awaitAllTransactionsForAward, saveBaseToken } from './common'; const network = Network.RMS; -let walletSpy: any; describe('Create award, base', () => { let guardian: string; @@ -41,35 +29,34 @@ describe('Create award, base', () => { let token: Token; beforeAll(async () => { - walletSpy = jest.spyOn(wallet, 'decodeAuth'); walletService = await getWallet(network); }); beforeEach(async () => { - guardian = await createMember(walletSpy); - member = await createMember(walletSpy); - space = await createSpace(walletSpy, guardian); + guardian = await testEnv.createMember(); + member = await testEnv.createMember(); + space = await testEnv.createSpace(guardian); - mockWalletReturnValue(walletSpy, member, { uid: space?.uid }); - await testEnv.wrap(joinSpace)({}); + mockWalletReturnValue(member, { uid: space?.uid }); + await testEnv.wrap(WEN_FUNC.joinSpace); token = await saveBaseToken(space.uid, guardian, network); - mockWalletReturnValue(walletSpy, guardian, awardRequest(space.uid, token.symbol)); - award = await testEnv.wrap(createAward)({}); + mockWalletReturnValue(guardian, awardRequest(space.uid, token.symbol)); + award = await testEnv.wrap(WEN_FUNC.createAward); }); it.each([false, true])( 'Should create, fund and participate in award, cancel', async (shouldCancel: boolean) => { - mockWalletReturnValue(walletSpy, guardian, { uid: award.uid }); - const order = await testEnv.wrap(fundAward)({}); + mockWalletReturnValue(guardian, { uid: award.uid }); + const order = await testEnv.wrap(WEN_FUNC.fundAward); const address = await walletService.getNewIotaAddressDetails(); await requestFundsFromFaucet(network, address.bech32, order.payload.amount); - await walletService.send(address, order.payload.targetAddress, order.payload.amount, {}); + await walletService.send(address, order.payload.targetAddress!, order.payload.amount!, {}); - const awardDocRef = build5Db().doc(`${COL.AWARD}/${award.uid}`); + const awardDocRef = build5Db().doc(COL.AWARD, award.uid); await wait(async () => { const award = await awardDocRef.get(); return award.approved && award.funded; @@ -80,23 +67,23 @@ describe('Create award, base', () => { expect(awardData.collectionBlockId).toBeDefined(); expect(awardData.collectionId).toBeDefined(); - mockWalletReturnValue(walletSpy, member, { uid: award.uid }); - await testEnv.wrap(awardParticipate)({}); + mockWalletReturnValue(member, { uid: award.uid }); + await testEnv.wrap(WEN_FUNC.participateAward); - mockWalletReturnValue(walletSpy, guardian, { award: award.uid, members: [member] }); - await testEnv.wrap(approveAwardParticipant)({}); + mockWalletReturnValue(guardian, { award: award.uid, members: [member] }); + await testEnv.wrap(WEN_FUNC.approveParticipantAward); if (shouldCancel) { - mockWalletReturnValue(walletSpy, guardian, { uid: award.uid }); - await testEnv.wrap(cancelAward)({}); + mockWalletReturnValue(guardian, { uid: award.uid }); + await testEnv.wrap(WEN_FUNC.cancelAward); } else { - await awardDocRef.update({ endDate: dateToTimestamp(dayjs().subtract(1, 'minute')) }); + await awardDocRef.update({ endDate: dayjs().subtract(1, 'minute').toDate() }); await processExpiredAwards(); await processExpiredAwards(); } - mockWalletReturnValue(walletSpy, member, { symbol: token.symbol }); - const claimOrder = await testEnv.wrap(claimMintedTokenOrder)({}); + mockWalletReturnValue(member, { symbol: token.symbol }); + const claimOrder = await testEnv.wrap(WEN_FUNC.claimMintedTokenOrder); await requestFundsFromFaucet( network, claimOrder.payload.targetAddress, @@ -106,7 +93,7 @@ describe('Create award, base', () => { const billPaymentQuery = build5Db() .collection(COL.TRANSACTION) .where('member', '==', member) - .where('type', '==', TransactionType.BILL_PAYMENT); + .where('type', '==', PgTransactionType.BILL_PAYMENT); await wait(async () => { const snap = await billPaymentQuery.get(); return snap.length === 1; @@ -115,7 +102,7 @@ describe('Create award, base', () => { const nttQuery = build5Db() .collection(COL.TRANSACTION) .where('member', '==', member) - .where('payload.type', '==', TransactionPayloadType.BADGE); + .where('payload_type', '==', PgTransactionPayloadType.BADGE); await wait(async () => { const snap = await nttQuery.get(); return snap.length === 1; @@ -124,7 +111,7 @@ describe('Create award, base', () => { const creditQuery = build5Db() .collection(COL.TRANSACTION) .where('member', '==', guardian) - .where('type', '==', TransactionType.CREDIT); + .where('type', '==', PgTransactionType.CREDIT); await wait(async () => { const snap = await creditQuery.get(); return snap.length === 1; @@ -139,10 +126,10 @@ describe('Create award, base', () => { const burnAliasQuery = build5Db() .collection(COL.TRANSACTION) - .where('payload.type', '==', TransactionPayloadType.BURN_ALIAS) + .where('payload_type', '==', PgTransactionPayloadType.BURN_ALIAS) .where('member', '==', guardian); await wait(async () => { - const snap = await burnAliasQuery.get(); + const snap = await burnAliasQuery.get(); return snap.length === 1 && snap[0]?.payload?.walletReference?.confirmed; }); diff --git a/packages/functions/test-tangle/award/award_5.spec.ts b/packages/functions/test-tangle/award/award_5.spec.ts index fb0c0a35f5..a0633a97d6 100644 --- a/packages/functions/test-tangle/award/award_5.spec.ts +++ b/packages/functions/test-tangle/award/award_5.spec.ts @@ -1,4 +1,4 @@ -import { build5Db } from '@build-5/database'; +import { PgTransactionPayloadType, PgTransactionType, build5Db } from '@build-5/database'; import { Award, COL, @@ -7,45 +7,28 @@ import { SOON_PROJECT_ID, Space, Token, - TokenDrop, TokenDropStatus, TokenStatus, Transaction, TransactionPayloadType, - TransactionType, + WEN_FUNC, } from '@build-5/interfaces'; import dayjs from 'dayjs'; import { processExpiredAwards } from '../../src/cron/award.cron'; -import { - approveAwardParticipant, - awardParticipate, - cancelAward, - createAward, - fundAward, -} from '../../src/runtime/firebase/award'; -import { joinSpace } from '../../src/runtime/firebase/space'; -import { claimMintedTokenOrder } from '../../src/runtime/firebase/token/minting'; import { MnemonicService } from '../../src/services/wallet/mnemonic'; import { Wallet } from '../../src/services/wallet/wallet'; import { AddressDetails } from '../../src/services/wallet/wallet.service'; import { getAddress } from '../../src/utils/address.utils'; import { mergeOutputs } from '../../src/utils/basic-output.utils'; -import { dateToTimestamp, serverTime } from '../../src/utils/dateTime.utils'; +import { serverTime } from '../../src/utils/dateTime.utils'; import * as wallet from '../../src/utils/wallet.utils'; -import { - createMember, - createSpace, - getRandomSymbol, - mockWalletReturnValue, - wait, -} from '../../test/controls/common'; -import { MEDIA, getWallet, testEnv } from '../../test/set-up'; +import { getRandomSymbol, wait } from '../../test/controls/common'; +import { MEDIA, getWallet, mockWalletReturnValue, testEnv } from '../../test/set-up'; import { awaitTransactionConfirmationsForToken } from '../common'; import { requestFundsFromFaucet, requestMintedTokenFromFaucet } from '../faucet'; import { awaitAllTransactionsForAward } from './common'; const network = Network.RMS; -let walletSpy: any; describe('Create award, native', () => { let guardian: string; @@ -57,32 +40,31 @@ describe('Create award, native', () => { let token: Token; beforeAll(async () => { - walletSpy = jest.spyOn(wallet, 'decodeAuth'); walletService = await getWallet(network); }); beforeEach(async () => { - guardian = await createMember(walletSpy); - member = await createMember(walletSpy); - space = await createSpace(walletSpy, guardian); + guardian = await testEnv.createMember(); + member = await testEnv.createMember(); + space = await testEnv.createSpace(guardian); - mockWalletReturnValue(walletSpy, member, { uid: space?.uid }); - await testEnv.wrap(joinSpace)({}); + mockWalletReturnValue(member, { uid: space?.uid }); + await testEnv.wrap(WEN_FUNC.joinSpace); token = await saveToken(space.uid, guardian); - mockWalletReturnValue(walletSpy, member, awardRequest(space.uid, token.symbol)); - award = await testEnv.wrap(createAward)({}); + mockWalletReturnValue(member, awardRequest(space.uid, token.symbol)); + award = await testEnv.wrap(WEN_FUNC.createAward); - const guardianDocRef = build5Db().doc(`${COL.MEMBER}/${guardian}`); + const guardianDocRef = build5Db().doc(COL.MEMBER, guardian); const guardianData = await guardianDocRef.get(); const guardianBech32 = getAddress(guardianData, network); guardianAddress = await walletService.getAddressDetails(guardianBech32); }); it.each([false, true])('Should create and fund award, cancel', async (shouldCancel: boolean) => { - mockWalletReturnValue(walletSpy, guardian, { uid: award.uid }); - const order = await testEnv.wrap(fundAward)({}); + mockWalletReturnValue(guardian, { uid: award.uid }); + const order = await testEnv.wrap(WEN_FUNC.fundAward); await requestFundsFromFaucet(network, guardianAddress.bech32, order.payload.amount); await requestMintedTokenFromFaucet( @@ -92,12 +74,12 @@ describe('Create award, native', () => { VAULT_MNEMONIC, 15, ); - await walletService.send(guardianAddress, order.payload.targetAddress, order.payload.amount, { + await walletService.send(guardianAddress, order.payload.targetAddress!, order.payload.amount!, { nativeTokens: [{ id: MINTED_TOKEN_ID, amount: BigInt(15) }], }); await MnemonicService.store(guardianAddress.bech32, guardianAddress.mnemonic); - const awardDocRef = build5Db().doc(`${COL.AWARD}/${award.uid}`); + const awardDocRef = build5Db().doc(COL.AWARD, award.uid); await wait(async () => { const award = await awardDocRef.get(); return award.approved && award.funded; @@ -108,17 +90,17 @@ describe('Create award, native', () => { expect(awardData.collectionBlockId).toBeDefined(); expect(awardData.collectionId).toBeDefined(); - mockWalletReturnValue(walletSpy, member, { uid: award.uid }); - await testEnv.wrap(awardParticipate)({}); + mockWalletReturnValue(member, { uid: award.uid }); + await testEnv.wrap(WEN_FUNC.participateAward); - mockWalletReturnValue(walletSpy, guardian, { award: award.uid, members: [member] }); - await testEnv.wrap(approveAwardParticipant)({}); + mockWalletReturnValue(guardian, { award: award.uid, members: [member] }); + await testEnv.wrap(WEN_FUNC.approveParticipantAward); if (shouldCancel) { - mockWalletReturnValue(walletSpy, guardian, { uid: award.uid }); - await testEnv.wrap(cancelAward)({}); + mockWalletReturnValue(guardian, { uid: award.uid }); + await testEnv.wrap(WEN_FUNC.cancelAward); } else { - await awardDocRef.update({ endDate: dateToTimestamp(dayjs().subtract(1, 'minute')) }); + await awardDocRef.update({ endDate: dayjs().subtract(1, 'minute').toDate() }); await processExpiredAwards(); await processExpiredAwards(); } @@ -126,7 +108,7 @@ describe('Create award, native', () => { const nttQuery = build5Db() .collection(COL.TRANSACTION) .where('member', '==', member) - .where('payload.type', '==', TransactionPayloadType.BADGE); + .where('payload_type', '==', PgTransactionPayloadType.BADGE); await wait(async () => { const snap = await nttQuery.get(); return snap.length === 1; @@ -134,7 +116,7 @@ describe('Create award, native', () => { await awaitAllTransactionsForAward(award.uid); - const memberDocRef = build5Db().doc(`${COL.MEMBER}/${member}`); + const memberDocRef = build5Db().doc(COL.MEMBER, member); const memberData = await memberDocRef.get(); const memberBech32 = getAddress(memberData, network); await wait(async () => { @@ -143,18 +125,18 @@ describe('Create award, native', () => { }); const airdropQuery = build5Db().collection(COL.AIRDROP).where('member', '==', member); - let airdropSnap = await airdropQuery.get(); + let airdropSnap = await airdropQuery.get(); expect(airdropSnap.length).toBe(1); - mockWalletReturnValue(walletSpy, member, { symbol: token.symbol }); - const claimOrder = await testEnv.wrap(claimMintedTokenOrder)({}); + mockWalletReturnValue(member, { symbol: token.symbol }); + const claimOrder = await testEnv.wrap(WEN_FUNC.claimMintedTokenOrder); await requestFundsFromFaucet( network, claimOrder.payload.targetAddress, claimOrder.payload.amount, ); await wait(async () => { - airdropSnap = await airdropQuery.get(); + airdropSnap = await airdropQuery.get(); const allClaimed = airdropSnap.reduce( (acc, doc) => acc && doc.status === TokenDropStatus.CLAIMED, true, @@ -170,10 +152,10 @@ describe('Create award, native', () => { const creditQuery = build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.CREDIT) + .where('type', '==', PgTransactionType.CREDIT) .where('member', '==', guardian); await wait(async () => { - const snap = await creditQuery.get(); + const snap = await creditQuery.get(); return snap.length === 1 && snap[0]?.payload?.walletReference?.confirmed; }); const credit = (await creditQuery.get())[0]; @@ -183,10 +165,10 @@ describe('Create award, native', () => { const burnAliasQuery = build5Db() .collection(COL.TRANSACTION) - .where('payload.type', '==', TransactionPayloadType.BURN_ALIAS) + .where('payload_type', '==', PgTransactionPayloadType.BURN_ALIAS) .where('member', '==', guardian); await wait(async () => { - const snap = await burnAliasQuery.get(); + const snap = await burnAliasQuery.get(); return snap.length === 1 && snap[0]?.payload?.walletReference?.confirmed; }); const { amount } = await walletService.getBalance(guardianAddress.bech32); @@ -229,9 +211,10 @@ const saveToken = async (space: string, guardian: string) => { network: Network.RMS, tokenId: MINTED_TOKEN_ID, }, - }; - await build5Db().doc(`${COL.TOKEN}/${token.uid}`).set(token); - return token as Token; + links: [] as URL[], + } as Token; + await build5Db().doc(COL.TOKEN, token.uid).create(token); + return token; }; export const VAULT_MNEMONIC = diff --git a/packages/functions/test-tangle/award/award_6.spec.ts b/packages/functions/test-tangle/award/award_6.spec.ts index 914b494a90..c901c80f0e 100644 --- a/packages/functions/test-tangle/award/award_6.spec.ts +++ b/packages/functions/test-tangle/award/award_6.spec.ts @@ -1,4 +1,4 @@ -import { build5Db } from '@build-5/database'; +import { PgTransactionType, build5Db } from '@build-5/database'; import { Award, COL, @@ -6,25 +6,19 @@ import { Network, Space, Token, - TokenDrop, TokenDropStatus, Transaction, TransactionPayloadType, - TransactionType, + WEN_FUNC, } from '@build-5/interfaces'; import dayjs from 'dayjs'; -import { validateAddress } from '../../src/runtime/firebase/address'; -import { approveAwardParticipant, createAward, fundAward } from '../../src/runtime/firebase/award'; -import { claimMintedTokenOrder } from '../../src/runtime/firebase/token/minting'; import { Wallet } from '../../src/services/wallet/wallet'; -import * as wallet from '../../src/utils/wallet.utils'; -import { createMember, createSpace, mockWalletReturnValue, wait } from '../../test/controls/common'; -import { MEDIA, getWallet, testEnv } from '../../test/set-up'; +import { wait } from '../../test/controls/common'; +import { MEDIA, getWallet, mockWalletReturnValue, testEnv } from '../../test/set-up'; import { requestFundsFromFaucet } from '../faucet'; import { saveBaseToken } from './common'; const network = Network.RMS; -let walletSpy: any; describe('Award', () => { let guardian: string; @@ -34,41 +28,41 @@ describe('Award', () => { let walletService: Wallet; beforeAll(async () => { - walletSpy = jest.spyOn(wallet, 'decodeAuth'); walletService = await getWallet(network); }); beforeEach(async () => { - guardian = await createMember(walletSpy); - space = await createSpace(walletSpy, guardian); + guardian = await testEnv.createMember(); + space = await testEnv.createSpace(guardian); token = await saveBaseToken(space.uid, guardian, network); - mockWalletReturnValue(walletSpy, guardian, awardRequest(space.uid, token.symbol)); - award = await testEnv.wrap(createAward)({}); + mockWalletReturnValue(guardian, awardRequest(space.uid, token.symbol)); + award = await testEnv.wrap(WEN_FUNC.createAward); }); it('Should issue many awards', async () => { - mockWalletReturnValue(walletSpy, guardian, { uid: award.uid }); - const order = await testEnv.wrap(fundAward)({}); + mockWalletReturnValue(guardian, { uid: award.uid }); + const order = await testEnv.wrap(WEN_FUNC.fundAward); await requestFundsFromFaucet(network, order.payload.targetAddress, order.payload.amount); - const awardDocRef = build5Db().doc(`${COL.AWARD}/${award.uid}`); + const awardDocRef = build5Db().doc(COL.AWARD, award.uid); await wait(async () => { const award = await awardDocRef.get(); return award.approved && award.funded; }); - const tmp = wallet.getRandomEthAddress(); - mockWalletReturnValue(walletSpy, guardian, { + const tmp = await testEnv.createMember(); + await build5Db().doc(COL.MEMBER, tmp).update({ rmsAddress: '' }); + mockWalletReturnValue(guardian, { award: award.uid, members: [tmp, tmp], }); - await testEnv.wrap(approveAwardParticipant)({}); + await testEnv.wrap(WEN_FUNC.approveParticipantAward); const tmpAddress = await walletService.getNewIotaAddressDetails(); - mockWalletReturnValue(walletSpy, tmp, { network: Network.RMS }); - const addressValidationOrder = await testEnv.wrap(validateAddress)({}); + mockWalletReturnValue(tmp, { network: Network.RMS }); + const addressValidationOrder = await testEnv.wrap(WEN_FUNC.validateAddress); await requestFundsFromFaucet( Network.RMS, tmpAddress.bech32, @@ -76,8 +70,8 @@ describe('Award', () => { ); await walletService.send( tmpAddress, - addressValidationOrder.payload.targetAddress, - addressValidationOrder.payload.amount, + addressValidationOrder.payload.targetAddress!, + addressValidationOrder.payload.amount!, {}, ); @@ -87,19 +81,18 @@ describe('Award', () => { }); const airdropQuery = build5Db().collection(COL.AIRDROP).where('member', '==', tmp); - let airdropSnap = await airdropQuery.get(); + let airdropSnap = await airdropQuery.get(); expect(airdropSnap.length).toBe(2); - mockWalletReturnValue(walletSpy, tmp, { symbol: token.symbol }); - const claimOrder = await testEnv.wrap(claimMintedTokenOrder)({}); + mockWalletReturnValue(tmp, { symbol: token.symbol }); + const claimOrder = await testEnv.wrap(WEN_FUNC.claimMintedTokenOrder); await requestFundsFromFaucet( network, claimOrder.payload.targetAddress, claimOrder.payload.amount, ); - await wait(async () => { - airdropSnap = await airdropQuery.get(); + airdropSnap = await airdropQuery.get(); const allClaimed = airdropSnap.reduce( (acc, doc) => acc && doc.status === TokenDropStatus.CLAIMED, true, @@ -111,14 +104,14 @@ describe('Award', () => { const { amount } = await walletService.getBalance(tmpAddress.bech32); return ( amount === - 2 * MIN_IOTA_AMOUNT + claimOrder.payload.amount + addressValidationOrder.payload.amount + 2 * MIN_IOTA_AMOUNT + claimOrder.payload.amount! + addressValidationOrder.payload.amount! ); }); const billPaymentQuery = build5Db() .collection(COL.TRANSACTION) .where('member', '==', tmp) - .where('type', '==', TransactionType.BILL_PAYMENT); + .where('type', '==', PgTransactionType.BILL_PAYMENT); const billPayments = (await billPaymentQuery.get()).map((d) => d as Transaction); billPayments.forEach((billPayment) => { expect(billPayment.payload.token).toBe(token.uid); diff --git a/packages/functions/test-tangle/award/award_7.spec.ts b/packages/functions/test-tangle/award/award_7.spec.ts index 90ff42f819..3f84f454cd 100644 --- a/packages/functions/test-tangle/award/award_7.spec.ts +++ b/packages/functions/test-tangle/award/award_7.spec.ts @@ -1,4 +1,4 @@ -import { build5Db } from '@build-5/database'; +import { PgTransactionPayloadType, build5Db } from '@build-5/database'; import { Award, COL, @@ -9,30 +9,22 @@ import { Token, TokenStatus, Transaction, - TransactionPayloadType, + WEN_FUNC, } from '@build-5/interfaces'; import { NftOutput } from '@iota/sdk'; import dayjs from 'dayjs'; -import { approveAwardParticipant, createAward, fundAward } from '../../src/runtime/firebase/award'; import { MnemonicService } from '../../src/services/wallet/mnemonic'; import { Wallet } from '../../src/services/wallet/wallet'; import { AddressDetails } from '../../src/services/wallet/wallet.service'; import { getAddress } from '../../src/utils/address.utils'; import { serverTime } from '../../src/utils/dateTime.utils'; import * as wallet from '../../src/utils/wallet.utils'; -import { - createMember, - createSpace, - getRandomSymbol, - mockWalletReturnValue, - wait, -} from '../../test/controls/common'; -import { MEDIA, getWallet, testEnv } from '../../test/set-up'; +import { getRandomSymbol, wait } from '../../test/controls/common'; +import { MEDIA, getWallet, mockWalletReturnValue, testEnv } from '../../test/set-up'; import { getNftMetadata } from '../collection-minting/Helper'; import { requestFundsFromFaucet, requestMintedTokenFromFaucet } from '../faucet'; const network = Network.RMS; -let walletSpy: any; describe('Create award, base', () => { let guardian: string; @@ -44,29 +36,28 @@ describe('Create award, base', () => { let guardianAddress: AddressDetails; beforeAll(async () => { - walletSpy = jest.spyOn(wallet, 'decodeAuth'); walletService = await getWallet(network); }); beforeEach(async () => { - guardian = await createMember(walletSpy); - member = await createMember(walletSpy); - space = await createSpace(walletSpy, guardian); + guardian = await testEnv.createMember(); + member = await testEnv.createMember(); + space = await testEnv.createSpace(guardian); token = await saveToken(space.uid, guardian); - mockWalletReturnValue(walletSpy, guardian, awardRequest(space.uid, token.symbol)); - award = await testEnv.wrap(createAward)({}); + mockWalletReturnValue(guardian, awardRequest(space.uid, token.symbol)); + award = await testEnv.wrap(WEN_FUNC.createAward); - const guardianDocRef = build5Db().doc(`${COL.MEMBER}/${guardian}`); + const guardianDocRef = build5Db().doc(COL.MEMBER, guardian); const guardianData = await guardianDocRef.get(); const guardianBech32 = getAddress(guardianData, network); guardianAddress = await walletService.getAddressDetails(guardianBech32); }); it('Should set correct metadata on award collection and ntt', async () => { - mockWalletReturnValue(walletSpy, guardian, { uid: award.uid }); - const order = await testEnv.wrap(fundAward)({}); + mockWalletReturnValue(guardian, { uid: award.uid }); + const order = await testEnv.wrap(WEN_FUNC.fundAward); await requestFundsFromFaucet(network, guardianAddress.bech32, order.payload.amount); await requestMintedTokenFromFaucet( @@ -76,28 +67,28 @@ describe('Create award, base', () => { VAULT_MNEMONIC, 10, ); - await walletService.send(guardianAddress, order.payload.targetAddress, order.payload.amount, { + await walletService.send(guardianAddress, order.payload.targetAddress!, order.payload.amount!, { nativeTokens: [{ id: MINTED_TOKEN_ID, amount: BigInt('0xA') }], }); await MnemonicService.store(guardianAddress.bech32, guardianAddress.mnemonic); - const awardDocRef = build5Db().doc(`${COL.AWARD}/${award.uid}`); + const awardDocRef = build5Db().doc(COL.AWARD, award.uid); await wait(async () => { award = await awardDocRef.get(); return award.approved && award.funded; }); - mockWalletReturnValue(walletSpy, guardian, { award: award.uid, members: [member, member] }); - await testEnv.wrap(approveAwardParticipant)({}); + mockWalletReturnValue(guardian, { award: award.uid, members: [member, member] }); + await testEnv.wrap(WEN_FUNC.approveParticipantAward); - const memberDocRef = build5Db().doc(`${COL.MEMBER}/${member}`); + const memberDocRef = build5Db().doc(COL.MEMBER, member); const memberData = await memberDocRef.get(); const memberBech32 = getAddress(memberData, network); const nttQuery = build5Db() .collection(COL.TRANSACTION) .where('member', '==', member) - .where('payload.type', '==', TransactionPayloadType.BADGE); + .where('payload_type', '==', PgTransactionPayloadType.BADGE); await wait(async () => { const snap = await nttQuery.get(); return snap.length === 2; @@ -108,7 +99,7 @@ describe('Create award, base', () => { return response.items.length === 2; }); - const spaceDocRef = build5Db().doc(`${COL.SPACE}/${space.uid}`); + const spaceDocRef = build5Db().doc(COL.SPACE, space.uid); space = await spaceDocRef.get(); expect(space.ipfsMedia).toBeDefined(); @@ -145,7 +136,7 @@ describe('Create award, base', () => { expect(nttMetadata.collectionId).toBe(award.collectionId); expect(nttMetadata.collectionName).toBe('award'); - const transactionDocRef = build5Db().doc(`${COL.TRANSACTION}/${nttMetadata.build5Id}`); + const transactionDocRef = build5Db().doc(COL.TRANSACTION, nttMetadata.build5Id); const transaction = await transactionDocRef.get(); expect(getAttributeValue(nttMetadata, 'award')).toBe(award.uid); expect(getAttributeValue(nttMetadata, 'tokenReward')).toBe(5); @@ -198,9 +189,9 @@ const saveToken = async (space: string, guardian: string) => { network: Network.RMS, tokenId: MINTED_TOKEN_ID, }, - }; - await build5Db().doc(`${COL.TOKEN}/${token.uid}`).set(token); - return token as Token; + } as Token; + await build5Db().doc(COL.TOKEN, token.uid).create(token); + return token; }; export const VAULT_MNEMONIC = diff --git a/packages/functions/test-tangle/award/award_8.spec.ts b/packages/functions/test-tangle/award/award_8.spec.ts index de44841ac5..f6c9c7274f 100644 --- a/packages/functions/test-tangle/award/award_8.spec.ts +++ b/packages/functions/test-tangle/award/award_8.spec.ts @@ -1,24 +1,23 @@ -import { build5Db } from '@build-5/database'; +import { build5Db, PgTransactionPayloadType } from '@build-5/database'; import { Award, + AwardApproveParticipantResponse, COL, Member, MIN_IOTA_AMOUNT, Network, Space, Token, - TransactionPayloadType, + Transaction, + WEN_FUNC, } from '@build-5/interfaces'; import dayjs from 'dayjs'; -import { approveAwardParticipant, createAward, fundAward } from '../../src/runtime/firebase/award'; -import * as wallet from '../../src/utils/wallet.utils'; -import { createMember, createSpace, mockWalletReturnValue, wait } from '../../test/controls/common'; -import { MEDIA, testEnv } from '../../test/set-up'; +import { wait } from '../../test/controls/common'; +import { MEDIA, mockWalletReturnValue, testEnv } from '../../test/set-up'; import { requestFundsFromFaucet } from '../faucet'; import { saveBaseToken } from './common'; const network = Network.RMS; -let walletSpy: any; describe('Create award, base', () => { let guardian: string; @@ -27,34 +26,32 @@ describe('Create award, base', () => { let awards: Award[] = []; let tokens: Token[] = []; - beforeAll(async () => { - walletSpy = jest.spyOn(wallet, 'decodeAuth'); - }); + beforeAll(async () => {}); beforeEach(async () => { - guardian = await createMember(walletSpy); - member = await createMember(walletSpy); - spaces = [await createSpace(walletSpy, guardian), await createSpace(walletSpy, guardian)]; + guardian = await testEnv.createMember(); + member = await testEnv.createMember(); + spaces = [await testEnv.createSpace(guardian), await testEnv.createSpace(guardian)]; tokens = [ await saveBaseToken(spaces[1].uid, guardian), await saveBaseToken(spaces[1].uid, guardian), ]; - mockWalletReturnValue(walletSpy, guardian, awardRequest(spaces[0].uid, tokens[0].symbol)); - awards[0] = await testEnv.wrap(createAward)({}); - mockWalletReturnValue(walletSpy, guardian, awardRequest(spaces[0].uid, tokens[1].symbol)); - awards[1] = await testEnv.wrap(createAward)({}); - mockWalletReturnValue(walletSpy, guardian, awardRequest(spaces[1].uid, tokens[0].symbol)); - awards[2] = await testEnv.wrap(createAward)({}); + mockWalletReturnValue(guardian, awardRequest(spaces[0].uid, tokens[0].symbol)); + awards[0] = await testEnv.wrap(WEN_FUNC.createAward); + mockWalletReturnValue(guardian, awardRequest(spaces[0].uid, tokens[1].symbol)); + awards[1] = await testEnv.wrap(WEN_FUNC.createAward); + mockWalletReturnValue(guardian, awardRequest(spaces[1].uid, tokens[0].symbol)); + awards[2] = await testEnv.wrap(WEN_FUNC.createAward); }); const fundAwardWrapper = async (awardId: string) => { - mockWalletReturnValue(walletSpy, guardian, { uid: awardId }); - const order = await testEnv.wrap(fundAward)({}); + mockWalletReturnValue(guardian, { uid: awardId }); + const order = await testEnv.wrap(WEN_FUNC.fundAward); await requestFundsFromFaucet(network, order.payload.targetAddress, order.payload.amount); - const awardDocRef = build5Db().doc(`${COL.AWARD}/${awardId}`); + const awardDocRef = build5Db().doc(COL.AWARD, awardId); await wait(async () => { const award = await awardDocRef.get(); return award.approved && award.funded; @@ -62,55 +59,30 @@ describe('Create award, base', () => { }; it('Should update member space properly', async () => { - let promises = awards.map((award) => fundAwardWrapper(award.uid)); + const promises = awards.map((award) => fundAwardWrapper(award.uid)); await Promise.all(promises); - promises = awards.map((award) => { - mockWalletReturnValue(walletSpy, guardian, { award: award.uid, members: [member, member] }); - return testEnv.wrap(approveAwardParticipant)({}); + const approvePromises = awards.map((award) => { + mockWalletReturnValue(guardian, { award: award.uid, members: [member, member] }); + return testEnv.wrap(WEN_FUNC.approveParticipantAward); }); - await Promise.all(promises); + await Promise.all(approvePromises); const nttQuery = build5Db() .collection(COL.TRANSACTION) .where('member', '==', member) - .where('payload.type', '==', TransactionPayloadType.BADGE); + .where('payload_type', '==', PgTransactionPayloadType.BADGE); await wait(async () => { const snap = await nttQuery.get(); return snap.length === 6; }); - const memberDocRef = build5Db().doc(`${COL.MEMBER}/${member}`); + const memberDocRef = build5Db().doc(COL.MEMBER, member); const memberData = await memberDocRef.get(); - assertMemberSpaceAwardStats( - memberData, - spaces[0].uid, - tokens[0], - 4, - 4 * MIN_IOTA_AMOUNT, - 2, - 2 * MIN_IOTA_AMOUNT, - ); - assertMemberSpaceAwardStats( - memberData, - spaces[0].uid, - tokens[1], - 4, - 4 * MIN_IOTA_AMOUNT, - 2, - 2 * MIN_IOTA_AMOUNT, - ); - - assertMemberSpaceAwardStats( - memberData, - spaces[1].uid, - tokens[0], - 2, - 2 * MIN_IOTA_AMOUNT, - 2, - 2 * MIN_IOTA_AMOUNT, - ); + assertMemberSpaceAwardStats(memberData, spaces[0].uid, tokens[0], 4, 2); + assertMemberSpaceAwardStats(memberData, spaces[0].uid, tokens[1], 4, 2); + assertMemberSpaceAwardStats(memberData, spaces[1].uid, tokens[0], 2, 2); }); }); @@ -119,16 +91,12 @@ const assertMemberSpaceAwardStats = ( spaceId: string, token: Token, totalCompleted: number, - totalReward: number, completed: number, - reward: number, ) => { const space = member.spaces![spaceId]; expect(space.awardsCompleted).toBe(totalCompleted); - expect(space.totalReward).toBe(totalReward); const stat = space.awardStat![token.uid]; expect(stat.completed).toBe(completed); - expect(stat.totalReward).toBe(reward); expect(stat.tokenSymbol).toBe(token.symbol); }; diff --git a/packages/functions/test-tangle/award/award_9.spec.ts b/packages/functions/test-tangle/award/award_9.spec.ts index 75a1bfcb75..e01d581660 100644 --- a/packages/functions/test-tangle/award/award_9.spec.ts +++ b/packages/functions/test-tangle/award/award_9.spec.ts @@ -1,38 +1,30 @@ -import { build5Db } from '@build-5/database'; +import { PgTransactionPayloadType, build5Db } from '@build-5/database'; import { Award, COL, Member, Network, SOON_PROJECT_ID, - Space, SUB_COL, + Space, Token, TokenDistribution, TokenStatus, - TransactionPayloadType, + Transaction, + WEN_FUNC, } from '@build-5/interfaces'; import dayjs from 'dayjs'; -import { approveAwardParticipant, createAward, fundAward } from '../../src/runtime/firebase/award'; -import { joinSpace } from '../../src/runtime/firebase/space'; import { MnemonicService } from '../../src/services/wallet/mnemonic'; import { Wallet } from '../../src/services/wallet/wallet'; import { AddressDetails } from '../../src/services/wallet/wallet.service'; import { getAddress } from '../../src/utils/address.utils'; import { serverTime } from '../../src/utils/dateTime.utils'; import * as wallet from '../../src/utils/wallet.utils'; -import { - createMember, - createSpace, - getRandomSymbol, - mockWalletReturnValue, - wait, -} from '../../test/controls/common'; -import { getWallet, MEDIA, testEnv } from '../../test/set-up'; +import { getRandomSymbol, wait } from '../../test/controls/common'; +import { MEDIA, getWallet, mockWalletReturnValue, testEnv } from '../../test/set-up'; import { requestFundsFromFaucet } from '../faucet'; const network = Network.RMS; -let walletSpy: any; describe('Create award, native', () => { let guardian: string; @@ -44,43 +36,42 @@ describe('Create award, native', () => { let token: Token; beforeAll(async () => { - walletSpy = jest.spyOn(wallet, 'decodeAuth'); walletService = await getWallet(network); }); beforeEach(async () => { - guardian = await createMember(walletSpy); - member = await createMember(walletSpy); - space = await createSpace(walletSpy, guardian); + guardian = await testEnv.createMember(); + member = await testEnv.createMember(); + space = await testEnv.createSpace(guardian); - mockWalletReturnValue(walletSpy, member, { uid: space?.uid }); - await testEnv.wrap(joinSpace)({}); + mockWalletReturnValue(member, { uid: space?.uid }); + await testEnv.wrap(WEN_FUNC.joinSpace); token = await saveToken(space.uid, guardian); - mockWalletReturnValue(walletSpy, member, awardRequest(space.uid, token.symbol)); - award = await testEnv.wrap(createAward)({}); + mockWalletReturnValue(member, awardRequest(space.uid, token.symbol)); + award = await testEnv.wrap(WEN_FUNC.createAward); - const guardianDocRef = build5Db().doc(`${COL.MEMBER}/${guardian}`); + const guardianDocRef = build5Db().doc(COL.MEMBER, guardian); const guardianData = await guardianDocRef.get(); const guardianBech32 = getAddress(guardianData, network); guardianAddress = await walletService.getAddressDetails(guardianBech32); }); it('Should create and fund native award, no reward', async () => { - mockWalletReturnValue(walletSpy, guardian, { uid: award.uid }); - const order = await testEnv.wrap(fundAward)({}); + mockWalletReturnValue(guardian, { uid: award.uid }); + const order = await testEnv.wrap(WEN_FUNC.fundAward); await requestFundsFromFaucet(network, guardianAddress.bech32, order.payload.amount); await walletService.send( guardianAddress, - order.payload.targetAddress, - order.payload.amount, + order.payload.targetAddress!, + order.payload.amount!, {}, ); await MnemonicService.store(guardianAddress.bech32, guardianAddress.mnemonic); - const awardDocRef = build5Db().doc(`${COL.AWARD}/${award.uid}`); + const awardDocRef = build5Db().doc(COL.AWARD, award.uid); await wait(async () => { const award = await awardDocRef.get(); return award.approved && award.funded; @@ -92,18 +83,17 @@ describe('Create award, native', () => { expect(awardData.collectionId).toBeDefined(); expect(awardData.nativeTokenStorageDeposit).toBe(0); - mockWalletReturnValue(walletSpy, guardian, { award: award.uid, members: [member, member] }); - await testEnv.wrap(approveAwardParticipant)({}); + mockWalletReturnValue(guardian, { award: award.uid, members: [member, member] }); + await testEnv.wrap(WEN_FUNC.approveParticipantAward); - const tokenDocRef = build5Db().doc(`${COL.TOKEN}/${token.uid}`); - const distributionDocRef = tokenDocRef.collection(SUB_COL.DISTRIBUTION).doc(member); + const distributionDocRef = build5Db().doc(COL.TOKEN, token.uid, SUB_COL.DISTRIBUTION, member); let distribution = await distributionDocRef.get(); expect(distribution?.totalUnclaimedAirdrop || 0).toBe(0); const nttQuery = build5Db() .collection(COL.TRANSACTION) .where('member', '==', member) - .where('payload.type', '==', TransactionPayloadType.BADGE); + .where('payload_type', '==', PgTransactionPayloadType.BADGE); await wait(async () => { const snap = await nttQuery.get(); return snap.length === 2; @@ -146,9 +136,9 @@ const saveToken = async (space: string, guardian: string) => { network: Network.RMS, tokenId: MINTED_TOKEN_ID, }, - }; - await build5Db().doc(`${COL.TOKEN}/${token.uid}`).set(token); - return token as Token; + } as Token; + await build5Db().doc(COL.TOKEN, token.uid).create(token); + return token; }; const MINTED_TOKEN_ID = diff --git a/packages/functions/test-tangle/award/common.ts b/packages/functions/test-tangle/award/common.ts index e096e85683..9b4b7c87c2 100644 --- a/packages/functions/test-tangle/award/common.ts +++ b/packages/functions/test-tangle/award/common.ts @@ -1,13 +1,5 @@ -import { IQuery, build5Db } from '@build-5/database'; -import { - COL, - Network, - SOON_PROJECT_ID, - Token, - TokenStatus, - TransactionPayloadType, - TransactionType, -} from '@build-5/interfaces'; +import { IQuery, PgTransactionPayloadType, PgTransactionType, build5Db } from '@build-5/database'; +import { COL, Network, SOON_PROJECT_ID, Token, TokenStatus } from '@build-5/interfaces'; import { serverTime } from '../../src/utils/dateTime.utils'; import { getRandomEthAddress } from '../../src/utils/wallet.utils'; import { getRandomSymbol, wait } from '../../test/controls/common'; @@ -16,20 +8,20 @@ import { MEDIA } from '../../test/set-up'; export const awaitAllTransactionsForAward = async (awardId: string) => { const baseTransQuery = build5Db() .collection(COL.TRANSACTION) - .where('payload.award', '==', awardId) - .where('type', 'in', [TransactionType.BILL_PAYMENT, TransactionType.CREDIT]); + .where('payload_award', '==', awardId) + .whereIn('type', [PgTransactionType.BILL_PAYMENT, PgTransactionType.CREDIT]); await allConfirmed(baseTransQuery); const nttQuery = build5Db() .collection(COL.TRANSACTION) - .where('payload.award', '==', awardId) - .where('payload.type', '==', TransactionPayloadType.BADGE); + .where('payload_award', '==', awardId) + .where('payload_type', '==', PgTransactionPayloadType.BADGE); await allConfirmed(nttQuery); }; -const allConfirmed = (query: IQuery) => +const allConfirmed = (query: IQuery) => wait(async () => { - const snap = await query.get>(); + const snap = await query.get(); const allConfirmed = snap.reduce( (acc, doc) => acc && doc?.payload?.walletReference?.confirmed, true, @@ -54,7 +46,7 @@ export const saveBaseToken = async (space: string, guardian: string, network = N mintingData: { network, }, - }; - await build5Db().doc(`${COL.TOKEN}/${token.uid}`).set(token); - return token as Token; + } as Token; + await build5Db().doc(COL.TOKEN, token.uid).create(token); + return token; }; diff --git a/packages/functions/test-tangle/base-token-trading/Helper.ts b/packages/functions/test-tangle/base-token-trading/Helper.ts index 4ec2133514..9d209536c2 100644 --- a/packages/functions/test-tangle/base-token-trading/Helper.ts +++ b/packages/functions/test-tangle/base-token-trading/Helper.ts @@ -1,21 +1,13 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ import { build5Db } from '@build-5/database'; import { COL, Member, Network, SOON_PROJECT_ID, Token, TokenStatus } from '@build-5/interfaces'; -import { createMember } from '../../src/runtime/firebase/member'; import { IotaWallet } from '../../src/services/wallet/IotaWalletService'; import { Wallet } from '../../src/services/wallet/wallet'; import { AddressDetails } from '../../src/services/wallet/wallet.service'; import { serverTime } from '../../src/utils/dateTime.utils'; import * as wallet from '../../src/utils/wallet.utils'; -import { - createMember as createMemberTest, - createRoyaltySpaces, - createSpace, - getRandomSymbol, - mockWalletReturnValue, -} from '../../test/controls/common'; +import { createRoyaltySpaces, getRandomSymbol } from '../../test/controls/common'; import { MEDIA, getWallet, testEnv } from '../../test/set-up'; -import { addValidatedAddress } from '../common'; export class Helper { public sourceNetwork = Network.ATOI; @@ -25,33 +17,38 @@ export class Helper { public buyer: Member | undefined; public buyerValidateAddress = {} as { [key: string]: AddressDetails }; public token: Token | undefined; - public walletSpy: any | undefined; public rmsWallet: Wallet | undefined; public atoiWallet: IotaWallet | undefined; public beforeEach = async () => { await createRoyaltySpaces(); - this.walletSpy = jest.spyOn(wallet, 'decodeAuth'); - const guardian = await createMemberTest(this.walletSpy); - const space = await createSpace(this.walletSpy, guardian); + const guardian = await testEnv.createMember(); + const space = await testEnv.createSpace(guardian); - const sellerId = wallet.getRandomEthAddress(); - mockWalletReturnValue(this.walletSpy, sellerId, {}); - await testEnv.wrap(createMember)({ address: sellerId }); - this.sellerValidateAddress[Network.ATOI] = await addValidatedAddress(Network.ATOI, sellerId); - this.sellerValidateAddress[Network.RMS] = await addValidatedAddress(Network.RMS, sellerId); - this.seller = await build5Db().doc(`${COL.MEMBER}/${sellerId}`).get(); - - const buyerId = wallet.getRandomEthAddress(); - mockWalletReturnValue(this.walletSpy, buyerId, {}); - await testEnv.wrap(createMember)({ address: buyerId }); - this.buyerValidateAddress[Network.ATOI] = await addValidatedAddress(Network.ATOI, buyerId); - this.buyerValidateAddress[Network.RMS] = await addValidatedAddress(Network.RMS, buyerId); - this.buyer = await build5Db().doc(`${COL.MEMBER}/${buyerId}`).get(); - this.token = await this.saveToken(space.uid, guardian); + const sellerId = await testEnv.createMember(); + this.seller = await build5Db().doc(COL.MEMBER, sellerId).get(); this.atoiWallet = (await getWallet(Network.ATOI)) as IotaWallet; this.rmsWallet = await getWallet(Network.RMS); + + this.sellerValidateAddress[Network.ATOI] = await this.atoiWallet.getAddressDetails( + this.seller.validatedAddress![Network.ATOI], + ); + this.sellerValidateAddress[Network.RMS] = await this.rmsWallet.getAddressDetails( + this.seller.validatedAddress![Network.RMS], + ); + + const buyerId = await testEnv.createMember(); + this.buyer = await build5Db().doc(COL.MEMBER, buyerId).get(); + + this.buyerValidateAddress[Network.ATOI] = await this.atoiWallet.getAddressDetails( + this.buyer.validatedAddress![Network.ATOI], + ); + this.buyerValidateAddress[Network.RMS] = await this.rmsWallet.getAddressDetails( + this.buyer.validatedAddress![Network.RMS], + ); + + this.token = await this.saveToken(space.uid, guardian); }; public saveToken = async (space: string, guardian: string) => { @@ -71,8 +68,9 @@ export class Helper { mintingData: { network: Network.ATOI, }, - }; - await build5Db().doc(`${COL.TOKEN}/${token.uid}`).set(token); - return token as Token; + links: [] as URL[], + } as Token; + await build5Db().doc(COL.TOKEN, token.uid).create(token); + return token; }; } diff --git a/packages/functions/test-tangle/base-token-trading/base-token-trading_1.spec.ts b/packages/functions/test-tangle/base-token-trading/base-token-trading_1.spec.ts index 3ce663be91..48e915aecc 100644 --- a/packages/functions/test-tangle/base-token-trading/base-token-trading_1.spec.ts +++ b/packages/functions/test-tangle/base-token-trading/base-token-trading_1.spec.ts @@ -1,4 +1,9 @@ -import { build5Db } from '@build-5/database'; +import { + PgTokenTradeOrderType, + PgTransactionPayloadType, + PgTransactionType, + build5Db, +} from '@build-5/database'; import { COL, MIN_IOTA_AMOUNT, @@ -10,15 +15,14 @@ import { TokenTradeOrderType, Transaction, TransactionPayloadType, - TransactionType, + WEN_FUNC, } from '@build-5/interfaces'; import dayjs from 'dayjs'; import { isEmpty } from 'lodash'; -import { tradeToken } from '../../src/runtime/firebase/token/trading'; import { getAddress } from '../../src/utils/address.utils'; import { dateToTimestamp } from '../../src/utils/dateTime.utils'; -import { mockWalletReturnValue, wait } from '../../test/controls/common'; -import { getWallet, testEnv } from '../../test/set-up'; +import { wait } from '../../test/controls/common'; +import { getWallet, mockWalletReturnValue, testEnv } from '../../test/set-up'; import { awaitTransactionConfirmationsForToken } from '../common'; import { requestFundsFromFaucet } from '../faucet'; import { Helper } from './Helper'; @@ -31,26 +35,26 @@ describe('Base token trading', () => { }); it('Should fulfill sell order', async () => { - mockWalletReturnValue(helper.walletSpy, helper.seller!.uid, { + mockWalletReturnValue(helper.seller!.uid, { symbol: helper.token!.symbol, count: MIN_IOTA_AMOUNT, price: 2, type: TokenTradeOrderType.SELL, }); - const sellOrder = await testEnv.wrap(tradeToken)({}); + const sellOrder = await testEnv.wrap(WEN_FUNC.tradeToken); await requestFundsFromFaucet( helper.sourceNetwork, sellOrder.payload.targetAddress, MIN_IOTA_AMOUNT, ); - mockWalletReturnValue(helper.walletSpy, helper.buyer!.uid, { + mockWalletReturnValue(helper.buyer!.uid, { symbol: helper.token!.symbol, count: MIN_IOTA_AMOUNT, price: 2, type: TokenTradeOrderType.BUY, }); - const buyOrder = await testEnv.wrap(tradeToken)({}); + const buyOrder = await testEnv.wrap(WEN_FUNC.tradeToken); await requestFundsFromFaucet( helper.targetNetwork, buyOrder.payload.targetAddress, @@ -94,12 +98,12 @@ describe('Base token trading', () => { expect(purchase.targetNetwork).toBe(helper.targetNetwork); expect(purchase.tokenStatus).toBe(TokenStatus.BASE); expect(purchase.sellerTier).toBe(0); - expect(purchase.sellerTokenTradingFeePercentage).toBeNull(); + expect(purchase.sellerTokenTradingFeePercentage).toBeUndefined(); const sellerBillPaymentsSnap = await build5Db() .collection(COL.TRANSACTION) .where('member', '==', helper.seller!.uid) - .where('type', '==', TransactionType.BILL_PAYMENT) + .where('type', '==', PgTransactionType.BILL_PAYMENT) .get(); const sellerBillPayments = sellerBillPaymentsSnap.map((d) => d as Transaction); expect( @@ -125,14 +129,14 @@ describe('Base token trading', () => { const sellerCreditSnap = await build5Db() .collection(COL.TRANSACTION) .where('member', '==', helper.seller!.uid) - .where('type', '==', TransactionType.CREDIT) + .where('type', '==', PgTransactionType.CREDIT) .get(); expect(sellerCreditSnap.length).toBe(0); const buyerBillPaymentsSnap = await build5Db() .collection(COL.TRANSACTION) .where('member', '==', helper.buyer!.uid) - .where('type', '==', TransactionType.BILL_PAYMENT) + .where('type', '==', PgTransactionType.BILL_PAYMENT) .get(); const buyerBillPayments = buyerBillPaymentsSnap.map((d) => d as Transaction); expect(buyerBillPayments.length).toBe(3); @@ -175,7 +179,7 @@ describe('Base token trading', () => { const buyerCreditnap = await build5Db() .collection(COL.TRANSACTION) .where('member', '==', helper.buyer!.uid) - .where('type', '==', TransactionType.CREDIT) + .where('type', '==', PgTransactionType.CREDIT) .get(); expect(buyerCreditnap.length).toBe(0); @@ -194,13 +198,13 @@ describe('Base token trading', () => { const date = dayjs().add(2, 'h').millisecond(0).toDate(); const expiresAt = dateToTimestamp(date); - mockWalletReturnValue(helper.walletSpy, helper.buyer!.uid, { + mockWalletReturnValue(helper.buyer!.uid, { symbol: helper.token!.symbol, count: MIN_IOTA_AMOUNT, price: 2, type: TokenTradeOrderType.BUY, }); - const buyOrder = await testEnv.wrap(tradeToken)({}); + const buyOrder = await testEnv.wrap(WEN_FUNC.tradeToken); await requestFundsFromFaucet( helper.targetNetwork, buyOrder.payload.targetAddress, @@ -221,13 +225,13 @@ describe('Base token trading', () => { }); it('Should not credit buy order with expiration unlock, custom amount', async () => { - mockWalletReturnValue(helper.walletSpy, helper.seller!.uid, { + mockWalletReturnValue(helper.seller!.uid, { symbol: helper.token!.symbol, count: MIN_IOTA_AMOUNT, price: 2, type: TokenTradeOrderType.SELL, }); - const sellOrder = await testEnv.wrap(tradeToken)({}); + const sellOrder = await testEnv.wrap(WEN_FUNC.tradeToken); await requestFundsFromFaucet( helper.sourceNetwork, sellOrder.payload.targetAddress, @@ -237,13 +241,13 @@ describe('Base token trading', () => { const date = dayjs().add(2, 'h').millisecond(0).toDate(); const expiresAt = dateToTimestamp(date) as Timestamp; - mockWalletReturnValue(helper.walletSpy, helper.buyer!.uid, { + mockWalletReturnValue(helper.buyer!.uid, { symbol: helper.token!.symbol, count: MIN_IOTA_AMOUNT, price: 2, type: TokenTradeOrderType.BUY, }); - const buyOrder = await testEnv.wrap(tradeToken)({}); + const buyOrder = await testEnv.wrap(WEN_FUNC.tradeToken); await requestFundsFromFaucet( helper.targetNetwork, buyOrder.payload.targetAddress, @@ -253,13 +257,13 @@ describe('Base token trading', () => { const buyQuery = build5Db() .collection(COL.TOKEN_MARKET) - .where('type', '==', TokenTradeOrderType.BUY) + .where('type', '==', PgTokenTradeOrderType.BUY) .where('owner', '==', helper.buyer?.uid); await wait(async () => { - const snap = await buyQuery.get(); + const snap = await buyQuery.get(); return snap.length === 1 && snap[0].status === TokenTradeOrderStatus.SETTLED; }); - const buy = (await buyQuery.get())[0]; + const buy = (await buyQuery.get())[0]; expect(buy.balance).toBe(2 * MIN_IOTA_AMOUNT); expect(buy.count).toBe(MIN_IOTA_AMOUNT); expect(buy.fulfilled).toBe(MIN_IOTA_AMOUNT); @@ -267,8 +271,8 @@ describe('Base token trading', () => { const credit = await build5Db() .collection(COL.TRANSACTION) .where('member', '==', helper.buyer?.uid) - .where('payload.type', '==', TransactionPayloadType.TOKEN_TRADE_FULLFILLMENT) - .get(); + .where('payload_type', '==', PgTransactionPayloadType.TOKEN_TRADE_FULLFILLMENT) + .get(); expect(credit.length).toBe(1); expect(credit[0].payload.amount).toBe(2 * MIN_IOTA_AMOUNT); }); diff --git a/packages/functions/test-tangle/base-token-trading/base-token-trading_10.spec.ts b/packages/functions/test-tangle/base-token-trading/base-token-trading_10.spec.ts index 2de1c202cd..a754a8928b 100644 --- a/packages/functions/test-tangle/base-token-trading/base-token-trading_10.spec.ts +++ b/packages/functions/test-tangle/base-token-trading/base-token-trading_10.spec.ts @@ -1,15 +1,14 @@ -import { build5Db } from '@build-5/database'; +import { PgTransactionType, build5Db } from '@build-5/database'; import { COL, MIN_IOTA_AMOUNT, TokenPurchase, TokenTradeOrderType, Transaction, - TransactionType, + WEN_FUNC, } from '@build-5/interfaces'; -import { tradeToken } from '../../src/runtime/firebase/token/trading'; -import { mockWalletReturnValue, wait } from '../../test/controls/common'; -import { testEnv } from '../../test/set-up'; +import { wait } from '../../test/controls/common'; +import { mockWalletReturnValue, testEnv } from '../../test/set-up'; import { awaitTransactionConfirmationsForToken } from '../common'; import { requestFundsFromFaucet } from '../faucet'; import { Helper } from './Helper'; @@ -22,26 +21,26 @@ describe('Base token trading', () => { }); it('Should not fill buy, dust and order not fulfilled', async () => { - mockWalletReturnValue(helper.walletSpy, helper.seller!.uid, { + mockWalletReturnValue(helper.seller!.uid, { symbol: helper.token!.symbol, count: MIN_IOTA_AMOUNT, price: 2, type: TokenTradeOrderType.SELL, }); - const sellOrder = await testEnv.wrap(tradeToken)({}); + const sellOrder = await testEnv.wrap(WEN_FUNC.tradeToken); await requestFundsFromFaucet( helper.sourceNetwork, sellOrder.payload.targetAddress, MIN_IOTA_AMOUNT, ); - mockWalletReturnValue(helper.walletSpy, helper.buyer!.uid, { + mockWalletReturnValue(helper.buyer!.uid, { symbol: helper.token!.symbol, count: MIN_IOTA_AMOUNT + 1, price: 2, type: TokenTradeOrderType.BUY, }); - const buyOrder = await testEnv.wrap(tradeToken)({}); + const buyOrder = await testEnv.wrap(WEN_FUNC.tradeToken); await requestFundsFromFaucet( helper.targetNetwork, buyOrder.payload.targetAddress, @@ -71,13 +70,13 @@ describe('Base token trading', () => { const tradesQuery = build5Db() .collection(COL.TOKEN_MARKET) .where('token', '==', helper.token!.uid); - mockWalletReturnValue(helper.walletSpy, helper.seller!.uid, { + mockWalletReturnValue(helper.seller!.uid, { symbol: helper.token!.symbol, count: MIN_IOTA_AMOUNT, price: 2, type: TokenTradeOrderType.SELL, }); - const sellOrder = await testEnv.wrap(tradeToken)({}); + const sellOrder = await testEnv.wrap(WEN_FUNC.tradeToken); await requestFundsFromFaucet( helper.sourceNetwork, sellOrder.payload.targetAddress, @@ -89,13 +88,13 @@ describe('Base token trading', () => { return snap.length === 1; }); - mockWalletReturnValue(helper.walletSpy, helper.buyer!.uid, { + mockWalletReturnValue(helper.buyer!.uid, { symbol: helper.token!.symbol, count: MIN_IOTA_AMOUNT, price: 2.001, type: TokenTradeOrderType.BUY, }); - const buyOrder = await testEnv.wrap(tradeToken)({}); + const buyOrder = await testEnv.wrap(WEN_FUNC.tradeToken); await requestFundsFromFaucet( helper.targetNetwork, buyOrder.payload.targetAddress, @@ -116,8 +115,8 @@ describe('Base token trading', () => { const billPayments = ( await build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.BILL_PAYMENT) - .where('payload.token', '==', helper.token!.uid) + .where('type', '==', PgTransactionType.BILL_PAYMENT) + .where('payload_token', '==', helper.token!.uid) .get() ).map((d) => d); diff --git a/packages/functions/test-tangle/base-token-trading/base-token-trading_11_a.spec.ts b/packages/functions/test-tangle/base-token-trading/base-token-trading_11_a.spec.ts index faf80a3058..a6c9d58a15 100644 --- a/packages/functions/test-tangle/base-token-trading/base-token-trading_11_a.spec.ts +++ b/packages/functions/test-tangle/base-token-trading/base-token-trading_11_a.spec.ts @@ -1,4 +1,4 @@ -import { build5Db } from '@build-5/database'; +import { PgTransactionType, build5Db } from '@build-5/database'; import { COL, MIN_IOTA_AMOUNT, @@ -6,11 +6,10 @@ import { TokenPurchase, TokenTradeOrderType, Transaction, - TransactionType, + WEN_FUNC, } from '@build-5/interfaces'; -import { tradeToken } from '../../src/runtime/firebase/token/trading'; -import { mockWalletReturnValue, wait } from '../../test/controls/common'; -import { testEnv } from '../../test/set-up'; +import { wait } from '../../test/controls/common'; +import { mockWalletReturnValue, testEnv } from '../../test/set-up'; import { awaitTransactionConfirmationsForToken } from '../common'; import { requestFundsFromFaucet } from '../faucet'; import { Helper } from './Helper'; @@ -23,17 +22,15 @@ describe('Base token trading', () => { }); it('Should not create royalty payments, zero percentage fee', async () => { - await build5Db() - .doc(`${COL.SYSTEM}/${SYSTEM_CONFIG_DOC_ID}`) - .set({ tokenTradingFeePercentage: 0 }); + await build5Db().doc(COL.SYSTEM, SYSTEM_CONFIG_DOC_ID).upsert({ tokenTradingFeePercentage: 0 }); - mockWalletReturnValue(helper.walletSpy, helper.seller!.uid, { + mockWalletReturnValue(helper.seller!.uid, { symbol: helper.token!.symbol, count: MIN_IOTA_AMOUNT, price: 2, type: TokenTradeOrderType.SELL, }); - const sellOrder = await testEnv.wrap(tradeToken)({}); + const sellOrder = await testEnv.wrap(WEN_FUNC.tradeToken); await requestFundsFromFaucet( helper.sourceNetwork, sellOrder.payload.targetAddress, @@ -48,13 +45,13 @@ describe('Base token trading', () => { return snap.length === 1; }); - mockWalletReturnValue(helper.walletSpy, helper.buyer!.uid, { + mockWalletReturnValue(helper.buyer!.uid, { symbol: helper.token!.symbol, count: MIN_IOTA_AMOUNT, price: 2, type: TokenTradeOrderType.BUY, }); - const buyOrder = await testEnv.wrap(tradeToken)({}); + const buyOrder = await testEnv.wrap(WEN_FUNC.tradeToken); await requestFundsFromFaucet( helper.targetNetwork, buyOrder.payload.targetAddress, @@ -75,8 +72,8 @@ describe('Base token trading', () => { const billPayments = ( await build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.BILL_PAYMENT) - .where('payload.token', '==', helper.token!.uid) + .where('type', '==', PgTransactionType.BILL_PAYMENT) + .where('payload_token', '==', helper.token!.uid) .get() ).map((d) => d); expect(billPayments.length).toBe(2); diff --git a/packages/functions/test-tangle/base-token-trading/base-token-trading_11_b.spec.ts b/packages/functions/test-tangle/base-token-trading/base-token-trading_11_b.spec.ts index 325a70dc24..56308ae1f5 100644 --- a/packages/functions/test-tangle/base-token-trading/base-token-trading_11_b.spec.ts +++ b/packages/functions/test-tangle/base-token-trading/base-token-trading_11_b.spec.ts @@ -1,17 +1,15 @@ -import { build5Db } from '@build-5/database'; +import { PgTransactionType, build5Db } from '@build-5/database'; import { COL, MIN_IOTA_AMOUNT, - StakeType, SUB_COL, TokenPurchase, TokenTradeOrderType, Transaction, - TransactionType, + WEN_FUNC, } from '@build-5/interfaces'; -import { tradeToken } from '../../src/runtime/firebase/token/trading'; -import { mockWalletReturnValue, wait } from '../../test/controls/common'; -import { soonTokenId, testEnv } from '../../test/set-up'; +import { wait } from '../../test/controls/common'; +import { mockWalletReturnValue, soonTokenId, testEnv } from '../../test/set-up'; import { awaitTransactionConfirmationsForToken } from '../common'; import { requestFundsFromFaucet } from '../faucet'; import { Helper } from './Helper'; @@ -24,32 +22,18 @@ describe('Base token trading', () => { }); it('Should not create royalty payments, zero percentage fee', async () => { + await build5Db().doc(COL.MEMBER, helper.seller!.uid).update({ tokenTradingFeePercentage: 0 }); await build5Db() - .doc(`${COL.MEMBER}/${helper.seller!.uid}`) - .update({ tokenTradingFeePercentage: 0 }); - await build5Db() - .collection(COL.TOKEN) - .doc(soonTokenId) - .collection(SUB_COL.DISTRIBUTION) - .doc(helper.seller?.uid!) - .set( - { - stakes: { - [StakeType.DYNAMIC]: { - value: 15000 * MIN_IOTA_AMOUNT, - }, - }, - }, - true, - ); + .doc(COL.TOKEN, soonTokenId, SUB_COL.DISTRIBUTION, helper.seller?.uid!) + .upsert({ stakes_dynamic_value: 15000 * MIN_IOTA_AMOUNT }); - mockWalletReturnValue(helper.walletSpy, helper.seller!.uid, { + mockWalletReturnValue(helper.seller!.uid, { symbol: helper.token!.symbol, count: MIN_IOTA_AMOUNT, price: 2, type: TokenTradeOrderType.SELL, }); - const sellOrder = await testEnv.wrap(tradeToken)({}); + const sellOrder = await testEnv.wrap(WEN_FUNC.tradeToken); await requestFundsFromFaucet( helper.sourceNetwork, sellOrder.payload.targetAddress, @@ -64,13 +48,13 @@ describe('Base token trading', () => { return snap.length === 1; }); - mockWalletReturnValue(helper.walletSpy, helper.buyer!.uid, { + mockWalletReturnValue(helper.buyer!.uid, { symbol: helper.token!.symbol, count: MIN_IOTA_AMOUNT, price: 2, type: TokenTradeOrderType.BUY, }); - const buyOrder = await testEnv.wrap(tradeToken)({}); + const buyOrder = await testEnv.wrap(WEN_FUNC.tradeToken); await requestFundsFromFaucet( helper.targetNetwork, buyOrder.payload.targetAddress, @@ -93,8 +77,8 @@ describe('Base token trading', () => { const billPayments = ( await build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.BILL_PAYMENT) - .where('payload.token', '==', helper.token!.uid) + .where('type', '==', PgTransactionType.BILL_PAYMENT) + .where('payload_token', '==', helper.token!.uid) .get() ).map((d) => d); expect(billPayments.length).toBe(2); @@ -113,16 +97,14 @@ describe('Base token trading', () => { }); it('Should create royalty payments only with dust', async () => { - await build5Db() - .doc(`${COL.MEMBER}/${helper.seller!.uid}`) - .update({ tokenTradingFeePercentage: 0 }); - mockWalletReturnValue(helper.walletSpy, helper.seller!.uid, { + await build5Db().doc(COL.MEMBER, helper.seller!.uid).update({ tokenTradingFeePercentage: 0 }); + mockWalletReturnValue(helper.seller!.uid, { symbol: helper.token!.symbol, count: MIN_IOTA_AMOUNT, price: 2, type: TokenTradeOrderType.SELL, }); - const sellOrder = await testEnv.wrap(tradeToken)({}); + const sellOrder = await testEnv.wrap(WEN_FUNC.tradeToken); await requestFundsFromFaucet( helper.sourceNetwork, sellOrder.payload.targetAddress, @@ -137,13 +119,13 @@ describe('Base token trading', () => { return snap.length === 1; }); - mockWalletReturnValue(helper.walletSpy, helper.buyer!.uid, { + mockWalletReturnValue(helper.buyer!.uid, { symbol: helper.token!.symbol, count: MIN_IOTA_AMOUNT, price: 2.001, type: TokenTradeOrderType.BUY, }); - const buyOrder = await testEnv.wrap(tradeToken)({}); + const buyOrder = await testEnv.wrap(WEN_FUNC.tradeToken); await requestFundsFromFaucet( helper.targetNetwork, buyOrder.payload.targetAddress, @@ -164,8 +146,8 @@ describe('Base token trading', () => { const billPayments = ( await build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.BILL_PAYMENT) - .where('payload.token', '==', helper.token!.uid) + .where('type', '==', PgTransactionType.BILL_PAYMENT) + .where('payload_token', '==', helper.token!.uid) .get() ).map((d) => d); expect(billPayments.length).toBe(3); @@ -184,16 +166,14 @@ describe('Base token trading', () => { }); it('Should create royalty payments for different percentage', async () => { - await build5Db() - .doc(`${COL.MEMBER}/${helper.seller!.uid}`) - .update({ tokenTradingFeePercentage: 1 }); - mockWalletReturnValue(helper.walletSpy, helper.seller!.uid, { + await build5Db().doc(COL.MEMBER, helper.seller!.uid).update({ tokenTradingFeePercentage: 1 }); + mockWalletReturnValue(helper.seller!.uid, { symbol: helper.token!.symbol, count: MIN_IOTA_AMOUNT, price: 2, type: TokenTradeOrderType.SELL, }); - const sellOrder = await testEnv.wrap(tradeToken)({}); + const sellOrder = await testEnv.wrap(WEN_FUNC.tradeToken); await requestFundsFromFaucet( helper.sourceNetwork, sellOrder.payload.targetAddress, @@ -208,13 +188,13 @@ describe('Base token trading', () => { return snap.length === 1; }); - mockWalletReturnValue(helper.walletSpy, helper.buyer!.uid, { + mockWalletReturnValue(helper.buyer!.uid, { symbol: helper.token!.symbol, count: MIN_IOTA_AMOUNT, price: 2, type: TokenTradeOrderType.BUY, }); - const buyOrder = await testEnv.wrap(tradeToken)({}); + const buyOrder = await testEnv.wrap(WEN_FUNC.tradeToken); await requestFundsFromFaucet( helper.targetNetwork, buyOrder.payload.targetAddress, @@ -235,8 +215,8 @@ describe('Base token trading', () => { const billPayments = ( await build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.BILL_PAYMENT) - .where('payload.token', '==', helper.token!.uid) + .where('type', '==', PgTransactionType.BILL_PAYMENT) + .where('payload_token', '==', helper.token!.uid) .get() ).map((d) => d); expect(billPayments.length).toBe(4); diff --git a/packages/functions/test-tangle/base-token-trading/base-token-trading_11_c.spec.ts b/packages/functions/test-tangle/base-token-trading/base-token-trading_11_c.spec.ts index 90e89bb18d..be1803894a 100644 --- a/packages/functions/test-tangle/base-token-trading/base-token-trading_11_c.spec.ts +++ b/packages/functions/test-tangle/base-token-trading/base-token-trading_11_c.spec.ts @@ -1,15 +1,14 @@ -import { build5Db } from '@build-5/database'; +import { PgTransactionType, build5Db } from '@build-5/database'; import { COL, MIN_IOTA_AMOUNT, TokenPurchase, TokenTradeOrderType, Transaction, - TransactionType, + WEN_FUNC, } from '@build-5/interfaces'; -import { tradeToken } from '../../src/runtime/firebase/token/trading'; -import { mockWalletReturnValue, wait } from '../../test/controls/common'; -import { testEnv } from '../../test/set-up'; +import { wait } from '../../test/controls/common'; +import { mockWalletReturnValue, testEnv } from '../../test/set-up'; import { awaitTransactionConfirmationsForToken } from '../common'; import { requestFundsFromFaucet } from '../faucet'; import { Helper } from './Helper'; @@ -22,16 +21,14 @@ describe('Base token trading', () => { }); it('Should create royalty payments only with dust', async () => { - await build5Db() - .doc(`${COL.MEMBER}/${helper.seller!.uid}`) - .update({ tokenTradingFeePercentage: 0 }); - mockWalletReturnValue(helper.walletSpy, helper.seller!.uid, { + await build5Db().doc(COL.MEMBER, helper.seller!.uid).update({ tokenTradingFeePercentage: 0 }); + mockWalletReturnValue(helper.seller!.uid, { symbol: helper.token!.symbol, count: MIN_IOTA_AMOUNT, price: 2, type: TokenTradeOrderType.SELL, }); - const sellOrder = await testEnv.wrap(tradeToken)({}); + const sellOrder = await testEnv.wrap(WEN_FUNC.tradeToken); await requestFundsFromFaucet( helper.sourceNetwork, sellOrder.payload.targetAddress, @@ -46,13 +43,13 @@ describe('Base token trading', () => { return snap.length === 1; }); - mockWalletReturnValue(helper.walletSpy, helper.buyer!.uid, { + mockWalletReturnValue(helper.buyer!.uid, { symbol: helper.token!.symbol, count: MIN_IOTA_AMOUNT, price: 2.001, type: TokenTradeOrderType.BUY, }); - const buyOrder = await testEnv.wrap(tradeToken)({}); + const buyOrder = await testEnv.wrap(WEN_FUNC.tradeToken); await requestFundsFromFaucet( helper.targetNetwork, buyOrder.payload.targetAddress, @@ -73,8 +70,8 @@ describe('Base token trading', () => { const billPayments = ( await build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.BILL_PAYMENT) - .where('payload.token', '==', helper.token!.uid) + .where('type', '==', PgTransactionType.BILL_PAYMENT) + .where('payload_token', '==', helper.token!.uid) .get() ).map((d) => d); expect(billPayments.length).toBe(3); diff --git a/packages/functions/test-tangle/base-token-trading/base-token-trading_11_d.spec.ts b/packages/functions/test-tangle/base-token-trading/base-token-trading_11_d.spec.ts index 49f74db50d..f46d018c2e 100644 --- a/packages/functions/test-tangle/base-token-trading/base-token-trading_11_d.spec.ts +++ b/packages/functions/test-tangle/base-token-trading/base-token-trading_11_d.spec.ts @@ -1,15 +1,14 @@ -import { build5Db } from '@build-5/database'; +import { PgTransactionType, build5Db } from '@build-5/database'; import { COL, MIN_IOTA_AMOUNT, TokenPurchase, TokenTradeOrderType, Transaction, - TransactionType, + WEN_FUNC, } from '@build-5/interfaces'; -import { tradeToken } from '../../src/runtime/firebase/token/trading'; -import { mockWalletReturnValue, wait } from '../../test/controls/common'; -import { testEnv } from '../../test/set-up'; +import { wait } from '../../test/controls/common'; +import { mockWalletReturnValue, testEnv } from '../../test/set-up'; import { awaitTransactionConfirmationsForToken } from '../common'; import { requestFundsFromFaucet } from '../faucet'; import { Helper } from './Helper'; @@ -22,16 +21,14 @@ describe('Base token trading', () => { }); it('Should create royalty payments for different percentage', async () => { - await build5Db() - .doc(`${COL.MEMBER}/${helper.seller!.uid}`) - .update({ tokenTradingFeePercentage: 1 }); - mockWalletReturnValue(helper.walletSpy, helper.seller!.uid, { + await build5Db().doc(COL.MEMBER, helper.seller!.uid).update({ tokenTradingFeePercentage: 1 }); + mockWalletReturnValue(helper.seller!.uid, { symbol: helper.token!.symbol, count: MIN_IOTA_AMOUNT, price: 2, type: TokenTradeOrderType.SELL, }); - const sellOrder = await testEnv.wrap(tradeToken)({}); + const sellOrder = await testEnv.wrap(WEN_FUNC.tradeToken); await requestFundsFromFaucet( helper.sourceNetwork, sellOrder.payload.targetAddress, @@ -46,13 +43,13 @@ describe('Base token trading', () => { return snap.length === 1; }); - mockWalletReturnValue(helper.walletSpy, helper.buyer!.uid, { + mockWalletReturnValue(helper.buyer!.uid, { symbol: helper.token!.symbol, count: MIN_IOTA_AMOUNT, price: 2, type: TokenTradeOrderType.BUY, }); - const buyOrder = await testEnv.wrap(tradeToken)({}); + const buyOrder = await testEnv.wrap(WEN_FUNC.tradeToken); await requestFundsFromFaucet( helper.targetNetwork, buyOrder.payload.targetAddress, @@ -73,8 +70,8 @@ describe('Base token trading', () => { const billPayments = ( await build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.BILL_PAYMENT) - .where('payload.token', '==', helper.token!.uid) + .where('type', '==', PgTransactionType.BILL_PAYMENT) + .where('payload_token', '==', helper.token!.uid) .get() ).map((d) => d); expect(billPayments.length).toBe(4); diff --git a/packages/functions/test-tangle/base-token-trading/base-token-trading_12.spec.ts b/packages/functions/test-tangle/base-token-trading/base-token-trading_12.spec.ts index 1c1238bef0..1be0ca764d 100644 --- a/packages/functions/test-tangle/base-token-trading/base-token-trading_12.spec.ts +++ b/packages/functions/test-tangle/base-token-trading/base-token-trading_12.spec.ts @@ -48,7 +48,7 @@ describe('Base token trading', () => { const snap = await query.get(); return snap.length > 0; }); - const orderSnap = await query.get(); + const orderSnap = await query.get(); const sellOrder = orderSnap[0]; expect(sellOrder.owner).toBe(helper.seller!.uid); expect(sellOrder.price).toBe(1.5); diff --git a/packages/functions/test-tangle/base-token-trading/base-token-trading_13.spec.ts b/packages/functions/test-tangle/base-token-trading/base-token-trading_13.spec.ts index 150cb480f0..7c4dd3264b 100644 --- a/packages/functions/test-tangle/base-token-trading/base-token-trading_13.spec.ts +++ b/packages/functions/test-tangle/base-token-trading/base-token-trading_13.spec.ts @@ -1,12 +1,5 @@ import { build5Db } from '@build-5/database'; -import { - COL, - MIN_IOTA_AMOUNT, - Network, - TangleRequestType, - TokenTradeOrder, - Transaction, -} from '@build-5/interfaces'; +import { COL, MIN_IOTA_AMOUNT, Network, TangleRequestType, Transaction } from '@build-5/interfaces'; import { wait } from '../../test/controls/common'; import { awaitTransactionConfirmationsForToken, getTangleOrder } from '../common'; import { requestFundsFromFaucet } from '../faucet'; @@ -64,21 +57,25 @@ describe('Base token trading', () => { }, }); - let query = build5Db().collection(COL.TOKEN_MARKET).where('owner', '==', helper.seller!.uid); + const queryBySeller = build5Db() + .collection(COL.TOKEN_MARKET) + .where('owner', '==', helper.seller!.uid); await wait(async () => { - const snap = await query.get(); + const snap = await queryBySeller.get(); return snap.length > 0; }); - const sell = (await query.get())[0]!; + const sell = (await queryBySeller.get())[0]!; - query = build5Db().collection(COL.TOKEN_MARKET).where('owner', '==', helper.buyer!.uid); + const queryByBuyer = build5Db() + .collection(COL.TOKEN_MARKET) + .where('owner', '==', helper.buyer!.uid); await wait(async () => { - const snap = await query.get(); + const snap = await queryByBuyer.get(); return snap.length > 0; }); - const buy = (await query.get())[0]!; + const buy = (await queryByBuyer.get())[0]!; - query = build5Db() + const query = build5Db() .collection(COL.TOKEN_PURCHASE) .where('sell', '==', sell.uid) .where('buy', '==', buy.uid); diff --git a/packages/functions/test-tangle/base-token-trading/base-token-trading_14.spec.ts b/packages/functions/test-tangle/base-token-trading/base-token-trading_14.spec.ts index 88bf95b2e6..8c1ed2cc0d 100644 --- a/packages/functions/test-tangle/base-token-trading/base-token-trading_14.spec.ts +++ b/packages/functions/test-tangle/base-token-trading/base-token-trading_14.spec.ts @@ -1,18 +1,17 @@ -import { build5Db } from '@build-5/database'; +import { PgTokenTradeOrderType, build5Db } from '@build-5/database'; import { COL, MAX_TOTAL_TOKEN_SUPPLY, MIN_IOTA_AMOUNT, Network, TangleRequestType, - TokenTradeOrder, TokenTradeOrderStatus, TokenTradeOrderType, Transaction, + WEN_FUNC, } from '@build-5/interfaces'; -import { tradeToken } from '../../src/runtime/firebase/token/trading'; -import { mockWalletReturnValue, wait } from '../../test/controls/common'; -import { testEnv } from '../../test/set-up'; +import { wait } from '../../test/controls/common'; +import { mockWalletReturnValue, testEnv } from '../../test/set-up'; import { getTangleOrder } from '../common'; import { requestFundsFromFaucet } from '../faucet'; import { Helper } from './Helper'; @@ -26,26 +25,26 @@ describe('Base token trading', () => { }); it('Should create market buy with tangle request, settle it, no balance', async () => { - mockWalletReturnValue(helper.walletSpy, helper.seller!.uid, { + mockWalletReturnValue(helper.seller!.uid, { symbol: helper.token!.symbol, count: MIN_IOTA_AMOUNT, price: 2, type: TokenTradeOrderType.SELL, }); - let sellOrder = await testEnv.wrap(tradeToken)({}); + let sellOrder = await testEnv.wrap(WEN_FUNC.tradeToken); await requestFundsFromFaucet( helper.sourceNetwork, sellOrder.payload.targetAddress, MIN_IOTA_AMOUNT, ); - mockWalletReturnValue(helper.walletSpy, helper.seller!.uid, { + mockWalletReturnValue(helper.seller!.uid, { symbol: helper.token!.symbol, count: MIN_IOTA_AMOUNT, price: 4, type: TokenTradeOrderType.SELL, }); - sellOrder = await testEnv.wrap(tradeToken)({}); + sellOrder = await testEnv.wrap(WEN_FUNC.tradeToken); await requestFundsFromFaucet( helper.sourceNetwork, sellOrder.payload.targetAddress, @@ -72,10 +71,10 @@ describe('Base token trading', () => { const query = build5Db().collection(COL.TOKEN_MARKET).where('owner', '==', helper.buyer!.uid); await wait(async () => { - const snap = await query.get(); + const snap = await query.get(); return snap.length === 1 && snap[0].status === TokenTradeOrderStatus.SETTLED; }); - const buyOrder = (await query.get())[0]; + const buyOrder = (await query.get())[0]; expect(buyOrder.count).toBe(MAX_TOTAL_TOKEN_SUPPLY); expect(buyOrder.fulfilled).toBe(1.5 * MIN_IOTA_AMOUNT); @@ -84,8 +83,8 @@ describe('Base token trading', () => { const sellOrders = await build5Db() .collection(COL.TOKEN_MARKET) .where('owner', '==', helper.seller?.uid) - .where('type', '==', TokenTradeOrderType.SELL) - .get(); + .where('type', '==', PgTokenTradeOrderType.SELL) + .get(); sellOrders.sort((a, b) => a.price - b.price); expect(sellOrders[0].price).toBe(2); diff --git a/packages/functions/test-tangle/base-token-trading/base-token-trading_15.spec.ts b/packages/functions/test-tangle/base-token-trading/base-token-trading_15.spec.ts index 6620f12d3c..b7911059db 100644 --- a/packages/functions/test-tangle/base-token-trading/base-token-trading_15.spec.ts +++ b/packages/functions/test-tangle/base-token-trading/base-token-trading_15.spec.ts @@ -1,17 +1,16 @@ -import { build5Db } from '@build-5/database'; +import { PgTokenTradeOrderType, build5Db } from '@build-5/database'; import { COL, MAX_TOTAL_TOKEN_SUPPLY, MIN_IOTA_AMOUNT, Network, TangleRequestType, - TokenTradeOrder, TokenTradeOrderType, Transaction, + WEN_FUNC, } from '@build-5/interfaces'; -import { tradeToken } from '../../src/runtime/firebase/token/trading'; -import { mockWalletReturnValue, wait } from '../../test/controls/common'; -import { testEnv } from '../../test/set-up'; +import { wait } from '../../test/controls/common'; +import { mockWalletReturnValue, testEnv } from '../../test/set-up'; import { getTangleOrder } from '../common'; import { requestFundsFromFaucet } from '../faucet'; import { Helper } from './Helper'; @@ -25,26 +24,26 @@ describe('Base token trading', () => { }); it('Should create market buy with tangle request,do not settle it', async () => { - mockWalletReturnValue(helper.walletSpy, helper.seller!.uid, { + mockWalletReturnValue(helper.seller!.uid, { symbol: helper.token!.symbol, count: MIN_IOTA_AMOUNT, price: 2, type: TokenTradeOrderType.SELL, }); - let sellOrder = await testEnv.wrap(tradeToken)({}); + let sellOrder = await testEnv.wrap(WEN_FUNC.tradeToken); await requestFundsFromFaucet( helper.sourceNetwork, sellOrder.payload.targetAddress, MIN_IOTA_AMOUNT, ); - mockWalletReturnValue(helper.walletSpy, helper.seller!.uid, { + mockWalletReturnValue(helper.seller!.uid, { symbol: helper.token!.symbol, count: MIN_IOTA_AMOUNT, price: 4, type: TokenTradeOrderType.SELL, }); - sellOrder = await testEnv.wrap(tradeToken)({}); + sellOrder = await testEnv.wrap(WEN_FUNC.tradeToken); await requestFundsFromFaucet( helper.sourceNetwork, sellOrder.payload.targetAddress, @@ -71,10 +70,10 @@ describe('Base token trading', () => { const query = build5Db().collection(COL.TOKEN_MARKET).where('owner', '==', helper.buyer!.uid); await wait(async () => { - const snap = await query.get(); + const snap = await query.get(); return snap.length === 1 && snap[0].fulfilled === 2 * MIN_IOTA_AMOUNT; }); - const buyOrder = (await query.get())[0]; + const buyOrder = (await query.get())[0]; expect(buyOrder.count).toBe(MAX_TOTAL_TOKEN_SUPPLY); expect(buyOrder.fulfilled).toBe(2 * MIN_IOTA_AMOUNT); @@ -83,8 +82,8 @@ describe('Base token trading', () => { const sellOrders = await build5Db() .collection(COL.TOKEN_MARKET) .where('owner', '==', helper.seller?.uid) - .where('type', '==', TokenTradeOrderType.SELL) - .get(); + .where('type', '==', PgTokenTradeOrderType.SELL) + .get(); sellOrders.sort((a, b) => a.price - b.price); expect(sellOrders[0].price).toBe(2); diff --git a/packages/functions/test-tangle/base-token-trading/base-token-trading_16.spec.ts b/packages/functions/test-tangle/base-token-trading/base-token-trading_16.spec.ts index 8a98260181..4320440a3f 100644 --- a/packages/functions/test-tangle/base-token-trading/base-token-trading_16.spec.ts +++ b/packages/functions/test-tangle/base-token-trading/base-token-trading_16.spec.ts @@ -5,14 +5,13 @@ import { MIN_PRICE_PER_TOKEN, Network, TangleRequestType, - TokenTradeOrder, TokenTradeOrderStatus, TokenTradeOrderType, Transaction, + WEN_FUNC, } from '@build-5/interfaces'; -import { tradeToken } from '../../src/runtime/firebase/token/trading'; -import { mockWalletReturnValue, wait } from '../../test/controls/common'; -import { testEnv } from '../../test/set-up'; +import { wait } from '../../test/controls/common'; +import { mockWalletReturnValue, testEnv } from '../../test/set-up'; import { getTangleOrder } from '../common'; import { requestFundsFromFaucet } from '../faucet'; import { Helper } from './Helper'; @@ -26,26 +25,26 @@ describe('Base token trading', () => { }); it('Should create market sell with tangle request, settle it', async () => { - mockWalletReturnValue(helper.walletSpy, helper.buyer!.uid, { + mockWalletReturnValue(helper.buyer!.uid, { symbol: helper.token!.symbol, count: 2 * MIN_IOTA_AMOUNT, price: 1, type: TokenTradeOrderType.BUY, }); - let buyOrder = await testEnv.wrap(tradeToken)({}); + let buyOrder = await testEnv.wrap(WEN_FUNC.tradeToken); await requestFundsFromFaucet( helper.sourceNetwork, buyOrder.payload.targetAddress, buyOrder.payload.amount, ); - mockWalletReturnValue(helper.walletSpy, helper.buyer!.uid, { + mockWalletReturnValue(helper.buyer!.uid, { symbol: helper.token!.symbol, count: 4 * MIN_IOTA_AMOUNT, price: 2, type: TokenTradeOrderType.BUY, }); - buyOrder = await testEnv.wrap(tradeToken)({}); + buyOrder = await testEnv.wrap(WEN_FUNC.tradeToken); await requestFundsFromFaucet( helper.sourceNetwork, buyOrder.payload.targetAddress, @@ -72,10 +71,10 @@ describe('Base token trading', () => { const query = build5Db().collection(COL.TOKEN_MARKET).where('owner', '==', helper.seller!.uid); await wait(async () => { - const snap = await query.get(); + const snap = await query.get(); return snap.length === 1 && snap[0].status === TokenTradeOrderStatus.SETTLED; }); - const sellOrder = (await query.get())[0]; + const sellOrder = (await query.get())[0]; expect(sellOrder.count).toBe(5 * MIN_IOTA_AMOUNT); expect(sellOrder.fulfilled).toBe(5 * MIN_IOTA_AMOUNT); @@ -85,7 +84,7 @@ describe('Base token trading', () => { const buyOrders = await build5Db() .collection(COL.TOKEN_MARKET) .where('owner', '==', helper.buyer?.uid) - .get(); + .get(); buyOrders.sort((a, b) => b.price - a.price); expect(buyOrders[0].price).toBe(2); diff --git a/packages/functions/test-tangle/base-token-trading/base-token-trading_17.spec.ts b/packages/functions/test-tangle/base-token-trading/base-token-trading_17.spec.ts index 70404f2cf5..ff31694aed 100644 --- a/packages/functions/test-tangle/base-token-trading/base-token-trading_17.spec.ts +++ b/packages/functions/test-tangle/base-token-trading/base-token-trading_17.spec.ts @@ -4,13 +4,12 @@ import { MIN_IOTA_AMOUNT, Network, TangleRequestType, - TokenTradeOrder, TokenTradeOrderType, Transaction, + WEN_FUNC, } from '@build-5/interfaces'; -import { tradeToken } from '../../src/runtime/firebase/token/trading'; -import { mockWalletReturnValue, wait } from '../../test/controls/common'; -import { testEnv } from '../../test/set-up'; +import { wait } from '../../test/controls/common'; +import { mockWalletReturnValue, testEnv } from '../../test/set-up'; import { getTangleOrder } from '../common'; import { requestFundsFromFaucet } from '../faucet'; import { Helper } from './Helper'; @@ -24,26 +23,26 @@ describe('Base token trading', () => { }); it('Should create market sell with tangle request, do not settle it', async () => { - mockWalletReturnValue(helper.walletSpy, helper.buyer!.uid, { + mockWalletReturnValue(helper.buyer!.uid, { symbol: helper.token!.symbol, count: 2 * MIN_IOTA_AMOUNT, price: 1, type: TokenTradeOrderType.BUY, }); - let buyOrder = await testEnv.wrap(tradeToken)({}); + let buyOrder = await testEnv.wrap(WEN_FUNC.tradeToken); await requestFundsFromFaucet( helper.sourceNetwork, buyOrder.payload.targetAddress, buyOrder.payload.amount, ); - mockWalletReturnValue(helper.walletSpy, helper.buyer!.uid, { + mockWalletReturnValue(helper.buyer!.uid, { symbol: helper.token!.symbol, count: 4 * MIN_IOTA_AMOUNT, price: 2, type: TokenTradeOrderType.BUY, }); - buyOrder = await testEnv.wrap(tradeToken)({}); + buyOrder = await testEnv.wrap(WEN_FUNC.tradeToken); await requestFundsFromFaucet( helper.sourceNetwork, buyOrder.payload.targetAddress, @@ -70,10 +69,10 @@ describe('Base token trading', () => { const query = build5Db().collection(COL.TOKEN_MARKET).where('owner', '==', helper.seller!.uid); await wait(async () => { - const snap = await query.get(); + const snap = await query.get(); return snap.length === 1 && snap[0].fulfilled === 6 * MIN_IOTA_AMOUNT; }); - const sellOrder = (await query.get())[0]; + const sellOrder = (await query.get())[0]; expect(sellOrder.count).toBe(7 * MIN_IOTA_AMOUNT); expect(sellOrder.fulfilled).toBe(6 * MIN_IOTA_AMOUNT); @@ -82,7 +81,7 @@ describe('Base token trading', () => { const buyOrders = await build5Db() .collection(COL.TOKEN_MARKET) .where('owner', '==', helper.buyer?.uid) - .get(); + .get(); buyOrders.sort((a, b) => b.price - a.price); expect(buyOrders[0].price).toBe(2); diff --git a/packages/functions/test-tangle/base-token-trading/base-token-trading_18.spec.ts b/packages/functions/test-tangle/base-token-trading/base-token-trading_18.spec.ts index 2bbe3a1ff6..0b56336eda 100644 --- a/packages/functions/test-tangle/base-token-trading/base-token-trading_18.spec.ts +++ b/packages/functions/test-tangle/base-token-trading/base-token-trading_18.spec.ts @@ -1,11 +1,5 @@ import { build5Db } from '@build-5/database'; -import { - COL, - MIN_IOTA_AMOUNT, - Network, - TangleRequestType, - TokenTradeOrder, -} from '@build-5/interfaces'; +import { COL, MIN_IOTA_AMOUNT, Network, TangleRequestType } from '@build-5/interfaces'; import { wait } from '../../test/controls/common'; import { getTangleOrder } from '../common'; import { requestFundsFromFaucet } from '../faucet'; @@ -34,7 +28,7 @@ describe('Base token trading', () => { const snap = await query.get(); return snap.length === 1; }); - const order = (await query.get())[0]; + const order = (await query.get())[0]; expect(order.sourceNetwork).toBe(Network.RMS); expect(order.targetNetwork).toBe(Network.ATOI); }); diff --git a/packages/functions/test-tangle/base-token-trading/base-token-trading_19.spec.ts b/packages/functions/test-tangle/base-token-trading/base-token-trading_19.spec.ts index d672b37e96..c4d4a60f88 100644 --- a/packages/functions/test-tangle/base-token-trading/base-token-trading_19.spec.ts +++ b/packages/functions/test-tangle/base-token-trading/base-token-trading_19.spec.ts @@ -1,11 +1,5 @@ import { build5Db } from '@build-5/database'; -import { - COL, - MIN_IOTA_AMOUNT, - Network, - TangleRequestType, - TokenTradeOrder, -} from '@build-5/interfaces'; +import { COL, MIN_IOTA_AMOUNT, Network, TangleRequestType } from '@build-5/interfaces'; import { wait } from '../../test/controls/common'; import { getTangleOrder } from '../common'; import { requestFundsFromFaucet } from '../faucet'; @@ -36,7 +30,7 @@ describe('Base token trading', () => { const snap = await query.get(); return snap.length === 1; }); - const order = (await query.get())[0]; + const order = (await query.get())[0]; expect(order.sourceNetwork).toBe(Network.ATOI); expect(order.targetNetwork).toBe(Network.RMS); }); diff --git a/packages/functions/test-tangle/base-token-trading/base-token-trading_2.spec.ts b/packages/functions/test-tangle/base-token-trading/base-token-trading_2.spec.ts index 386db4cd0f..bee5c71230 100644 --- a/packages/functions/test-tangle/base-token-trading/base-token-trading_2.spec.ts +++ b/packages/functions/test-tangle/base-token-trading/base-token-trading_2.spec.ts @@ -1,4 +1,4 @@ -import { build5Db } from '@build-5/database'; +import { PgTransactionType, build5Db } from '@build-5/database'; import { COL, MIN_IOTA_AMOUNT, @@ -6,13 +6,12 @@ import { TokenTradeOrder, TokenTradeOrderType, Transaction, - TransactionType, + WEN_FUNC, } from '@build-5/interfaces'; import { isEmpty } from 'lodash'; -import { tradeToken } from '../../src/runtime/firebase/token/trading'; import { getAddress } from '../../src/utils/address.utils'; -import { mockWalletReturnValue, wait } from '../../test/controls/common'; -import { getWallet, testEnv } from '../../test/set-up'; +import { wait } from '../../test/controls/common'; +import { getWallet, mockWalletReturnValue, testEnv } from '../../test/set-up'; import { awaitTransactionConfirmationsForToken } from '../common'; import { requestFundsFromFaucet } from '../faucet'; import { Helper } from './Helper'; @@ -25,13 +24,13 @@ describe('Base token trading', () => { }); it('Should fulfil trade with half price', async () => { - mockWalletReturnValue(helper.walletSpy, helper.seller!.uid, { + mockWalletReturnValue(helper.seller!.uid, { symbol: helper.token!.symbol, count: MIN_IOTA_AMOUNT, price: 1, type: TokenTradeOrderType.SELL, }); - const sellOrder = await testEnv.wrap(tradeToken)({}); + const sellOrder = await testEnv.wrap(WEN_FUNC.tradeToken); await requestFundsFromFaucet( helper.sourceNetwork, sellOrder.payload.targetAddress, @@ -46,13 +45,13 @@ describe('Base token trading', () => { return snap.length !== 0; }); - mockWalletReturnValue(helper.walletSpy, helper.buyer!.uid, { + mockWalletReturnValue(helper.buyer!.uid, { symbol: helper.token!.symbol, count: MIN_IOTA_AMOUNT, price: 2, type: TokenTradeOrderType.BUY, }); - const buyOrder = await testEnv.wrap(tradeToken)({}); + const buyOrder = await testEnv.wrap(WEN_FUNC.tradeToken); await requestFundsFromFaucet( helper.targetNetwork, buyOrder.payload.targetAddress, @@ -88,7 +87,7 @@ describe('Base token trading', () => { const sellerBillPaymentsSnap = await build5Db() .collection(COL.TRANSACTION) .where('member', '==', helper.seller!.uid) - .where('type', '==', TransactionType.BILL_PAYMENT) + .where('type', '==', PgTransactionType.BILL_PAYMENT) .get(); const sellerBillPayments = sellerBillPaymentsSnap.map((d) => d as Transaction); expect( @@ -109,7 +108,7 @@ describe('Base token trading', () => { const sellerCreditnap = await build5Db() .collection(COL.TRANSACTION) .where('member', '==', helper.seller!.uid) - .where('type', '==', TransactionType.CREDIT) + .where('type', '==', PgTransactionType.CREDIT) .get(); const sellerCredit = sellerCreditnap.map((d) => d as Transaction); expect(sellerCredit.length).toBe(0); @@ -117,7 +116,7 @@ describe('Base token trading', () => { const buyerBillPaymentsSnap = await build5Db() .collection(COL.TRANSACTION) .where('member', '==', helper.buyer!.uid) - .where('type', '==', TransactionType.BILL_PAYMENT) + .where('type', '==', PgTransactionType.BILL_PAYMENT) .get(); const buyerBillPayments = buyerBillPaymentsSnap.map((d) => d as Transaction); expect(buyerBillPayments.length).toBe(3); @@ -155,8 +154,8 @@ describe('Base token trading', () => { const buyerCreditnap = await build5Db() .collection(COL.TRANSACTION) .where('member', '==', helper.buyer!.uid) - .where('type', '==', TransactionType.CREDIT) - .get(); + .where('type', '==', PgTransactionType.CREDIT) + .get(); expect(buyerCreditnap.length).toBe(1); expect(buyerCreditnap[0]?.payload.amount).toBe(MIN_IOTA_AMOUNT); buy = (await buyQuery.get())[0]; diff --git a/packages/functions/test-tangle/base-token-trading/base-token-trading_3.spec.ts b/packages/functions/test-tangle/base-token-trading/base-token-trading_3.spec.ts index 3f7d2f7ef1..caebb17fe3 100644 --- a/packages/functions/test-tangle/base-token-trading/base-token-trading_3.spec.ts +++ b/packages/functions/test-tangle/base-token-trading/base-token-trading_3.spec.ts @@ -1,15 +1,14 @@ -import { build5Db } from '@build-5/database'; +import { PgTransactionType, build5Db } from '@build-5/database'; import { COL, MIN_IOTA_AMOUNT, TokenTradeOrder, TokenTradeOrderType, Transaction, - TransactionType, + WEN_FUNC, } from '@build-5/interfaces'; -import { tradeToken } from '../../src/runtime/firebase/token/trading'; -import { mockWalletReturnValue, wait } from '../../test/controls/common'; -import { testEnv } from '../../test/set-up'; +import { wait } from '../../test/controls/common'; +import { mockWalletReturnValue, testEnv } from '../../test/set-up'; import { awaitTransactionConfirmationsForToken } from '../common'; import { requestFundsFromFaucet } from '../faucet'; import { Helper } from './Helper'; @@ -22,39 +21,39 @@ describe('Base token trading', () => { }); it('Should fulfill sell with two buys', async () => { - mockWalletReturnValue(helper.walletSpy, helper.seller!.uid, { + mockWalletReturnValue(helper.seller!.uid, { symbol: helper.token!.symbol, count: 2 * MIN_IOTA_AMOUNT, price: 1, type: TokenTradeOrderType.SELL, }); - const sellOrder = await testEnv.wrap(tradeToken)({}); + const sellOrder = await testEnv.wrap(WEN_FUNC.tradeToken); await requestFundsFromFaucet( helper.sourceNetwork, sellOrder.payload.targetAddress, 2 * MIN_IOTA_AMOUNT, ); - mockWalletReturnValue(helper.walletSpy, helper.buyer!.uid, { + mockWalletReturnValue(helper.buyer!.uid, { symbol: helper.token!.symbol, count: MIN_IOTA_AMOUNT, price: 1, type: TokenTradeOrderType.BUY, }); - const buyOrder = await testEnv.wrap(tradeToken)({}); + const buyOrder = await testEnv.wrap(WEN_FUNC.tradeToken); await requestFundsFromFaucet( helper.targetNetwork, buyOrder.payload.targetAddress, MIN_IOTA_AMOUNT, ); - mockWalletReturnValue(helper.walletSpy, helper.buyer!.uid, { + mockWalletReturnValue(helper.buyer!.uid, { symbol: helper.token!.symbol, count: MIN_IOTA_AMOUNT, price: 1, type: TokenTradeOrderType.BUY, }); - const buyOrder2 = await testEnv.wrap(tradeToken)({}); + const buyOrder2 = await testEnv.wrap(WEN_FUNC.tradeToken); await requestFundsFromFaucet( helper.targetNetwork, buyOrder2.payload.targetAddress, @@ -87,21 +86,21 @@ describe('Base token trading', () => { const sellerBillPaymentsSnap = await build5Db() .collection(COL.TRANSACTION) .where('member', '==', helper.seller!.uid) - .where('type', '==', TransactionType.BILL_PAYMENT) + .where('type', '==', PgTransactionType.BILL_PAYMENT) .get(); const sellerBillPayments = sellerBillPaymentsSnap.map((d) => d as Transaction); expect(sellerBillPayments.filter((p) => p.payload.amount === MIN_IOTA_AMOUNT).length).toBe(2); const sellerCreditnap = await build5Db() .collection(COL.TRANSACTION) .where('member', '==', helper.seller!.uid) - .where('type', '==', TransactionType.CREDIT) + .where('type', '==', PgTransactionType.CREDIT) .get(); expect(sellerCreditnap.length).toBe(0); const buyerBillPaymentsSnap = await build5Db() .collection(COL.TRANSACTION) .where('member', '==', helper.buyer!.uid) - .where('type', '==', TransactionType.BILL_PAYMENT) + .where('type', '==', PgTransactionType.BILL_PAYMENT) .get(); const buyerBillPayments = buyerBillPaymentsSnap.map((d) => d as Transaction); expect(buyerBillPayments.length).toBe(6); @@ -119,7 +118,7 @@ describe('Base token trading', () => { const buyerCreditnap = await build5Db() .collection(COL.TRANSACTION) .where('member', '==', helper.buyer!.uid) - .where('type', '==', TransactionType.CREDIT) + .where('type', '==', PgTransactionType.CREDIT) .get(); expect(buyerCreditnap.length).toBe(0); diff --git a/packages/functions/test-tangle/base-token-trading/base-token-trading_4.spec.ts b/packages/functions/test-tangle/base-token-trading/base-token-trading_4.spec.ts index cda71e4e7f..f46697b1c5 100644 --- a/packages/functions/test-tangle/base-token-trading/base-token-trading_4.spec.ts +++ b/packages/functions/test-tangle/base-token-trading/base-token-trading_4.spec.ts @@ -1,15 +1,14 @@ -import { build5Db } from '@build-5/database'; +import { PgTransactionType, build5Db } from '@build-5/database'; import { COL, MIN_IOTA_AMOUNT, TokenTradeOrder, TokenTradeOrderType, Transaction, - TransactionType, + WEN_FUNC, } from '@build-5/interfaces'; -import { tradeToken } from '../../src/runtime/firebase/token/trading'; -import { mockWalletReturnValue, wait } from '../../test/controls/common'; -import { testEnv } from '../../test/set-up'; +import { wait } from '../../test/controls/common'; +import { mockWalletReturnValue, testEnv } from '../../test/set-up'; import { awaitTransactionConfirmationsForToken } from '../common'; import { requestFundsFromFaucet } from '../faucet'; import { Helper } from './Helper'; @@ -22,39 +21,39 @@ describe('Base token trading', () => { }); it('Should fulfill buy with two sells', async () => { - mockWalletReturnValue(helper.walletSpy, helper.seller!.uid, { + mockWalletReturnValue(helper.seller!.uid, { symbol: helper.token!.symbol, count: MIN_IOTA_AMOUNT, price: 1, type: TokenTradeOrderType.SELL, }); - const sellOrder = await testEnv.wrap(tradeToken)({}); + const sellOrder = await testEnv.wrap(WEN_FUNC.tradeToken); await requestFundsFromFaucet( helper.sourceNetwork, sellOrder.payload.targetAddress, MIN_IOTA_AMOUNT, ); - mockWalletReturnValue(helper.walletSpy, helper.seller!.uid, { + mockWalletReturnValue(helper.seller!.uid, { symbol: helper.token!.symbol, count: MIN_IOTA_AMOUNT, price: 1, type: TokenTradeOrderType.SELL, }); - const sellOrder2 = await testEnv.wrap(tradeToken)({}); + const sellOrder2 = await testEnv.wrap(WEN_FUNC.tradeToken); await requestFundsFromFaucet( helper.sourceNetwork, sellOrder2.payload.targetAddress, MIN_IOTA_AMOUNT, ); - mockWalletReturnValue(helper.walletSpy, helper.buyer!.uid, { + mockWalletReturnValue(helper.buyer!.uid, { symbol: helper.token!.symbol, count: 2 * MIN_IOTA_AMOUNT, price: 1, type: TokenTradeOrderType.BUY, }); - const buyOrder = await testEnv.wrap(tradeToken)({}); + const buyOrder = await testEnv.wrap(WEN_FUNC.tradeToken); await requestFundsFromFaucet( helper.targetNetwork, buyOrder.payload.targetAddress, @@ -87,21 +86,21 @@ describe('Base token trading', () => { const sellerBillPaymentsSnap = await build5Db() .collection(COL.TRANSACTION) .where('member', '==', helper.seller!.uid) - .where('type', '==', TransactionType.BILL_PAYMENT) + .where('type', '==', PgTransactionType.BILL_PAYMENT) .get(); const sellerBillPayments = sellerBillPaymentsSnap.map((d) => d as Transaction); expect(sellerBillPayments.filter((p) => p.payload.amount === MIN_IOTA_AMOUNT).length).toBe(2); const sellerCreditnap = await build5Db() .collection(COL.TRANSACTION) .where('member', '==', helper.seller!.uid) - .where('type', '==', TransactionType.CREDIT) + .where('type', '==', PgTransactionType.CREDIT) .get(); expect(sellerCreditnap.length).toBe(0); const buyerBillPaymentsSnap = await build5Db() .collection(COL.TRANSACTION) .where('member', '==', helper.buyer!.uid) - .where('type', '==', TransactionType.BILL_PAYMENT) + .where('type', '==', PgTransactionType.BILL_PAYMENT) .get(); const buyerBillPayments = buyerBillPaymentsSnap.map((d) => d as Transaction); expect(buyerBillPayments.length).toBe(6); @@ -119,7 +118,7 @@ describe('Base token trading', () => { const buyerCreditnap = await build5Db() .collection(COL.TRANSACTION) .where('member', '==', helper.buyer!.uid) - .where('type', '==', TransactionType.CREDIT) + .where('type', '==', PgTransactionType.CREDIT) .get(); expect(buyerCreditnap.length).toBe(0); diff --git a/packages/functions/test-tangle/base-token-trading/base-token-trading_5.spec.ts b/packages/functions/test-tangle/base-token-trading/base-token-trading_5.spec.ts index 9a7e87626b..5940d0573b 100644 --- a/packages/functions/test-tangle/base-token-trading/base-token-trading_5.spec.ts +++ b/packages/functions/test-tangle/base-token-trading/base-token-trading_5.spec.ts @@ -1,8 +1,14 @@ import { build5Db } from '@build-5/database'; -import { COL, MIN_IOTA_AMOUNT, TokenPurchase, TokenTradeOrderType } from '@build-5/interfaces'; -import { tradeToken } from '../../src/runtime/firebase/token/trading'; -import { mockWalletReturnValue, wait } from '../../test/controls/common'; -import { testEnv } from '../../test/set-up'; +import { + COL, + MIN_IOTA_AMOUNT, + TokenPurchase, + TokenTradeOrderType, + Transaction, + WEN_FUNC, +} from '@build-5/interfaces'; +import { wait } from '../../test/controls/common'; +import { mockWalletReturnValue, testEnv } from '../../test/set-up'; import { awaitTransactionConfirmationsForToken } from '../common'; import { requestFundsFromFaucet } from '../faucet'; import { Helper } from './Helper'; @@ -15,26 +21,26 @@ describe('Base token trading', () => { }); it('Should fulfill buy with lowest sell', async () => { - mockWalletReturnValue(helper.walletSpy, helper.seller!.uid, { + mockWalletReturnValue(helper.seller!.uid, { symbol: helper.token!.symbol, count: MIN_IOTA_AMOUNT, price: 2, type: TokenTradeOrderType.SELL, }); - const sellOrder = await testEnv.wrap(tradeToken)({}); + const sellOrder = await testEnv.wrap(WEN_FUNC.tradeToken); await requestFundsFromFaucet( helper.sourceNetwork, sellOrder.payload.targetAddress, sellOrder.payload.amount, ); - mockWalletReturnValue(helper.walletSpy, helper.seller!.uid, { + mockWalletReturnValue(helper.seller!.uid, { symbol: helper.token!.symbol, count: MIN_IOTA_AMOUNT, price: 1, type: TokenTradeOrderType.SELL, }); - const sellOrder2 = await testEnv.wrap(tradeToken)({}); + const sellOrder2 = await testEnv.wrap(WEN_FUNC.tradeToken); await requestFundsFromFaucet( helper.sourceNetwork, sellOrder2.payload.targetAddress, @@ -49,13 +55,13 @@ describe('Base token trading', () => { return snap.length === 2; }); - mockWalletReturnValue(helper.walletSpy, helper.buyer!.uid, { + mockWalletReturnValue(helper.buyer!.uid, { symbol: helper.token!.symbol, count: MIN_IOTA_AMOUNT, price: 2, type: TokenTradeOrderType.BUY, }); - const buyOrder = await testEnv.wrap(tradeToken)({}); + const buyOrder = await testEnv.wrap(WEN_FUNC.tradeToken); await requestFundsFromFaucet( helper.targetNetwork, buyOrder.payload.targetAddress, diff --git a/packages/functions/test-tangle/base-token-trading/base-token-trading_6.spec.ts b/packages/functions/test-tangle/base-token-trading/base-token-trading_6.spec.ts index 89f5d5904e..8430de9411 100644 --- a/packages/functions/test-tangle/base-token-trading/base-token-trading_6.spec.ts +++ b/packages/functions/test-tangle/base-token-trading/base-token-trading_6.spec.ts @@ -1,8 +1,14 @@ import { build5Db } from '@build-5/database'; -import { COL, MIN_IOTA_AMOUNT, TokenPurchase, TokenTradeOrderType } from '@build-5/interfaces'; -import { tradeToken } from '../../src/runtime/firebase/token/trading'; -import { mockWalletReturnValue, wait } from '../../test/controls/common'; -import { testEnv } from '../../test/set-up'; +import { + COL, + MIN_IOTA_AMOUNT, + TokenPurchase, + TokenTradeOrderType, + Transaction, + WEN_FUNC, +} from '@build-5/interfaces'; +import { wait } from '../../test/controls/common'; +import { mockWalletReturnValue, testEnv } from '../../test/set-up'; import { awaitTransactionConfirmationsForToken } from '../common'; import { requestFundsFromFaucet } from '../faucet'; import { Helper } from './Helper'; @@ -15,26 +21,26 @@ describe('Base token trading', () => { }); it('Should fulfill sell with highest buy', async () => { - mockWalletReturnValue(helper.walletSpy, helper.buyer!.uid, { + mockWalletReturnValue(helper.buyer!.uid, { symbol: helper.token!.symbol, count: MIN_IOTA_AMOUNT, price: 1, type: TokenTradeOrderType.BUY, }); - const buyOrder = await testEnv.wrap(tradeToken)({}); + const buyOrder = await testEnv.wrap(WEN_FUNC.tradeToken); await requestFundsFromFaucet( helper.targetNetwork, buyOrder.payload.targetAddress, buyOrder.payload.amount, ); - mockWalletReturnValue(helper.walletSpy, helper.buyer!.uid, { + mockWalletReturnValue(helper.buyer!.uid, { symbol: helper.token!.symbol, count: MIN_IOTA_AMOUNT, price: 2, type: TokenTradeOrderType.BUY, }); - const buyOrder2 = await testEnv.wrap(tradeToken)({}); + const buyOrder2 = await testEnv.wrap(WEN_FUNC.tradeToken); await requestFundsFromFaucet( helper.targetNetwork, buyOrder2.payload.targetAddress, @@ -49,13 +55,13 @@ describe('Base token trading', () => { return snap.length === 2; }); - mockWalletReturnValue(helper.walletSpy, helper.seller!.uid, { + mockWalletReturnValue(helper.seller!.uid, { symbol: helper.token!.symbol, count: MIN_IOTA_AMOUNT, price: 1, type: TokenTradeOrderType.SELL, }); - const sellOrder = await testEnv.wrap(tradeToken)({}); + const sellOrder = await testEnv.wrap(WEN_FUNC.tradeToken); await requestFundsFromFaucet( helper.sourceNetwork, sellOrder.payload.targetAddress, diff --git a/packages/functions/test-tangle/base-token-trading/base-token-trading_7.spec.ts b/packages/functions/test-tangle/base-token-trading/base-token-trading_7.spec.ts index 0dc2d0c2fb..d4206c89a1 100644 --- a/packages/functions/test-tangle/base-token-trading/base-token-trading_7.spec.ts +++ b/packages/functions/test-tangle/base-token-trading/base-token-trading_7.spec.ts @@ -8,14 +8,13 @@ import { TokenTradeOrderStatus, TokenTradeOrderType, Transaction, + WEN_FUNC, } from '@build-5/interfaces'; import dayjs from 'dayjs'; import { cancelExpiredSale } from '../../src/cron/token.cron'; -import { tradeToken } from '../../src/runtime/firebase/token/trading'; import { getAddress } from '../../src/utils/address.utils'; -import { dateToTimestamp } from '../../src/utils/dateTime.utils'; -import { mockWalletReturnValue, wait } from '../../test/controls/common'; -import { testEnv } from '../../test/set-up'; +import { wait } from '../../test/controls/common'; +import { mockWalletReturnValue, testEnv } from '../../test/set-up'; import { requestFundsFromFaucet } from '../faucet'; import { Helper } from './Helper'; @@ -32,13 +31,13 @@ describe('Base token trading', () => { const network = type === TokenTradeOrderType.SELL ? Network.ATOI : Network.RMS; const member = type === TokenTradeOrderType.SELL ? helper.seller! : helper.buyer!; - mockWalletReturnValue(helper.walletSpy, member.uid, { + mockWalletReturnValue(member.uid, { symbol: helper.token!.symbol, count: MIN_IOTA_AMOUNT, price: 1, type, }); - const tradeOrder = await testEnv.wrap(tradeToken)({}); + const tradeOrder = await testEnv.wrap(WEN_FUNC.tradeToken); await requestFundsFromFaucet( network, tradeOrder.payload.targetAddress, @@ -54,15 +53,15 @@ describe('Base token trading', () => { }); let trade = (await tradeQuery.get())[0]; await build5Db() - .doc(`${COL.TOKEN_MARKET}/${trade.uid}`) - .update({ expiresAt: dateToTimestamp(dayjs().subtract(1, 'd')) }); + .doc(COL.TOKEN_MARKET, trade.uid) + .update({ expiresAt: dayjs().subtract(1, 'd').toDate() }); await cancelExpiredSale(); trade = (await tradeQuery.get())[0]; expect(trade.status).toBe(TokenTradeOrderStatus.EXPIRED); - const creditDocRef = build5Db().doc(`${COL.TRANSACTION}/${trade.creditTransactionId}`); + const creditDocRef = build5Db().doc(COL.TRANSACTION, trade.creditTransactionId!); await wait(async () => { const credit = await creditDocRef.get(); return credit.payload?.walletReference?.confirmed; diff --git a/packages/functions/test-tangle/base-token-trading/base-token-trading_8.spec.ts b/packages/functions/test-tangle/base-token-trading/base-token-trading_8.spec.ts index 143713df79..f126100e09 100644 --- a/packages/functions/test-tangle/base-token-trading/base-token-trading_8.spec.ts +++ b/packages/functions/test-tangle/base-token-trading/base-token-trading_8.spec.ts @@ -7,10 +7,10 @@ import { TokenTradeOrderStatus, TokenTradeOrderType, Transaction, + WEN_FUNC, } from '@build-5/interfaces'; -import { tradeToken } from '../../src/runtime/firebase/token/trading'; -import { mockWalletReturnValue, wait } from '../../test/controls/common'; -import { testEnv } from '../../test/set-up'; +import { wait } from '../../test/controls/common'; +import { mockWalletReturnValue, testEnv } from '../../test/set-up'; import { requestFundsForManyFromFaucet, requestFundsFromFaucet } from '../faucet'; import { Helper } from './Helper'; @@ -24,13 +24,15 @@ describe('Base token trading', () => { it('Should fulfill many sells with buy', async () => { const count = 15; - mockWalletReturnValue(helper.walletSpy, helper.seller!.uid, { + mockWalletReturnValue(helper.seller!.uid, { symbol: helper.token!.symbol, count: MIN_IOTA_AMOUNT, price: 1, type: TokenTradeOrderType.SELL, }); - const promises = Array.from(Array(count)).map(() => testEnv.wrap(tradeToken)({})); + const promises = Array.from(Array(count)).map(() => + testEnv.wrap(WEN_FUNC.tradeToken), + ); const orders: Transaction[] = await Promise.all(promises); await requestFundsForManyFromFaucet( @@ -46,13 +48,13 @@ describe('Base token trading', () => { return snap.length === count; }); - mockWalletReturnValue(helper.walletSpy, helper.buyer!.uid, { + mockWalletReturnValue(helper.buyer!.uid, { symbol: helper.token!.symbol, count: count * MIN_IOTA_AMOUNT, price: 1, type: TokenTradeOrderType.BUY, }); - const trade = await testEnv.wrap(tradeToken)({}); + const trade = await testEnv.wrap(WEN_FUNC.tradeToken); await requestFundsFromFaucet(Network.RMS, trade.payload.targetAddress, trade.payload.amount); await wait(async () => { diff --git a/packages/functions/test-tangle/base-token-trading/base-token-trading_9.spec.ts b/packages/functions/test-tangle/base-token-trading/base-token-trading_9.spec.ts index f7c0d9b5dd..dc8068eaed 100644 --- a/packages/functions/test-tangle/base-token-trading/base-token-trading_9.spec.ts +++ b/packages/functions/test-tangle/base-token-trading/base-token-trading_9.spec.ts @@ -7,10 +7,10 @@ import { TokenTradeOrderStatus, TokenTradeOrderType, Transaction, + WEN_FUNC, } from '@build-5/interfaces'; -import { tradeToken } from '../../src/runtime/firebase/token/trading'; -import { mockWalletReturnValue, wait } from '../../test/controls/common'; -import { testEnv } from '../../test/set-up'; +import { wait } from '../../test/controls/common'; +import { mockWalletReturnValue, testEnv } from '../../test/set-up'; import { requestFundsForManyFromFaucet, requestFundsFromFaucet } from '../faucet'; import { Helper } from './Helper'; @@ -24,13 +24,15 @@ describe('Base token trading', () => { it('Should fulfill many buys with sell', async () => { const count = 15; - mockWalletReturnValue(helper.walletSpy, helper.buyer!.uid, { + mockWalletReturnValue(helper.buyer!.uid, { symbol: helper.token!.symbol, count: MIN_IOTA_AMOUNT, price: 1, type: TokenTradeOrderType.BUY, }); - const promises = Array.from(Array(count)).map(() => testEnv.wrap(tradeToken)({})); + const promises = Array.from(Array(count)).map(() => + testEnv.wrap(WEN_FUNC.tradeToken), + ); const orders: Transaction[] = await Promise.all(promises); await requestFundsForManyFromFaucet( Network.RMS, @@ -45,13 +47,13 @@ describe('Base token trading', () => { return snap.length === count; }); - mockWalletReturnValue(helper.walletSpy, helper.seller!.uid, { + mockWalletReturnValue(helper.seller!.uid, { symbol: helper.token!.symbol, count: count * MIN_IOTA_AMOUNT, price: 1, type: TokenTradeOrderType.SELL, }); - const trade = await testEnv.wrap(tradeToken)({}); + const trade = await testEnv.wrap(WEN_FUNC.tradeToken); await requestFundsFromFaucet(Network.ATOI, trade.payload.targetAddress, trade.payload.amount); await wait(async () => { diff --git a/packages/functions/test-tangle/collection-minting/Helper.ts b/packages/functions/test-tangle/collection-minting/Helper.ts index d5ce76c913..ddb754662f 100644 --- a/packages/functions/test-tangle/collection-minting/Helper.ts +++ b/packages/functions/test-tangle/collection-minting/Helper.ts @@ -1,5 +1,5 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ -import { build5Db } from '@build-5/database'; +import { PgTransactionPayloadType, PgTransactionType, build5Db } from '@build-5/database'; import { Access, COL, @@ -14,59 +14,45 @@ import { NftStatus, Space, Transaction, - TransactionPayloadType, - TransactionType, UnsoldMintingOptions, + WEN_FUNC, } from '@build-5/interfaces'; import { FeatureType, MetadataFeature, NftOutput, hexToUtf8 } from '@iota/sdk'; import dayjs from 'dayjs'; import { set } from 'lodash'; -import { createCollection, mintCollection } from '../../src/runtime/firebase/collection/index'; -import { openBid } from '../../src/runtime/firebase/nft'; -import { createNft, orderNft, setForSaleNft } from '../../src/runtime/firebase/nft/index'; import { NftWallet } from '../../src/services/wallet/NftWallet'; import { Wallet } from '../../src/services/wallet/wallet'; -import * as wallet from '../../src/utils/wallet.utils'; import { getRandomEthAddress } from '../../src/utils/wallet.utils'; -import { - createMember as createMemberTest, - createSpace, - mockWalletReturnValue, - submitMilestoneFunc, - wait, -} from '../../test/controls/common'; -import { MEDIA, getWallet, testEnv } from '../../test/set-up'; +import { submitMilestoneFunc, wait } from '../../test/controls/common'; +import { MEDIA, getWallet, mockWalletReturnValue, testEnv } from '../../test/set-up'; import { requestFundsFromFaucet } from '../faucet'; export class CollectionMintHelper { - public walletSpy: any | undefined; - public network: Network = Network.RMS; - public collection: string | undefined; - public guardian: string | undefined; - public space: Space | undefined; - public royaltySpace: Space | undefined; - public member: string | undefined; - public walletService: Wallet | undefined; - public nftWallet: NftWallet | undefined; + public network = Network.RMS; + public collection = ''; + public guardian = ''; + public space: Space = {} as any; + public royaltySpace: Space = {} as any; + public member = ''; + public walletService: Wallet = {} as any; + public nftWallet: NftWallet = {} as any; public beforeAll = async () => { - this.walletSpy = jest.spyOn(wallet, 'decodeAuth'); this.walletService = await getWallet(this.network); this.nftWallet = new NftWallet(this.walletService); }; public beforeEach = async () => { - this.guardian = await createMemberTest(this.walletSpy); - this.member = await createMemberTest(this.walletSpy); - this.space = await createSpace(this.walletSpy, this.guardian); - this.royaltySpace = await createSpace(this.walletSpy, this.guardian); + this.guardian = await testEnv.createMember(); + this.member = await testEnv.createMember(); + this.space = await testEnv.createSpace(this.guardian); + this.royaltySpace = await testEnv.createSpace(this.guardian); mockWalletReturnValue( - this.walletSpy, this.guardian, this.createDummyCollection(this.space.uid, this.royaltySpace.uid), ); - this.collection = (await testEnv.wrap(createCollection)({})).uid; + this.collection = (await testEnv.wrap(WEN_FUNC.createCollection)).uid; }; public createLockedNft = async () => { @@ -74,19 +60,19 @@ export class CollectionMintHelper { delete nft.uid; delete nft.status; delete nft.placeholderNft; - mockWalletReturnValue(this.walletSpy, this.guardian!, nft); - nft = await testEnv.wrap(createNft)({}); + mockWalletReturnValue(this.guardian!, nft); + nft = await testEnv.wrap(WEN_FUNC.createNft); await build5Db() - .doc(`${COL.NFT}/${nft.uid}`) + .doc(COL.NFT, nft.uid) .update({ availableFrom: dayjs().subtract(1, 'h').toDate() }); - mockWalletReturnValue(this.walletSpy, this.guardian!, { + mockWalletReturnValue(this.guardian!, { collection: this.collection, nft: nft.uid, }); - await testEnv.wrap(orderNft)({}); - return await build5Db().doc(`${COL.NFT}/${nft.uid}`).get(); + await testEnv.wrap(WEN_FUNC.orderNft); + return await build5Db().doc(COL.NFT, nft.uid).get(); }; public createAndOrderNft = async (buyAndAuctionId = false, shouldBid = false) => { @@ -94,34 +80,32 @@ export class CollectionMintHelper { delete nft.uid; delete nft.status; delete nft.placeholderNft; - mockWalletReturnValue(this.walletSpy, this.guardian!, nft); - nft = await testEnv.wrap(createNft)({}); + mockWalletReturnValue(this.guardian!, nft); + nft = await testEnv.wrap(WEN_FUNC.createNft); if (buyAndAuctionId) { await build5Db() - .doc(`${COL.NFT}/${nft.uid}`) + .doc(COL.NFT, nft.uid) .update({ availableFrom: dayjs().subtract(1, 'h').toDate() }); - mockWalletReturnValue(this.walletSpy, this.guardian!, { + mockWalletReturnValue(this.guardian!, { collection: this.collection, nft: nft.uid, }); - const order = await testEnv.wrap(orderNft)({}); + const order = await testEnv.wrap(WEN_FUNC.orderNft); await submitMilestoneFunc(order); - mockWalletReturnValue(this.walletSpy, this.guardian!, this.dummyAuctionData(nft.uid)); - await testEnv.wrap(setForSaleNft)({}); - await wait( - async () => (await build5Db().doc(`${COL.NFT}/${nft.uid}`).get())?.available === 3, - ); + mockWalletReturnValue(this.guardian!, this.dummyAuctionData(nft.uid)); + await testEnv.wrap(WEN_FUNC.setForSaleNft); + await wait(async () => (await build5Db().doc(COL.NFT, nft.uid).get())?.available === 3); if (shouldBid) { - mockWalletReturnValue(this.walletSpy, this.member!, { nft: nft.uid }); - const bidOrder = await testEnv.wrap(openBid)({}); + mockWalletReturnValue(this.member!, { nft: nft.uid }); + const bidOrder = await testEnv.wrap(WEN_FUNC.openBid); await submitMilestoneFunc(bidOrder, 2 * MIN_IOTA_AMOUNT); } } - return await build5Db().doc(`${COL.NFT}/${nft.uid}`).get(); + return await build5Db().doc(COL.NFT, nft.uid).get(); }; public mintCollection = async ( @@ -136,14 +120,14 @@ export class CollectionMintHelper { if (unsoldMintingOptions === UnsoldMintingOptions.SET_NEW_PRICE) { set(request, 'price', price); } - mockWalletReturnValue(this.walletSpy, this.guardian!, request); - const collectionMintOrder = await testEnv.wrap(mintCollection)({}); + mockWalletReturnValue(this.guardian!, request); + const collectionMintOrder = await testEnv.wrap(WEN_FUNC.mintCollection); await requestFundsFromFaucet( this.network!, collectionMintOrder.payload.targetAddress, collectionMintOrder.payload.amount, ); - const collectionDocRef = build5Db().doc(`${COL.COLLECTION}/${this.collection}`); + const collectionDocRef = build5Db().doc(COL.COLLECTION, this.collection); await wait(async () => { const data = await collectionDocRef.get(); return data.status === CollectionStatus.MINTED; @@ -159,8 +143,8 @@ export class CollectionMintHelper { const ownerChangeTran = ( await build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.MINT_COLLECTION) - .where('payload.type', '==', TransactionPayloadType.SEND_ALIAS_TO_GUARDIAN) + .where('type', '==', PgTransactionType.MINT_COLLECTION) + .where('payload_type', '==', PgTransactionPayloadType.SEND_ALIAS_TO_GUARDIAN) .where('member', '==', this.guardian) .get() ).map((d) => d); @@ -173,8 +157,8 @@ export class CollectionMintHelper { const lockTran = ( await build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.MINT_COLLECTION) - .where('payload.type', '==', TransactionPayloadType.LOCK_COLLECTION) + .where('type', '==', PgTransactionType.MINT_COLLECTION) + .where('payload_type', '==', PgTransactionPayloadType.LOCK_COLLECTION) .where('member', '==', this.guardian) .get() ).map((d) => d); diff --git a/packages/functions/test-tangle/collection-minting/collection-minting_1.spec.ts b/packages/functions/test-tangle/collection-minting/collection-minting_1.spec.ts index ef5f4dbfc5..277d9c9591 100644 --- a/packages/functions/test-tangle/collection-minting/collection-minting_1.spec.ts +++ b/packages/functions/test-tangle/collection-minting/collection-minting_1.spec.ts @@ -1,7 +1,6 @@ -import { UnsoldMintingOptions, WenError } from '@build-5/interfaces'; -import { mintCollection } from '../../src/runtime/firebase/collection/index'; -import { expectThrow, mockWalletReturnValue } from '../../test/controls/common'; -import { testEnv } from '../../test/set-up'; +import { Transaction, UnsoldMintingOptions, WEN_FUNC, WenError } from '@build-5/interfaces'; +import { expectThrow } from '../../test/controls/common'; +import { mockWalletReturnValue, testEnv } from '../../test/set-up'; import { CollectionMintHelper } from './Helper'; describe('Collection minting', () => { @@ -16,21 +15,27 @@ describe('Collection minting', () => { }); it('Should throw, no nfts', async () => { - mockWalletReturnValue(helper.walletSpy, helper.guardian!, { + mockWalletReturnValue(helper.guardian!, { collection: helper.collection, network: helper.network, unsoldMintingOptions: UnsoldMintingOptions.KEEP_PRICE, }); - await expectThrow(testEnv.wrap(mintCollection)({}), WenError.no_nfts_to_mint.key); + await expectThrow( + testEnv.wrap(WEN_FUNC.mintCollection), + WenError.no_nfts_to_mint.key, + ); }); it('Should throw, all nfts will be burned', async () => { await helper.createAndOrderNft(); - mockWalletReturnValue(helper.walletSpy, helper.guardian!, { + mockWalletReturnValue(helper.guardian!, { collection: helper.collection, network: helper.network, unsoldMintingOptions: UnsoldMintingOptions.BURN_UNSOLD, }); - await expectThrow(testEnv.wrap(mintCollection)({}), WenError.no_nfts_to_mint.key); + await expectThrow( + testEnv.wrap(WEN_FUNC.mintCollection), + WenError.no_nfts_to_mint.key, + ); }); }); diff --git a/packages/functions/test-tangle/collection-minting/collection-minting_10.spec.ts b/packages/functions/test-tangle/collection-minting/collection-minting_10.spec.ts index 58a3973f5e..2b06783fe9 100644 --- a/packages/functions/test-tangle/collection-minting/collection-minting_10.spec.ts +++ b/packages/functions/test-tangle/collection-minting/collection-minting_10.spec.ts @@ -16,14 +16,14 @@ describe('Collection minting', () => { it('Should hide placeholder nft, all are sold before mint', async () => { await helper.createAndOrderNft(true, true); let placeholderNft = await helper.createAndOrderNft(true, false); - await build5Db().doc(`${COL.NFT}/${placeholderNft.uid}`).update({ placeholderNft: true }); + await build5Db().doc(COL.NFT, placeholderNft.uid).update({ placeholderNft: true }); await build5Db() - .doc(`${COL.COLLECTION}/${helper.collection}`) + .doc(COL.COLLECTION, helper.collection) .update({ total: build5Db().inc(-1) }); await helper.mintCollection(); - placeholderNft = await build5Db().doc(`${COL.NFT}/${placeholderNft.uid}`).get(); + placeholderNft = await build5Db().doc(COL.NFT, placeholderNft.uid).get(); expect(placeholderNft.hidden).toBe(true); }); }); diff --git a/packages/functions/test-tangle/collection-minting/collection-minting_11.spec.ts b/packages/functions/test-tangle/collection-minting/collection-minting_11.spec.ts index 113d5fabae..e4bdc0ab40 100644 --- a/packages/functions/test-tangle/collection-minting/collection-minting_11.spec.ts +++ b/packages/functions/test-tangle/collection-minting/collection-minting_11.spec.ts @@ -19,16 +19,16 @@ describe('Collection minting', () => { await helper.createAndOrderNft(true, true); let nft: Nft | undefined = await helper.createAndOrderNft(); let placeholderNft = await helper.createAndOrderNft(true, false); - await build5Db().doc(`${COL.NFT}/${placeholderNft.uid}`).update({ placeholderNft: true }); + await build5Db().doc(COL.NFT, placeholderNft.uid).update({ placeholderNft: true }); await build5Db() - .doc(`${COL.COLLECTION}/${helper.collection}`) + .doc(COL.COLLECTION, helper.collection) .update({ total: build5Db().inc(-1) }); await helper.mintCollection(unsoldMintingOptions); - placeholderNft = await build5Db().doc(`${COL.NFT}/${placeholderNft.uid}`).get(); + placeholderNft = await build5Db().doc(COL.NFT, placeholderNft.uid).get(); expect(placeholderNft.hidden).toBe(true); - nft = await build5Db().doc(`${COL.NFT}/${nft.uid}`).get(); + nft = await build5Db().doc(COL.NFT, nft.uid).get(); if (unsoldMintingOptions === UnsoldMintingOptions.BURN_UNSOLD) { expect(nft).toBe(undefined); } else { diff --git a/packages/functions/test-tangle/collection-minting/collection-minting_12.spec.ts b/packages/functions/test-tangle/collection-minting/collection-minting_12.spec.ts index 7f9fc72268..e3cb46c1f8 100644 --- a/packages/functions/test-tangle/collection-minting/collection-minting_12.spec.ts +++ b/packages/functions/test-tangle/collection-minting/collection-minting_12.spec.ts @@ -17,16 +17,16 @@ describe('Collection minting', () => { await helper.createAndOrderNft(true, true); let nft: Nft | undefined = await helper.createAndOrderNft(); let placeholderNft = await helper.createAndOrderNft(true, false); - await build5Db().doc(`${COL.NFT}/${placeholderNft.uid}`).update({ placeholderNft: true }); + await build5Db().doc(COL.NFT, placeholderNft.uid).update({ placeholderNft: true }); await build5Db() - .doc(`${COL.COLLECTION}/${helper.collection}`) + .doc(COL.COLLECTION, helper.collection) .update({ total: build5Db().inc(-1) }); await helper.mintCollection(); - placeholderNft = await build5Db().doc(`${COL.NFT}/${placeholderNft.uid}`).get(); + placeholderNft = await build5Db().doc(COL.NFT, placeholderNft.uid).get(); expect(placeholderNft.hidden).toBe(false); - nft = await build5Db().doc(`${COL.NFT}/${nft.uid}`).get(); + nft = await build5Db().doc(COL.NFT, nft.uid).get(); expect(nft).toBeDefined(); }); }); diff --git a/packages/functions/test-tangle/collection-minting/collection-minting_13.spec.ts b/packages/functions/test-tangle/collection-minting/collection-minting_13.spec.ts index 146c1f29d7..c95ec08d58 100644 --- a/packages/functions/test-tangle/collection-minting/collection-minting_13.spec.ts +++ b/packages/functions/test-tangle/collection-minting/collection-minting_13.spec.ts @@ -1,10 +1,9 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ import { build5Db } from '@build-5/database'; -import { COL, Collection, CollectionStatus, Nft } from '@build-5/interfaces'; +import { COL, Collection, CollectionStatus, Nft, WEN_FUNC } from '@build-5/interfaces'; import { NftOutput } from '@iota/sdk'; -import { createCollection } from '../../src/runtime/firebase/collection'; -import { mockWalletReturnValue, wait } from '../../test/controls/common'; -import { testEnv } from '../../test/set-up'; +import { wait } from '../../test/controls/common'; +import { mockWalletReturnValue, testEnv } from '../../test/set-up'; import { CollectionMintHelper, getNftMetadata } from './Helper'; describe('Collection minting', () => { @@ -20,19 +19,19 @@ describe('Collection minting', () => { it('Should mint without royalty space', async () => { const dummyCollection = helper.createDummyCollection(helper.space!.uid); - mockWalletReturnValue(helper.walletSpy, helper.guardian!, dummyCollection); - helper.collection = (await testEnv.wrap(createCollection)({})).uid; + mockWalletReturnValue(helper.guardian!, dummyCollection); + helper.collection = (await testEnv.wrap(WEN_FUNC.createCollection)).uid; let nft = await helper.createAndOrderNft(); await helper.mintCollection(); - const collectionDocRef = build5Db().doc(`${COL.COLLECTION}/${helper.collection}`); + const collectionDocRef = build5Db().doc(COL.COLLECTION, helper.collection); await wait(async () => { - const collection = await collectionDocRef.get(); + const collection = await collectionDocRef.get(); return collection?.status === CollectionStatus.MINTED; }); - const collection = await collectionDocRef.get(); + const collection = await collectionDocRef.get(); const client = helper.walletService?.client!; const collectionOutputId = await client.nftOutputId(collection?.mintingData?.nftId!); @@ -40,7 +39,7 @@ describe('Collection minting', () => { const collectionMetadata = getNftMetadata(collectionOutput as NftOutput); expect(collectionMetadata.royalties).toEqual({}); - const nftDocRef = build5Db().doc(`${COL.NFT}/${nft.uid}`); + const nftDocRef = build5Db().doc(COL.NFT, nft.uid); nft = await nftDocRef.get(); const nftOutputId = await client.nftOutputId(nft.mintingData?.nftId!); const nftOutput = (await client.getOutput(nftOutputId)).output; diff --git a/packages/functions/test-tangle/collection-minting/collection-minting_2.spec.ts b/packages/functions/test-tangle/collection-minting/collection-minting_2.spec.ts index 11c6330e53..dff1f0e621 100644 --- a/packages/functions/test-tangle/collection-minting/collection-minting_2.spec.ts +++ b/packages/functions/test-tangle/collection-minting/collection-minting_2.spec.ts @@ -1,16 +1,16 @@ -import { build5Db } from '@build-5/database'; +import { PgCollectionStatus, PgMediaStatus, build5Db } from '@build-5/database'; import { COL, Collection, CollectionStatus, - MediaStatus, - Nft, SOON_PROJECT_ID, + Transaction, UnsoldMintingOptions, + WEN_FUNC, } from '@build-5/interfaces'; -import { mintCollection } from '../../src/runtime/firebase/collection'; -import { mockWalletReturnValue, wait } from '../../test/controls/common'; -import { MEDIA, testEnv } from '../../test/set-up'; +import { dateToTimestamp } from '../../src/utils/dateTime.utils'; +import { wait } from '../../test/controls/common'; +import { MEDIA, mockWalletReturnValue, testEnv } from '../../test/set-up'; import { requestFundsFromFaucet } from '../faucet'; import { CollectionMintHelper } from './Helper'; @@ -27,15 +27,19 @@ describe('Collection minting', () => { it('Should retry minting when prepare ipfs failed', async () => { const count = 5; - const collectionDocRef = build5Db().doc(`${COL.COLLECTION}/${helper.collection}`); + const collectionDocRef = build5Db().doc(COL.COLLECTION, helper.collection!); await collectionDocRef.update({ total: count }); const promises = Array.from(Array(count)).map(async () => { const nft = helper.createDummyNft(helper.collection!); await build5Db() - .doc(`${COL.NFT}/${nft.uid}`) - .create({ ...nft, project: SOON_PROJECT_ID }); - return nft; + .doc(COL.NFT, nft.uid) + .create({ + ...nft, + availableFrom: dateToTimestamp(nft.availableFrom), + project: SOON_PROJECT_ID, + } as any); + return (await build5Db().doc(COL.NFT, nft.uid).get())!; }); const nfts = await Promise.all(promises); @@ -45,11 +49,11 @@ describe('Collection minting', () => { unsoldMintingOptions: UnsoldMintingOptions.KEEP_PRICE, }; - mockWalletReturnValue(helper.walletSpy, helper.guardian!, request); - const collectionMintOrder = await testEnv.wrap(mintCollection)({}); + mockWalletReturnValue(helper.guardian!, request); + const collectionMintOrder = await testEnv.wrap(WEN_FUNC.mintCollection); for (let i = 0; i < nfts.length; ++i) { - const docRef = build5Db().doc(`${COL.NFT}/${nfts[i].uid}`); - await docRef.update({ media: i > 2 ? 'asd' : MEDIA }); + const docRef = build5Db().doc(COL.NFT, nfts[i].uid); + await docRef.update({ media: i > 2 ? 'name' : MEDIA }); } await requestFundsFromFaucet( helper.network!, @@ -60,24 +64,24 @@ describe('Collection minting', () => { const nftQuery = build5Db() .collection(COL.NFT) .where('collection', '==', helper.collection!) - .where('mediaStatus', '==', MediaStatus.PENDING_UPLOAD); + .where('mediaStatus', '==', PgMediaStatus.PENDING_UPLOAD); await wait(async () => { const nfts = await nftQuery.get(); return nfts.length === 3; }); - const pendingUploadNfts = await nftQuery.limit(2).get(); + const pendingUploadNfts = await nftQuery.limit(2).get(); for (const nft of pendingUploadNfts) { - const docRef = build5Db().doc(`${COL.NFT}/${nft.uid}`); - await docRef.update({ mediaStatus: MediaStatus.UPLOADED }); + const docRef = build5Db().doc(COL.NFT, nft.uid); + await docRef.update({ mediaStatus: PgMediaStatus.UPLOADED }); } - await collectionDocRef.update({ 'mintingData.nftMediaToUpload': 3 }); + await collectionDocRef.update({ mintingData_nftMediaToUpload: 3 }); for (const nft of nfts) { - const docRef = build5Db().doc(`${COL.NFT}/${nft.uid}`); + const docRef = build5Db().doc(COL.NFT, nft.uid); await docRef.update({ media: MEDIA }); } - await collectionDocRef.update({ status: 'asd' }); - await collectionDocRef.update({ status: CollectionStatus.MINTING }); + await collectionDocRef.update({ status: PgCollectionStatus.PRE_MINTED }); + await collectionDocRef.update({ status: PgCollectionStatus.MINTING }); await wait(async () => { const data = await collectionDocRef.get(); return data.status === CollectionStatus.MINTED; diff --git a/packages/functions/test-tangle/collection-minting/collection-minting_3.only.spec.ts b/packages/functions/test-tangle/collection-minting/collection-minting_3.only.spec.ts index a7c22609c3..e16142f748 100644 --- a/packages/functions/test-tangle/collection-minting/collection-minting_3.only.spec.ts +++ b/packages/functions/test-tangle/collection-minting/collection-minting_3.only.spec.ts @@ -1,14 +1,7 @@ -import { build5Db } from '@build-5/database'; -import { - COL, - Nft, - NftStatus, - SOON_PROJECT_ID, - Transaction, - TransactionPayloadType, - TransactionType, -} from '@build-5/interfaces'; +import { PgTransactionPayloadType, PgTransactionType, build5Db } from '@build-5/database'; +import { COL, Nft, NftStatus, SOON_PROJECT_ID } from '@build-5/interfaces'; import { isEmpty } from 'lodash'; +import { dateToTimestamp } from '../../src/utils/dateTime.utils'; import { CollectionMintHelper } from './Helper'; describe('Collection minting', () => { @@ -24,22 +17,27 @@ describe('Collection minting', () => { it('Should mint huge nfts', async () => { const count = 30; - await build5Db().doc(`${COL.COLLECTION}/${helper.collection}`).update({ total: count }); - const promises = Array.from(Array(count)).map(() => { + await build5Db().doc(COL.COLLECTION, helper.collection).update({ total: count }); + const promises = Array.from(Array(count)).map(async () => { const nft = helper.createDummyNft(helper.collection!, helper.getRandomDescrptiron()); - return build5Db() - .doc(`${COL.NFT}/${nft.uid}`) - .create({ ...nft, project: SOON_PROJECT_ID }); + await build5Db() + .doc(COL.NFT, nft.uid) + .create({ + ...nft, + availableFrom: dateToTimestamp(nft.availableFrom), + project: SOON_PROJECT_ID, + } as any); + return (await build5Db().doc(COL.NFT, nft.uid).get())!; }); await Promise.all(promises); await helper.mintCollection(); const nftMintSnap = await build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.MINT_COLLECTION) - .where('payload.type', '==', TransactionPayloadType.MINT_NFTS) - .where('payload.collection', '==', helper.collection) - .get(); + .where('type', '==', PgTransactionType.MINT_COLLECTION) + .where('payload_type', '==', PgTransactionPayloadType.MINT_NFTS) + .where('payload_collection', '==', helper.collection) + .get(); expect(nftMintSnap.length).toBeGreaterThan(1); expect(nftMintSnap.reduce((acc, act) => acc && act?.payload.amount! > 0, true)).toBe(true); expect(nftMintSnap.reduce((acc, act) => acc && !isEmpty(act?.payload.nfts), true)).toBe(true); diff --git a/packages/functions/test-tangle/collection-minting/collection-minting_4_a.spec.ts b/packages/functions/test-tangle/collection-minting/collection-minting_4_a.spec.ts index 21d3472552..fb41e34694 100644 --- a/packages/functions/test-tangle/collection-minting/collection-minting_4_a.spec.ts +++ b/packages/functions/test-tangle/collection-minting/collection-minting_4_a.spec.ts @@ -1,5 +1,5 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ -import { build5Db } from '@build-5/database'; +import { PgTransactionType, build5Db } from '@build-5/database'; import { COL, Collection, @@ -10,7 +10,6 @@ import { NftStatus, Space, Transaction, - TransactionType, } from '@build-5/interfaces'; import { getAddress } from '../../src/utils/address.utils'; import { CollectionMintHelper, getNftMetadata } from './Helper'; @@ -31,9 +30,9 @@ describe('Collection minting', () => { await helper.createAndOrderNft(true); await helper.createAndOrderNft(true, true); let placeholderNft = await helper.createAndOrderNft(true, false); - await build5Db().doc(`${COL.NFT}/${placeholderNft.uid}`).update({ placeholderNft: true }); + await build5Db().doc(COL.NFT, placeholderNft.uid).update({ placeholderNft: true }); await build5Db() - .doc(`${COL.COLLECTION}/${helper.collection}`) + .doc(COL.COLLECTION, helper.collection) .update({ total: build5Db().inc(-1) }); await helper.mintCollection(); @@ -41,8 +40,8 @@ describe('Collection minting', () => { const bidCredit = ( await build5Db() .collection(COL.TRANSACTION) - .where('payload.collection', '==', helper.collection) - .where('type', '==', TransactionType.CREDIT) + .where('payload_collection', '==', helper.collection) + .where('type', '==', PgTransactionType.CREDIT) .get() ).map((d) => d); expect(bidCredit.length).toBe(1); @@ -56,23 +55,19 @@ describe('Collection minting', () => { const allCancelled = nfts.reduce( (acc, act) => acc && - act.auctionFrom === null && - act.auctionTo === null && - act.auctionFloorPrice === null && - act.auctionLength === null && - act.auctionHighestBid === null && - act.auctionHighestBidder === null && - (!act.sold || (act.availableFrom === null && act.availablePrice === null)), + act.auctionFrom === undefined && + act.auctionTo === undefined && + act.auctionFloorPrice === undefined && + act.auctionLength === undefined && + act.auctionHighestBid === undefined && + act.auctionHighestBidder === undefined && + (!act.sold || (act.availableFrom === undefined && act.availablePrice === undefined)), true, ); expect(allCancelled).toBe(true); - const collection = ( - await build5Db().doc(`${COL.COLLECTION}/${helper.collection}`).get() - ); - const royaltySpace = ( - await build5Db().doc(`${COL.SPACE}/${collection.royaltiesSpace}`).get() - ); + const collection = await build5Db().doc(COL.COLLECTION, helper.collection).get(); + const royaltySpace = await build5Db().doc(COL.SPACE, collection.royaltiesSpace!).get(); const collectionOutput = await helper.nftWallet!.getNftOutputs( collection.mintingData?.nftId, @@ -110,7 +105,7 @@ describe('Collection minting', () => { expect(metadata.build5Id).toBe(nft.uid); } - placeholderNft = await build5Db().doc(`${COL.NFT}/${placeholderNft.uid}`).get(); + placeholderNft = await build5Db().doc(COL.NFT, placeholderNft.uid).get(); expect(placeholderNft.status).toBe(NftStatus.PRE_MINTED); }); }); diff --git a/packages/functions/test-tangle/collection-minting/collection-minting_4_b.spec.ts b/packages/functions/test-tangle/collection-minting/collection-minting_4_b.spec.ts index 2dfd4436b9..c75412753c 100644 --- a/packages/functions/test-tangle/collection-minting/collection-minting_4_b.spec.ts +++ b/packages/functions/test-tangle/collection-minting/collection-minting_4_b.spec.ts @@ -1,5 +1,5 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ -import { build5Db } from '@build-5/database'; +import { PgTransactionType, build5Db } from '@build-5/database'; import { COL, Collection, @@ -10,7 +10,6 @@ import { NftStatus, Space, Transaction, - TransactionType, } from '@build-5/interfaces'; import { NftOutput } from '@iota/sdk'; import { getAddress } from '../../src/utils/address.utils'; @@ -33,9 +32,9 @@ describe('Collection minting', () => { await helper.createAndOrderNft(true); await helper.createAndOrderNft(true, true); let placeholderNft = await helper.createAndOrderNft(true, false); - await build5Db().doc(`${COL.NFT}/${placeholderNft.uid}`).update({ placeholderNft: true }); + await build5Db().doc(COL.NFT, placeholderNft.uid).update({ placeholderNft: true }); - const collectionDocRef = build5Db().doc(`${COL.COLLECTION}/${helper.collection}`); + const collectionDocRef = build5Db().doc(COL.COLLECTION, helper.collection); await collectionDocRef.update({ total: build5Db().inc(-1), limitedEdition: true }); await helper.mintCollection(); @@ -49,8 +48,8 @@ describe('Collection minting', () => { const bidCredit = ( await build5Db() .collection(COL.TRANSACTION) - .where('payload.collection', '==', helper.collection) - .where('type', '==', TransactionType.CREDIT) + .where('payload_collection', '==', helper.collection) + .where('type', '==', PgTransactionType.CREDIT) .get() ).map((d) => d); expect(bidCredit.length).toBe(1); @@ -64,21 +63,19 @@ describe('Collection minting', () => { const allCancelled = nfts.reduce( (acc, act) => acc && - act.auctionFrom === null && - act.auctionTo === null && - act.auctionFloorPrice === null && - act.auctionLength === null && - act.auctionHighestBid === null && - act.auctionHighestBidder === null && - (!act.sold || (act.availableFrom === null && act.availablePrice === null)), + act.auctionFrom === undefined && + act.auctionTo === undefined && + act.auctionFloorPrice === undefined && + act.auctionLength === undefined && + act.auctionHighestBid === undefined && + act.auctionHighestBidder === undefined && + (!act.sold || (act.availableFrom === undefined && act.availablePrice === undefined)), true, ); expect(allCancelled).toBe(true); collection = await collectionDocRef.get(); - const royaltySpace = ( - await build5Db().doc(`${COL.SPACE}/${collection.royaltiesSpace}`).get() - ); + const royaltySpace = await build5Db().doc(COL.SPACE, collection.royaltiesSpace!).get(); const collectionOutput = await helper.nftWallet!.getNftOutputs( collection.mintingData?.nftId, @@ -116,7 +113,7 @@ describe('Collection minting', () => { expect(metadata.build5Id).toBe(nft.uid); } - placeholderNft = await build5Db().doc(`${COL.NFT}/${placeholderNft.uid}`).get(); + placeholderNft = await build5Db().doc(COL.NFT, placeholderNft.uid).get(); expect(placeholderNft.status).toBe(NftStatus.PRE_MINTED); }); }); diff --git a/packages/functions/test-tangle/collection-minting/collection-minting_4_c.spec.ts b/packages/functions/test-tangle/collection-minting/collection-minting_4_c.spec.ts index 7acc45bb8f..386d1bbb2a 100644 --- a/packages/functions/test-tangle/collection-minting/collection-minting_4_c.spec.ts +++ b/packages/functions/test-tangle/collection-minting/collection-minting_4_c.spec.ts @@ -1,6 +1,6 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ import { build5Db } from '@build-5/database'; -import { COL, Nft, NftStatus, Transaction } from '@build-5/interfaces'; +import { COL, NftStatus, Transaction } from '@build-5/interfaces'; import { CollectionMintHelper } from './Helper'; describe('Collection minting', () => { @@ -18,13 +18,13 @@ describe('Collection minting', () => { let lockedNft = await helper.createLockedNft(); await helper.mintCollection(); const lockedNftOrder = ( - await build5Db().doc(`${COL.TRANSACTION}/${lockedNft.lockedBy}`).get() + await build5Db().doc(COL.TRANSACTION, lockedNft.lockedBy!).get() ); expect(lockedNftOrder.payload.void).toBe(true); - lockedNft = await build5Db().doc(`${COL.NFT}/${lockedNft.uid}`).get(); + lockedNft = (await build5Db().doc(COL.NFT, lockedNft.uid).get())!; expect(lockedNft.locked).toBe(false); - expect(lockedNft.lockedBy).toBe(null); + expect(lockedNft.lockedBy).toBe(undefined); expect(lockedNft.mintingData).toBeDefined(); expect(lockedNft.status).toBe(NftStatus.MINTED); }); diff --git a/packages/functions/test-tangle/collection-minting/collection-minting_5.spec.ts b/packages/functions/test-tangle/collection-minting/collection-minting_5.spec.ts index 4603d18643..a7a04c93b9 100644 --- a/packages/functions/test-tangle/collection-minting/collection-minting_5.spec.ts +++ b/packages/functions/test-tangle/collection-minting/collection-minting_5.spec.ts @@ -1,16 +1,15 @@ -import { build5Db } from '@build-5/database'; +import { PgTransactionType, build5Db } from '@build-5/database'; import { COL, Collection, CollectionStatus, Transaction, - TransactionType, UnsoldMintingOptions, + WEN_FUNC, } from '@build-5/interfaces'; import { isEqual } from 'lodash'; -import { mintCollection } from '../../src/runtime/firebase/collection/index'; -import { mockWalletReturnValue, wait } from '../../test/controls/common'; -import { testEnv } from '../../test/set-up'; +import { wait } from '../../test/controls/common'; +import { mockWalletReturnValue, testEnv } from '../../test/set-up'; import { requestFundsFromFaucet } from '../faucet'; import { CollectionMintHelper } from './Helper'; @@ -30,18 +29,18 @@ describe('Collection minting', () => { const tmpAddress1 = await helper.walletService!.getNewIotaAddressDetails(); const tmpAddress2 = await helper.walletService!.getNewIotaAddressDetails(); - mockWalletReturnValue(helper.walletSpy, helper.guardian!, { + mockWalletReturnValue(helper.guardian!, { collection: helper.collection, network: helper.network, unsoldMintingOptions: UnsoldMintingOptions.KEEP_PRICE, }); - const collectionMintOrder1 = await testEnv.wrap(mintCollection)({}); - mockWalletReturnValue(helper.walletSpy, helper.guardian!, { + const collectionMintOrder1 = await testEnv.wrap(WEN_FUNC.mintCollection); + mockWalletReturnValue(helper.guardian!, { collection: helper.collection, network: helper.network, unsoldMintingOptions: UnsoldMintingOptions.KEEP_PRICE, }); - const collectionMintOrder2 = await testEnv.wrap(mintCollection)({}); + const collectionMintOrder2 = await testEnv.wrap(WEN_FUNC.mintCollection); expect(isEqual(collectionMintOrder1, collectionMintOrder2)).toBe(false); expect(collectionMintOrder1.payload.amount).toBe(collectionMintOrder2.payload.amount); @@ -61,14 +60,14 @@ describe('Collection minting', () => { const promises = [tmpAddress1, tmpAddress2].map((address, i) => helper.walletService!.send( address, - orders[i].payload.targetAddress, - orders[i].payload.amount, + orders[i].payload.targetAddress!, + orders[i].payload.amount!, {}, ), ); await Promise.all(promises); - const collectionDocRef = build5Db().doc(`${COL.COLLECTION}/${helper.collection}`); + const collectionDocRef = build5Db().doc(COL.COLLECTION, helper.collection); let collection = await collectionDocRef.get(); await wait(async () => { collection = await collectionDocRef.get(); @@ -78,10 +77,10 @@ describe('Collection minting', () => { const creditQuery = build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.CREDIT) - .where('payload.collection', '==', helper.collection); + .where('type', '==', PgTransactionType.CREDIT) + .where('payload_collection', '==', helper.collection); await wait(async () => { - const snap = await creditQuery.get(); + const snap = await creditQuery.get(); const allConfirmed = snap.reduce( (acc, act) => acc && (act.payload?.walletReference?.confirmed || false), true, diff --git a/packages/functions/test-tangle/collection-minting/collection-minting_6.spec.ts b/packages/functions/test-tangle/collection-minting/collection-minting_6.spec.ts index 84417c6ff1..e3f5b4c720 100644 --- a/packages/functions/test-tangle/collection-minting/collection-minting_6.spec.ts +++ b/packages/functions/test-tangle/collection-minting/collection-minting_6.spec.ts @@ -19,19 +19,17 @@ describe('Collection minting', () => { await helper.createAndOrderNft(true); let nft = await helper.createAndOrderNft(); let collectionData = ( - await build5Db().doc(`${COL.COLLECTION}/${helper.collection}`).get() + await build5Db().doc(COL.COLLECTION, helper.collection).get() ); expect(collectionData.total).toBe(2); await helper.mintCollection(unsoldMintingOptions); - collectionData = ( - await build5Db().doc(`${COL.COLLECTION}/${helper.collection}`).get() - ); + collectionData = await build5Db().doc(COL.COLLECTION, helper.collection).get(); expect(collectionData.total).toBe( unsoldMintingOptions === UnsoldMintingOptions.BURN_UNSOLD ? 1 : 2, ); - nft = await build5Db().doc(`${COL.NFT}/${nft?.uid}`).get(); + nft = await build5Db().doc(COL.NFT, nft?.uid!).get(); expect(nft === undefined).toBe(unsoldMintingOptions === UnsoldMintingOptions.BURN_UNSOLD); }, ); diff --git a/packages/functions/test-tangle/collection-minting/collection-minting_7.spec.ts b/packages/functions/test-tangle/collection-minting/collection-minting_7.spec.ts index c298bd3811..0ebaf33616 100644 --- a/packages/functions/test-tangle/collection-minting/collection-minting_7.spec.ts +++ b/packages/functions/test-tangle/collection-minting/collection-minting_7.spec.ts @@ -1,16 +1,16 @@ -import { build5Db } from '@build-5/database'; +import { PgCollectionType, build5Db } from '@build-5/database'; import { COL, Collection, - CollectionType, MIN_IOTA_AMOUNT, Nft, + Transaction, UnsoldMintingOptions, + WEN_FUNC, WenError, } from '@build-5/interfaces'; -import { mintCollection } from '../../src/runtime/firebase/collection/index'; -import { expectThrow, mockWalletReturnValue } from '../../test/controls/common'; -import { testEnv } from '../../test/set-up'; +import { expectThrow } from '../../test/controls/common'; +import { mockWalletReturnValue, testEnv } from '../../test/set-up'; import { CollectionMintHelper } from './Helper'; describe('Collection minting', () => { @@ -24,45 +24,49 @@ describe('Collection minting', () => { await helper.beforeEach(); }); - it.each([CollectionType.GENERATED, CollectionType.SFT, CollectionType.CLASSIC])( + it.each([PgCollectionType.GENERATED, PgCollectionType.SFT, PgCollectionType.CLASSIC])( 'Should set new price', - async (type: CollectionType) => { - await build5Db().doc(`${COL.COLLECTION}/${helper.collection}`).update({ type }); + async (type: PgCollectionType) => { + await build5Db().doc(COL.COLLECTION, helper.collection).update({ type }); let nft = await helper.createAndOrderNft(); let collectionData = ( - await build5Db().doc(`${COL.COLLECTION}/${helper.collection}`).get() + await build5Db().doc(COL.COLLECTION, helper.collection).get() ); expect(collectionData.total).toBe(1); - if (type === CollectionType.CLASSIC) { - mockWalletReturnValue(helper.walletSpy, helper.guardian!, { + if (type === PgCollectionType.CLASSIC) { + mockWalletReturnValue(helper.guardian!, { collection: helper.collection, network: helper.network, unsoldMintingOptions: UnsoldMintingOptions.SET_NEW_PRICE, price: 2 * MIN_IOTA_AMOUNT, }); - await expectThrow(testEnv.wrap(mintCollection)({}), WenError.invalid_collection_status.key); + await expectThrow( + testEnv.wrap(WEN_FUNC.mintCollection), + WenError.invalid_collection_status.key, + ); return; } await helper.mintCollection(UnsoldMintingOptions.SET_NEW_PRICE, 2 * MIN_IOTA_AMOUNT); - collectionData = ( - await build5Db().doc(`${COL.COLLECTION}/${helper.collection}`).get() - ); + collectionData = await build5Db().doc(COL.COLLECTION, helper.collection).get(); expect(collectionData.total).toBe(1); - nft = await build5Db().doc(`${COL.NFT}/${nft?.uid}`).get(); + nft = await build5Db().doc(COL.NFT, nft?.uid!).get(); expect(nft.availablePrice).toBe(2 * MIN_IOTA_AMOUNT); expect(nft.price).toBe(2 * MIN_IOTA_AMOUNT); }, ); it('Should throw, min price below mint iota', async () => { - mockWalletReturnValue(helper.walletSpy, helper.guardian!, { + mockWalletReturnValue(helper.guardian!, { collection: helper.collection, network: helper.network, unsoldMintingOptions: UnsoldMintingOptions.SET_NEW_PRICE, price: MIN_IOTA_AMOUNT / 2, }); - await expectThrow(testEnv.wrap(mintCollection)({}), WenError.invalid_params.key); + await expectThrow( + testEnv.wrap(WEN_FUNC.mintCollection), + WenError.invalid_params.key, + ); }); }); diff --git a/packages/functions/test-tangle/collection-minting/collection-minting_8.spec.ts b/packages/functions/test-tangle/collection-minting/collection-minting_8.spec.ts index b24e8b422f..16a87b1ebb 100644 --- a/packages/functions/test-tangle/collection-minting/collection-minting_8.spec.ts +++ b/packages/functions/test-tangle/collection-minting/collection-minting_8.spec.ts @@ -1,15 +1,15 @@ -import { build5Db } from '@build-5/database'; +import { PgCollectionType, build5Db } from '@build-5/database'; import { COL, Collection, - CollectionType, Nft, + Transaction, UnsoldMintingOptions, + WEN_FUNC, WenError, } from '@build-5/interfaces'; -import { mintCollection } from '../../src/runtime/firebase/collection/index'; -import { expectThrow, mockWalletReturnValue } from '../../test/controls/common'; -import { testEnv } from '../../test/set-up'; +import { expectThrow } from '../../test/controls/common'; +import { mockWalletReturnValue, testEnv } from '../../test/set-up'; import { CollectionMintHelper } from './Helper'; describe('Collection minting', () => { @@ -23,33 +23,34 @@ describe('Collection minting', () => { await helper.beforeEach(); }); - it.each([CollectionType.GENERATED, CollectionType.SFT, CollectionType.CLASSIC])( + it.each([PgCollectionType.GENERATED, PgCollectionType.SFT, PgCollectionType.CLASSIC])( 'Should set owner to guardian', - async (type: CollectionType) => { - await build5Db().doc(`${COL.COLLECTION}/${helper.collection}`).update({ type }); + async (type: PgCollectionType) => { + await build5Db().doc(COL.COLLECTION, helper.collection).update({ type }); let nft = await helper.createAndOrderNft(); let collectionData = ( - await build5Db().doc(`${COL.COLLECTION}/${helper.collection}`).get() + await build5Db().doc(COL.COLLECTION, helper.collection).get() ); expect(collectionData.total).toBe(1); expect(collectionData.sold).toBe(0); - if (type !== CollectionType.CLASSIC) { - mockWalletReturnValue(helper.walletSpy, helper.guardian!, { + if (type !== PgCollectionType.CLASSIC) { + mockWalletReturnValue(helper.guardian!, { collection: helper.collection, network: helper.network, unsoldMintingOptions: UnsoldMintingOptions.TAKE_OWNERSHIP, }); - await expectThrow(testEnv.wrap(mintCollection)({}), WenError.invalid_collection_status.key); + await expectThrow( + testEnv.wrap(WEN_FUNC.mintCollection), + WenError.invalid_collection_status.key, + ); return; } await helper.mintCollection(UnsoldMintingOptions.TAKE_OWNERSHIP); - collectionData = ( - await build5Db().doc(`${COL.COLLECTION}/${helper.collection}`).get() - ); + collectionData = await build5Db().doc(COL.COLLECTION, helper.collection).get(); expect(collectionData.total).toBe(1); - nft = await build5Db().doc(`${COL.NFT}/${nft?.uid}`).get(); + nft = await build5Db().doc(COL.NFT, nft?.uid!).get(); expect(nft.isOwned).toBe(true); expect(nft.owner).toBe(helper.guardian); expect(nft.sold).toBe(true); diff --git a/packages/functions/test-tangle/collection-minting/collection-minting_9.spec.ts b/packages/functions/test-tangle/collection-minting/collection-minting_9.spec.ts index 3c6e8b3402..57ec4953ae 100644 --- a/packages/functions/test-tangle/collection-minting/collection-minting_9.spec.ts +++ b/packages/functions/test-tangle/collection-minting/collection-minting_9.spec.ts @@ -1,8 +1,7 @@ import { build5Db } from '@build-5/database'; -import { COL, UnsoldMintingOptions, WenError } from '@build-5/interfaces'; -import { mintCollection } from '../../src/runtime/firebase/collection/index'; -import { expectThrow, mockWalletReturnValue } from '../../test/controls/common'; -import { testEnv } from '../../test/set-up'; +import { COL, Transaction, UnsoldMintingOptions, WEN_FUNC, WenError } from '@build-5/interfaces'; +import { expectThrow } from '../../test/controls/common'; +import { mockWalletReturnValue, testEnv } from '../../test/set-up'; import { CollectionMintHelper } from './Helper'; describe('Collection minting', () => { @@ -17,42 +16,46 @@ describe('Collection minting', () => { }); it('Should throw, member has no valid address', async () => { - await build5Db().doc(`${COL.MEMBER}/${helper.guardian}`).update({ validatedAddress: {} }); - mockWalletReturnValue(helper.walletSpy, helper.guardian!, { + await build5Db() + .doc(COL.MEMBER, helper.guardian) + .update({ rmsAddress: '', smrAddress: '', iotaAddress: '', atoiAddress: '' }); + mockWalletReturnValue(helper.guardian!, { collection: helper.collection, network: helper.network, unsoldMintingOptions: UnsoldMintingOptions.KEEP_PRICE, }); await expectThrow( - testEnv.wrap(mintCollection)({}), + testEnv.wrap(WEN_FUNC.mintCollection), WenError.member_must_have_validated_address.key, ); }); it('Should throw, space has no valid address', async () => { - await build5Db().doc(`${COL.SPACE}/${helper.space!.uid}`).update({ validatedAddress: {} }); - mockWalletReturnValue(helper.walletSpy, helper.guardian!, { + await build5Db() + .doc(COL.SPACE, helper.space!.uid) + .update({ rmsAddress: '', smrAddress: '', iotaAddress: '', atoiAddress: '' }); + mockWalletReturnValue(helper.guardian!, { collection: helper.collection, network: helper.network, unsoldMintingOptions: UnsoldMintingOptions.KEEP_PRICE, }); await expectThrow( - testEnv.wrap(mintCollection)({}), + testEnv.wrap(WEN_FUNC.mintCollection), WenError.space_must_have_validated_address.key, ); }); it('Should throw, royalty space has no valid address', async () => { await build5Db() - .doc(`${COL.SPACE}/${helper.royaltySpace!.uid}`) - .update({ validatedAddress: {} }); - mockWalletReturnValue(helper.walletSpy, helper.guardian!, { + .doc(COL.SPACE, helper.royaltySpace!.uid) + .update({ rmsAddress: '', smrAddress: '', iotaAddress: '', atoiAddress: '' }); + mockWalletReturnValue(helper.guardian!, { collection: helper.collection, network: helper.network, unsoldMintingOptions: UnsoldMintingOptions.KEEP_PRICE, }); await expectThrow( - testEnv.wrap(mintCollection)({}), + testEnv.wrap(WEN_FUNC.mintCollection), WenError.space_must_have_validated_address.key, ); }); diff --git a/packages/functions/test-tangle/common.ts b/packages/functions/test-tangle/common.ts index 826880b3fd..481e73d508 100644 --- a/packages/functions/test-tangle/common.ts +++ b/packages/functions/test-tangle/common.ts @@ -1,4 +1,4 @@ -import { build5Db } from '@build-5/database'; +import { PgTransactionType, build5Db } from '@build-5/database'; import { COL, MAX_WALLET_RETRY, @@ -28,7 +28,7 @@ export const addValidatedAddress = async (network: Network, member: string) => { const walletService = await getWallet(network); const address = await walletService.getNewIotaAddressDetails(); await build5Db() - .doc(`${COL.MEMBER}/${member}`) + .doc(COL.MEMBER, member) .update({ [`validatedAddress.${network}`]: address.bech32 }); return address; }; @@ -36,8 +36,8 @@ export const addValidatedAddress = async (network: Network, member: string) => { export const awaitTransactionConfirmationsForToken = async (token: string) => { const query = build5Db() .collection(COL.TRANSACTION) - .where('payload.token', '==', token) - .where('type', 'in', [TransactionType.CREDIT, TransactionType.BILL_PAYMENT]); + .where('payload_token', '==', token) + .whereIn('type', [PgTransactionType.CREDIT, PgTransactionType.BILL_PAYMENT]); await wait(async () => { const transactions = (await query.get()).map((d) => d); const hasErrors = transactions.filter((t) => { @@ -88,7 +88,7 @@ export const getTangleOrder = async (network: Network) => { }, linkedTransactions: [], }; - await build5Db().doc(`${COL.TRANSACTION}/${order.uid}`).create(order); + await build5Db().doc(COL.TRANSACTION, order.uid).create(order); tangleOrders[network] = order; return tangleOrders[network]; }; diff --git a/packages/functions/test-tangle/faucet.ts b/packages/functions/test-tangle/faucet.ts index ef8b594159..986a247bb0 100644 --- a/packages/functions/test-tangle/faucet.ts +++ b/packages/functions/test-tangle/faucet.ts @@ -17,8 +17,8 @@ export const getSenderAddress = async (network: Network, amountNeeded: number) = export const requestFundsFromFaucet = async ( network: Network, - targetBech32: string, - amount: number, + targetBech32: string | undefined, + amount: number | undefined, expiresAt?: Timestamp, ) => { const wallet = await getWallet(network); @@ -26,7 +26,7 @@ export const requestFundsFromFaucet = async ( const faucetAddress = await wallet.getIotaAddressDetails(getFaucetMnemonic(network)); try { await MnemonicService.store(faucetAddress.bech32, faucetAddress.mnemonic, network); - const blockId = await wallet.send(faucetAddress, targetBech32, amount, { + const blockId = await wallet.send(faucetAddress, targetBech32!, amount!, { expiration: expiresAt ? { expiresAt, returnAddressBech32: faucetAddress.bech32 } : undefined, diff --git a/packages/functions/test-tangle/metadata-nft/Helper.ts b/packages/functions/test-tangle/metadata-nft/Helper.ts index ed29345196..76710cafdf 100644 --- a/packages/functions/test-tangle/metadata-nft/Helper.ts +++ b/packages/functions/test-tangle/metadata-nft/Helper.ts @@ -1,19 +1,9 @@ import { build5Db } from '@build-5/database'; -import { - COL, - MIN_IOTA_AMOUNT, - Member, - Network, - Space, - Token, - Transaction, -} from '@build-5/interfaces'; +import { COL, MIN_IOTA_AMOUNT, Network, Space, Token, Transaction } from '@build-5/interfaces'; import { Wallet } from '../../src/services/wallet/wallet'; import { AddressDetails } from '../../src/services/wallet/wallet.service'; import { getAddress } from '../../src/utils/address.utils'; -import * as wallet from '../../src/utils/wallet.utils'; -import { createMember } from '../../test/controls/common'; -import { getWallet } from '../../test/set-up'; +import { getWallet, testEnv } from '../../test/set-up'; import { getTangleOrder } from '../common'; import { requestFundsFromFaucet } from '../faucet'; @@ -25,19 +15,17 @@ export class Helper { public member: string = ''; public memberAddress: AddressDetails = {} as any; public walletService: Wallet = {} as any; - public walletSpy: any; public tangleOrder: Transaction = {} as any; public beforeEach = async (network: Network) => { this.network = network; this.walletService = await getWallet(this.network); - this.walletSpy = jest.spyOn(wallet, 'decodeAuth'); - this.member = await createMember(this.walletSpy); + this.member = await testEnv.createMember(); this.tangleOrder = await getTangleOrder(this.network); - const memberData = await build5Db().doc(`${COL.MEMBER}/${this.member}`).get(); + const memberData = await build5Db().doc(COL.MEMBER, this.member).get(); const memberAddress = getAddress(memberData, this.network); this.memberAddress = await this.walletService.getAddressDetails(memberAddress); await requestFundsFromFaucet(this.network, memberAddress, 10 * MIN_IOTA_AMOUNT); diff --git a/packages/functions/test-tangle/metadata-nft/mint-metadata-nft_1.spec.ts b/packages/functions/test-tangle/metadata-nft/mint-metadata-nft_1.spec.ts index fe3db995fd..2d9f7ec561 100644 --- a/packages/functions/test-tangle/metadata-nft/mint-metadata-nft_1.spec.ts +++ b/packages/functions/test-tangle/metadata-nft/mint-metadata-nft_1.spec.ts @@ -1,15 +1,5 @@ -import { build5Db } from '@build-5/database'; -import { - COL, - Collection, - MIN_IOTA_AMOUNT, - Network, - Nft, - Space, - TangleRequestType, - Transaction, - TransactionType, -} from '@build-5/interfaces'; +import { PgTransactionType, build5Db } from '@build-5/database'; +import { COL, MIN_IOTA_AMOUNT, Network, TangleRequestType } from '@build-5/interfaces'; import { BasicOutput, RegularTransactionEssence, TransactionPayload } from '@iota/sdk'; import { MnemonicService } from '../../src/services/wallet/mnemonic'; import { getOutputMetadata } from '../../src/utils/basic-output.utils'; @@ -21,7 +11,7 @@ describe('Metadata nft', () => { it('Should mint metada nft', async () => { await helper.beforeEach(Network.RMS); - const metadata = { mytest: 'mytest', asd: 'asdasdasd' }; + const metadata = { mytest: 'mytest', name: 'asdasdasd' }; const blockId = await helper.walletService.send( helper.memberAddress, helper.tangleOrder.payload.targetAddress!, @@ -44,7 +34,7 @@ describe('Metadata nft', () => { const mintMetadataNftQuery = build5Db() .collection(COL.TRANSACTION) .where('member', '==', helper.member) - .where('type', '==', TransactionType.METADATA_NFT); + .where('type', '==', PgTransactionType.METADATA_NFT); await wait(async () => { const snap = await mintMetadataNftQuery.get(); return snap.length === 3; @@ -53,12 +43,12 @@ describe('Metadata nft', () => { const creditQuery = build5Db() .collection(COL.TRANSACTION) .where('member', '==', helper.member) - .where('type', '==', TransactionType.CREDIT); + .where('type', '==', PgTransactionType.CREDIT); await wait(async () => { - const snap = await creditQuery.get(); + const snap = await creditQuery.get(); return snap.length === 1 && snap[0]?.payload?.walletReference?.confirmed; }); - const credit = (await creditQuery.get())[0]; + const credit = (await creditQuery.get())[0]; const block = await helper.walletService.client.getBlock( credit.payload.walletReference!.chainReference!, ); @@ -67,11 +57,9 @@ describe('Metadata nft', () => { const outputMetadata = getOutputMetadata(output); const nftQuery = build5Db().collection(COL.NFT).where('owner', '==', helper.member); - const nft = (await nftQuery.get())[0]; - const collection = await build5Db() - .doc(`${COL.COLLECTION}/${nft.collection}`) - .get(); - const space = await build5Db().doc(`${COL.SPACE}/${nft.space}`).get(); + const nft = (await nftQuery.get())[0]; + const collection = await build5Db().doc(COL.COLLECTION, nft.collection).get(); + const space = await build5Db().doc(COL.SPACE, nft.space).get(); expect(outputMetadata).toEqual({ nftId: nft!.mintingData!.nftId, collectionId: collection!.mintingData!.nftId, diff --git a/packages/functions/test-tangle/metadata-nft/mint-metadata-nft_10.spec.ts b/packages/functions/test-tangle/metadata-nft/mint-metadata-nft_10.spec.ts index 3c4534f73d..6f0d98cd31 100644 --- a/packages/functions/test-tangle/metadata-nft/mint-metadata-nft_10.spec.ts +++ b/packages/functions/test-tangle/metadata-nft/mint-metadata-nft_10.spec.ts @@ -1,10 +1,9 @@ -import { build5Db } from '@build-5/database'; -import { COL, Collection, Network, Nft, Transaction, TransactionType } from '@build-5/interfaces'; +import { PgTransactionType, build5Db } from '@build-5/database'; +import { COL, Collection, Network, Transaction, WEN_FUNC } from '@build-5/interfaces'; import { NftOutput } from '@iota/sdk'; -import { mintMetadataNft } from '../../src/runtime/firebase/nft'; import { getOutputMetadata } from '../../src/utils/basic-output.utils'; -import { mockWalletReturnValue, wait } from '../../test/controls/common'; -import { testEnv } from '../../test/set-up'; +import { wait } from '../../test/controls/common'; +import { mockWalletReturnValue, testEnv } from '../../test/set-up'; import { requestFundsFromFaucet } from '../faucet'; import { Helper } from './Helper'; @@ -15,63 +14,63 @@ describe('Metadata nft', () => { const network = Network.RMS; await h.beforeEach(network); - const metadata = { mytest: 'mytest', asd: 'asdasdasd' }; + const metadata = { mytest: 'mytest', name: 'asdasdasd' }; - mockWalletReturnValue(h.walletSpy, h.member, { network, metadata }); - const order: Transaction = await testEnv.wrap(mintMetadataNft)({}); + mockWalletReturnValue(h.member, { network, metadata }); + const order = await testEnv.wrap(WEN_FUNC.mintMetadataNft); await requestFundsFromFaucet(network, order.payload.targetAddress!, order.payload.amount!); - let query = build5Db() + const typeQuery = build5Db() .collection(COL.TRANSACTION) .where('member', '==', h.member) - .where('type', '==', TransactionType.METADATA_NFT); + .where('type', '==', PgTransactionType.METADATA_NFT); await wait(async () => { - const snap = await query.get(); + const snap = await typeQuery.get(); return ( snap.length === 3 && snap.reduce((acc, act) => (acc && act.payload?.walletReference?.confirmed) || false, true) ); }); - query = build5Db() + let addressQuery = build5Db() .collection(COL.NFT) - .where('mintingData.address', '==', order.payload.targetAddress); + .where('mintingData_address', '==', order.payload.targetAddress); await wait(async () => { - const nfts = await query.get(); + const nfts = await addressQuery.get(); return nfts.length === 1; }); - const nft = (await query.get())[0]; + const nft = (await addressQuery.get())[0]; const client = h.walletService.client; let nftOutputId = await client.nftOutputId(nft.mintingData!.nftId!); let nftOutput = (await client.getOutput(nftOutputId)).output as NftOutput; let outputMetadata = getOutputMetadata(nftOutput); expect(outputMetadata).toEqual(metadata); - const collectionDocRef = build5Db().doc(`${COL.COLLECTION}/${nft.collection}`); + const collectionDocRef = build5Db().doc(COL.COLLECTION, nft.collection); const collection = await collectionDocRef.get(); - mockWalletReturnValue(h.walletSpy, h.member, { + mockWalletReturnValue(h.member, { network, metadata: { name: 'SecondNft' }, collectionId: collection.mintingData?.nftId!, }); - const secondOrder: Transaction = await testEnv.wrap(mintMetadataNft)({}); + const secondOrder = await testEnv.wrap(WEN_FUNC.mintMetadataNft); await requestFundsFromFaucet( network, secondOrder.payload.targetAddress!, secondOrder.payload.amount!, ); - query = build5Db() + addressQuery = build5Db() .collection(COL.NFT) - .where('mintingData.address', '==', secondOrder.payload.targetAddress); + .where('mintingData_address', '==', secondOrder.payload.targetAddress); await wait(async () => { - const nfts = await query.get(); + const nfts = await addressQuery.get(); return nfts.length === 1; }); - const secondNft = (await query.get())[0]; + const secondNft = (await addressQuery.get())[0]; expect(nft.collection).toBe(secondNft.collection); }); diff --git a/packages/functions/test-tangle/metadata-nft/mint-metadata-nft_1_b.spec.ts b/packages/functions/test-tangle/metadata-nft/mint-metadata-nft_1_b.spec.ts index f70a6ab353..c68fead9a9 100644 --- a/packages/functions/test-tangle/metadata-nft/mint-metadata-nft_1_b.spec.ts +++ b/packages/functions/test-tangle/metadata-nft/mint-metadata-nft_1_b.spec.ts @@ -1,15 +1,5 @@ -import { build5Db } from '@build-5/database'; -import { - COL, - Collection, - MIN_IOTA_AMOUNT, - Network, - Nft, - Space, - TangleRequestType, - Transaction, - TransactionType, -} from '@build-5/interfaces'; +import { PgTransactionType, build5Db } from '@build-5/database'; +import { COL, MIN_IOTA_AMOUNT, Network, TangleRequestType } from '@build-5/interfaces'; import { BasicOutput, RegularTransactionEssence, TransactionPayload } from '@iota/sdk'; import { MnemonicService } from '../../src/services/wallet/mnemonic'; import { getOutputMetadata } from '../../src/utils/basic-output.utils'; @@ -21,7 +11,7 @@ describe('Metadata nft', () => { it('Should mint metada nft', async () => { await helper.beforeEach(Network.ATOI); - const metadata = { mytest: 'mytest', asd: 'asdasdasd' }; + const metadata = { mytest: 'mytest', name: 'asdasdasd' }; const blockId = await helper.walletService.send( helper.memberAddress, helper.tangleOrder.payload.targetAddress!, @@ -44,7 +34,7 @@ describe('Metadata nft', () => { const mintMetadataNftQuery = build5Db() .collection(COL.TRANSACTION) .where('member', '==', helper.member) - .where('type', '==', TransactionType.METADATA_NFT); + .where('type', '==', PgTransactionType.METADATA_NFT); await wait(async () => { const snap = await mintMetadataNftQuery.get(); return snap.length === 3; @@ -53,12 +43,12 @@ describe('Metadata nft', () => { const creditQuery = build5Db() .collection(COL.TRANSACTION) .where('member', '==', helper.member) - .where('type', '==', TransactionType.CREDIT); + .where('type', '==', PgTransactionType.CREDIT); await wait(async () => { - const snap = await creditQuery.get(); + const snap = await creditQuery.get(); return snap.length === 1 && snap[0]?.payload?.walletReference?.confirmed; }); - const credit = (await creditQuery.get())[0]; + const credit = (await creditQuery.get())[0]; const block = await helper.walletService.client.getBlock( credit.payload.walletReference!.chainReference!, ); @@ -67,11 +57,9 @@ describe('Metadata nft', () => { const outputMetadata = getOutputMetadata(output); const nftQuery = build5Db().collection(COL.NFT).where('owner', '==', helper.member); - const nft = (await nftQuery.get())[0]; - const collection = await build5Db() - .doc(`${COL.COLLECTION}/${nft.collection}`) - .get(); - const space = await build5Db().doc(`${COL.SPACE}/${nft.space}`).get(); + const nft = (await nftQuery.get())[0]; + const collection = await build5Db().doc(COL.COLLECTION, nft.collection).get(); + const space = await build5Db().doc(COL.SPACE, nft.space).get(); expect(outputMetadata).toEqual({ nftId: nft!.mintingData!.nftId, collectionId: collection!.mintingData!.nftId, diff --git a/packages/functions/test-tangle/metadata-nft/mint-metadata-nft_2.spec.ts b/packages/functions/test-tangle/metadata-nft/mint-metadata-nft_2.spec.ts index 16a538559e..8566ec1ccb 100644 --- a/packages/functions/test-tangle/metadata-nft/mint-metadata-nft_2.spec.ts +++ b/packages/functions/test-tangle/metadata-nft/mint-metadata-nft_2.spec.ts @@ -1,14 +1,5 @@ -import { build5Db } from '@build-5/database'; -import { - COL, - Collection, - MIN_IOTA_AMOUNT, - Network, - Space, - TangleRequestType, - Transaction, - TransactionType, -} from '@build-5/interfaces'; +import { PgTransactionType, build5Db } from '@build-5/database'; +import { COL, MIN_IOTA_AMOUNT, Network, Space, TangleRequestType } from '@build-5/interfaces'; import { BasicOutput, RegularTransactionEssence, TransactionPayload } from '@iota/sdk'; import { MnemonicService } from '../../src/services/wallet/mnemonic'; import { Wallet } from '../../src/services/wallet/wallet'; @@ -23,7 +14,7 @@ describe('Metadata nft', () => { 'Should mint metada nft, mint new one for same collection', async (network: Network) => { await helper.beforeEach(network); - const metadata = { mytest: 'mytest', asd: 'asdasdasd' }; + const metadata = { mytest: 'mytest', name: 'asdasdasd' }; await helper.walletService.send( helper.memberAddress, helper.tangleOrder.payload.targetAddress!, @@ -46,7 +37,7 @@ describe('Metadata nft', () => { const mintMetadataNftQuery = build5Db() .collection(COL.TRANSACTION) .where('member', '==', helper.member) - .where('type', '==', TransactionType.METADATA_NFT); + .where('type', '==', PgTransactionType.METADATA_NFT); await wait(async () => { const snap = await mintMetadataNftQuery.get(); return snap.length === 3; @@ -55,16 +46,16 @@ describe('Metadata nft', () => { const creditQuery = build5Db() .collection(COL.TRANSACTION) .where('member', '==', helper.member) - .where('type', '==', TransactionType.CREDIT); + .where('type', '==', PgTransactionType.CREDIT); await wait(async () => { - const snap = await creditQuery.get(); + const snap = await creditQuery.get(); return snap.length === 1 && snap[0]?.payload?.walletReference?.confirmed; }); - const credit = (await creditQuery.get())[0]; + const credit = (await creditQuery.get())[0]; - const space = await build5Db().doc(`${COL.SPACE}/${credit.space}`).get(); + const space = await build5Db().doc(COL.SPACE, credit.space!).get(); const collectionQuery = build5Db().collection(COL.COLLECTION).where('space', '==', space.uid); - const collection = (await collectionQuery.get())[0]; + const collection = (await collectionQuery.get())[0]; await helper.walletService.send( helper.memberAddress, @@ -87,13 +78,13 @@ describe('Metadata nft', () => { ); await wait(async () => { - const snap = await creditQuery.get(); + const snap = await creditQuery.get(); return ( snap.length === 2 && snap.reduce((acc, act) => acc && (act.payload?.walletReference?.confirmed || false), true) ); }); - const credits = await creditQuery.get(); + const credits = await creditQuery.get(); const credit1Meta = await getMetadata( helper.walletService, credits[0].payload.walletReference!.chainReference!, diff --git a/packages/functions/test-tangle/metadata-nft/mint-metadata-nft_3.spec.ts b/packages/functions/test-tangle/metadata-nft/mint-metadata-nft_3.spec.ts index a99119f206..70db5cf8bb 100644 --- a/packages/functions/test-tangle/metadata-nft/mint-metadata-nft_3.spec.ts +++ b/packages/functions/test-tangle/metadata-nft/mint-metadata-nft_3.spec.ts @@ -1,13 +1,5 @@ -import { build5Db } from '@build-5/database'; -import { - COL, - MIN_IOTA_AMOUNT, - Network, - Nft, - TangleRequestType, - Transaction, - TransactionType, -} from '@build-5/interfaces'; +import { PgTransactionType, build5Db } from '@build-5/database'; +import { COL, MIN_IOTA_AMOUNT, Network, TangleRequestType } from '@build-5/interfaces'; import { NftOutput } from '@iota/sdk'; import { MnemonicService } from '../../src/services/wallet/mnemonic'; import { getOutputMetadata } from '../../src/utils/basic-output.utils'; @@ -19,7 +11,7 @@ describe('Metadata nft', () => { it('Should mint metada nft then update metadata', async () => { await helper.beforeEach(Network.RMS); - const metadata = { mytest: 'mytest', asd: 'asdasdasd' }; + const metadata = { mytest: 'mytest', name: 'asdasdasd' }; await helper.walletService.send( helper.memberAddress, helper.tangleOrder.payload.targetAddress!, @@ -42,7 +34,7 @@ describe('Metadata nft', () => { const mintMetadataNftQuery = build5Db() .collection(COL.TRANSACTION) .where('member', '==', helper.member) - .where('type', '==', TransactionType.METADATA_NFT); + .where('type', '==', PgTransactionType.METADATA_NFT); await wait(async () => { const snap = await mintMetadataNftQuery.get(); return snap.length === 3; @@ -51,14 +43,14 @@ describe('Metadata nft', () => { const creditQuery = build5Db() .collection(COL.TRANSACTION) .where('member', '==', helper.member) - .where('type', '==', TransactionType.CREDIT); + .where('type', '==', PgTransactionType.CREDIT); await wait(async () => { - const snap = await creditQuery.get(); + const snap = await creditQuery.get(); return snap.length === 1 && snap[0]?.payload?.walletReference?.confirmed; }); const nftQuery = build5Db().collection(COL.NFT).where('owner', '==', helper.member); - const nft = (await nftQuery.get())[0]; + const nft = (await nftQuery.get())[0]; await helper.walletService.send( helper.memberAddress, @@ -68,7 +60,7 @@ describe('Metadata nft', () => { customMetadata: { request: { requestType: TangleRequestType.MINT_METADATA_NFT, - metadata: { asd: 'hello' }, + metadata: { name: 'hello' }, nftId: nft.mintingData?.nftId, }, }, @@ -81,7 +73,7 @@ describe('Metadata nft', () => { ); await wait(async () => { - const snap = await creditQuery.get(); + const snap = await creditQuery.get(); return ( snap.length === 2 && snap.reduce((acc, act) => acc && (act.payload?.walletReference?.confirmed || false), true) @@ -91,7 +83,7 @@ describe('Metadata nft', () => { let nftOutputId = await helper.walletService.client.nftOutputId(nft.mintingData?.nftId!); let nftOutput = (await helper.walletService.client.getOutput(nftOutputId)).output as NftOutput; let meta = getOutputMetadata(nftOutput); - expect(meta).toEqual({ asd: 'hello' }); + expect(meta).toEqual({ name: 'hello' }); await helper.walletService.send( helper.memberAddress, @@ -101,7 +93,7 @@ describe('Metadata nft', () => { customMetadata: { request: { requestType: TangleRequestType.MINT_METADATA_NFT, - metadata: { asd: 'helloasdasd2' }, + metadata: { name: 'helloasdasd2' }, nftId: nft.mintingData?.nftId, }, }, @@ -114,7 +106,7 @@ describe('Metadata nft', () => { ); await wait(async () => { - const snap = await creditQuery.get(); + const snap = await creditQuery.get(); return ( snap.length === 3 && snap.reduce((acc, act) => acc && (act.payload?.walletReference?.confirmed || false), true) @@ -124,6 +116,6 @@ describe('Metadata nft', () => { nftOutputId = await helper.walletService.client.nftOutputId(nft.mintingData?.nftId!); nftOutput = (await helper.walletService.client.getOutput(nftOutputId)).output as NftOutput; meta = getOutputMetadata(nftOutput); - expect(meta).toEqual({ asd: 'helloasdasd2' }); + expect(meta).toEqual({ name: 'helloasdasd2' }); }); }); diff --git a/packages/functions/test-tangle/metadata-nft/mint-metadata-nft_3_b.spec.ts b/packages/functions/test-tangle/metadata-nft/mint-metadata-nft_3_b.spec.ts index 8bcd35639b..1fc6070aa7 100644 --- a/packages/functions/test-tangle/metadata-nft/mint-metadata-nft_3_b.spec.ts +++ b/packages/functions/test-tangle/metadata-nft/mint-metadata-nft_3_b.spec.ts @@ -1,13 +1,5 @@ -import { build5Db } from '@build-5/database'; -import { - COL, - MIN_IOTA_AMOUNT, - Network, - Nft, - TangleRequestType, - Transaction, - TransactionType, -} from '@build-5/interfaces'; +import { PgTransactionType, build5Db } from '@build-5/database'; +import { COL, MIN_IOTA_AMOUNT, Network, TangleRequestType } from '@build-5/interfaces'; import { NftOutput } from '@iota/sdk'; import { MnemonicService } from '../../src/services/wallet/mnemonic'; import { getOutputMetadata } from '../../src/utils/basic-output.utils'; @@ -19,7 +11,7 @@ describe('Metadata nft', () => { it('Should mint metada nft then update metadata', async () => { await helper.beforeEach(Network.ATOI); - const metadata = { mytest: 'mytest', asd: 'asdasdasd' }; + const metadata = { mytest: 'mytest', name: 'asdasdasd' }; await helper.walletService.send( helper.memberAddress, helper.tangleOrder.payload.targetAddress!, @@ -42,7 +34,7 @@ describe('Metadata nft', () => { const mintMetadataNftQuery = build5Db() .collection(COL.TRANSACTION) .where('member', '==', helper.member) - .where('type', '==', TransactionType.METADATA_NFT); + .where('type', '==', PgTransactionType.METADATA_NFT); await wait(async () => { const snap = await mintMetadataNftQuery.get(); return snap.length === 3; @@ -51,14 +43,14 @@ describe('Metadata nft', () => { const creditQuery = build5Db() .collection(COL.TRANSACTION) .where('member', '==', helper.member) - .where('type', '==', TransactionType.CREDIT); + .where('type', '==', PgTransactionType.CREDIT); await wait(async () => { - const snap = await creditQuery.get(); + const snap = await creditQuery.get(); return snap.length === 1 && snap[0]?.payload?.walletReference?.confirmed; }); const nftQuery = build5Db().collection(COL.NFT).where('owner', '==', helper.member); - const nft = (await nftQuery.get())[0]; + const nft = (await nftQuery.get())[0]; await helper.walletService.send( helper.memberAddress, @@ -68,7 +60,7 @@ describe('Metadata nft', () => { customMetadata: { request: { requestType: TangleRequestType.MINT_METADATA_NFT, - metadata: { asd: 'hello' }, + metadata: { name: 'hello' }, nftId: nft.mintingData?.nftId, }, }, @@ -81,7 +73,7 @@ describe('Metadata nft', () => { ); await wait(async () => { - const snap = await creditQuery.get(); + const snap = await creditQuery.get(); return ( snap.length === 2 && snap.reduce((acc, act) => acc && (act.payload?.walletReference?.confirmed || false), true) @@ -91,7 +83,7 @@ describe('Metadata nft', () => { let nftOutputId = await helper.walletService.client.nftOutputId(nft.mintingData?.nftId!); let nftOutput = (await helper.walletService.client.getOutput(nftOutputId)).output as NftOutput; let meta = getOutputMetadata(nftOutput); - expect(meta).toEqual({ asd: 'hello' }); + expect(meta).toEqual({ name: 'hello' }); await helper.walletService.send( helper.memberAddress, @@ -101,7 +93,7 @@ describe('Metadata nft', () => { customMetadata: { request: { requestType: TangleRequestType.MINT_METADATA_NFT, - metadata: { asd: 'helloasdasd2' }, + metadata: { name: 'helloasdasd2' }, nftId: nft.mintingData?.nftId, }, }, @@ -114,7 +106,7 @@ describe('Metadata nft', () => { ); await wait(async () => { - const snap = await creditQuery.get(); + const snap = await creditQuery.get(); return ( snap.length === 3 && snap.reduce((acc, act) => acc && (act.payload?.walletReference?.confirmed || false), true) @@ -124,6 +116,6 @@ describe('Metadata nft', () => { nftOutputId = await helper.walletService.client.nftOutputId(nft.mintingData?.nftId!); nftOutput = (await helper.walletService.client.getOutput(nftOutputId)).output as NftOutput; meta = getOutputMetadata(nftOutput); - expect(meta).toEqual({ asd: 'helloasdasd2' }); + expect(meta).toEqual({ name: 'helloasdasd2' }); }); }); diff --git a/packages/functions/test-tangle/metadata-nft/mint-metadata-nft_4.spec.ts b/packages/functions/test-tangle/metadata-nft/mint-metadata-nft_4.spec.ts index a21debf61a..a5bbe2a294 100644 --- a/packages/functions/test-tangle/metadata-nft/mint-metadata-nft_4.spec.ts +++ b/packages/functions/test-tangle/metadata-nft/mint-metadata-nft_4.spec.ts @@ -1,15 +1,5 @@ -import { build5Db } from '@build-5/database'; -import { - COL, - Collection, - MIN_IOTA_AMOUNT, - Network, - Nft, - Space, - TangleRequestType, - Transaction, - TransactionType, -} from '@build-5/interfaces'; +import { PgTransactionType, build5Db } from '@build-5/database'; +import { COL, MIN_IOTA_AMOUNT, Network, Space, TangleRequestType } from '@build-5/interfaces'; import { MnemonicService } from '../../src/services/wallet/mnemonic'; import { wait } from '../../test/controls/common'; import { Helper } from './Helper'; @@ -22,7 +12,7 @@ describe('Metadata nft', () => { async (network: Network) => { await helper.beforeEach(network); - const metadata = { mytest: 'mytest', asd: 'asdasdasd' }; + const metadata = { mytest: 'mytest', name: 'asdasdasd' }; await helper.walletService.send( helper.memberAddress, helper.tangleOrder.payload.targetAddress!, @@ -45,7 +35,7 @@ describe('Metadata nft', () => { const mintMetadataNftQuery = build5Db() .collection(COL.TRANSACTION) .where('member', '==', helper.member) - .where('type', '==', TransactionType.METADATA_NFT); + .where('type', '==', PgTransactionType.METADATA_NFT); await wait(async () => { const snap = await mintMetadataNftQuery.get(); return snap.length === 3; @@ -54,14 +44,14 @@ describe('Metadata nft', () => { const creditQuery = build5Db() .collection(COL.TRANSACTION) .where('member', '==', helper.member) - .where('type', '==', TransactionType.CREDIT); + .where('type', '==', PgTransactionType.CREDIT); await wait(async () => { - const snap = await creditQuery.get(); + const snap = await creditQuery.get(); return snap.length === 1 && snap[0]?.payload?.walletReference?.confirmed; }); - const credit = (await creditQuery.get())[0]; + const credit = (await creditQuery.get())[0]; - const space = await build5Db().doc(`${COL.SPACE}/${credit.space}`).get(); + const space = await build5Db().doc(COL.SPACE, credit.space!).get(); await helper.walletService.send( helper.memberAddress, @@ -84,24 +74,21 @@ describe('Metadata nft', () => { ); await wait(async () => { - const snap = await creditQuery.get(); + const snap = await creditQuery.get(); return ( snap.length === 2 && snap.reduce((acc, act) => acc && (act.payload?.walletReference?.confirmed || false), true) ); }); - const nfts = await build5Db() - .collection(COL.NFT) - .where('owner', '==', helper.member) - .get(); + const nfts = await build5Db().collection(COL.NFT).where('owner', '==', helper.member).get(); expect(nfts[0].collection).not.toBe(nfts[1].collection); expect(nfts[0].space).toBe(nfts[1].space); const collections = await build5Db() .collection(COL.COLLECTION) .where('space', '==', space.uid) - .get(); + .get(); expect(collections.length).toBe(2); }, ); diff --git a/packages/functions/test-tangle/metadata-nft/mint-metadata-nft_5.spec.ts b/packages/functions/test-tangle/metadata-nft/mint-metadata-nft_5.spec.ts index c533d56d27..8c2778a9f3 100644 --- a/packages/functions/test-tangle/metadata-nft/mint-metadata-nft_5.spec.ts +++ b/packages/functions/test-tangle/metadata-nft/mint-metadata-nft_5.spec.ts @@ -1,14 +1,5 @@ -import { build5Db } from '@build-5/database'; -import { - COL, - Collection, - MIN_IOTA_AMOUNT, - Network, - Space, - TangleRequestType, - Transaction, - TransactionType, -} from '@build-5/interfaces'; +import { PgTransactionType, build5Db } from '@build-5/database'; +import { COL, MIN_IOTA_AMOUNT, Network, Space, TangleRequestType } from '@build-5/interfaces'; import { MnemonicService } from '../../src/services/wallet/mnemonic'; import { wait } from '../../test/controls/common'; import { Helper } from './Helper'; @@ -19,7 +10,7 @@ describe('Metadata nft', () => { it('Should mint metada nft, mint two new one for same collection&alias, in parallel', async () => { await helper.beforeEach(Network.RMS); - const metadata = { mytest: 'mytest', asd: 'asdasdasd' }; + const metadata = { mytest: 'mytest', name: 'asdasdasd' }; await helper.walletService.send( helper.memberAddress, helper.tangleOrder.payload.targetAddress!, @@ -42,7 +33,7 @@ describe('Metadata nft', () => { const mintMetadataNftQuery = build5Db() .collection(COL.TRANSACTION) .where('member', '==', helper.member) - .where('type', '==', TransactionType.METADATA_NFT); + .where('type', '==', PgTransactionType.METADATA_NFT); await wait(async () => { const snap = await mintMetadataNftQuery.get(); return snap.length === 3; @@ -51,16 +42,16 @@ describe('Metadata nft', () => { const creditQuery = build5Db() .collection(COL.TRANSACTION) .where('member', '==', helper.member) - .where('type', '==', TransactionType.CREDIT); + .where('type', '==', PgTransactionType.CREDIT); await wait(async () => { - const snap = await creditQuery.get(); + const snap = await creditQuery.get(); return snap.length === 1 && snap[0]?.payload?.walletReference?.confirmed; }); - const credit = (await creditQuery.get())[0]; + const credit = (await creditQuery.get())[0]; - const space = await build5Db().doc(`${COL.SPACE}/${credit.space}`).get(); + const space = await build5Db().doc(COL.SPACE, credit.space!).get(); const collection = ( - await build5Db().collection(COL.COLLECTION).where('space', '==', space.uid).get() + await build5Db().collection(COL.COLLECTION).where('space', '==', space.uid).get() )[0]; await helper.walletService.sendToMany( @@ -100,7 +91,7 @@ describe('Metadata nft', () => { ); await wait(async () => { - const snap = await creditQuery.get(); + const snap = await creditQuery.get(); return ( snap.length === 3 && snap.reduce((acc, act) => acc && (act.payload?.walletReference?.confirmed || false), true) diff --git a/packages/functions/test-tangle/metadata-nft/mint-metadata-nft_5_b.spec.ts b/packages/functions/test-tangle/metadata-nft/mint-metadata-nft_5_b.spec.ts index 757b9ae910..e3f81035bb 100644 --- a/packages/functions/test-tangle/metadata-nft/mint-metadata-nft_5_b.spec.ts +++ b/packages/functions/test-tangle/metadata-nft/mint-metadata-nft_5_b.spec.ts @@ -1,14 +1,5 @@ -import { build5Db } from '@build-5/database'; -import { - COL, - Collection, - MIN_IOTA_AMOUNT, - Network, - Space, - TangleRequestType, - Transaction, - TransactionType, -} from '@build-5/interfaces'; +import { PgTransactionType, build5Db } from '@build-5/database'; +import { COL, MIN_IOTA_AMOUNT, Network, Space, TangleRequestType } from '@build-5/interfaces'; import { MnemonicService } from '../../src/services/wallet/mnemonic'; import { wait } from '../../test/controls/common'; import { Helper } from './Helper'; @@ -19,7 +10,7 @@ describe('Metadata nft', () => { it('Should mint metada nft, mint two new one for same collection&alias, in parallel', async () => { await helper.beforeEach(Network.ATOI); - const metadata = { mytest: 'mytest', asd: 'asdasdasd' }; + const metadata = { mytest: 'mytest', name: 'asdasdasd' }; await helper.walletService.send( helper.memberAddress, helper.tangleOrder.payload.targetAddress!, @@ -42,7 +33,7 @@ describe('Metadata nft', () => { const mintMetadataNftQuery = build5Db() .collection(COL.TRANSACTION) .where('member', '==', helper.member) - .where('type', '==', TransactionType.METADATA_NFT); + .where('type', '==', PgTransactionType.METADATA_NFT); await wait(async () => { const snap = await mintMetadataNftQuery.get(); return snap.length === 3; @@ -51,16 +42,16 @@ describe('Metadata nft', () => { const creditQuery = build5Db() .collection(COL.TRANSACTION) .where('member', '==', helper.member) - .where('type', '==', TransactionType.CREDIT); + .where('type', '==', PgTransactionType.CREDIT); await wait(async () => { - const snap = await creditQuery.get(); + const snap = await creditQuery.get(); return snap.length === 1 && snap[0]?.payload?.walletReference?.confirmed; }); - const credit = (await creditQuery.get())[0]; + const credit = (await creditQuery.get())[0]; - const space = await build5Db().doc(`${COL.SPACE}/${credit.space}`).get(); + const space = await build5Db().doc(COL.SPACE, credit.space!).get(); const collection = ( - await build5Db().collection(COL.COLLECTION).where('space', '==', space.uid).get() + await build5Db().collection(COL.COLLECTION).where('space', '==', space.uid).get() )[0]; await helper.walletService.sendToMany( @@ -100,7 +91,7 @@ describe('Metadata nft', () => { ); await wait(async () => { - const snap = await creditQuery.get(); + const snap = await creditQuery.get(); return ( snap.length === 3 && snap.reduce((acc, act) => acc && (act.payload?.walletReference?.confirmed || false), true) diff --git a/packages/functions/test-tangle/metadata-nft/mint-metadata-nft_6.spec.ts b/packages/functions/test-tangle/metadata-nft/mint-metadata-nft_6.spec.ts index cd834e32bd..9e7561a6f2 100644 --- a/packages/functions/test-tangle/metadata-nft/mint-metadata-nft_6.spec.ts +++ b/packages/functions/test-tangle/metadata-nft/mint-metadata-nft_6.spec.ts @@ -1,13 +1,5 @@ -import { build5Db } from '@build-5/database'; -import { - COL, - MIN_IOTA_AMOUNT, - Network, - TangleRequestType, - Transaction, - TransactionType, - WenError, -} from '@build-5/interfaces'; +import { PgTransactionType, build5Db } from '@build-5/database'; +import { COL, MIN_IOTA_AMOUNT, Network, TangleRequestType, WenError } from '@build-5/interfaces'; import { MnemonicService } from '../../src/services/wallet/mnemonic'; import { getRandomEthAddress } from '../../src/utils/wallet.utils'; import { wait } from '../../test/controls/common'; @@ -20,7 +12,7 @@ describe('Metadata nft', () => { 'Should throw invalid nft id on update', async (network: Network) => { await helper.beforeEach(network); - const metadata = { mytest: 'mytest', asd: 'asdasdasd' }; + const metadata = { mytest: 'mytest', name: 'asdasdasd' }; await helper.walletService.send( helper.memberAddress, helper.tangleOrder.payload.targetAddress!, @@ -43,7 +35,7 @@ describe('Metadata nft', () => { const mintMetadataNftQuery = build5Db() .collection(COL.TRANSACTION) .where('member', '==', helper.member) - .where('type', '==', TransactionType.METADATA_NFT); + .where('type', '==', PgTransactionType.METADATA_NFT); await wait(async () => { const snap = await mintMetadataNftQuery.get(); return snap.length === 3; @@ -52,9 +44,9 @@ describe('Metadata nft', () => { let creditQuery = build5Db() .collection(COL.TRANSACTION) .where('member', '==', helper.member) - .where('type', '==', TransactionType.CREDIT); + .where('type', '==', PgTransactionType.CREDIT); await wait(async () => { - const snap = await creditQuery.get(); + const snap = await creditQuery.get(); return snap.length === 1 && snap[0]?.payload?.walletReference?.confirmed; }); @@ -66,7 +58,7 @@ describe('Metadata nft', () => { customMetadata: { request: { requestType: TangleRequestType.MINT_METADATA_NFT, - metadata: { asd: 'hello' }, + metadata: { name: 'hello' }, nftId: getRandomEthAddress(), }, }, @@ -81,12 +73,12 @@ describe('Metadata nft', () => { creditQuery = build5Db() .collection(COL.TRANSACTION) .where('member', '==', helper.member) - .where('type', '==', TransactionType.CREDIT_TANGLE_REQUEST); + .where('type', '==', PgTransactionType.CREDIT_TANGLE_REQUEST); await wait(async () => { - const snap = await creditQuery.get(); + const snap = await creditQuery.get(); return snap.length === 1 && snap[0]?.payload?.walletReference?.confirmed; }); - const snap = await creditQuery.get(); + const snap = await creditQuery.get(); expect((snap[0].payload.response as any).message).toBe(WenError.invalid_nft_id.key); }, ); diff --git a/packages/functions/test-tangle/metadata-nft/mint-metadata-nft_7.spec.ts b/packages/functions/test-tangle/metadata-nft/mint-metadata-nft_7.spec.ts index 6a57aa8e16..d72a04876b 100644 --- a/packages/functions/test-tangle/metadata-nft/mint-metadata-nft_7.spec.ts +++ b/packages/functions/test-tangle/metadata-nft/mint-metadata-nft_7.spec.ts @@ -1,13 +1,5 @@ -import { build5Db } from '@build-5/database'; -import { - COL, - MIN_IOTA_AMOUNT, - Network, - TangleRequestType, - Transaction, - TransactionType, - WenError, -} from '@build-5/interfaces'; +import { PgTransactionType, build5Db } from '@build-5/database'; +import { COL, MIN_IOTA_AMOUNT, Network, TangleRequestType, WenError } from '@build-5/interfaces'; import { MnemonicService } from '../../src/services/wallet/mnemonic'; import { getRandomEthAddress } from '../../src/utils/wallet.utils'; import { wait } from '../../test/controls/common'; @@ -21,7 +13,7 @@ describe('Metadata nft', () => { async (network: Network) => { await helper.beforeEach(network); - const metadata = { mytest: 'mytest', asd: 'asdasdasd' }; + const metadata = { mytest: 'mytest', name: 'asdasdasd' }; await helper.walletService.send( helper.memberAddress, helper.tangleOrder.payload.targetAddress!, @@ -44,7 +36,7 @@ describe('Metadata nft', () => { const mintMetadataNftQuery = build5Db() .collection(COL.TRANSACTION) .where('member', '==', helper.member) - .where('type', '==', TransactionType.METADATA_NFT); + .where('type', '==', PgTransactionType.METADATA_NFT); await wait(async () => { const snap = await mintMetadataNftQuery.get(); return snap.length === 3; @@ -53,9 +45,9 @@ describe('Metadata nft', () => { let creditQuery = build5Db() .collection(COL.TRANSACTION) .where('member', '==', helper.member) - .where('type', '==', TransactionType.CREDIT); + .where('type', '==', PgTransactionType.CREDIT); await wait(async () => { - const snap = await creditQuery.get(); + const snap = await creditQuery.get(); return snap.length === 1 && snap[0]?.payload?.walletReference?.confirmed; }); @@ -76,12 +68,12 @@ describe('Metadata nft', () => { creditQuery = build5Db() .collection(COL.TRANSACTION) .where('member', '==', helper.member) - .where('type', '==', TransactionType.CREDIT_TANGLE_REQUEST); + .where('type', '==', PgTransactionType.CREDIT_TANGLE_REQUEST); await wait(async () => { - const snap = await creditQuery.get(); + const snap = await creditQuery.get(); return snap.length === 1 && snap[0]?.payload?.walletReference?.confirmed; }); - const snap = await creditQuery.get(); + const snap = await creditQuery.get(); expect((snap[0].payload.response as any).message).toBe(WenError.invalid_collection_id.key); }, ); diff --git a/packages/functions/test-tangle/metadata-nft/mint-metadata-nft_8.spec.ts b/packages/functions/test-tangle/metadata-nft/mint-metadata-nft_8.spec.ts index c31ad6270b..f50f5ac5cc 100644 --- a/packages/functions/test-tangle/metadata-nft/mint-metadata-nft_8.spec.ts +++ b/packages/functions/test-tangle/metadata-nft/mint-metadata-nft_8.spec.ts @@ -1,10 +1,9 @@ -import { build5Db } from '@build-5/database'; -import { COL, Network, Nft, Transaction, TransactionType } from '@build-5/interfaces'; +import { PgTransactionType, build5Db } from '@build-5/database'; +import { COL, Network, Transaction, WEN_FUNC } from '@build-5/interfaces'; import { NftOutput } from '@iota/sdk'; -import { mintMetadataNft } from '../../src/runtime/firebase/nft'; import { getOutputMetadata } from '../../src/utils/basic-output.utils'; -import { mockWalletReturnValue, wait } from '../../test/controls/common'; -import { testEnv } from '../../test/set-up'; +import { wait } from '../../test/controls/common'; +import { mockWalletReturnValue, testEnv } from '../../test/set-up'; import { requestFundsFromFaucet } from '../faucet'; import { Helper } from './Helper'; @@ -15,34 +14,34 @@ describe('Metadata nft', () => { const network = Network.RMS; await h.beforeEach(network); - const metadata = { mytest: 'mytest', asd: 'asdasdasd' }; + const metadata = { mytest: 'mytest', name: 'asdasdasd' }; - mockWalletReturnValue(h.walletSpy, h.member, { network, metadata }); - const order: Transaction = await testEnv.wrap(mintMetadataNft)({}); + mockWalletReturnValue(h.member, { network, metadata }); + const order = await testEnv.wrap(WEN_FUNC.mintMetadataNft); await requestFundsFromFaucet(network, order.payload.targetAddress!, order.payload.amount!); - let query = build5Db() + const typeQuery = build5Db() .collection(COL.TRANSACTION) .where('member', '==', h.member) - .where('type', '==', TransactionType.METADATA_NFT); + .where('type', '==', PgTransactionType.METADATA_NFT); await wait(async () => { - const snap = await query.get(); + const snap = await typeQuery.get(); return ( snap.length === 3 && snap.reduce((acc, act) => (acc && act.payload?.walletReference?.confirmed) || false, true) ); }); - query = build5Db() + const addressQuery = build5Db() .collection(COL.NFT) - .where('mintingData.address', '==', order.payload.targetAddress); + .where('mintingData_address', '==', order.payload.targetAddress); await wait(async () => { - const nfts = await query.get(); + const nfts = await addressQuery.get(); return nfts.length === 1; }); - const nft = (await query.get())[0]; + const nft = (await addressQuery.get())[0]; const client = h.walletService.client; const nftOutputId = await client.nftOutputId(nft.mintingData!.nftId!); const nftOutput = (await client.getOutput(nftOutputId)).output as NftOutput; diff --git a/packages/functions/test-tangle/metadata-nft/mint-metadata-nft_9.spec.ts b/packages/functions/test-tangle/metadata-nft/mint-metadata-nft_9.spec.ts index 89efa85fbf..257d262c79 100644 --- a/packages/functions/test-tangle/metadata-nft/mint-metadata-nft_9.spec.ts +++ b/packages/functions/test-tangle/metadata-nft/mint-metadata-nft_9.spec.ts @@ -1,17 +1,9 @@ -import { build5Db } from '@build-5/database'; -import { - COL, - Network, - Nft, - Transaction, - TransactionPayloadType, - TransactionType, -} from '@build-5/interfaces'; +import { PgTransactionPayloadType, PgTransactionType, build5Db } from '@build-5/database'; +import { COL, Network, Transaction, WEN_FUNC } from '@build-5/interfaces'; import { NftOutput } from '@iota/sdk'; -import { mintMetadataNft } from '../../src/runtime/firebase/nft'; import { getOutputMetadata } from '../../src/utils/basic-output.utils'; -import { mockWalletReturnValue, wait } from '../../test/controls/common'; -import { testEnv } from '../../test/set-up'; +import { wait } from '../../test/controls/common'; +import { mockWalletReturnValue, testEnv } from '../../test/set-up'; import { requestFundsFromFaucet } from '../faucet'; import { Helper } from './Helper'; @@ -22,65 +14,65 @@ describe('Metadata nft', () => { const network = Network.RMS; await h.beforeEach(network); - const metadata = { mytest: 'mytest', asd: 'asdasdasd' }; + const metadata = { mytest: 'mytest', sayhi: 'asdasdasd' }; - mockWalletReturnValue(h.walletSpy, h.member, { network, metadata }); - const order: Transaction = await testEnv.wrap(mintMetadataNft)({}); + mockWalletReturnValue(h.member, { network, metadata }); + const order = await testEnv.wrap(WEN_FUNC.mintMetadataNft); await requestFundsFromFaucet(network, order.payload.targetAddress!, order.payload.amount!); - let query = build5Db() + const typeQuery = build5Db() .collection(COL.TRANSACTION) .where('member', '==', h.member) - .where('type', '==', TransactionType.METADATA_NFT); + .where('type', '==', PgTransactionType.METADATA_NFT); await wait(async () => { - const snap = await query.get(); + const snap = await typeQuery.get(); return ( snap.length === 3 && snap.reduce((acc, act) => (acc && act.payload?.walletReference?.confirmed) || false, true) ); }); - query = build5Db() + const addressQuery = build5Db() .collection(COL.NFT) - .where('mintingData.address', '==', order.payload.targetAddress); + .where('mintingData_address', '==', order.payload.targetAddress); await wait(async () => { - const nfts = await query.get(); + const nfts = await addressQuery.get(); return nfts.length === 1; }); - const nft = (await query.get())[0]; + const nft = (await addressQuery.get())[0]; const client = h.walletService.client; let nftOutputId = await client.nftOutputId(nft.mintingData!.nftId!); let nftOutput = (await client.getOutput(nftOutputId)).output as NftOutput; let outputMetadata = getOutputMetadata(nftOutput); expect(outputMetadata).toEqual(metadata); - mockWalletReturnValue(h.walletSpy, h.member, { + mockWalletReturnValue(h.member, { network, - metadata: { asd: 'hello' }, + metadata: { sayhi: 'hello' }, nftId: nft.mintingData?.nftId, }); - const updateOrder: Transaction = await testEnv.wrap(mintMetadataNft)({}); + const updateOrder = await testEnv.wrap(WEN_FUNC.mintMetadataNft); await requestFundsFromFaucet( network, updateOrder.payload.targetAddress!, updateOrder.payload.amount!, ); - query = build5Db() + const typesQuery = build5Db() .collection(COL.TRANSACTION) .where('member', '==', h.member) - .where('type', '==', TransactionType.METADATA_NFT) - .where('payload.type', '==', TransactionPayloadType.UPDATE_MINTED_NFT); + .where('type', '==', PgTransactionType.METADATA_NFT) + .where('payload_type', '==', PgTransactionPayloadType.UPDATE_MINTED_NFT); await wait(async () => { - const snap = await query.get(); + const snap = await typesQuery.get(); return snap.length === 1 && snap[0].payload?.walletReference?.confirmed; }); nftOutputId = await client.nftOutputId(nft.mintingData!.nftId!); nftOutput = (await client.getOutput(nftOutputId)).output as NftOutput; outputMetadata = getOutputMetadata(nftOutput); - expect(outputMetadata).toEqual({ asd: 'hello' }); + expect(outputMetadata).toEqual({ sayhi: 'hello' }); }); }); diff --git a/packages/functions/test-tangle/minted-nft-trading/Helper.ts b/packages/functions/test-tangle/minted-nft-trading/Helper.ts index 9f6b8f95cc..4126b1449a 100644 --- a/packages/functions/test-tangle/minted-nft-trading/Helper.ts +++ b/packages/functions/test-tangle/minted-nft-trading/Helper.ts @@ -2,8 +2,8 @@ import { build5Db } from '@build-5/database'; import { Access, - Categories, COL, + Categories, Collection, CollectionStatus, CollectionType, @@ -18,82 +18,72 @@ import { Transaction, TransactionType, UnsoldMintingOptions, + WEN_FUNC, } from '@build-5/interfaces'; import dayjs from 'dayjs'; -import { createCollection, mintCollection } from '../../src/runtime/firebase/collection/index'; -import { createNft, orderNft, setForSaleNft } from '../../src/runtime/firebase/nft/index'; import { NftWallet } from '../../src/services/wallet/NftWallet'; import { Wallet } from '../../src/services/wallet/wallet'; import { AddressDetails } from '../../src/services/wallet/wallet.service'; import { serverTime } from '../../src/utils/dateTime.utils'; import * as wallet from '../../src/utils/wallet.utils'; -import { - createMember as createMemberTest, - createSpace, - mockWalletReturnValue, - submitMilestoneFunc, - wait, -} from '../../test/controls/common'; -import { getWallet, MEDIA, testEnv } from '../../test/set-up'; +import { submitMilestoneFunc, wait } from '../../test/controls/common'; +import { MEDIA, getWallet, mockWalletReturnValue, testEnv } from '../../test/set-up'; import { getTangleOrder } from '../common'; import { requestFundsFromFaucet } from '../faucet'; export class Helper { - public walletSpy: any | undefined; public network = Network.RMS; - public collection: string | undefined; - public guardian: string | undefined; - public space: Space | undefined; - public royaltySpace: Space | undefined; - public member: string | undefined; - public walletService: Wallet | undefined; - public nftWallet: NftWallet | undefined; - public nft: Nft | undefined; + public collection = ''; + public guardian = ''; + public space: Space = {} as any; + public royaltySpace: Space = {} as any; + public member = ''; + public walletService: Wallet = {} as any; + public nftWallet: NftWallet = {} as any; + public nft: Nft = {} as any; public tangleOrder: Transaction = {} as any; public beforeEach = async (network: Network, collectionType = CollectionType.CLASSIC) => { this.network = network; - this.walletSpy = jest.spyOn(wallet, 'decodeAuth'); this.walletService = await getWallet(this.network); this.nftWallet = new NftWallet(this.walletService); this.tangleOrder = await getTangleOrder(network); - this.guardian = await createMemberTest(this.walletSpy); - this.member = await createMemberTest(this.walletSpy); - this.space = await createSpace(this.walletSpy, this.guardian); - this.royaltySpace = await createSpace(this.walletSpy, this.guardian); + this.guardian = await testEnv.createMember(); + this.member = await testEnv.createMember(); + this.space = await testEnv.createSpace(this.guardian); + this.royaltySpace = await testEnv.createSpace(this.guardian); mockWalletReturnValue( - this.walletSpy, this.guardian, this.createDummyCollection(this.space.uid, this.royaltySpace.uid, collectionType), ); - this.collection = (await testEnv.wrap(createCollection)({})).uid; + this.collection = (await testEnv.wrap(WEN_FUNC.createCollection)).uid; - await build5Db().doc(`${COL.COLLECTION}/${this.collection}`).update({ approved: true }); + await build5Db().doc(COL.COLLECTION, this.collection).update({ approved: true }); }; public mintCollection = async (expiresAt?: Timestamp) => { - mockWalletReturnValue(this.walletSpy, this.guardian!, { + mockWalletReturnValue(this.guardian!, { collection: this.collection, network: this.network, unsoldMintingOptions: UnsoldMintingOptions.KEEP_PRICE, }); - const collectionMintOrder = await testEnv.wrap(mintCollection)({}); + const collectionMintOrder = await testEnv.wrap(WEN_FUNC.mintCollection); await requestFundsFromFaucet( this.network!, collectionMintOrder.payload.targetAddress, collectionMintOrder.payload.amount, expiresAt, ); - const collectionDocRef = build5Db().doc(`${COL.COLLECTION}/${this.collection}`); + const collectionDocRef = build5Db().doc(COL.COLLECTION, this.collection); await wait(async () => { const data = await collectionDocRef.get(); return data.status === CollectionStatus.MINTED; }); - const nftDocRef = build5Db().doc(`${COL.NFT}/${this.nft?.uid}`); + const nftDocRef = build5Db().doc(COL.NFT, this.nft?.uid); this.nft = await nftDocRef.get(); }; @@ -102,37 +92,37 @@ export class Helper { delete nft.uid; delete nft.status; delete nft.placeholderNft; - mockWalletReturnValue(this.walletSpy, this.guardian!, nft); - nft = await testEnv.wrap(createNft)({}); + mockWalletReturnValue(this.guardian!, nft); + nft = await testEnv.wrap(WEN_FUNC.createNft); await build5Db() - .doc(`${COL.NFT}/${nft.uid}`) + .doc(COL.NFT, nft.uid) .update({ availableFrom: dayjs().subtract(1, 'h').toDate() }); if (shouldOrder) { - mockWalletReturnValue(this.walletSpy, this.guardian!, { + mockWalletReturnValue(this.guardian!, { collection: this.collection, nft: nft.uid, }); - const order = await testEnv.wrap(orderNft)({}); + const order = await testEnv.wrap(WEN_FUNC.orderNft); await submitMilestoneFunc(order); } - this.nft = await build5Db().doc(`${COL.NFT}/${nft.uid}`).get(); + this.nft = await build5Db().doc(COL.NFT, nft.uid).get(); return this.nft; }; public setAvailableForAuction = async (nft?: string) => { const uid = nft || this.nft?.uid!; - mockWalletReturnValue(this.walletSpy, this.guardian!, this.dummyAuctionData(uid)); - await testEnv.wrap(setForSaleNft)({}); - await wait(async () => (await build5Db().doc(`${COL.NFT}/${uid}`).get())?.available === 3); + mockWalletReturnValue(this.guardian!, this.dummyAuctionData(uid)); + await testEnv.wrap(WEN_FUNC.setForSaleNft); + await wait(async () => (await build5Db().doc(COL.NFT, uid).get())?.available === 3); }; public setAvailableForSale = async (nftId?: string) => { const uid = nftId || this.nft!.uid; - mockWalletReturnValue(this.walletSpy, this.guardian!, this.dummySaleData(uid)); - await testEnv.wrap(setForSaleNft)({}); - await wait(async () => (await build5Db().doc(`${COL.NFT}/${uid}`).get())?.available === 1); + mockWalletReturnValue(this.guardian!, this.dummySaleData(uid)); + await testEnv.wrap(WEN_FUNC.setForSaleNft); + await wait(async () => (await build5Db().doc(COL.NFT, uid).get())?.available === 1); }; public createDummyCollection = (space: string, royaltiesSpace: string, type: CollectionType) => ({ @@ -197,7 +187,7 @@ export class Helper { nftId, }, }; - await build5Db().doc(`${COL.TRANSACTION}/${order.uid}`).create(order); + await build5Db().doc(COL.TRANSACTION, order.uid).create(order); return order.uid; }; } diff --git a/packages/functions/test-tangle/minted-nft-trading/minted-nft-trading_1.spec.ts b/packages/functions/test-tangle/minted-nft-trading/minted-nft-trading_1.spec.ts index 8f398471d4..b0ea754f87 100644 --- a/packages/functions/test-tangle/minted-nft-trading/minted-nft-trading_1.spec.ts +++ b/packages/functions/test-tangle/minted-nft-trading/minted-nft-trading_1.spec.ts @@ -1,25 +1,24 @@ -import { build5Db } from '@build-5/database'; +import { PgTransactionType, build5Db } from '@build-5/database'; import { COL, - Member, MIN_IOTA_AMOUNT, + Member, Network, Nft, NftStatus, Transaction, - TransactionType, + WEN_FUNC, WenError, } from '@build-5/interfaces'; import { NftOutput } from '@iota/sdk'; import dayjs from 'dayjs'; import { isEmpty } from 'lodash'; import { finalizeAuctions } from '../../src/cron/auction.cron'; -import { openBid, withdrawNft } from '../../src/runtime/firebase/nft/index'; import { getAddress } from '../../src/utils/address.utils'; import { Bech32AddressHelper } from '../../src/utils/bech32-address.helper'; import { dateToTimestamp } from '../../src/utils/dateTime.utils'; -import { expectThrow, mockWalletReturnValue, wait } from '../../test/controls/common'; -import { testEnv } from '../../test/set-up'; +import { expectThrow, wait } from '../../test/controls/common'; +import { mockWalletReturnValue, testEnv } from '../../test/set-up'; import { requestFundsFromFaucet } from '../faucet'; import { Helper } from './Helper'; @@ -33,15 +32,18 @@ describe('Minted nft trading', () => { await helper.setAvailableForAuction(); - const nftDocRef = build5Db().doc(`${COL.NFT}/${helper.nft!.uid}`); + const nftDocRef = build5Db().doc(COL.NFT, helper.nft!.uid); - mockWalletReturnValue(helper.walletSpy, helper.member!, { nft: helper.nft!.uid }); - await expectThrow(testEnv.wrap(withdrawNft)({}), WenError.you_must_be_the_owner_of_nft.key); + mockWalletReturnValue(helper.member!, { nft: helper.nft!.uid }); + await expectThrow( + testEnv.wrap(WEN_FUNC.withdrawNft), + WenError.you_must_be_the_owner_of_nft.key, + ); const expiresAt = dateToTimestamp(dayjs().add(2, 'h').toDate()); - mockWalletReturnValue(helper.walletSpy, helper.member!, { nft: helper.nft!.uid }); - const bidOrder = await testEnv.wrap(openBid)({}); + mockWalletReturnValue(helper.member!, { nft: helper.nft!.uid }); + const bidOrder = await testEnv.wrap(WEN_FUNC.openBid); await requestFundsFromFaucet( Network.RMS, bidOrder.payload.targetAddress, @@ -54,7 +56,7 @@ describe('Minted nft trading', () => { return !isEmpty(helper.nft.auctionHighestBidder); }); - const bidOrder2 = await testEnv.wrap(openBid)({}); + const bidOrder2 = await testEnv.wrap(WEN_FUNC.openBid); await requestFundsFromFaucet( Network.RMS, bidOrder2.payload.targetAddress, @@ -68,16 +70,16 @@ describe('Minted nft trading', () => { const payment = ( await build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.PAYMENT) - .where('payload.sourceTransaction', 'array-contains', bidOrder2.uid) - .get() + .where('type', '==', PgTransactionType.PAYMENT) + .where('payload_sourceTransaction', 'array-contains', bidOrder2.uid as any) + .get() )[0]; return nft.auctionHighestBidder === payment?.member; }); await build5Db() - .doc(`${COL.AUCTION}/${helper.nft!.auction}`) - .update({ auctionTo: dateToTimestamp(dayjs().subtract(1, 'm').toDate()) }); + .doc(COL.AUCTION, helper.nft!.auction!) + .update({ auctionTo: dayjs().subtract(1, 'm').toDate() }); await finalizeAuctions(); @@ -86,8 +88,8 @@ describe('Minted nft trading', () => { return nft.owner === helper.member; }); - mockWalletReturnValue(helper.walletSpy, helper.member!, { nft: helper.nft!.uid }); - await testEnv.wrap(withdrawNft)({}); + mockWalletReturnValue(helper.member!, { nft: helper.nft!.uid }); + await testEnv.wrap(WEN_FUNC.withdrawNft); helper.nft = await nftDocRef.get(); expect(helper.nft.status).toBe(NftStatus.WITHDRAWN); @@ -96,9 +98,9 @@ describe('Minted nft trading', () => { const transaction = ( await build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.WITHDRAW_NFT) - .where('payload.nft', '==', helper.nft!.uid) - .get() + .where('type', '==', PgTransactionType.WITHDRAW_NFT) + .where('payload_nft', '==', helper.nft!.uid) + .get() )[0]; return transaction?.payload?.walletReference?.confirmed; }); @@ -109,7 +111,7 @@ describe('Minted nft trading', () => { ) ).output; const ownerAddress = Bech32AddressHelper.bech32FromUnlockConditions(output as NftOutput, 'rms'); - const member = await build5Db().doc(`${COL.MEMBER}/${helper.member}`).get(); + const member = await build5Db().doc(COL.MEMBER, helper.member).get(); expect(ownerAddress).toBe(getAddress(member, Network.RMS)); }); }); diff --git a/packages/functions/test-tangle/minted-nft-trading/minted-nft-trading_10.spec.ts b/packages/functions/test-tangle/minted-nft-trading/minted-nft-trading_10.spec.ts index d46ed97972..6c375d66ca 100644 --- a/packages/functions/test-tangle/minted-nft-trading/minted-nft-trading_10.spec.ts +++ b/packages/functions/test-tangle/minted-nft-trading/minted-nft-trading_10.spec.ts @@ -3,7 +3,6 @@ import { COL, MIN_IOTA_AMOUNT, Network, - Nft, NftPurchaseTangleRequest, TangleRequestType, } from '@build-5/interfaces'; @@ -64,12 +63,12 @@ describe('Minted nft trading', () => { ); await MnemonicService.store(address.bech32, address.mnemonic, Network.RMS); - const nftDocRef1 = build5Db().doc(`${COL.NFT}/${nft1.uid}`); - const nftDocRef2 = build5Db().doc(`${COL.NFT}/${nft2.uid}`); + const nftDocRef1 = build5Db().doc(COL.NFT, nft1.uid); + const nftDocRef2 = build5Db().doc(COL.NFT, nft2.uid); await wait(async () => { - nft1 = (await nftDocRef1.get())!; - nft2 = (await nftDocRef2.get())!; + nft1 = (await nftDocRef1.get())!; + nft2 = (await nftDocRef2.get())!; return nft1?.owner === address.bech32 && nft2?.owner === address.bech32; }); }); diff --git a/packages/functions/test-tangle/minted-nft-trading/minted-nft-trading_11.only.spec.ts b/packages/functions/test-tangle/minted-nft-trading/minted-nft-trading_11.only.spec.ts index 0770fc11e1..b133effcdc 100644 --- a/packages/functions/test-tangle/minted-nft-trading/minted-nft-trading_11.only.spec.ts +++ b/packages/functions/test-tangle/minted-nft-trading/minted-nft-trading_11.only.spec.ts @@ -1,14 +1,11 @@ -import { build5Db } from '@build-5/database'; +import { PgTransactionType, build5Db } from '@build-5/database'; import { COL, MIN_IOTA_AMOUNT, Network, - Nft, NftPurchaseTangleRequest, NftStatus, TangleRequestType, - Transaction, - TransactionType, } from '@build-5/interfaces'; import { MnemonicService } from '../../src/services/wallet/mnemonic'; import { wait } from '../../test/controls/common'; @@ -21,7 +18,7 @@ describe('Minted nft trading', () => { it('Should buy 2 nft in parallel, and deposit in parallel', async () => { await helper.beforeEach(Network.RMS); const address = await helper.walletService!.getNewIotaAddressDetails(); - requestFundsFromFaucet(Network.RMS, address.bech32, 5 * MIN_IOTA_AMOUNT); + await requestFundsFromFaucet(Network.RMS, address.bech32, 5 * MIN_IOTA_AMOUNT); let nft1 = await helper.createAndOrderNft(); let nft2 = await helper.createAndOrderNft(); @@ -65,17 +62,17 @@ describe('Minted nft trading', () => { ); await MnemonicService.store(address.bech32, address.mnemonic, Network.RMS); - const nftDocRef1 = build5Db().doc(`${COL.NFT}/${nft1.uid}`); - const nftDocRef2 = build5Db().doc(`${COL.NFT}/${nft2.uid}`); - nft1 = (await nftDocRef1.get())!; - nft2 = (await nftDocRef2.get())!; + const nftDocRef1 = build5Db().doc(COL.NFT, nft1.uid); + const nftDocRef2 = build5Db().doc(COL.NFT, nft2.uid); + nft1 = (await nftDocRef1.get())!; + nft2 = (await nftDocRef2.get())!; const query = build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.WITHDRAW_NFT) + .where('type', '==', PgTransactionType.WITHDRAW_NFT) .where('member', '==', address.bech32); await wait(async () => { - const snap = await query.get(); + const snap = await query.get(); return ( snap.length === 2 && snap[0]?.payload?.walletReference?.confirmed && @@ -95,8 +92,8 @@ describe('Minted nft trading', () => { ); await wait(async () => { - nft1 = (await nftDocRef1.get())!; - nft2 = (await nftDocRef2.get())!; + nft1 = (await nftDocRef1.get())!; + nft2 = (await nftDocRef2.get())!; return nft1?.status === NftStatus.MINTED && nft2?.status === NftStatus.MINTED; }); }); diff --git a/packages/functions/test-tangle/minted-nft-trading/minted-nft-trading_1_b.spec.ts b/packages/functions/test-tangle/minted-nft-trading/minted-nft-trading_1_b.spec.ts index 914d625d6e..6da379908d 100644 --- a/packages/functions/test-tangle/minted-nft-trading/minted-nft-trading_1_b.spec.ts +++ b/packages/functions/test-tangle/minted-nft-trading/minted-nft-trading_1_b.spec.ts @@ -1,25 +1,23 @@ -import { build5Db } from '@build-5/database'; +import { PgTransactionType, build5Db } from '@build-5/database'; import { COL, - Member, MIN_IOTA_AMOUNT, + Member, Network, Nft, NftStatus, Transaction, - TransactionType, + WEN_FUNC, WenError, } from '@build-5/interfaces'; import { NftOutput } from '@iota/sdk'; import dayjs from 'dayjs'; import { isEmpty } from 'lodash'; import { finalizeAuctions } from '../../src/cron/auction.cron'; -import { openBid, withdrawNft } from '../../src/runtime/firebase/nft/index'; import { getAddress } from '../../src/utils/address.utils'; import { Bech32AddressHelper } from '../../src/utils/bech32-address.helper'; -import { dateToTimestamp } from '../../src/utils/dateTime.utils'; -import { expectThrow, mockWalletReturnValue, wait } from '../../test/controls/common'; -import { testEnv } from '../../test/set-up'; +import { expectThrow, wait } from '../../test/controls/common'; +import { mockWalletReturnValue, testEnv } from '../../test/set-up'; import { requestFundsFromFaucet } from '../faucet'; import { Helper } from './Helper'; @@ -33,13 +31,16 @@ describe('Minted nft trading', () => { await helper.setAvailableForAuction(); - const nftDocRef = build5Db().doc(`${COL.NFT}/${helper.nft!.uid}`); + const nftDocRef = build5Db().doc(COL.NFT, helper.nft!.uid); - mockWalletReturnValue(helper.walletSpy, helper.member!, { nft: helper.nft!.uid }); - await expectThrow(testEnv.wrap(withdrawNft)({}), WenError.you_must_be_the_owner_of_nft.key); + mockWalletReturnValue(helper.member!, { nft: helper.nft!.uid }); + await expectThrow( + testEnv.wrap(WEN_FUNC.withdrawNft), + WenError.you_must_be_the_owner_of_nft.key, + ); - mockWalletReturnValue(helper.walletSpy, helper.member!, { nft: helper.nft!.uid }); - const bidOrder = await testEnv.wrap(openBid)({}); + mockWalletReturnValue(helper.member!, { nft: helper.nft!.uid }); + const bidOrder = await testEnv.wrap(WEN_FUNC.openBid); await requestFundsFromFaucet(Network.RMS, bidOrder.payload.targetAddress, MIN_IOTA_AMOUNT); await wait(async () => { @@ -47,7 +48,7 @@ describe('Minted nft trading', () => { return !isEmpty(helper.nft.auctionHighestBidder); }); - const bidOrder2 = await testEnv.wrap(openBid)({}); + const bidOrder2 = await testEnv.wrap(WEN_FUNC.openBid); await requestFundsFromFaucet(Network.RMS, bidOrder2.payload.targetAddress, 2 * MIN_IOTA_AMOUNT); await wait(async () => { @@ -56,16 +57,16 @@ describe('Minted nft trading', () => { const payment = ( await build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.PAYMENT) - .where('payload.sourceTransaction', 'array-contains', bidOrder2.uid) - .get() + .where('type', '==', PgTransactionType.PAYMENT) + .where('payload_sourceTransaction', 'array-contains', bidOrder2.uid as any) + .get() )[0]; return helper.nft.auctionHighestBidder === payment?.member; }); await build5Db() - .doc(`${COL.AUCTION}/${helper.nft!.auction}`) - .update({ auctionTo: dateToTimestamp(dayjs().subtract(1, 'm').toDate()) }); + .doc(COL.AUCTION, helper.nft!.auction!) + .update({ auctionTo: dayjs().subtract(1, 'm').toDate() }); await finalizeAuctions(); @@ -74,8 +75,8 @@ describe('Minted nft trading', () => { return nft.owner === helper.member; }); - mockWalletReturnValue(helper.walletSpy, helper.member!, { nft: helper.nft!.uid }); - await testEnv.wrap(withdrawNft)({}); + mockWalletReturnValue(helper.member!, { nft: helper.nft!.uid }); + await testEnv.wrap(WEN_FUNC.withdrawNft); helper.nft = await nftDocRef.get(); expect(helper.nft.status).toBe(NftStatus.WITHDRAWN); @@ -84,9 +85,9 @@ describe('Minted nft trading', () => { const transaction = ( await build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.WITHDRAW_NFT) - .where('payload.nft', '==', helper.nft!.uid) - .get() + .where('type', '==', PgTransactionType.WITHDRAW_NFT) + .where('payload_nft', '==', helper.nft!.uid) + .get() )[0]; return transaction?.payload?.walletReference?.confirmed; }); @@ -97,7 +98,7 @@ describe('Minted nft trading', () => { ) ).output as NftOutput; const ownerAddress = Bech32AddressHelper.bech32FromUnlockConditions(output, 'rms'); - const member = await build5Db().doc(`${COL.MEMBER}/${helper.member}`).get(); + const member = await build5Db().doc(COL.MEMBER, helper.member).get(); expect(ownerAddress).toBe(getAddress(member, Network.ATOI)); }); }); diff --git a/packages/functions/test-tangle/minted-nft-trading/minted-nft-trading_2.spec.ts b/packages/functions/test-tangle/minted-nft-trading/minted-nft-trading_2.spec.ts index ec6f27f362..7bf31b2891 100644 --- a/packages/functions/test-tangle/minted-nft-trading/minted-nft-trading_2.spec.ts +++ b/packages/functions/test-tangle/minted-nft-trading/minted-nft-trading_2.spec.ts @@ -1,4 +1,4 @@ -import { build5Db } from '@build-5/database'; +import { PgTransactionType, build5Db } from '@build-5/database'; import { COL, Member, @@ -6,17 +6,16 @@ import { Nft, NftStatus, Transaction, - TransactionType, + WEN_FUNC, WenError, } from '@build-5/interfaces'; import { NftOutput } from '@iota/sdk'; import dayjs from 'dayjs'; -import { orderNft, withdrawNft } from '../../src/runtime/firebase/nft/index'; import { getAddress } from '../../src/utils/address.utils'; import { Bech32AddressHelper } from '../../src/utils/bech32-address.helper'; import { dateToTimestamp } from '../../src/utils/dateTime.utils'; -import { expectThrow, mockWalletReturnValue, wait } from '../../test/controls/common'; -import { testEnv } from '../../test/set-up'; +import { expectThrow, wait } from '../../test/controls/common'; +import { mockWalletReturnValue, testEnv } from '../../test/set-up'; import { requestFundsFromFaucet } from '../faucet'; import { Helper } from './Helper'; @@ -32,14 +31,17 @@ describe('Minted nft trading', () => { await helper.setAvailableForSale(); - mockWalletReturnValue(helper.walletSpy, helper.member!, { nft: helper.nft!.uid }); - await expectThrow(testEnv.wrap(withdrawNft)({}), WenError.you_must_be_the_owner_of_nft.key); + mockWalletReturnValue(helper.member!, { nft: helper.nft!.uid }); + await expectThrow( + testEnv.wrap(WEN_FUNC.withdrawNft), + WenError.you_must_be_the_owner_of_nft.key, + ); - mockWalletReturnValue(helper.walletSpy, helper.member!, { + mockWalletReturnValue(helper.member!, { collection: helper.collection!, nft: helper.nft!.uid, }); - const order = await testEnv.wrap(orderNft)({}); + const order = await testEnv.wrap(WEN_FUNC.orderNft); await requestFundsFromFaucet( Network.RMS, order.payload.targetAddress, @@ -48,23 +50,23 @@ describe('Minted nft trading', () => { ); await wait(async () => { - const nft = await build5Db().doc(`${COL.NFT}/${helper.nft!.uid}`).get(); + const nft = await build5Db().doc(COL.NFT, helper.nft!.uid).get(); return nft.owner === helper.member; }); - mockWalletReturnValue(helper.walletSpy, helper.member!, { nft: helper.nft!.uid }); - await testEnv.wrap(withdrawNft)({}); + mockWalletReturnValue(helper.member!, { nft: helper.nft!.uid }); + await testEnv.wrap(WEN_FUNC.withdrawNft); - const nft = await build5Db().doc(`${COL.NFT}/${helper.nft!.uid}`).get(); + const nft = await build5Db().doc(COL.NFT, helper.nft!.uid).get(); expect(nft.status).toBe(NftStatus.WITHDRAWN); await wait(async () => { const transaction = ( await build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.WITHDRAW_NFT) - .where('payload.nft', '==', helper.nft!.uid) - .get() + .where('type', '==', PgTransactionType.WITHDRAW_NFT) + .where('payload_nft', '==', helper.nft!.uid) + .get() )[0]; return transaction?.payload?.walletReference?.confirmed; }); @@ -75,7 +77,7 @@ describe('Minted nft trading', () => { ) ).output; const ownerAddress = Bech32AddressHelper.bech32FromUnlockConditions(output as NftOutput, 'rms'); - const member = await build5Db().doc(`${COL.MEMBER}/${helper.member}`).get(); + const member = await build5Db().doc(COL.MEMBER, helper.member).get(); expect(ownerAddress).toBe(getAddress(member, Network.RMS)); }); }); diff --git a/packages/functions/test-tangle/minted-nft-trading/minted-nft-trading_3.spec.ts b/packages/functions/test-tangle/minted-nft-trading/minted-nft-trading_3.spec.ts index 6950bfcc18..47b715e51c 100644 --- a/packages/functions/test-tangle/minted-nft-trading/minted-nft-trading_3.spec.ts +++ b/packages/functions/test-tangle/minted-nft-trading/minted-nft-trading_3.spec.ts @@ -4,12 +4,13 @@ import { Collection, CollectionStatus, Network, + Transaction, UnsoldMintingOptions, + WEN_FUNC, WenError, } from '@build-5/interfaces'; -import { mintCollection } from '../../src/runtime/firebase/collection/index'; -import { expectThrow, mockWalletReturnValue, wait } from '../../test/controls/common'; -import { testEnv } from '../../test/set-up'; +import { expectThrow, wait } from '../../test/controls/common'; +import { mockWalletReturnValue, testEnv } from '../../test/set-up'; import { requestFundsFromFaucet } from '../faucet'; import { Helper } from './Helper'; @@ -20,12 +21,12 @@ describe('Minted nft trading', () => { await helper.beforeEach(Network.RMS); await helper.createAndOrderNft(); - mockWalletReturnValue(helper.walletSpy, helper.guardian!, { + mockWalletReturnValue(helper.guardian!, { collection: helper.collection, network: helper.network, unsoldMintingOptions: UnsoldMintingOptions.KEEP_PRICE, }); - const collectionMintOrder = await testEnv.wrap(mintCollection)({}); + const collectionMintOrder = await testEnv.wrap(WEN_FUNC.mintCollection); await requestFundsFromFaucet( helper.network!, collectionMintOrder.payload.targetAddress, @@ -33,9 +34,7 @@ describe('Minted nft trading', () => { ); await wait(async () => { - const collection = ( - await build5Db().doc(`${COL.COLLECTION}/${helper.collection}`).get() - ); + const collection = await build5Db().doc(COL.COLLECTION, helper.collection).get(); return collection.status === CollectionStatus.MINTING; }); diff --git a/packages/functions/test-tangle/minted-nft-trading/minted-nft-trading_4.spec.ts b/packages/functions/test-tangle/minted-nft-trading/minted-nft-trading_4.spec.ts index a0d8180463..cff124be07 100644 --- a/packages/functions/test-tangle/minted-nft-trading/minted-nft-trading_4.spec.ts +++ b/packages/functions/test-tangle/minted-nft-trading/minted-nft-trading_4.spec.ts @@ -1,4 +1,4 @@ -import { build5Db } from '@build-5/database'; +import { PgTransactionPayloadType, PgTransactionType, build5Db } from '@build-5/database'; import { COL, Collection, @@ -7,9 +7,6 @@ import { Nft, NftStatus, TangleRequestType, - Transaction, - TransactionPayloadType, - TransactionType, } from '@build-5/interfaces'; import { MnemonicService } from '../../src/services/wallet/mnemonic'; import { wait } from '../../test/controls/common'; @@ -47,14 +44,14 @@ describe('Minted nft trading', () => { const snap = await build5Db() .collection(COL.TRANSACTION) .where('member', '==', address.bech32) - .where('type', '==', TransactionType.CREDIT_TANGLE_REQUEST) - .get(); + .where('type', '==', PgTransactionType.CREDIT_TANGLE_REQUEST) + .get(); return snap.length > 0 && snap[0]?.payload?.walletReference?.confirmed; }); await helper.setAvailableForSale(); - const collectionDocRef = build5Db().doc(`${COL.COLLECTION}/${helper.nft?.collection}`); + const collectionDocRef = build5Db().doc(COL.COLLECTION, helper.nft?.collection); let collection = await collectionDocRef.get(); expect(collection.nftsOnSale).toBe(1); expect(collection.nftsOnAuction).toBe(0); @@ -74,7 +71,7 @@ describe('Minted nft trading', () => { }, ); - const nftDocRef = build5Db().doc(`${COL.NFT}/${helper.nft?.uid}`); + const nftDocRef = build5Db().doc(COL.NFT, helper.nft?.uid); await wait(async () => { const nft = await nftDocRef.get(); return nft.status === NftStatus.WITHDRAWN; @@ -84,8 +81,8 @@ describe('Minted nft trading', () => { const snap = await build5Db() .collection(COL.TRANSACTION) .where('member', '==', address.bech32) - .where('type', '==', TransactionType.WITHDRAW_NFT) - .get(); + .where('type', '==', PgTransactionType.WITHDRAW_NFT) + .get(); return snap.length > 0 && snap[0]?.payload?.walletReference?.confirmed; }); @@ -100,9 +97,9 @@ describe('Minted nft trading', () => { const orders = await build5Db() .collection(COL.TRANSACTION) - .where('payload.type', '==', TransactionPayloadType.NFT_PURCHASE) - .where('payload.nft', '==', helper.nft!.uid) - .get(); + .where('payload_type', '==', PgTransactionPayloadType.NFT_PURCHASE) + .where('payload_nft', '==', helper.nft!.uid) + .get(); for (const order of orders) { expect(order.payload.restrictions!.collection).toEqual({ access: collection.access, @@ -110,16 +107,16 @@ describe('Minted nft trading', () => { accessCollections: collection.accessCollections || [], }); expect(order.payload.restrictions!.nft).toEqual({ - saleAccess: helper.nft!.saleAccess || null, + saleAccess: helper.nft!.saleAccess || undefined, saleAccessMembers: helper.nft!.saleAccessMembers || [], }); } const billPayments = await build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.BILL_PAYMENT) - .where('payload.nft', '==', helper.nft!.uid) - .get(); + .where('type', '==', PgTransactionType.BILL_PAYMENT) + .where('payload_nft', '==', helper.nft!.uid) + .get(); for (const billPayment of billPayments) { expect(billPayment.payload.restrictions).toEqual(orders[0].payload.restrictions); } diff --git a/packages/functions/test-tangle/minted-nft-trading/minted-nft-trading_5.spec.ts b/packages/functions/test-tangle/minted-nft-trading/minted-nft-trading_5.spec.ts index 6ac9f123f6..faf9070a33 100644 --- a/packages/functions/test-tangle/minted-nft-trading/minted-nft-trading_5.spec.ts +++ b/packages/functions/test-tangle/minted-nft-trading/minted-nft-trading_5.spec.ts @@ -1,4 +1,4 @@ -import { build5Db } from '@build-5/database'; +import { PgTransactionType, build5Db } from '@build-5/database'; import { COL, Collection, @@ -7,7 +7,6 @@ import { Nft, TangleRequestType, Transaction, - TransactionType, } from '@build-5/interfaces'; import { MnemonicService } from '../../src/services/wallet/mnemonic'; import { wait } from '../../test/controls/common'; @@ -44,15 +43,15 @@ describe('Minted nft trading', () => { const creditQuery = build5Db() .collection(COL.TRANSACTION) .where('member', '==', address.bech32) - .where('type', '==', TransactionType.CREDIT_TANGLE_REQUEST); + .where('type', '==', PgTransactionType.CREDIT_TANGLE_REQUEST); await wait(async () => { - const snap = await creditQuery.get(); + const snap = await creditQuery.get(); return snap.length > 0 && snap[0]?.payload?.walletReference?.confirmed; }); const snap = await creditQuery.get(); const credit = snap[0] as Transaction; - const collectionDocRef = build5Db().doc(`${COL.COLLECTION}/${helper.nft?.collection}`); + const collectionDocRef = build5Db().doc(COL.COLLECTION, helper.nft?.collection); const collection = await collectionDocRef.get(); expect(collection.availableNfts).toBe(1); expect(collection.nftsOnSale).toBe(0); @@ -69,7 +68,7 @@ describe('Minted nft trading', () => { {}, ); - const nftDocRef = build5Db().doc(`${COL.NFT}/${helper.nft?.uid}`); + const nftDocRef = build5Db().doc(COL.NFT, helper.nft?.uid); await wait(async () => { const nft = await nftDocRef.get(); return nft.sold || false; @@ -78,7 +77,7 @@ describe('Minted nft trading', () => { expect(nft.owner).toBe(address.bech32); await wait(async () => { - const collectionDocRef = build5Db().doc(`${COL.COLLECTION}/${helper.nft?.collection}`); + const collectionDocRef = build5Db().doc(COL.COLLECTION, helper.nft?.collection); const collection = await collectionDocRef.get(); return !collection.availableNfts && !collection.nftsOnSale && !collection.nftsOnAuction; }); diff --git a/packages/functions/test-tangle/minted-nft-trading/minted-nft-trading_6.spec.ts b/packages/functions/test-tangle/minted-nft-trading/minted-nft-trading_6.spec.ts index 59d73936da..bb58612d51 100644 --- a/packages/functions/test-tangle/minted-nft-trading/minted-nft-trading_6.spec.ts +++ b/packages/functions/test-tangle/minted-nft-trading/minted-nft-trading_6.spec.ts @@ -1,12 +1,10 @@ -import { build5Db } from '@build-5/database'; +import { PgTransactionType, build5Db } from '@build-5/database'; import { COL, CollectionType, MIN_IOTA_AMOUNT, Network, TangleRequestType, - Transaction, - TransactionType, } from '@build-5/interfaces'; import { MnemonicService } from '../../src/services/wallet/mnemonic'; import { wait } from '../../test/controls/common'; @@ -45,8 +43,8 @@ describe('Minted nft trading', () => { const snap = await build5Db() .collection(COL.TRANSACTION) .where('member', '==', address.bech32) - .where('type', '==', TransactionType.WITHDRAW_NFT) - .get(); + .where('type', '==', PgTransactionType.WITHDRAW_NFT) + .get(); return snap.length > 0 && snap[0]?.payload?.walletReference?.confirmed; }); const nftOutputIds = await helper.walletService!.client.nftOutputIds([ diff --git a/packages/functions/test-tangle/minted-nft-trading/minted-nft-trading_7.spec.ts b/packages/functions/test-tangle/minted-nft-trading/minted-nft-trading_7.spec.ts index afe142ac32..6a3636ed36 100644 --- a/packages/functions/test-tangle/minted-nft-trading/minted-nft-trading_7.spec.ts +++ b/packages/functions/test-tangle/minted-nft-trading/minted-nft-trading_7.spec.ts @@ -1,4 +1,4 @@ -import { build5Db } from '@build-5/database'; +import { PgTransactionPayloadType, PgTransactionType, build5Db } from '@build-5/database'; import { COL, Collection, @@ -8,9 +8,6 @@ import { NftStatus, TangleRequestType, TangleResponse, - Transaction, - TransactionPayloadType, - TransactionType, } from '@build-5/interfaces'; import { MnemonicService } from '../../src/services/wallet/mnemonic'; import { wait } from '../../test/controls/common'; @@ -51,20 +48,20 @@ describe('Minted nft trading', () => { const creditQuery = build5Db() .collection(COL.TRANSACTION) .where('member', '==', address.bech32) - .where('type', '==', TransactionType.CREDIT_TANGLE_REQUEST); + .where('type', '==', PgTransactionType.CREDIT_TANGLE_REQUEST); await wait(async () => { - const snap = await creditQuery.get(); + const snap = await creditQuery.get(); return snap.length > 0 && snap[0].payload?.walletReference?.confirmed; }); - const snap = await creditQuery.get(); + const snap = await creditQuery.get(); const credit = snap[0]; const response = credit.payload.response as TangleResponse; await helper.walletService!.send(address, response.address!, response.amount!, {}); await MnemonicService.store(address.bech32, address.mnemonic, Network.RMS); - const nftDocRef = build5Db().doc(`${COL.NFT}/${helper.nft?.uid}`); + const nftDocRef = build5Db().doc(COL.NFT, helper.nft?.uid); await wait(async () => { const nft = await nftDocRef.get(); return nft.status === NftStatus.WITHDRAWN; @@ -74,8 +71,8 @@ describe('Minted nft trading', () => { const snap = await build5Db() .collection(COL.TRANSACTION) .where('member', '==', address.bech32) - .where('type', '==', TransactionType.WITHDRAW_NFT) - .get(); + .where('type', '==', PgTransactionType.WITHDRAW_NFT) + .get(); return snap.length > 0 && snap[0].payload?.walletReference?.confirmed; }); @@ -84,22 +81,22 @@ describe('Minted nft trading', () => { ]); expect(nftOutputIds.items.length).toBe(1); - const collectionDocRef = build5Db().doc(`${COL.COLLECTION}/${helper.nft?.collection}`); + const collectionDocRef = build5Db().doc(COL.COLLECTION, helper.nft?.collection); const collection = await collectionDocRef.get(); expect(collection.nftsOnSale).toBe(0); expect(collection.nftsOnAuction).toBe(0); const orders = await build5Db() .collection(COL.TRANSACTION) - .where('payload.type', '==', TransactionPayloadType.NFT_PURCHASE) - .where('payload.nft', '==', helper.nft!.uid) - .get(); + .where('payload_type', '==', PgTransactionPayloadType.NFT_PURCHASE) + .where('payload_nft', '==', helper.nft!.uid) + .get(); const billPayments = await build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.BILL_PAYMENT) - .where('payload.nft', '==', helper.nft!.uid) - .get(); + .where('type', '==', PgTransactionType.BILL_PAYMENT) + .where('payload_nft', '==', helper.nft!.uid) + .get(); for (const billPayment of billPayments) { expect(billPayment.payload.restrictions).toEqual(orders[0].payload.restrictions); } diff --git a/packages/functions/test-tangle/minted-nft-trading/minted-nft-trading_8.spec.ts b/packages/functions/test-tangle/minted-nft-trading/minted-nft-trading_8.spec.ts index ff3519abd0..4fc1d596c7 100644 --- a/packages/functions/test-tangle/minted-nft-trading/minted-nft-trading_8.spec.ts +++ b/packages/functions/test-tangle/minted-nft-trading/minted-nft-trading_8.spec.ts @@ -3,7 +3,6 @@ import { COL, MIN_IOTA_AMOUNT, Network, - Nft, NftPurchaseTangleRequest, NftStatus, TangleRequestType, @@ -44,9 +43,9 @@ describe('Minted nft trading', () => { ); await MnemonicService.store(address.bech32, address.mnemonic, Network.RMS); - const nftDocRef = build5Db().doc(`${COL.NFT}/${helper.nft!.uid}`); + const nftDocRef = build5Db().doc(COL.NFT, helper.nft!.uid); await wait(async () => { - const nft = await nftDocRef.get(); + const nft = await nftDocRef.get(); return nft?.owner === address.bech32 && nft.status === NftStatus.MINTED; }); }, diff --git a/packages/functions/test-tangle/minted-token-airdrop/Helper.ts b/packages/functions/test-tangle/minted-token-airdrop/Helper.ts index e87370af8d..f0414ae780 100644 --- a/packages/functions/test-tangle/minted-token-airdrop/Helper.ts +++ b/packages/functions/test-tangle/minted-token-airdrop/Helper.ts @@ -1,5 +1,5 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ -import { build5Db } from '@build-5/database'; +import { PgTokenDropStatus, build5Db } from '@build-5/database'; import { COL, Network, @@ -7,39 +7,36 @@ import { Space, Token, TokenDrop, - TokenDropStatus, TokenStatus, } from '@build-5/interfaces'; import { MnemonicService } from '../../src/services/wallet/mnemonic'; import { Wallet } from '../../src/services/wallet/wallet'; import { serverTime } from '../../src/utils/dateTime.utils'; import * as wallet from '../../src/utils/wallet.utils'; -import { createMember, createSpace, getRandomSymbol } from '../../test/controls/common'; -import { MEDIA, getWallet } from '../../test/set-up'; +import { getRandomSymbol } from '../../test/controls/common'; +import { MEDIA, getWallet, testEnv } from '../../test/set-up'; export class Helper { public network = Network.RMS; - public space: Space | undefined; - public token: Token | undefined; + public space: Space = {} as any; + public token: Token = {} as any; - public guardian: string | undefined; - public member: string | undefined; - public walletService: Wallet | undefined; - public walletSpy: any; + public guardian = ''; + public member = ''; + public walletService: Wallet = {} as any; public berforeAll = async () => { this.walletService = await getWallet(this.network); - this.walletSpy = jest.spyOn(wallet, 'decodeAuth'); }; public beforeEach = async () => { - this.guardian = await createMember(this.walletSpy); - this.member = await createMember(this.walletSpy); - this.space = await createSpace(this.walletSpy, this.guardian); + this.guardian = await testEnv.createMember(); + this.member = await testEnv.createMember(); + this.space = await testEnv.createSpace(this.guardian); this.token = (await saveToken(this.space.uid, this.guardian, this.walletService!)) as Token; }; - public getAirdropsForMember = async (member: string, status = TokenDropStatus.UNCLAIMED) => { + public getAirdropsForMember = async (member: string, status = PgTokenDropStatus.UNCLAIMED) => { const snap = await build5Db() .collection(COL.AIRDROP) .where('member', '==', member) @@ -76,8 +73,8 @@ export const saveToken = async ( }, access: 0, icon: MEDIA, - }; - await build5Db().doc(`${COL.TOKEN}/${token.uid}`).set(token); + } as Token; + await build5Db().doc(COL.TOKEN, token.uid).create(token); return token; }; diff --git a/packages/functions/test-tangle/minted-token-airdrop/minted-token-airdrop_1_a.spec.ts b/packages/functions/test-tangle/minted-token-airdrop/minted-token-airdrop_1_a.spec.ts index fa48f13c1c..fafae96c11 100644 --- a/packages/functions/test-tangle/minted-token-airdrop/minted-token-airdrop_1_a.spec.ts +++ b/packages/functions/test-tangle/minted-token-airdrop/minted-token-airdrop_1_a.spec.ts @@ -1,6 +1,6 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ -import { build5Db } from '@build-5/database'; +import { PgTokenDropStatus, PgTransactionType, build5Db } from '@build-5/database'; import { COL, MIN_IOTA_AMOUNT, @@ -9,22 +9,17 @@ import { StakeType, Token, TokenDistribution, - TokenDropStatus, TokenStats, Transaction, TransactionPayloadType, - TransactionType, + WEN_FUNC, WenError, } from '@build-5/interfaces'; import dayjs from 'dayjs'; -import { head } from 'lodash'; -import { - airdropMintedToken, - claimMintedTokenOrder, -} from '../../src/runtime/firebase/token/minting'; +import { head, isEmpty } from 'lodash'; import { getAddress } from '../../src/utils/address.utils'; -import { expectThrow, mockWalletReturnValue, wait } from '../../test/controls/common'; -import { testEnv } from '../../test/set-up'; +import { expectThrow, wait } from '../../test/controls/common'; +import { mockWalletReturnValue, testEnv } from '../../test/set-up'; import { awaitTransactionConfirmationsForToken } from '../common'; import { requestFundsFromFaucet, requestMintedTokenFromFaucet } from '../faucet'; import { Helper, VAULT_MNEMONIC } from './Helper'; @@ -51,17 +46,20 @@ describe('Minted token airdrop', () => { { count: 1, recipient: helper.member!, vestingAt: dayjs().add(2, 'M').toDate(), stakeType }, ]; const total = drops.reduce((acc, act) => acc + act.count, 0); - mockWalletReturnValue(helper.walletSpy, helper.guardian!, { + mockWalletReturnValue(helper.guardian!, { token: helper.token!.uid, drops, }); - let order = await testEnv.wrap(airdropMintedToken)({}); + let order = await testEnv.wrap(WEN_FUNC.airdropMintedToken); expect(order.payload.unclaimedAirdrops).toBe(2); - mockWalletReturnValue(helper.walletSpy, helper.member!, { symbol: helper.token!.symbol }); - await expectThrow(testEnv.wrap(claimMintedTokenOrder)({}), WenError.no_tokens_to_claim.key); + mockWalletReturnValue(helper.member!, { symbol: helper.token!.symbol }); + await expectThrow( + testEnv.wrap(WEN_FUNC.claimMintedTokenOrder), + WenError.no_tokens_to_claim.key, + ); - const guardian = await build5Db().doc(`${COL.MEMBER}/${helper.guardian}`).get(); + const guardian = await build5Db().doc(COL.MEMBER, helper.guardian!).get(); const guardianAddress = await helper.walletService!.getAddressDetails( getAddress(guardian, helper.network), ); @@ -74,7 +72,7 @@ describe('Minted token airdrop', () => { total, ); - await helper.walletService!.send(guardianAddress, order.payload.targetAddress, 0, { + await helper.walletService!.send(guardianAddress, order.payload.targetAddress!, 0, { nativeTokens: [{ id: helper.token?.mintingData?.tokenId!, amount: BigInt(total) }], }); @@ -84,16 +82,19 @@ describe('Minted token airdrop', () => { }); const distributionDocRef = build5Db().doc( - `${COL.TOKEN}/${helper.token!.uid}/${SUB_COL.DISTRIBUTION}/${helper.member}`, + COL.TOKEN, + helper.token!.uid, + SUB_COL.DISTRIBUTION, + helper.member, ); let distribution = await distributionDocRef.get(); expect(distribution.totalUnclaimedAirdrop).toBe(2); - mockWalletReturnValue(helper.walletSpy, helper.member!, { + mockWalletReturnValue(helper.member!, { symbol: helper.token!.symbol, }); - const claimOrder = await testEnv.wrap(claimMintedTokenOrder)({}); - const claimOrder2 = await testEnv.wrap(claimMintedTokenOrder)({}); + const claimOrder = await testEnv.wrap(WEN_FUNC.claimMintedTokenOrder); + const claimOrder2 = await testEnv.wrap(WEN_FUNC.claimMintedTokenOrder); await requestFundsFromFaucet( helper.network, claimOrder.payload.targetAddress, @@ -106,12 +107,12 @@ describe('Minted token airdrop', () => { ); await wait(async () => { - const orderDocRef = build5Db().doc(`${COL.TRANSACTION}/${order.uid}`); + const orderDocRef = build5Db().doc(COL.TRANSACTION, order.uid); order = await orderDocRef.get(); return order.payload.unclaimedAirdrops === 0; }); - const airdrops = await helper.getAirdropsForMember(helper.member!, TokenDropStatus.CLAIMED); + const airdrops = await helper.getAirdropsForMember(helper.member!, PgTokenDropStatus.CLAIMED); expect(airdrops.length).toBe(2); await awaitTransactionConfirmationsForToken(helper.token!.uid); @@ -119,7 +120,7 @@ describe('Minted token airdrop', () => { const billPayments = ( await build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.BILL_PAYMENT) + .where('type', '==', PgTransactionType.BILL_PAYMENT) .where('member', '==', helper.member) .get() ).map((d) => d as Transaction); @@ -129,25 +130,26 @@ describe('Minted token airdrop', () => { expect(billPayment.payload.tokenSymbol).toBe(helper.token!.symbol); expect(billPayment.payload.type).toBe(TransactionPayloadType.MINTED_AIRDROP_CLAIM); }); + for (let i = 0; i < drops.length; ++i) { - expect( - billPayments.find((bp) => { - if (dayjs(drops[i].vestingAt).isBefore(dayjs())) { - return bp.payload.vestingAt === null; - } - return ( - bp.payload.vestingAt && - dayjs(bp.payload.vestingAt.toDate()).isSame(dayjs(drops[i].vestingAt)) - ); - }), - ).toBeDefined(); + const billPayment = billPayments.find((bp) => { + if (dayjs(drops[i].vestingAt).isBefore(dayjs())) { + return isEmpty(bp.payload.vestingAt); + } + + return ( + bp.payload.vestingAt && + dayjs(bp.payload.vestingAt.toDate()).isSame(dayjs(drops[i].vestingAt)) + ); + }); + expect(billPayment).toBeDefined(); } await wait(async () => { const snap = await build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.CREDIT) - .where('member', 'in', [helper.guardian, helper.member]) + .where('type', '==', PgTransactionType.CREDIT) + .whereIn('member', [helper.guardian, helper.member]) .get(); return snap.length === 2; }); @@ -155,7 +157,7 @@ describe('Minted token airdrop', () => { const { amount } = await helper.walletService!.getBalance(guardianAddress.bech32); expect(amount).toBe(5 * MIN_IOTA_AMOUNT); - const member = await build5Db().doc(`${COL.MEMBER}/${helper.member}`).get(); + const member = await build5Db().doc(COL.MEMBER, helper.member!).get(); const memberAddress = await helper.walletService!.getAddressDetails( getAddress(member, helper.network), ); @@ -178,10 +180,10 @@ describe('Minted token airdrop', () => { const tokenUid = helper.token?.uid; - helper.token = await build5Db().doc(`${COL.TOKEN}/${tokenUid}`).get(); + helper.token = await build5Db().doc(COL.TOKEN, tokenUid!).get(); expect(helper.token.mintingData?.tokensInVault).toBe(0); - const statsDocRef = build5Db().doc(`${COL.TOKEN}/${tokenUid}/${SUB_COL.STATS}/${tokenUid}`); + const statsDocRef = build5Db().doc(COL.TOKEN, tokenUid!, SUB_COL.STATS, tokenUid); const tokenStats = await statsDocRef.get(); expect(tokenStats.stakes![stakeType]?.amount).toBe(1); expect(tokenStats.stakes![stakeType]?.totalAmount).toBe(1); diff --git a/packages/functions/test-tangle/minted-token-airdrop/minted-token-airdrop_1_b.spec.ts b/packages/functions/test-tangle/minted-token-airdrop/minted-token-airdrop_1_b.spec.ts index e6b59c77d8..37da29e6f4 100644 --- a/packages/functions/test-tangle/minted-token-airdrop/minted-token-airdrop_1_b.spec.ts +++ b/packages/functions/test-tangle/minted-token-airdrop/minted-token-airdrop_1_b.spec.ts @@ -1,6 +1,6 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ -import { build5Db } from '@build-5/database'; +import { PgTokenDropStatus, PgTransactionType, build5Db } from '@build-5/database'; import { COL, MIN_IOTA_AMOUNT, @@ -9,23 +9,18 @@ import { StakeType, Token, TokenDistribution, - TokenDropStatus, TokenStats, Transaction, TransactionPayloadType, - TransactionType, + WEN_FUNC, WenError, } from '@build-5/interfaces'; import dayjs from 'dayjs'; import { head } from 'lodash'; -import { - airdropMintedToken, - claimMintedTokenOrder, -} from '../../src/runtime/firebase/token/minting'; import { getAddress } from '../../src/utils/address.utils'; import { dateToTimestamp } from '../../src/utils/dateTime.utils'; -import { expectThrow, mockWalletReturnValue, wait } from '../../test/controls/common'; -import { testEnv } from '../../test/set-up'; +import { expectThrow, wait } from '../../test/controls/common'; +import { mockWalletReturnValue, testEnv } from '../../test/set-up'; import { awaitTransactionConfirmationsForToken } from '../common'; import { requestFundsFromFaucet, requestMintedTokenFromFaucet } from '../faucet'; import { Helper, VAULT_MNEMONIC } from './Helper'; @@ -53,17 +48,20 @@ describe('Minted token airdrop', () => { { count: 1, recipient: helper.member!, vestingAt: dayjs().add(2, 'M').toDate(), stakeType }, ]; const total = drops.reduce((acc, act) => acc + act.count, 0); - mockWalletReturnValue(helper.walletSpy, helper.guardian!, { + mockWalletReturnValue(helper.guardian!, { token: helper.token!.uid, drops, }); - let order = await testEnv.wrap(airdropMintedToken)({}); + let order = await testEnv.wrap(WEN_FUNC.airdropMintedToken); expect(order.payload.unclaimedAirdrops).toBe(2); - mockWalletReturnValue(helper.walletSpy, helper.member!, { symbol: helper.token!.symbol }); - await expectThrow(testEnv.wrap(claimMintedTokenOrder)({}), WenError.no_tokens_to_claim.key); + mockWalletReturnValue(helper.member!, { symbol: helper.token!.symbol }); + await expectThrow( + testEnv.wrap(WEN_FUNC.claimMintedTokenOrder), + WenError.no_tokens_to_claim.key, + ); - const guardian = await build5Db().doc(`${COL.MEMBER}/${helper.guardian}`).get(); + const guardian = await build5Db().doc(COL.MEMBER, helper.guardian).get(); const guardianAddress = await helper.walletService!.getAddressDetails( getAddress(guardian, helper.network), ); @@ -82,7 +80,7 @@ describe('Minted token airdrop', () => { expiresAt, ); - await helper.walletService!.send(guardianAddress, order.payload.targetAddress, 0, { + await helper.walletService!.send(guardianAddress, order.payload.targetAddress!, 0, { expiration: expiresAt ? { expiresAt, returnAddressBech32: guardianAddress.bech32 } : undefined, @@ -95,16 +93,19 @@ describe('Minted token airdrop', () => { }); const distributionDocRef = build5Db().doc( - `${COL.TOKEN}/${helper.token!.uid}/${SUB_COL.DISTRIBUTION}/${helper.member}`, + COL.TOKEN, + helper.token!.uid, + SUB_COL.DISTRIBUTION, + helper.member, ); let distribution = await distributionDocRef.get(); expect(distribution.totalUnclaimedAirdrop).toBe(2); - mockWalletReturnValue(helper.walletSpy, helper.member!, { + mockWalletReturnValue(helper.member!, { symbol: helper.token!.symbol, }); - const claimOrder = await testEnv.wrap(claimMintedTokenOrder)({}); - const claimOrder2 = await testEnv.wrap(claimMintedTokenOrder)({}); + const claimOrder = await testEnv.wrap(WEN_FUNC.claimMintedTokenOrder); + const claimOrder2 = await testEnv.wrap(WEN_FUNC.claimMintedTokenOrder); await requestFundsFromFaucet( helper.network, claimOrder.payload.targetAddress, @@ -119,12 +120,12 @@ describe('Minted token airdrop', () => { ); await wait(async () => { - const orderDocRef = build5Db().doc(`${COL.TRANSACTION}/${order.uid}`); + const orderDocRef = build5Db().doc(COL.TRANSACTION, order.uid); order = await orderDocRef.get(); return order.payload.unclaimedAirdrops === 0; }); - const airdrops = await helper.getAirdropsForMember(helper.member!, TokenDropStatus.CLAIMED); + const airdrops = await helper.getAirdropsForMember(helper.member!, PgTokenDropStatus.CLAIMED); expect(airdrops.length).toBe(2); await awaitTransactionConfirmationsForToken(helper.token!.uid); @@ -132,7 +133,7 @@ describe('Minted token airdrop', () => { const billPayments = ( await build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.BILL_PAYMENT) + .where('type', '==', PgTransactionType.BILL_PAYMENT) .where('member', '==', helper.member) .get() ).map((d) => d as Transaction); @@ -146,7 +147,7 @@ describe('Minted token airdrop', () => { expect( billPayments.find((bp) => { if (dayjs(drops[i].vestingAt).isBefore(dayjs())) { - return bp.payload.vestingAt === null; + return bp.payload.vestingAt === undefined; } return ( bp.payload.vestingAt && @@ -159,8 +160,8 @@ describe('Minted token airdrop', () => { await wait(async () => { const snap = await build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.CREDIT) - .where('member', 'in', [helper.guardian, helper.member]) + .where('type', '==', PgTransactionType.CREDIT) + .whereIn('member', [helper.guardian, helper.member]) .get(); return snap.length === 2; }); @@ -168,7 +169,7 @@ describe('Minted token airdrop', () => { const { amount } = await helper.walletService!.getBalance(guardianAddress.bech32); expect(amount).toBe(5 * MIN_IOTA_AMOUNT); - const member = await build5Db().doc(`${COL.MEMBER}/${helper.member}`).get(); + const member = await build5Db().doc(COL.MEMBER, helper.member).get(); const memberAddress = await helper.walletService!.getAddressDetails( getAddress(member, helper.network), ); @@ -191,10 +192,10 @@ describe('Minted token airdrop', () => { const tokenUid = helper.token?.uid; - helper.token = await build5Db().doc(`${COL.TOKEN}/${tokenUid}`).get(); + helper.token = await build5Db().doc(COL.TOKEN, tokenUid).get(); expect(helper.token.mintingData?.tokensInVault).toBe(0); - const statsDocRef = build5Db().doc(`${COL.TOKEN}/${tokenUid}/${SUB_COL.STATS}/${tokenUid}`); + const statsDocRef = build5Db().doc(COL.TOKEN, tokenUid, SUB_COL.STATS, tokenUid); const tokenStats = await statsDocRef.get(); expect(tokenStats.stakes![stakeType]?.amount).toBe(1); expect(tokenStats.stakes![stakeType]?.totalAmount).toBe(1); diff --git a/packages/functions/test-tangle/minted-token-airdrop/minted-token-airdrop_1_c.spec.ts b/packages/functions/test-tangle/minted-token-airdrop/minted-token-airdrop_1_c.spec.ts index dca93dcbb7..e854c83352 100644 --- a/packages/functions/test-tangle/minted-token-airdrop/minted-token-airdrop_1_c.spec.ts +++ b/packages/functions/test-tangle/minted-token-airdrop/minted-token-airdrop_1_c.spec.ts @@ -11,15 +11,12 @@ import { TokenDrop, TokenDropStatus, Transaction, + WEN_FUNC, } from '@build-5/interfaces'; import dayjs from 'dayjs'; -import { - airdropMintedToken, - claimMintedTokenOrder, -} from '../../src/runtime/firebase/token/minting'; import { getAddress } from '../../src/utils/address.utils'; -import { mockWalletReturnValue, wait } from '../../test/controls/common'; -import { testEnv } from '../../test/set-up'; +import { wait } from '../../test/controls/common'; +import { mockWalletReturnValue, testEnv } from '../../test/set-up'; import { awaitTransactionConfirmationsForToken } from '../common'; import { requestFundsFromFaucet, requestMintedTokenFromFaucet } from '../faucet'; import { Helper, VAULT_MNEMONIC } from './Helper'; @@ -45,11 +42,11 @@ describe('Minted token airdrop', () => { stakeType, }, ]; - mockWalletReturnValue(helper.walletSpy, helper.guardian!, { + mockWalletReturnValue(helper.guardian!, { token: helper.token!.uid, drops, }); - let order = await testEnv.wrap(airdropMintedToken)({}); + let order = await testEnv.wrap(WEN_FUNC.airdropMintedToken); const airdropQuery = build5Db().collection(COL.AIRDROP).where('member', '==', helper.member); let airdropsSnap = await airdropQuery.get(); @@ -62,7 +59,7 @@ describe('Minted token airdrop', () => { expect(airdrop.token).toEqual(helper.token?.uid!); expect(airdrop.status).toEqual(TokenDropStatus.DEPOSIT_NEEDED); - const guardianDocRef = build5Db().doc(`${COL.MEMBER}/${helper.guardian}`); + const guardianDocRef = build5Db().doc(COL.MEMBER, helper.guardian); const guardian = await guardianDocRef.get(); const guardianAddress = await helper.walletService!.getAddressDetails( getAddress(guardian, helper.network), @@ -76,19 +73,19 @@ describe('Minted token airdrop', () => { 1, ); - await helper.walletService!.send(guardianAddress, order.payload.targetAddress, 0, { + await helper.walletService!.send(guardianAddress, order.payload.targetAddress!, 0, { nativeTokens: [{ id: helper.token?.mintingData?.tokenId!, amount: BigInt(1) }], }); await wait(async () => { - const airdropsSnap = await airdropQuery.get(); + const airdropsSnap = await airdropQuery.get(); return airdropsSnap.length === 1 && airdropsSnap[0]?.status === TokenDropStatus.UNCLAIMED; }); - mockWalletReturnValue(helper.walletSpy, helper.member!, { + mockWalletReturnValue(helper.member!, { symbol: helper.token!.symbol, }); - const claimOrder = await testEnv.wrap(claimMintedTokenOrder)({}); + const claimOrder = await testEnv.wrap(WEN_FUNC.claimMintedTokenOrder); await requestFundsFromFaucet( helper.network, claimOrder.payload.targetAddress, @@ -96,7 +93,7 @@ describe('Minted token airdrop', () => { ); await wait(async () => { - const docRef = build5Db().doc(`${COL.TRANSACTION}/${order.uid}`); + const docRef = build5Db().doc(COL.TRANSACTION, order.uid); order = await docRef.get(); return order.payload.unclaimedAirdrops === 0; }); @@ -104,7 +101,10 @@ describe('Minted token airdrop', () => { await awaitTransactionConfirmationsForToken(helper.token!.uid); const distributionDocRef = build5Db().doc( - `${COL.TOKEN}/${helper.token!.uid}/${SUB_COL.DISTRIBUTION}/${helper.member}`, + COL.TOKEN, + helper.token!.uid, + SUB_COL.DISTRIBUTION, + helper.member, ); const distribution = await distributionDocRef.get(); expect(distribution?.stakes![stakeType].value).toBe(2); diff --git a/packages/functions/test-tangle/minted-token-airdrop/minted-token-airdrop_2.spec.ts b/packages/functions/test-tangle/minted-token-airdrop/minted-token-airdrop_2.spec.ts index 04e51db5b3..542eb63c8e 100644 --- a/packages/functions/test-tangle/minted-token-airdrop/minted-token-airdrop_2.spec.ts +++ b/packages/functions/test-tangle/minted-token-airdrop/minted-token-airdrop_2.spec.ts @@ -1,10 +1,10 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ -import { build5Db } from '@build-5/database'; +import { PgTokenStatus, PgTransactionType, build5Db } from '@build-5/database'; import { COL, - Member, MIN_IOTA_AMOUNT, + Member, SOON_PROJECT_ID, SUB_COL, Token, @@ -13,19 +13,14 @@ import { TokenDropStatus, TokenStatus, Transaction, - TransactionType, + WEN_FUNC, } from '@build-5/interfaces'; import dayjs from 'dayjs'; -import { - airdropMintedToken, - claimMintedTokenOrder, - mintTokenOrder, -} from '../../src/runtime/firebase/token/minting'; import { getAddress } from '../../src/utils/address.utils'; import { dateToTimestamp, serverTime } from '../../src/utils/dateTime.utils'; import { getRandomEthAddress } from '../../src/utils/wallet.utils'; -import { mockWalletReturnValue, wait } from '../../test/controls/common'; -import { testEnv } from '../../test/set-up'; +import { wait } from '../../test/controls/common'; +import { mockWalletReturnValue, testEnv } from '../../test/set-up'; import { awaitTransactionConfirmationsForToken } from '../common'; import { requestFundsFromFaucet } from '../faucet'; import { Helper } from './Helper'; @@ -42,14 +37,29 @@ describe('Minted token airdrop', () => { }); it('Mint token, airdrop then claim all', async () => { - await build5Db().doc(`${COL.TOKEN}/${helper.token!.uid}`).update({ - mintingData: {}, - status: TokenStatus.AVAILABLE, + await build5Db().doc(COL.TOKEN, helper.token!.uid).update({ + mintingData_mintedBy: undefined, + mintingData_mintedOn: undefined, + mintingData_aliasBlockId: undefined, + mintingData_aliasId: undefined, + mintingData_aliasStorageDeposit: undefined, + mintingData_tokenId: undefined, + mintingData_blockId: undefined, + mintingData_foundryStorageDeposit: undefined, + mintingData_network: undefined, + mintingData_networkFormat: undefined, + mintingData_vaultAddress: undefined, + mintingData_tokensInVault: undefined, + mintingData_vaultStorageDeposit: undefined, + mintingData_guardianStorageDeposit: undefined, + mintingData_meltedTokens: undefined, + mintingData_circulatingSupply: undefined, + status: PgTokenStatus.AVAILABLE, totalSupply: Number.MAX_SAFE_INTEGER, }); await build5Db() - .doc(`${COL.TOKEN}/${helper.token!.uid}/${SUB_COL.DISTRIBUTION}/${helper.member}`) - .set({ tokenOwned: 1 }); + .doc(COL.TOKEN, helper.token!.uid, SUB_COL.DISTRIBUTION, helper.member) + .upsert({ tokenOwned: 1 }); const airdrop: TokenDrop = { project: SOON_PROJECT_ID, @@ -62,27 +72,27 @@ describe('Minted token airdrop', () => { count: 1, status: TokenDropStatus.UNCLAIMED, }; - await build5Db().doc(`${COL.AIRDROP}/${airdrop.uid}`).create(airdrop); + await build5Db().doc(COL.AIRDROP, airdrop.uid).create(airdrop); - mockWalletReturnValue(helper.walletSpy, helper.guardian!, { + mockWalletReturnValue(helper.guardian!, { token: helper.token!.uid, network: helper.network, }); - const mintingOrder = await testEnv.wrap(mintTokenOrder)({}); + const mintingOrder = await testEnv.wrap(WEN_FUNC.mintTokenOrder); await requestFundsFromFaucet( helper.network, mintingOrder.payload.targetAddress, mintingOrder.payload.amount, ); - const guardian = await build5Db().doc(`${COL.MEMBER}/${helper.guardian}`).get(); + const guardian = await build5Db().doc(COL.MEMBER, helper.guardian).get(); await requestFundsFromFaucet( helper.network, getAddress(guardian, helper.network), MIN_IOTA_AMOUNT, ); await wait(async () => { - const tokenDocRef = await build5Db().doc(`${COL.TOKEN}/${helper.token!.uid}`).get(); + const tokenDocRef = await build5Db().doc(COL.TOKEN, helper.token!.uid).get(); return tokenDocRef?.status === TokenStatus.MINTED; }); @@ -90,16 +100,16 @@ describe('Minted token airdrop', () => { { count: 1, recipient: helper.member!, vestingAt: dayjs().subtract(1, 'm').toDate() }, { count: 1, recipient: helper.member!, vestingAt: dayjs().add(2, 'h').toDate() }, ]; - mockWalletReturnValue(helper.walletSpy, helper.guardian!, { + mockWalletReturnValue(helper.guardian!, { token: helper.token!.uid, drops, }); - let order = await testEnv.wrap(airdropMintedToken)({}); + let order = await testEnv.wrap(WEN_FUNC.airdropMintedToken); const guardianAddress = await helper.walletService!.getAddressDetails( getAddress(guardian, helper.network), ); - const token = await build5Db().doc(`${COL.TOKEN}/${helper.token!.uid}`).get(); - await helper.walletService!.send(guardianAddress, order.payload.targetAddress, 0, { + const token = await build5Db().doc(COL.TOKEN, helper.token!.uid).get(); + await helper.walletService!.send(guardianAddress, order.payload.targetAddress!, 0, { nativeTokens: [{ id: token.mintingData?.tokenId!, amount: BigInt(2) }], }); @@ -108,22 +118,25 @@ describe('Minted token airdrop', () => { return airdrops.length === 3; }); - mockWalletReturnValue(helper.walletSpy, helper.member!, { symbol: helper.token!.symbol }); - const claimOrder = await testEnv.wrap(claimMintedTokenOrder)({}); + mockWalletReturnValue(helper.member!, { symbol: helper.token!.symbol }); + const claimOrder = await testEnv.wrap(WEN_FUNC.claimMintedTokenOrder); await requestFundsFromFaucet( helper.network, claimOrder.payload.targetAddress, claimOrder.payload.amount, ); - const orderDocRef = build5Db().doc(`${COL.TRANSACTION}/${order.uid}`); + const orderDocRef = build5Db().doc(COL.TRANSACTION, order.uid); await wait(async () => { order = await orderDocRef.get(); return order.payload.unclaimedAirdrops === 0; }); const distributionDocRef = build5Db().doc( - `${COL.TOKEN}/${helper.token!.uid}/${SUB_COL.DISTRIBUTION}/${helper.member}`, + COL.TOKEN, + helper.token!.uid, + SUB_COL.DISTRIBUTION, + helper.member, ); const distribution = await distributionDocRef.get(); expect(distribution?.tokenOwned).toBe(4); @@ -134,7 +147,7 @@ describe('Minted token airdrop', () => { const billPayments = ( await build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.BILL_PAYMENT) + .where('type', '==', PgTransactionType.BILL_PAYMENT) .where('member', '==', helper.member) .get() ).map((d) => d as Transaction); @@ -143,13 +156,13 @@ describe('Minted token airdrop', () => { const credit = ( await build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.CREDIT) + .where('type', '==', PgTransactionType.CREDIT) .where('member', '==', order.member) .get() ).map((d) => d); expect(credit.length).toBe(2); - const member = await build5Db().doc(`${COL.MEMBER}/${helper.member}`).get(); + const member = await build5Db().doc(COL.MEMBER, helper.member).get(); const memberAddress = await helper.walletService!.getAddressDetails( getAddress(member, helper.network), ); diff --git a/packages/functions/test-tangle/minted-token-airdrop/minted-token-airdrop_4.spec.ts b/packages/functions/test-tangle/minted-token-airdrop/minted-token-airdrop_4.spec.ts index 41b524c924..be7c606727 100644 --- a/packages/functions/test-tangle/minted-token-airdrop/minted-token-airdrop_4.spec.ts +++ b/packages/functions/test-tangle/minted-token-airdrop/minted-token-airdrop_4.spec.ts @@ -1,26 +1,24 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ -import { build5Db } from '@build-5/database'; +import { PgTokenDropStatus, PgTransactionType, build5Db } from '@build-5/database'; import { COL, - Member, MIN_IOTA_AMOUNT, + Member, Network, - StakeType, SUB_COL, + StakeType, TangleRequestType, TokenDistribution, - TokenDropStatus, Transaction, - TransactionType, + WEN_FUNC, } from '@build-5/interfaces'; import dayjs from 'dayjs'; -import { airdropMintedToken } from '../../src/runtime/firebase/token/minting'; import { MnemonicService } from '../../src/services/wallet/mnemonic'; import { getAddress } from '../../src/utils/address.utils'; import { dateToTimestamp } from '../../src/utils/dateTime.utils'; -import { mockWalletReturnValue, wait } from '../../test/controls/common'; -import { testEnv } from '../../test/set-up'; +import { wait } from '../../test/controls/common'; +import { mockWalletReturnValue, testEnv } from '../../test/set-up'; import { awaitTransactionConfirmationsForToken, getTangleOrder } from '../common'; import { requestFundsFromFaucet, requestMintedTokenFromFaucet } from '../faucet'; import { Helper, VAULT_MNEMONIC } from './Helper'; @@ -50,14 +48,14 @@ describe('Minted token airdrop tangle claim', () => { { count: 1, recipient: helper.member!, vestingAt: dayjs().add(2, 'M').toDate(), stakeType }, ]; const total = drops.reduce((acc, act) => acc + act.count, 0); - mockWalletReturnValue(helper.walletSpy, helper.guardian!, { + mockWalletReturnValue(helper.guardian!, { token: helper.token!.uid, drops, }); - const airdropOrder = await testEnv.wrap(airdropMintedToken)({}); + const airdropOrder = await testEnv.wrap(WEN_FUNC.airdropMintedToken); expect(airdropOrder.payload.unclaimedAirdrops).toBe(2); - const guardian = await build5Db().doc(`${COL.MEMBER}/${helper.guardian}`).get(); + const guardian = await build5Db().doc(COL.MEMBER, helper.guardian).get(); const guardianAddress = await helper.walletService!.getAddressDetails( getAddress(guardian, helper.network), ); @@ -76,7 +74,7 @@ describe('Minted token airdrop tangle claim', () => { expiresAt, ); - await helper.walletService!.send(guardianAddress, airdropOrder.payload.targetAddress, 0, { + await helper.walletService!.send(guardianAddress, airdropOrder.payload.targetAddress!, 0, { expiration: expiresAt ? { expiresAt, returnAddressBech32: guardianAddress.bech32 } : undefined, @@ -89,12 +87,15 @@ describe('Minted token airdrop tangle claim', () => { }); const distributionDocRef = build5Db().doc( - `${COL.TOKEN}/${helper.token!.uid}/${SUB_COL.DISTRIBUTION}/${helper.member}`, + COL.TOKEN, + helper.token!.uid, + SUB_COL.DISTRIBUTION, + helper.member, ); let distribution = await distributionDocRef.get(); expect(distribution.totalUnclaimedAirdrop).toBe(2); - const member = await build5Db().doc(`${COL.MEMBER}/${helper.member}`).get(); + const member = await build5Db().doc(COL.MEMBER, helper.member).get(); const memberAddress = await helper.walletService!.getAddressDetails( getAddress(member, helper.network), ); @@ -118,7 +119,7 @@ describe('Minted token airdrop tangle claim', () => { const orderQuery = build5Db() .collection(COL.TRANSACTION) .where('member', '==', helper.member) - .where('type', '==', TransactionType.CREDIT_TANGLE_REQUEST); + .where('type', '==', PgTransactionType.CREDIT_TANGLE_REQUEST); await wait(async () => { const snap = await orderQuery.get(); @@ -134,12 +135,12 @@ describe('Minted token airdrop tangle claim', () => { ); await wait(async () => { - const orderDocRef = build5Db().doc(`${COL.TRANSACTION}/${airdropOrder.uid}`); + const orderDocRef = build5Db().doc(COL.TRANSACTION, airdropOrder.uid); const order = await orderDocRef.get(); return order.payload.unclaimedAirdrops === 0; }); - const airdrops = await helper.getAirdropsForMember(helper.member!, TokenDropStatus.CLAIMED); + const airdrops = await helper.getAirdropsForMember(helper.member!, PgTokenDropStatus.CLAIMED); expect(airdrops.length).toBe(2); await awaitTransactionConfirmationsForToken(helper.token!.uid); diff --git a/packages/functions/test-tangle/minted-token-airdrop/minted-token-airdrop_5.spec.ts b/packages/functions/test-tangle/minted-token-airdrop/minted-token-airdrop_5.spec.ts index f19541b52e..18ddafbd08 100644 --- a/packages/functions/test-tangle/minted-token-airdrop/minted-token-airdrop_5.spec.ts +++ b/packages/functions/test-tangle/minted-token-airdrop/minted-token-airdrop_5.spec.ts @@ -2,23 +2,20 @@ import { COL, - Member, MIN_IOTA_AMOUNT, + Member, SUB_COL, TokenDistribution, Transaction, + WEN_FUNC, WenError, } from '@build-5/interfaces'; import { build5Db } from '@build-5/database'; import dayjs from 'dayjs'; -import { - airdropMintedToken, - claimMintedTokenOrder, -} from '../../src/runtime/firebase/token/minting'; import { getAddress } from '../../src/utils/address.utils'; -import { expectThrow, mockWalletReturnValue, wait } from '../../test/controls/common'; -import { testEnv } from '../../test/set-up'; +import { expectThrow, wait } from '../../test/controls/common'; +import { mockWalletReturnValue, testEnv } from '../../test/set-up'; import { requestFundsFromFaucet, requestMintedTokenFromFaucet } from '../faucet'; import { Helper, VAULT_MNEMONIC } from './Helper'; @@ -34,7 +31,7 @@ describe('Minted token airdrop', () => { }); it('Should airdrop and claim 600', async () => { - mockWalletReturnValue(helper.walletSpy, helper.guardian!, { + mockWalletReturnValue(helper.guardian!, { token: helper.token!.uid, drops: Array.from(Array(600)).map(() => ({ count: 1, @@ -42,13 +39,16 @@ describe('Minted token airdrop', () => { vestingAt: dayjs().add(1, 'y').toDate(), })), }); - let order = await testEnv.wrap(airdropMintedToken)({}); + let order = await testEnv.wrap(WEN_FUNC.airdropMintedToken); expect(order.payload.unclaimedAirdrops).toBe(600); - mockWalletReturnValue(helper.walletSpy, helper.member!, { symbol: helper.token!.symbol }); - await expectThrow(testEnv.wrap(claimMintedTokenOrder)({}), WenError.no_tokens_to_claim.key); + mockWalletReturnValue(helper.member!, { symbol: helper.token!.symbol }); + await expectThrow( + testEnv.wrap(WEN_FUNC.claimMintedTokenOrder), + WenError.no_tokens_to_claim.key, + ); - const guardian = await build5Db().doc(`${COL.MEMBER}/${helper.guardian}`).get(); + const guardian = await build5Db().doc(COL.MEMBER, helper.guardian).get(); const guardianAddress = await helper.walletService!.getAddressDetails( getAddress(guardian, helper.network), ); @@ -60,7 +60,7 @@ describe('Minted token airdrop', () => { VAULT_MNEMONIC, 600, ); - await helper.walletService!.send(guardianAddress, order.payload.targetAddress, 0, { + await helper.walletService!.send(guardianAddress, order.payload.targetAddress!, 0, { nativeTokens: [{ id: helper.token?.mintingData?.tokenId!, amount: BigInt(600) }], }); @@ -69,10 +69,10 @@ describe('Minted token airdrop', () => { return airdrops.length === 600; }); - mockWalletReturnValue(helper.walletSpy, helper.member!, { + mockWalletReturnValue(helper.member!, { symbol: helper.token!.symbol, }); - const claimOrder = await testEnv.wrap(claimMintedTokenOrder)({}); + const claimOrder = await testEnv.wrap(WEN_FUNC.claimMintedTokenOrder); await requestFundsFromFaucet( helper.network, claimOrder.payload.targetAddress, @@ -80,13 +80,16 @@ describe('Minted token airdrop', () => { ); await wait(async () => { - const orderDocRef = build5Db().doc(`${COL.TRANSACTION}/${order.uid}`); + const orderDocRef = build5Db().doc(COL.TRANSACTION, order.uid); order = await orderDocRef.get(); return order.payload.unclaimedAirdrops === 0; }); const distributionDocRef = build5Db().doc( - `${COL.TOKEN}/${helper.token?.uid}/${SUB_COL.DISTRIBUTION}/${helper.member!}`, + COL.TOKEN, + helper.token?.uid, + SUB_COL.DISTRIBUTION, + helper.member!, ); const distribution = await distributionDocRef.get(); expect(distribution.tokenOwned).toBe(600); diff --git a/packages/functions/test-tangle/minted-token-claim/Helper.ts b/packages/functions/test-tangle/minted-token-claim/Helper.ts index 9fd421173c..edc213b337 100644 --- a/packages/functions/test-tangle/minted-token-claim/Helper.ts +++ b/packages/functions/test-tangle/minted-token-claim/Helper.ts @@ -1,14 +1,21 @@ import { build5Db } from '@build-5/database'; -import { COL, Member, Network, SOON_PROJECT_ID, Space, TokenStatus } from '@build-5/interfaces'; +import { + COL, + Member, + Network, + SOON_PROJECT_ID, + Space, + Token, + TokenStatus, +} from '@build-5/interfaces'; import { MnemonicService } from '../../src/services/wallet/mnemonic'; import { Wallet } from '../../src/services/wallet/wallet'; import { serverTime } from '../../src/utils/dateTime.utils'; import * as walletUtil from '../../src/utils/wallet.utils'; -import { createMember, createSpace, getRandomSymbol } from '../../test/controls/common'; -import { MEDIA, getWallet } from '../../test/set-up'; +import { getRandomSymbol } from '../../test/controls/common'; +import { MEDIA, getWallet, testEnv } from '../../test/set-up'; export class Helper { - public walletSpy: any; public network = Network.RMS; public guardian: Member = {} as any; public space: Space = {} as any; @@ -17,12 +24,11 @@ export class Helper { public beforeEach = async (vaultMnemonic: string, mintedTokenId: string, notMinted = false) => { this.wallet = await getWallet(this.network); - this.walletSpy = jest.spyOn(walletUtil, 'decodeAuth'); - const guardianId = await createMember(this.walletSpy); - this.guardian = await build5Db().doc(`${COL.MEMBER}/${guardianId}`).get(); + const guardianId = await testEnv.createMember(); + this.guardian = await build5Db().doc(COL.MEMBER, guardianId).get(); - this.space = await createSpace(this.walletSpy, this.guardian.uid); + this.space = await testEnv.createSpace(this.guardian.uid); this.token = await this.saveToken( this.space.uid, this.guardian.uid, @@ -64,8 +70,8 @@ export class Helper { access: 0, totalSupply: 10, icon: MEDIA, - }; - await build5Db().doc(`${COL.TOKEN}/${token.uid}`).set(token); + } as Token; + await build5Db().doc(COL.TOKEN, token.uid).create(token); return token; }; } diff --git a/packages/functions/test-tangle/minted-token-claim/token.claim.minted_1.spec.ts b/packages/functions/test-tangle/minted-token-claim/token.claim.minted_1.spec.ts index 5af97d7f21..e8cb2fcf27 100644 --- a/packages/functions/test-tangle/minted-token-claim/token.claim.minted_1.spec.ts +++ b/packages/functions/test-tangle/minted-token-claim/token.claim.minted_1.spec.ts @@ -1,10 +1,9 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ -import { build5Db } from '@build-5/database'; -import { COL, SUB_COL, Token, Transaction, TransactionType } from '@build-5/interfaces'; -import { claimMintedTokenOrder } from '../../src/runtime/firebase/token/minting'; -import { mockWalletReturnValue, wait } from '../../test/controls/common'; -import { testEnv } from '../../test/set-up'; +import { PgTransactionType, build5Db } from '@build-5/database'; +import { COL, SUB_COL, Token, Transaction, WEN_FUNC } from '@build-5/interfaces'; +import { wait } from '../../test/controls/common'; +import { mockWalletReturnValue, testEnv } from '../../test/set-up'; import { awaitTransactionConfirmationsForToken } from '../common'; import { requestFundsFromFaucet } from '../faucet'; import { Helper } from './Helper'; @@ -18,16 +17,16 @@ describe('Token minting', () => { it('Claim minted tokens by guardian', async () => { await build5Db() - .doc(`${COL.TOKEN}/${helper.token.uid}/${SUB_COL.DISTRIBUTION}/${helper.guardian.uid}`) - .set({ tokenOwned: 1 }); + .doc(COL.TOKEN, helper.token.uid, SUB_COL.DISTRIBUTION, helper.guardian.uid) + .upsert({ tokenOwned: 1 }); - mockWalletReturnValue(helper.walletSpy, helper.guardian.uid, { symbol: helper.token.symbol }); - const order = await testEnv.wrap(claimMintedTokenOrder)({}); + mockWalletReturnValue(helper.guardian.uid, { symbol: helper.token.symbol }); + const order = await testEnv.wrap(WEN_FUNC.claimMintedTokenOrder); await requestFundsFromFaucet(helper.network, order.payload.targetAddress, order.payload.amount); const query = build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.BILL_PAYMENT) + .where('type', '==', PgTransactionType.BILL_PAYMENT) .where('member', '==', helper.guardian.uid); await wait(async () => { const snap = await query.get(); @@ -37,7 +36,7 @@ describe('Token minting', () => { expect(billPayment.payload.amount).toBe(order.payload.amount); expect(billPayment.payload.nativeTokens![0].amount).toBe(1); - const tokenData = await build5Db().doc(`${COL.TOKEN}/${helper.token.uid}`).get(); + const tokenData = await build5Db().doc(COL.TOKEN, helper.token.uid).get(); expect(tokenData.mintingData?.tokensInVault).toBe(9); await awaitTransactionConfirmationsForToken(helper.token.uid); diff --git a/packages/functions/test-tangle/minted-token-claim/token.claim.minted_2.spec.ts b/packages/functions/test-tangle/minted-token-claim/token.claim.minted_2.spec.ts index 8c6e5b6035..597b82308e 100644 --- a/packages/functions/test-tangle/minted-token-claim/token.claim.minted_2.spec.ts +++ b/packages/functions/test-tangle/minted-token-claim/token.claim.minted_2.spec.ts @@ -1,6 +1,6 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ -import { build5Db } from '@build-5/database'; +import { PgTransactionType, build5Db } from '@build-5/database'; import { COL, SOON_PROJECT_ID, @@ -9,15 +9,14 @@ import { TokenDrop, TokenDropStatus, Transaction, - TransactionType, + WEN_FUNC, } from '@build-5/interfaces'; import dayjs from 'dayjs'; import { isEmpty } from 'lodash'; -import { claimMintedTokenOrder } from '../../src/runtime/firebase/token/minting'; import { dateToTimestamp, serverTime } from '../../src/utils/dateTime.utils'; import { getRandomEthAddress } from '../../src/utils/wallet.utils'; -import { mockWalletReturnValue, wait } from '../../test/controls/common'; -import { testEnv } from '../../test/set-up'; +import { wait } from '../../test/controls/common'; +import { mockWalletReturnValue, testEnv } from '../../test/set-up'; import { awaitTransactionConfirmationsForToken } from '../common'; import { requestFundsFromFaucet } from '../faucet'; import { Helper } from './Helper'; @@ -31,9 +30,12 @@ describe('Token minting', () => { it('Claim owned and airdroped-vesting', async () => { const distributionDocRef = build5Db().doc( - `${COL.TOKEN}/${helper.token.uid}/${SUB_COL.DISTRIBUTION}/${helper.guardian.uid}`, + COL.TOKEN, + helper.token.uid, + SUB_COL.DISTRIBUTION, + helper.guardian.uid, ); - await distributionDocRef.set({ tokenOwned: 1 }); + await distributionDocRef.upsert({ tokenOwned: 1 }); const airdrop: TokenDrop = { project: SOON_PROJECT_ID, @@ -46,15 +48,15 @@ describe('Token minting', () => { count: 1, status: TokenDropStatus.UNCLAIMED, }; - await build5Db().doc(`${COL.AIRDROP}/${airdrop.uid}`).create(airdrop); + await build5Db().doc(COL.AIRDROP, airdrop.uid).create(airdrop); - mockWalletReturnValue(helper.walletSpy, helper.guardian.uid, { symbol: helper.token.symbol }); - const order = await testEnv.wrap(claimMintedTokenOrder)({}); + mockWalletReturnValue(helper.guardian.uid, { symbol: helper.token.symbol }); + const order = await testEnv.wrap(WEN_FUNC.claimMintedTokenOrder); await requestFundsFromFaucet(helper.network, order.payload.targetAddress, order.payload.amount); const query = build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.BILL_PAYMENT) + .where('type', '==', PgTransactionType.BILL_PAYMENT) .where('member', '==', helper.guardian.uid); await wait(async () => { const snap = await query.get(); @@ -66,10 +68,10 @@ describe('Token minting', () => { expect(vesting.payload.nativeTokens![0].amount).toBe(1); const unlocked = billPayments.filter((bp) => isEmpty(bp.payload.vestingAt))[0]; - expect(unlocked.payload.amount).toBe(order.payload.amount - 50100); + expect(unlocked.payload.amount).toBe(order.payload.amount! - 50100); expect(unlocked.payload.nativeTokens![0].amount).toBe(1); - const tokenData = await build5Db().doc(`${COL.TOKEN}/${helper.token.uid}`).get(); + const tokenData = await build5Db().doc(COL.TOKEN, helper.token.uid).get(); expect(tokenData.mintingData?.tokensInVault).toBe(8); await awaitTransactionConfirmationsForToken(helper.token.uid); }); diff --git a/packages/functions/test-tangle/minted-token-claim/token.claim.minted_3.spec.ts b/packages/functions/test-tangle/minted-token-claim/token.claim.minted_3.spec.ts index 339e49aaf8..52ac5526f6 100644 --- a/packages/functions/test-tangle/minted-token-claim/token.claim.minted_3.spec.ts +++ b/packages/functions/test-tangle/minted-token-claim/token.claim.minted_3.spec.ts @@ -1,20 +1,20 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ -import { build5Db } from '@build-5/database'; +import { PgTransactionType, build5Db } from '@build-5/database'; import { COL, SOON_PROJECT_ID, Token, TokenDrop, TokenDropStatus, - TransactionType, + Transaction, + WEN_FUNC, } from '@build-5/interfaces'; import dayjs from 'dayjs'; -import { claimMintedTokenOrder } from '../../src/runtime/firebase/token/minting'; import { dateToTimestamp, serverTime } from '../../src/utils/dateTime.utils'; import { getRandomEthAddress } from '../../src/utils/wallet.utils'; -import { mockWalletReturnValue, wait } from '../../test/controls/common'; -import { testEnv } from '../../test/set-up'; +import { wait } from '../../test/controls/common'; +import { mockWalletReturnValue, testEnv } from '../../test/set-up'; import { awaitTransactionConfirmationsForToken } from '../common'; import { requestFundsFromFaucet } from '../faucet'; import { Helper } from './Helper'; @@ -38,22 +38,22 @@ describe('Token minting', () => { count: 1, status: TokenDropStatus.UNCLAIMED, }; - await build5Db().doc(`${COL.AIRDROP}/${airdrop.uid}`).create(airdrop); + await build5Db().doc(COL.AIRDROP, airdrop.uid).create(airdrop); - mockWalletReturnValue(helper.walletSpy, helper.guardian.uid, { symbol: helper.token.symbol }); - const order = await testEnv.wrap(claimMintedTokenOrder)({}); + mockWalletReturnValue(helper.guardian.uid, { symbol: helper.token.symbol }); + const order = await testEnv.wrap(WEN_FUNC.claimMintedTokenOrder); await requestFundsFromFaucet(helper.network, order.payload.targetAddress, order.payload.amount); const query = build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.BILL_PAYMENT) + .where('type', '==', PgTransactionType.BILL_PAYMENT) .where('member', '==', helper.guardian.uid); await wait(async () => { const snap = await query.get(); return snap.length === 1; }); - const tokenData = await build5Db().doc(`${COL.TOKEN}/${helper.token.uid}`).get(); + const tokenData = await build5Db().doc(COL.TOKEN, helper.token.uid).get(); expect(tokenData.mintingData?.tokensInVault).toBe(9); await awaitTransactionConfirmationsForToken(helper.token.uid); diff --git a/packages/functions/test-tangle/minted-token-claim/token.claim.minted_4.spec.ts b/packages/functions/test-tangle/minted-token-claim/token.claim.minted_4.spec.ts index d9c81b6067..d806f2df40 100644 --- a/packages/functions/test-tangle/minted-token-claim/token.claim.minted_4.spec.ts +++ b/packages/functions/test-tangle/minted-token-claim/token.claim.minted_4.spec.ts @@ -1,6 +1,6 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ -import { build5Db } from '@build-5/database'; +import { PgTransactionType, build5Db } from '@build-5/database'; import { COL, SOON_PROJECT_ID, @@ -8,16 +8,15 @@ import { TokenDrop, TokenDropStatus, Transaction, - TransactionType, + WEN_FUNC, } from '@build-5/interfaces'; import dayjs from 'dayjs'; import { isEmpty } from 'lodash'; import { retryWallet } from '../../src/cron/wallet.cron'; -import { claimMintedTokenOrder } from '../../src/runtime/firebase/token/minting'; import { dateToTimestamp, serverTime } from '../../src/utils/dateTime.utils'; import { getRandomEthAddress } from '../../src/utils/wallet.utils'; -import { mockWalletReturnValue, wait } from '../../test/controls/common'; -import { testEnv } from '../../test/set-up'; +import { wait } from '../../test/controls/common'; +import { mockWalletReturnValue, testEnv } from '../../test/set-up'; import { awaitTransactionConfirmationsForToken } from '../common'; import { requestFundsFromFaucet } from '../faucet'; import { Helper } from './Helper'; @@ -42,32 +41,32 @@ describe('Token minting', () => { count: i + 1, status: TokenDropStatus.UNCLAIMED, }; - await build5Db().doc(`${COL.AIRDROP}/${airdrop.uid}`).create(airdrop); + await build5Db().doc(COL.AIRDROP, airdrop.uid).create(airdrop); } - mockWalletReturnValue(helper.walletSpy, helper.guardian.uid, { symbol: helper.token.symbol }); - const order = await testEnv.wrap(claimMintedTokenOrder)({}); + mockWalletReturnValue(helper.guardian.uid, { symbol: helper.token.symbol }); + const order = await testEnv.wrap(WEN_FUNC.claimMintedTokenOrder); await requestFundsFromFaucet(helper.network, order.payload.targetAddress, order.payload.amount); const query = build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.BILL_PAYMENT) + .where('type', '==', PgTransactionType.BILL_PAYMENT) .where('member', '==', helper.guardian.uid); await wait(async () => { const snap = await query.get(); return snap.length === 3; }); - const tokenData = await build5Db().doc(`${COL.TOKEN}/${helper.token.uid}`).get(); + const tokenData = await build5Db().doc(COL.TOKEN, helper.token.uid).get(); expect(tokenData.mintingData?.tokensInVault).toBe(4); await wait(async () => { - const snap = await query.get(); + const snap = await query.get(); const processed = snap.filter((d) => !isEmpty(d?.payload?.walletReference?.processedOn)); return processed.length == 3; }); await wait(async () => { - const snap = await query.get(); + const snap = await query.get(); const confirmed = snap.filter((d) => d!.payload.walletReference?.confirmed).length; if (confirmed !== 3) { await retryWallet(); diff --git a/packages/functions/test-tangle/minted-token-claim/token.claim.minted_5.spec.ts b/packages/functions/test-tangle/minted-token-claim/token.claim.minted_5.spec.ts index 5a99b98b8d..3a37ddf964 100644 --- a/packages/functions/test-tangle/minted-token-claim/token.claim.minted_5.spec.ts +++ b/packages/functions/test-tangle/minted-token-claim/token.claim.minted_5.spec.ts @@ -1,10 +1,9 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ -import { build5Db } from '@build-5/database'; -import { COL, SUB_COL, Token, TokenDistribution, TransactionType } from '@build-5/interfaces'; -import { claimMintedTokenOrder } from '../../src/runtime/firebase/token/minting'; -import { mockWalletReturnValue, wait } from '../../test/controls/common'; -import { testEnv } from '../../test/set-up'; +import { PgTransactionType, build5Db } from '@build-5/database'; +import { COL, SUB_COL, Token, TokenDistribution, Transaction, WEN_FUNC } from '@build-5/interfaces'; +import { wait } from '../../test/controls/common'; +import { mockWalletReturnValue, testEnv } from '../../test/set-up'; import { requestFundsFromFaucet } from '../faucet'; import { Helper } from './Helper'; @@ -17,11 +16,11 @@ describe('Token minting', () => { it('Should credit second claim', async () => { await build5Db() - .doc(`${COL.TOKEN}/${helper.token.uid}/${SUB_COL.DISTRIBUTION}/${helper.guardian.uid}`) - .set({ tokenOwned: 1 }); - mockWalletReturnValue(helper.walletSpy, helper.guardian.uid, { symbol: helper.token.symbol }); - const order = await testEnv.wrap(claimMintedTokenOrder)({}); - const order2 = await testEnv.wrap(claimMintedTokenOrder)({}); + .doc(COL.TOKEN, helper.token.uid, SUB_COL.DISTRIBUTION, helper.guardian.uid) + .upsert({ tokenOwned: 1 }); + mockWalletReturnValue(helper.guardian.uid, { symbol: helper.token.symbol }); + const order = await testEnv.wrap(WEN_FUNC.claimMintedTokenOrder); + const order2 = await testEnv.wrap(WEN_FUNC.claimMintedTokenOrder); await requestFundsFromFaucet(helper.network, order.payload.targetAddress, order.payload.amount); await requestFundsFromFaucet( @@ -32,7 +31,10 @@ describe('Token minting', () => { await wait(async () => { const distributionDocRef = build5Db().doc( - `${COL.TOKEN}/${helper.token.uid}/${SUB_COL.DISTRIBUTION}/${helper.guardian.uid}`, + COL.TOKEN, + helper.token.uid, + SUB_COL.DISTRIBUTION, + helper.guardian.uid, ); const distribution = await distributionDocRef.get(); return distribution?.mintedClaimedOn !== undefined; @@ -41,13 +43,13 @@ describe('Token minting', () => { const query = build5Db() .collection(COL.TRANSACTION) .where('member', '==', helper.guardian.uid) - .where('type', '==', TransactionType.CREDIT); + .where('type', '==', PgTransactionType.CREDIT); await wait(async () => { const snap = await query.get(); return snap.length === 1; }); - const tokenData = await build5Db().doc(`${COL.TOKEN}/${helper.token.uid}`).get(); + const tokenData = await build5Db().doc(COL.TOKEN, helper.token.uid).get(); expect(tokenData.mintingData?.tokensInVault).toBe(9); }); }); diff --git a/packages/functions/test-tangle/minted-token-claim/token.claim.minted_6.spec.ts b/packages/functions/test-tangle/minted-token-claim/token.claim.minted_6.spec.ts index 7fc65efded..a791a031b5 100644 --- a/packages/functions/test-tangle/minted-token-claim/token.claim.minted_6.spec.ts +++ b/packages/functions/test-tangle/minted-token-claim/token.claim.minted_6.spec.ts @@ -1,10 +1,17 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ import { build5Db } from '@build-5/database'; -import { COL, SUB_COL, Token, TokenDistribution, WenError } from '@build-5/interfaces'; -import { claimMintedTokenOrder } from '../../src/runtime/firebase/token/minting'; -import { expectThrow, mockWalletReturnValue, wait } from '../../test/controls/common'; -import { testEnv } from '../../test/set-up'; +import { + COL, + SUB_COL, + Token, + TokenDistribution, + Transaction, + WEN_FUNC, + WenError, +} from '@build-5/interfaces'; +import { expectThrow, wait } from '../../test/controls/common'; +import { mockWalletReturnValue, testEnv } from '../../test/set-up'; import { awaitTransactionConfirmationsForToken } from '../common'; import { requestFundsFromFaucet } from '../faucet'; import { Helper } from './Helper'; @@ -18,23 +25,29 @@ describe('Token minting', () => { it('Should throw, nothing to claim, can not create order', async () => { await build5Db() - .doc(`${COL.TOKEN}/${helper.token.uid}/${SUB_COL.DISTRIBUTION}/${helper.guardian.uid}`) - .set({ tokenOwned: 1 }); - mockWalletReturnValue(helper.walletSpy, helper.guardian.uid, { symbol: helper.token.symbol }); - const order = await testEnv.wrap(claimMintedTokenOrder)({}); + .doc(COL.TOKEN, helper.token.uid, SUB_COL.DISTRIBUTION, helper.guardian.uid) + .upsert({ tokenOwned: 1 }); + mockWalletReturnValue(helper.guardian.uid, { symbol: helper.token.symbol }); + const order = await testEnv.wrap(WEN_FUNC.claimMintedTokenOrder); await requestFundsFromFaucet(helper.network, order.payload.targetAddress, order.payload.amount); await wait(async () => { const distributionDocRef = build5Db().doc( - `${COL.TOKEN}/${helper.token.uid}/${SUB_COL.DISTRIBUTION}/${helper.guardian.uid}`, + COL.TOKEN, + helper.token.uid, + SUB_COL.DISTRIBUTION, + helper.guardian.uid, ); const distribution = await distributionDocRef.get(); return distribution.mintedClaimedOn !== undefined; }); - await expectThrow(testEnv.wrap(claimMintedTokenOrder)({}), WenError.no_tokens_to_claim.key); + await expectThrow( + testEnv.wrap(WEN_FUNC.claimMintedTokenOrder), + WenError.no_tokens_to_claim.key, + ); - const tokenData = await build5Db().doc(`${COL.TOKEN}/${helper.token.uid}`).get(); + const tokenData = await build5Db().doc(COL.TOKEN, helper.token.uid).get(); expect(tokenData.mintingData?.tokensInVault).toBe(9); await awaitTransactionConfirmationsForToken(helper.token.uid); diff --git a/packages/functions/test-tangle/minted-token-claim/token.claim.minted_7.spec.ts b/packages/functions/test-tangle/minted-token-claim/token.claim.minted_7.spec.ts index 6cb682a671..db7c9a2f1f 100644 --- a/packages/functions/test-tangle/minted-token-claim/token.claim.minted_7.spec.ts +++ b/packages/functions/test-tangle/minted-token-claim/token.claim.minted_7.spec.ts @@ -1,10 +1,9 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ -import { build5Db } from '@build-5/database'; -import { COL, Member, SUB_COL, Token, TokenStatus, TransactionType } from '@build-5/interfaces'; -import { claimMintedTokenOrder, mintTokenOrder } from '../../src/runtime/firebase/token/minting'; -import { createMember, createSpace, mockWalletReturnValue, wait } from '../../test/controls/common'; -import { testEnv } from '../../test/set-up'; +import { PgTransactionType, build5Db } from '@build-5/database'; +import { COL, Member, SUB_COL, TokenStatus, Transaction, WEN_FUNC } from '@build-5/interfaces'; +import { wait } from '../../test/controls/common'; +import { mockWalletReturnValue, testEnv } from '../../test/set-up'; import { awaitTransactionConfirmationsForToken } from '../common'; import { requestFundsFromFaucet } from '../faucet'; import { Helper } from './Helper'; @@ -17,9 +16,9 @@ describe('Token minting', () => { }); it('Should return deposit after claiming all', async () => { - const minterId = await createMember(helper.walletSpy); - const minter = await build5Db().doc(`${COL.MEMBER}/${minterId}`).get(); - helper.space = await createSpace(helper.walletSpy, minter.uid); + const minterId = await testEnv.createMember(); + const minter = await build5Db().doc(COL.MEMBER, minterId).get(); + helper.space = await testEnv.createSpace(minter.uid); helper.token = await helper.saveToken( helper.space.uid, minter.uid, @@ -28,19 +27,19 @@ describe('Token minting', () => { true, ); await build5Db() - .doc(`${COL.TOKEN}/${helper.token.uid}/${SUB_COL.DISTRIBUTION}/${helper.guardian.uid}`) - .set({ tokenOwned: 1 }); + .doc(COL.TOKEN, helper.token.uid, SUB_COL.DISTRIBUTION, helper.guardian.uid) + .upsert({ tokenOwned: 1 }); - mockWalletReturnValue(helper.walletSpy, minter.uid, { + mockWalletReturnValue(minter.uid, { token: helper.token.uid, network: helper.network, }); - const order = await testEnv.wrap(mintTokenOrder)({}); + const order = await testEnv.wrap(WEN_FUNC.mintTokenOrder); await requestFundsFromFaucet(helper.network, order.payload.targetAddress, order.payload.amount); - const tokenDocRef = build5Db().doc(`${COL.TOKEN}/${helper.token.uid}`); + const tokenDocRef = build5Db().doc(COL.TOKEN, helper.token.uid); await wait(async () => { - const snap = await tokenDocRef.get(); + const snap = await tokenDocRef.get(); return snap?.status === TokenStatus.MINTED; }); @@ -52,8 +51,8 @@ describe('Token minting', () => { return Number(Object.values(nativeTokens)[0]) === 1; }); - mockWalletReturnValue(helper.walletSpy, helper.guardian.uid, { symbol: helper.token.symbol }); - const claimOrder = await testEnv.wrap(claimMintedTokenOrder)({}); + mockWalletReturnValue(helper.guardian.uid, { symbol: helper.token.symbol }); + const claimOrder = await testEnv.wrap(WEN_FUNC.claimMintedTokenOrder); await requestFundsFromFaucet( helper.network, claimOrder.payload.targetAddress, @@ -62,7 +61,7 @@ describe('Token minting', () => { const query = build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.BILL_PAYMENT) + .where('type', '==', PgTransactionType.BILL_PAYMENT) .where('member', '==', helper.guardian.uid); await wait(async () => { const snap = await query.get(); @@ -71,7 +70,7 @@ describe('Token minting', () => { const creditQuery = build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.CREDIT) + .where('type', '==', PgTransactionType.CREDIT) .where('member', '==', minter.uid); await wait(async () => { const snap = await creditQuery.get(); diff --git a/packages/functions/test-tangle/minted-token-trade/Helper.ts b/packages/functions/test-tangle/minted-token-trade/Helper.ts index 8200a9ba3d..a3851414de 100644 --- a/packages/functions/test-tangle/minted-token-trade/Helper.ts +++ b/packages/functions/test-tangle/minted-token-trade/Helper.ts @@ -12,52 +12,43 @@ import { TokenStatus, TokenTradeOrderType, Transaction, + WEN_FUNC, } from '@build-5/interfaces'; -import { tradeToken } from '../../src/runtime/firebase/token/trading'; import { MnemonicService } from '../../src/services/wallet/mnemonic'; import { Wallet } from '../../src/services/wallet/wallet'; import { AddressDetails } from '../../src/services/wallet/wallet.service'; import { getAddress } from '../../src/utils/address.utils'; import { serverTime } from '../../src/utils/dateTime.utils'; import * as wallet from '../../src/utils/wallet.utils'; -import { - createMember, - createRoyaltySpaces, - createSpace, - getRandomSymbol, - mockWalletReturnValue, - wait, -} from '../../test/controls/common'; -import { getWallet, MEDIA, testEnv } from '../../test/set-up'; +import { createRoyaltySpaces, getRandomSymbol, wait } from '../../test/controls/common'; +import { getWallet, MEDIA, mockWalletReturnValue, testEnv } from '../../test/set-up'; import { requestFundsFromFaucet, requestMintedTokenFromFaucet } from '../faucet'; export class Helper { public network = Network.RMS; - public seller: string | undefined; - public space: Space | undefined; - public token: Token | undefined; - public sellerAddress: AddressDetails | undefined; - public buyer: string | undefined; - public buyerAddress: AddressDetails | undefined; + public seller = ''; + public space: Space = {} as any; + public token: Token = {} as any; + public sellerAddress: AddressDetails = {} as any; + public buyer = ''; + public buyerAddress: AddressDetails = {} as any; - public guardian: string | undefined; - public walletService: Wallet | undefined; - public walletSpy: any; + public guardian = ''; + public walletService: Wallet = {} as any; public berforeAll = async () => { this.walletService = await getWallet(this.network); await createRoyaltySpaces(); - this.walletSpy = jest.spyOn(wallet, 'decodeAuth'); }; public beforeEach = async () => { - this.guardian = await createMember(this.walletSpy); - this.space = await createSpace(this.walletSpy, this.guardian); + this.guardian = await testEnv.createMember(); + this.space = await testEnv.createSpace(this.guardian); this.token = (await saveToken(this.space.uid, this.guardian, this.walletService!)) as Token; - this.seller = await createMember(this.walletSpy); - const sellerDoc = await build5Db().doc(`${COL.MEMBER}/${this.seller}`).get(); + this.seller = await testEnv.createMember(); + const sellerDoc = await build5Db().doc(COL.MEMBER, this.seller).get(); this.sellerAddress = await this.walletService!.getAddressDetails( getAddress(sellerDoc, this.network!), ); @@ -69,8 +60,8 @@ export class Helper { VAULT_MNEMONIC, ); - this.buyer = await createMember(this.walletSpy); - const buyerDoc = await build5Db().doc(`${COL.MEMBER}/${this.buyer}`).get(); + this.buyer = await testEnv.createMember(); + const buyerDoc = await build5Db().doc(COL.MEMBER, this.buyer).get(); this.buyerAddress = await this.walletService!.getAddressDetails( getAddress(buyerDoc, this.network), ); @@ -81,13 +72,13 @@ export class Helper { price = MIN_IOTA_AMOUNT, expiresAt?: Timestamp, ) => { - mockWalletReturnValue(this.walletSpy, this.seller!, { + mockWalletReturnValue(this.seller!, { symbol: this.token!.symbol, count, price, type: TokenTradeOrderType.SELL, }); - const sellOrder: Transaction = await testEnv.wrap(tradeToken)({}); + const sellOrder: Transaction = await testEnv.wrap(WEN_FUNC.tradeToken); await this.walletService!.send(this.sellerAddress!, sellOrder.payload.targetAddress!, 0, { nativeTokens: [{ amount: BigInt(count), id: this.token!.mintingData?.tokenId! }], expiration: expiresAt @@ -113,13 +104,13 @@ export class Helper { }; public createBuyOrder = async (count = 10, price = MIN_IOTA_AMOUNT, expiresAt?: Timestamp) => { - mockWalletReturnValue(this.walletSpy, this.buyer!, { + mockWalletReturnValue(this.buyer!, { symbol: this.token!.symbol, count, price, type: TokenTradeOrderType.BUY, }); - const buyOrder: Transaction = await testEnv.wrap(tradeToken)({}); + const buyOrder: Transaction = await testEnv.wrap(WEN_FUNC.tradeToken); await requestFundsFromFaucet( this.network, buyOrder.payload.targetAddress!, @@ -163,8 +154,8 @@ export const saveToken = async ( }, access: 0, icon: MEDIA, - }; - await build5Db().doc(`${COL.TOKEN}/${token.uid}`).set(token); + } as Token; + await build5Db().doc(COL.TOKEN, token.uid).create(token); return token; }; diff --git a/packages/functions/test-tangle/minted-token-trade/minted-token-trade_1.spec.ts b/packages/functions/test-tangle/minted-token-trade/minted-token-trade_1.spec.ts index b969fd8461..5c10b38293 100644 --- a/packages/functions/test-tangle/minted-token-trade/minted-token-trade_1.spec.ts +++ b/packages/functions/test-tangle/minted-token-trade/minted-token-trade_1.spec.ts @@ -1,6 +1,6 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ -import { build5Db } from '@build-5/database'; +import { PgTransactionType, build5Db } from '@build-5/database'; import { COL, MIN_IOTA_AMOUNT, @@ -10,7 +10,6 @@ import { TokenTradeOrderType, Transaction, TransactionPayloadType, - TransactionType, } from '@build-5/interfaces'; import { wait } from '../../test/controls/common'; import { awaitTransactionConfirmationsForToken } from '../common'; @@ -40,8 +39,8 @@ describe('Token minting', () => { const billPaymentsQuery = build5Db() .collection(COL.TRANSACTION) - .where('member', 'in', [helper.seller, helper.buyer]) - .where('type', '==', TransactionType.BILL_PAYMENT); + .where('type', '==', PgTransactionType.BILL_PAYMENT) + .whereIn('member', [helper.seller, helper.buyer]); await wait(async () => { const snap = await billPaymentsQuery.get(); return snap.length === 4; @@ -69,7 +68,7 @@ describe('Token minting', () => { )!; expect(paymentToSeller.payload.amount).toBe(9602600); expect(paymentToSeller.payload.sourceAddress).toBe(buyOrder.payload.targetAddress); - expect(paymentToSeller.payload.storageReturn).toBeUndefined(); + expect(paymentToSeller.payload.storageReturn).toEqual({}); const royaltyOnePayment = billPayments.find((bp) => bp.payload.amount === 271800)!; expect(royaltyOnePayment.payload.storageReturn!.address).toBe(helper.sellerAddress!.bech32); @@ -94,7 +93,7 @@ describe('Token minting', () => { const sellerCreditSnap = await build5Db() .collection(COL.TRANSACTION) .where('member', '==', helper.seller!) - .where('type', '==', TransactionType.CREDIT) + .where('type', '==', PgTransactionType.CREDIT) .get(); expect(sellerCreditSnap.length).toBe(1); const sellerCredit = sellerCreditSnap.map((d) => d as Transaction)[0]; @@ -113,7 +112,7 @@ describe('Token minting', () => { expect(purchase.count).toBe(10); expect(purchase.tokenStatus).toBe(TokenStatus.MINTED); expect(purchase.sellerTier).toBe(0); - expect(purchase.sellerTokenTradingFeePercentage).toBeNull(); + expect(purchase.sellerTokenTradingFeePercentage).toBeUndefined(); await awaitTransactionConfirmationsForToken(helper.token!.uid); }); }); diff --git a/packages/functions/test-tangle/minted-token-trade/minted-token-trade_12.spec.ts b/packages/functions/test-tangle/minted-token-trade/minted-token-trade_12.spec.ts index ee31cf8b22..eef29c4b9c 100644 --- a/packages/functions/test-tangle/minted-token-trade/minted-token-trade_12.spec.ts +++ b/packages/functions/test-tangle/minted-token-trade/minted-token-trade_12.spec.ts @@ -3,8 +3,8 @@ import { build5Db } from '@build-5/database'; import { COL, - Member, MIN_IOTA_AMOUNT, + Member, Network, TokenTradeOrder, TokenTradeOrderStatus, @@ -13,7 +13,6 @@ import { import dayjs from 'dayjs'; import { cancelExpiredSale } from '../../src/cron/token.cron'; import { getAddress } from '../../src/utils/address.utils'; -import { dateToTimestamp } from '../../src/utils/dateTime.utils'; import { wait } from '../../test/controls/common'; import { awaitTransactionConfirmationsForToken } from '../common'; import { Helper } from './Helper'; @@ -40,22 +39,22 @@ describe('Token minting', () => { }); let buy = (await query.get())[0]; await build5Db() - .doc(`${COL.TOKEN_MARKET}/${buy.uid}`) - .update({ expiresAt: dateToTimestamp(dayjs().subtract(1, 'd').toDate()) }); + .doc(COL.TOKEN_MARKET, buy.uid) + .update({ expiresAt: dayjs().subtract(1, 'd').toDate() }); await cancelExpiredSale(); - const buyQuery = build5Db().doc(`${COL.TOKEN_MARKET}/${buy.uid}`); + const buyQuery = build5Db().doc(COL.TOKEN_MARKET, buy.uid); await wait(async () => { buy = await buyQuery.get(); return buy.status === TokenTradeOrderStatus.EXPIRED; }); const credit = ( - await build5Db().doc(`${COL.TRANSACTION}/${buy.creditTransactionId}`).get() + await build5Db().doc(COL.TRANSACTION, buy.creditTransactionId!).get() ); expect(credit.member).toBe(helper.buyer); - const buyer = await build5Db().doc(`${COL.MEMBER}/${helper.buyer!}`).get(); + const buyer = await build5Db().doc(COL.MEMBER, helper.buyer!).get(); expect(credit.payload.targetAddress).toBe(getAddress(buyer, Network.RMS)); expect(credit.payload.amount).toBe(5 * MIN_IOTA_AMOUNT); diff --git a/packages/functions/test-tangle/minted-token-trade/minted-token-trade_12_b.spec.ts b/packages/functions/test-tangle/minted-token-trade/minted-token-trade_12_b.spec.ts index 492407ad6a..3371cac151 100644 --- a/packages/functions/test-tangle/minted-token-trade/minted-token-trade_12_b.spec.ts +++ b/packages/functions/test-tangle/minted-token-trade/minted-token-trade_12_b.spec.ts @@ -3,8 +3,8 @@ import { build5Db } from '@build-5/database'; import { COL, - Member, MIN_IOTA_AMOUNT, + Member, Network, TokenTradeOrder, TokenTradeOrderStatus, @@ -13,7 +13,6 @@ import { import dayjs from 'dayjs'; import { cancelExpiredSale } from '../../src/cron/token.cron'; import { getAddress } from '../../src/utils/address.utils'; -import { dateToTimestamp } from '../../src/utils/dateTime.utils'; import { wait } from '../../test/controls/common'; import { awaitTransactionConfirmationsForToken } from '../common'; import { Helper } from './Helper'; @@ -40,22 +39,22 @@ describe('Token minting', () => { }); let sell = (await query.get())[0]; await build5Db() - .doc(`${COL.TOKEN_MARKET}/${sell.uid}`) - .update({ expiresAt: dateToTimestamp(dayjs().subtract(1, 'd').toDate()) }); + .doc(COL.TOKEN_MARKET, sell.uid) + .update({ expiresAt: dayjs().subtract(1, 'd').toDate() }); await cancelExpiredSale(); - const sellQuery = build5Db().doc(`${COL.TOKEN_MARKET}/${sell.uid}`); + const sellQuery = build5Db().doc(COL.TOKEN_MARKET, sell.uid); await wait(async () => { sell = await sellQuery.get(); return sell.status === TokenTradeOrderStatus.EXPIRED; }); const credit = ( - await build5Db().doc(`${COL.TRANSACTION}/${sell.creditTransactionId}`).get() + await build5Db().doc(COL.TRANSACTION, sell.creditTransactionId!).get() ); expect(credit.member).toBe(helper.seller); - const seller = await build5Db().doc(`${COL.MEMBER}/${helper.seller!}`).get(); + const seller = await build5Db().doc(COL.MEMBER, helper.seller!).get(); expect(credit.payload.targetAddress).toBe(getAddress(seller, Network.RMS)); expect(credit.payload.amount).toBe(49600); expect(credit.payload.nativeTokens![0].amount).toBe(5); diff --git a/packages/functions/test-tangle/minted-token-trade/minted-token-trade_13.spec.ts b/packages/functions/test-tangle/minted-token-trade/minted-token-trade_13.spec.ts index a7031c36e9..ade26bd979 100644 --- a/packages/functions/test-tangle/minted-token-trade/minted-token-trade_13.spec.ts +++ b/packages/functions/test-tangle/minted-token-trade/minted-token-trade_13.spec.ts @@ -8,10 +8,11 @@ import { TokenTradeOrder, TokenTradeOrderStatus, TokenTradeOrderType, + Transaction, + WEN_FUNC, } from '@build-5/interfaces'; -import { tradeToken } from '../../src/runtime/firebase/token/trading'; -import { mockWalletReturnValue, wait } from '../../test/controls/common'; -import { testEnv } from '../../test/set-up'; +import { wait } from '../../test/controls/common'; +import { mockWalletReturnValue, testEnv } from '../../test/set-up'; import { requestFundsForManyFromFaucet } from '../faucet'; import { Helper } from './Helper'; @@ -28,17 +29,19 @@ describe('Token minting', () => { it('Fulfill many buys with sell', async () => { const count = 15; - mockWalletReturnValue(helper.walletSpy, helper.buyer!, { + mockWalletReturnValue(helper.buyer!, { symbol: helper.token!.symbol, count: 1, price: MIN_IOTA_AMOUNT, type: TokenTradeOrderType.BUY, }); - const promises = Array.from(Array(count)).map(() => testEnv.wrap(tradeToken)({})); + const promises = Array.from(Array(count)).map(() => + testEnv.wrap(WEN_FUNC.tradeToken), + ); const orders = await Promise.all(promises); await requestFundsForManyFromFaucet( Network.RMS, - orders.map((o) => ({ toAddress: o.payload.targetAddress, amount: o.payload.amount })), + orders.map((o) => ({ toAddress: o.payload.targetAddress!, amount: o.payload.amount! })), ); const tradeQuery = build5Db() diff --git a/packages/functions/test-tangle/minted-token-trade/minted-token-trade_14.spec.ts b/packages/functions/test-tangle/minted-token-trade/minted-token-trade_14.spec.ts index 411ca4faa9..f0b9b0f9ad 100644 --- a/packages/functions/test-tangle/minted-token-trade/minted-token-trade_14.spec.ts +++ b/packages/functions/test-tangle/minted-token-trade/minted-token-trade_14.spec.ts @@ -1,13 +1,7 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ -import { build5Db } from '@build-5/database'; -import { - COL, - MIN_IOTA_AMOUNT, - TokenPurchase, - Transaction, - TransactionType, -} from '@build-5/interfaces'; +import { PgTransactionType, build5Db } from '@build-5/database'; +import { COL, MIN_IOTA_AMOUNT, TokenPurchase, Transaction } from '@build-5/interfaces'; import { head } from 'lodash'; import { wait } from '../../test/controls/common'; import { awaitTransactionConfirmationsForToken } from '../common'; @@ -43,8 +37,8 @@ describe('Token minting', () => { const billPayments = ( await build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.BILL_PAYMENT) - .where('payload.token', '==', helper.token!.uid) + .where('type', '==', PgTransactionType.BILL_PAYMENT) + .where('payload_token', '==', helper.token!.uid) .get() ).map((d) => d); diff --git a/packages/functions/test-tangle/minted-token-trade/minted-token-trade_15.only.spec.ts b/packages/functions/test-tangle/minted-token-trade/minted-token-trade_15.only.spec.ts index 2b57cf2b3c..1972bc3f1e 100644 --- a/packages/functions/test-tangle/minted-token-trade/minted-token-trade_15.only.spec.ts +++ b/packages/functions/test-tangle/minted-token-trade/minted-token-trade_15.only.spec.ts @@ -1,15 +1,13 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ -import { build5Db } from '@build-5/database'; +import { PgTransactionType, build5Db } from '@build-5/database'; import { COL, MIN_IOTA_AMOUNT, - StakeType, SUB_COL, SYSTEM_CONFIG_DOC_ID, TokenPurchase, Transaction, - TransactionType, } from '@build-5/interfaces'; import { head } from 'lodash'; import { wait } from '../../test/controls/common'; @@ -32,28 +30,14 @@ describe('Token minting', () => { 'Should not create royalty payments, zero percentage', async (isMember: boolean) => { if (isMember) { + await build5Db().doc(COL.MEMBER, helper.seller!).update({ tokenTradingFeePercentage: 0 }); await build5Db() - .doc(`${COL.MEMBER}/${helper.seller}`) - .update({ tokenTradingFeePercentage: 0 }); - await build5Db() - .collection(COL.TOKEN) - .doc(soonTokenId) - .collection(SUB_COL.DISTRIBUTION) - .doc(helper.seller!) - .set( - { - stakes: { - [StakeType.DYNAMIC]: { - value: 15000 * MIN_IOTA_AMOUNT, - }, - }, - }, - true, - ); + .doc(COL.TOKEN, soonTokenId, SUB_COL.DISTRIBUTION, helper.seller!) + .upsert({ stakes_dynamic_value: 15000 * MIN_IOTA_AMOUNT }); } else { await build5Db() - .doc(`${COL.SYSTEM}/${SYSTEM_CONFIG_DOC_ID}`) - .set({ tokenTradingFeePercentage: 0 }); + .doc(COL.SYSTEM, SYSTEM_CONFIG_DOC_ID) + .upsert({ tokenTradingFeePercentage: 0 }); } await helper.createSellTradeOrder(20, MIN_IOTA_AMOUNT); @@ -78,8 +62,8 @@ describe('Token minting', () => { const billPayments = ( await build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.BILL_PAYMENT) - .where('payload.token', '==', helper.token!.uid) + .where('type', '==', PgTransactionType.BILL_PAYMENT) + .where('payload_token', '==', helper.token!.uid) .get() ).map((d) => d); expect(billPayments.length).toBe(2); @@ -99,7 +83,7 @@ describe('Token minting', () => { ); it('Should create royalty payments for different percentage', async () => { - await build5Db().doc(`${COL.MEMBER}/${helper.seller}`).update({ tokenTradingFeePercentage: 1 }); + await build5Db().doc(COL.MEMBER, helper.seller).update({ tokenTradingFeePercentage: 1 }); await helper.createSellTradeOrder(20, MIN_IOTA_AMOUNT); await helper.createBuyOrder(20, MIN_IOTA_AMOUNT); @@ -119,8 +103,8 @@ describe('Token minting', () => { const billPayments = ( await build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.BILL_PAYMENT) - .where('payload.token', '==', helper.token!.uid) + .where('type', '==', PgTransactionType.BILL_PAYMENT) + .where('payload_token', '==', helper.token!.uid) .get() ).map((d) => d); expect(billPayments.length).toBe(4); @@ -154,7 +138,7 @@ describe('Token minting', () => { }); it('Should not create royalty payments as percentage is zero, but send dust', async () => { - await build5Db().doc(`${COL.MEMBER}/${helper.seller}`).update({ tokenTradingFeePercentage: 0 }); + await build5Db().doc(COL.MEMBER, helper.seller).update({ tokenTradingFeePercentage: 0 }); await helper.createSellTradeOrder(20, MIN_IOTA_AMOUNT); await helper.createBuyOrder(20, MIN_IOTA_AMOUNT + 0.1); @@ -173,8 +157,8 @@ describe('Token minting', () => { const billPayments = ( await build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.BILL_PAYMENT) - .where('payload.token', '==', helper.token!.uid) + .where('type', '==', PgTransactionType.BILL_PAYMENT) + .where('payload_token', '==', helper.token!.uid) .get() ).map((d) => d); expect(billPayments.length).toBe(3); diff --git a/packages/functions/test-tangle/minted-token-trade/minted-token-trade_16.spec.ts b/packages/functions/test-tangle/minted-token-trade/minted-token-trade_16.spec.ts index 4a8b29023e..93aed95e1d 100644 --- a/packages/functions/test-tangle/minted-token-trade/minted-token-trade_16.spec.ts +++ b/packages/functions/test-tangle/minted-token-trade/minted-token-trade_16.spec.ts @@ -1,18 +1,17 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ -import { build5Db } from '@build-5/database'; +import { PgTransactionType, build5Db } from '@build-5/database'; import { COL, MIN_IOTA_AMOUNT, TokenTradeOrder, TokenTradeOrderType, Transaction, - TransactionType, + WEN_FUNC, } from '@build-5/interfaces'; -import { cancelTradeOrder, tradeToken } from '../../src/runtime/firebase/token/trading'; import { MnemonicService } from '../../src/services/wallet/mnemonic'; -import { mockWalletReturnValue, wait } from '../../test/controls/common'; -import { testEnv } from '../../test/set-up'; +import { wait } from '../../test/controls/common'; +import { mockWalletReturnValue, testEnv } from '../../test/set-up'; import { awaitTransactionConfirmationsForToken } from '../common'; import { Helper } from './Helper'; @@ -28,13 +27,13 @@ describe('Token minting', () => { }); it('Should create sell with higher storage deposit', async () => { - mockWalletReturnValue(helper.walletSpy, helper.seller!, { + mockWalletReturnValue(helper.seller!, { symbol: helper.token!.symbol, count: 1, price: 5 * MIN_IOTA_AMOUNT, type: TokenTradeOrderType.SELL, }); - const sellOrder: Transaction = await testEnv.wrap(tradeToken)({}); + const sellOrder: Transaction = await testEnv.wrap(WEN_FUNC.tradeToken); await helper.walletService!.send( helper.sellerAddress!, sellOrder.payload.targetAddress!, @@ -65,13 +64,13 @@ describe('Token minting', () => { )[0] ); - mockWalletReturnValue(helper.walletSpy, helper.seller!, { uid: sell.uid }); - await testEnv.wrap(cancelTradeOrder)({}); + mockWalletReturnValue(helper.seller!, { uid: sell.uid }); + await testEnv.wrap(WEN_FUNC.cancelTradeOrder); const sellerCreditSnap = await build5Db() .collection(COL.TRANSACTION) .where('member', '==', helper.seller) - .where('type', '==', TransactionType.CREDIT) + .where('type', '==', PgTransactionType.CREDIT) .get(); expect(sellerCreditSnap.length).toBe(1); const sellerCredit = sellerCreditSnap.map((d) => d as Transaction)[0]; @@ -83,13 +82,13 @@ describe('Token minting', () => { it('Should fulfill sell and credit higher storage deposit', async () => { await helper.createBuyOrder(1, 5 * MIN_IOTA_AMOUNT); - mockWalletReturnValue(helper.walletSpy, helper.seller!, { + mockWalletReturnValue(helper.seller!, { symbol: helper.token!.symbol, count: 1, price: 5 * MIN_IOTA_AMOUNT, type: TokenTradeOrderType.SELL, }); - const sellOrder: Transaction = await testEnv.wrap(tradeToken)({}); + const sellOrder: Transaction = await testEnv.wrap(WEN_FUNC.tradeToken); await helper.walletService!.send( helper.sellerAddress!, sellOrder.payload.targetAddress!, @@ -122,7 +121,7 @@ describe('Token minting', () => { const sellerCreditSnap = await build5Db() .collection(COL.TRANSACTION) .where('member', '==', helper.seller) - .where('type', '==', TransactionType.CREDIT) + .where('type', '==', PgTransactionType.CREDIT) .get(); expect(sellerCreditSnap.length).toBe(1); const sellerCredit = sellerCreditSnap.map((d) => d as Transaction)[0]; diff --git a/packages/functions/test-tangle/minted-token-trade/minted-token-trade_17.spec.ts b/packages/functions/test-tangle/minted-token-trade/minted-token-trade_17.spec.ts index 20cd3a3006..84cd899208 100644 --- a/packages/functions/test-tangle/minted-token-trade/minted-token-trade_17.spec.ts +++ b/packages/functions/test-tangle/minted-token-trade/minted-token-trade_17.spec.ts @@ -1,18 +1,16 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ -import { build5Db } from '@build-5/database'; +import { PgTransactionType, build5Db } from '@build-5/database'; import { COL, IgnoreWalletReason, MIN_IOTA_AMOUNT, TokenTradeOrderType, Transaction, - TransactionType, + WEN_FUNC, } from '@build-5/interfaces'; -import { creditUnrefundable } from '../../src/runtime/firebase/credit/index'; -import { tradeToken } from '../../src/runtime/firebase/token/trading'; -import { mockWalletReturnValue, wait } from '../../test/controls/common'; -import { testEnv } from '../../test/set-up'; +import { wait } from '../../test/controls/common'; +import { mockWalletReturnValue, testEnv } from '../../test/set-up'; import { requestFundsFromFaucet } from '../faucet'; import { Helper } from './Helper'; @@ -28,23 +26,23 @@ describe('Token minting', () => { }); it('Should credit sell order, storage deposit unlock condition', async () => { - mockWalletReturnValue(helper.walletSpy, helper.seller!, { + mockWalletReturnValue(helper.seller!, { symbol: helper.token!.symbol, count: 10, price: MIN_IOTA_AMOUNT, type: TokenTradeOrderType.SELL, }); - const sellOrder: Transaction = await testEnv.wrap(tradeToken)({}); + const sellOrder: Transaction = await testEnv.wrap(WEN_FUNC.tradeToken); await helper.walletService!.send(helper.sellerAddress!, sellOrder.payload.targetAddress!, 0, { nativeTokens: [{ amount: BigInt(10), id: helper.token!.mintingData?.tokenId! }], storageDepositReturnAddress: helper.sellerAddress?.bech32, }); const query = build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.CREDIT) + .where('type', '==', PgTransactionType.CREDIT) .where('member', '==', helper.seller); await wait(async () => { - const snap = await query.get(); + const snap = await query.get(); return ( snap.length === 1 && snap[0]!.ignoreWalletReason === @@ -52,27 +50,27 @@ describe('Token minting', () => { snap[0]!.payload.targetAddress === helper.sellerAddress!.bech32 ); }); - const snap = await query.get(); - mockWalletReturnValue(helper.walletSpy, helper.seller!, { + const snap = await query.get(); + mockWalletReturnValue(helper.seller!, { transaction: snap[0].uid, }); - const order = await testEnv.wrap(creditUnrefundable)({}); + const order = await testEnv.wrap(WEN_FUNC.creditUnrefundable); await requestFundsFromFaucet(helper.network, order.payload.targetAddress, order.payload.amount); await wait(async () => { - const snap = await query.get(); + const snap = await query.get(); return snap.length === 1 && snap[0]!.payload?.walletReference?.confirmed; }); const creditStorageTran = ( ( await build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.CREDIT_STORAGE_DEPOSIT_LOCKED) + .where('type', '==', PgTransactionType.CREDIT_STORAGE_DEPOSIT_LOCKED) .where('member', '==', helper.seller) .get() )[0] ); - const creditSnap = await query.get(); + const creditSnap = await query.get(); expect(creditSnap[0]!.payload?.walletReference?.chainReference).toBe( creditStorageTran.payload.walletReference?.chainReference, ); @@ -97,23 +95,23 @@ describe('Token minting', () => { }); it('Shoult credit second unlock credit', async () => { - mockWalletReturnValue(helper.walletSpy, helper.seller!, { + mockWalletReturnValue(helper.seller!, { symbol: helper.token!.symbol, count: 10, price: MIN_IOTA_AMOUNT, type: TokenTradeOrderType.SELL, }); - const sellOrder: Transaction = await testEnv.wrap(tradeToken)({}); + const sellOrder: Transaction = await testEnv.wrap(WEN_FUNC.tradeToken); await helper.walletService!.send(helper.sellerAddress!, sellOrder.payload.targetAddress!, 0, { nativeTokens: [{ amount: BigInt(10), id: helper.token!.mintingData?.tokenId! }], storageDepositReturnAddress: helper.sellerAddress?.bech32, }); const query = build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.CREDIT) + .where('type', '==', PgTransactionType.CREDIT) .where('member', '==', helper.seller); await wait(async () => { - const snap = await query.get(); + const snap = await query.get(); return ( snap.length === 1 && snap[0]!.ignoreWalletReason === @@ -121,12 +119,12 @@ describe('Token minting', () => { snap[0]!.payload.targetAddress === helper.sellerAddress!.bech32 ); }); - const snap = await query.get(); - mockWalletReturnValue(helper.walletSpy, helper.seller!, { + const snap = await query.get(); + mockWalletReturnValue(helper.seller!, { transaction: snap[0].uid, }); - const order = await testEnv.wrap(creditUnrefundable)({}); - const order2 = await testEnv.wrap(creditUnrefundable)({}); + const order = await testEnv.wrap(WEN_FUNC.creditUnrefundable); + const order2 = await testEnv.wrap(WEN_FUNC.creditUnrefundable); await requestFundsFromFaucet(helper.network, order.payload.targetAddress, order.payload.amount); await requestFundsFromFaucet( @@ -138,15 +136,13 @@ describe('Token minting', () => { await wait(async () => { const snap = await build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.CREDIT) + .where('type', '==', PgTransactionType.CREDIT) .where('member', '==', helper.seller) .get(); return snap.length == 2; }); - const transaction = ( - await build5Db().doc(`${COL.TRANSACTION}/${snap[0].uid}`).get() - ); + const transaction = await build5Db().doc(COL.TRANSACTION, snap[0].uid).get(); expect(transaction.payload.unlockedBy).toBeDefined(); }); }); diff --git a/packages/functions/test-tangle/minted-token-trade/minted-token-trade_18.spec.ts b/packages/functions/test-tangle/minted-token-trade/minted-token-trade_18.spec.ts index 70b5539338..0621cdb4aa 100644 --- a/packages/functions/test-tangle/minted-token-trade/minted-token-trade_18.spec.ts +++ b/packages/functions/test-tangle/minted-token-trade/minted-token-trade_18.spec.ts @@ -1,4 +1,4 @@ -import { build5Db } from '@build-5/database'; +import { PgTransactionType, build5Db } from '@build-5/database'; import { COL, MIN_IOTA_AMOUNT, @@ -7,7 +7,6 @@ import { TokenTradeOrder, TokenTradeOrderType, Transaction, - TransactionType, } from '@build-5/interfaces'; import dayjs from 'dayjs'; import { dateToTimestamp } from '../../src/utils/dateTime.utils'; @@ -43,7 +42,7 @@ describe('Minted toke trading tangle request', () => { }, }, }); - await build5Db().doc(`${COL.MNEMONIC}/${tmp.bech32}`).update({ consumedOutputIds: [] }); + await build5Db().doc(COL.MNEMONIC, tmp.bech32).update({ consumedOutputIds: [] }); const query = build5Db().collection(COL.TOKEN_MARKET).where('owner', '==', tmp.bech32); await wait(async () => { @@ -113,7 +112,7 @@ describe('Minted toke trading tangle request', () => { ); it('Should throw, trading disabled', async () => { - await build5Db().doc(`${COL.TOKEN}/${helper.token!.uid}`).update({ tradingDisabled: true }); + await build5Db().doc(COL.TOKEN, helper.token!.uid).update({ tradingDisabled: true }); const tmp = await helper.walletService!.getNewIotaAddressDetails(); await requestFundsFromFaucet(Network.RMS, tmp.bech32, 10 * MIN_IOTA_AMOUNT); @@ -127,11 +126,11 @@ describe('Minted toke trading tangle request', () => { }, }, }); - await build5Db().doc(`${COL.MNEMONIC}/${tmp.bech32}`).update({ consumedOutputIds: [] }); + await build5Db().doc(COL.MNEMONIC, tmp.bech32).update({ consumedOutputIds: [] }); const creditQuery = build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.CREDIT_TANGLE_REQUEST) + .where('type', '==', PgTransactionType.CREDIT_TANGLE_REQUEST) .where('member', '==', tmp.bech32); await wait(async () => { const snap = await creditQuery.get(); diff --git a/packages/functions/test-tangle/minted-token-trade/minted-token-trade_19.spec.ts b/packages/functions/test-tangle/minted-token-trade/minted-token-trade_19.spec.ts index 7f46b009d2..0592ee2dc2 100644 --- a/packages/functions/test-tangle/minted-token-trade/minted-token-trade_19.spec.ts +++ b/packages/functions/test-tangle/minted-token-trade/minted-token-trade_19.spec.ts @@ -1,11 +1,4 @@ -import { - COL, - MIN_IOTA_AMOUNT, - Network, - TangleRequestType, - TokenTradeOrder, - Transaction, -} from '@build-5/interfaces'; +import { COL, MIN_IOTA_AMOUNT, Network, TangleRequestType, Transaction } from '@build-5/interfaces'; import { build5Db } from '@build-5/database'; import { wait } from '../../test/controls/common'; @@ -75,26 +68,28 @@ describe('Minted toke trading tangle request', () => { }, ); - let query = build5Db().collection(COL.TOKEN_MARKET).where('owner', '==', helper.seller); + const queryBySeller = build5Db() + .collection(COL.TOKEN_MARKET) + .where('owner', '==', helper.seller); await wait(async () => { - const snap = await query.get(); + const snap = await queryBySeller.get(); return snap.length > 0; }); - const sell = (await query.get())[0]!; + const sell = (await queryBySeller.get())[0]!; - query = build5Db().collection(COL.TOKEN_MARKET).where('owner', '==', helper.buyer); + const queryByOwner = build5Db().collection(COL.TOKEN_MARKET).where('owner', '==', helper.buyer); await wait(async () => { - const snap = await query.get(); + const snap = await queryByOwner.get(); return snap.length > 0; }); - const buy = (await query.get())[0]!; + const buy = (await queryByOwner.get())[0]!; - query = build5Db() + const queryByTrade = build5Db() .collection(COL.TOKEN_PURCHASE) .where('sell', '==', sell.uid) .where('buy', '==', buy.uid); await wait(async () => { - const snap = await query.get(); + const snap = await queryByTrade.get(); return snap.length > 0; }); diff --git a/packages/functions/test-tangle/minted-token-trade/minted-token-trade_2.spec.ts b/packages/functions/test-tangle/minted-token-trade/minted-token-trade_2.spec.ts index 26c5d9c45e..34f652595f 100644 --- a/packages/functions/test-tangle/minted-token-trade/minted-token-trade_2.spec.ts +++ b/packages/functions/test-tangle/minted-token-trade/minted-token-trade_2.spec.ts @@ -1,13 +1,7 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ -import { build5Db } from '@build-5/database'; -import { - COL, - MIN_IOTA_AMOUNT, - Transaction, - TransactionPayloadType, - TransactionType, -} from '@build-5/interfaces'; +import { PgTransactionType, build5Db } from '@build-5/database'; +import { COL, MIN_IOTA_AMOUNT, Transaction, TransactionPayloadType } from '@build-5/interfaces'; import { wait } from '../../test/controls/common'; import { awaitTransactionConfirmationsForToken } from '../common'; import { Helper } from './Helper'; @@ -29,8 +23,8 @@ describe('Token minting', () => { const billPaymentsQuery = build5Db() .collection(COL.TRANSACTION) - .where('member', 'in', [helper.seller, helper.buyer]) - .where('type', '==', TransactionType.BILL_PAYMENT); + .where('type', '==', PgTransactionType.BILL_PAYMENT) + .whereIn('member', [helper.seller, helper.buyer]); await wait(async () => { const snap = await billPaymentsQuery.get(); return snap.length === 4; @@ -43,7 +37,7 @@ describe('Token minting', () => { expect(paymentToSeller.payload.amount).toBe(9602600); expect(paymentToSeller.payload.sourceAddress).toBe(buyOrder.payload.targetAddress); - expect(paymentToSeller.payload.storageReturn).toBeUndefined(); + expect(paymentToSeller.payload.storageReturn).toEqual({}); const royaltyOnePayment = billPayments.find((bp) => bp.payload.amount === 271800)!; expect(royaltyOnePayment.payload.storageReturn!.address).toBe(helper.sellerAddress!.bech32); @@ -68,7 +62,7 @@ describe('Token minting', () => { const sellerCreditSnap = await build5Db() .collection(COL.TRANSACTION) .where('member', '==', helper.seller) - .where('type', '==', TransactionType.CREDIT) + .where('type', '==', PgTransactionType.CREDIT) .get(); expect(sellerCreditSnap.length).toBe(1); const sellerCredit = sellerCreditSnap.map((d) => d as Transaction)[0]; @@ -77,7 +71,7 @@ describe('Token minting', () => { const buyerCreditSnap = await build5Db() .collection(COL.TRANSACTION) .where('member', '==', helper.buyer) - .where('type', '==', TransactionType.CREDIT) + .where('type', '==', PgTransactionType.CREDIT) .get(); expect(buyerCreditSnap.length).toBe(1); const buyerCredit = buyerCreditSnap.map((d) => d as Transaction)[0]; diff --git a/packages/functions/test-tangle/minted-token-trade/minted-token-trade_20.spec.ts b/packages/functions/test-tangle/minted-token-trade/minted-token-trade_20.spec.ts index 2e0c137397..27a611166a 100644 --- a/packages/functions/test-tangle/minted-token-trade/minted-token-trade_20.spec.ts +++ b/packages/functions/test-tangle/minted-token-trade/minted-token-trade_20.spec.ts @@ -1,6 +1,6 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ -import { build5Db } from '@build-5/database'; +import { PgTransactionType, build5Db } from '@build-5/database'; import { COL, IgnoreWalletReason, @@ -8,14 +8,12 @@ import { TRANSACTION_AUTO_EXPIRY_MS, TokenTradeOrderType, Transaction, - TransactionType, + WEN_FUNC, } from '@build-5/interfaces'; import dayjs from 'dayjs'; -import { creditUnrefundable } from '../../src/runtime/firebase/credit/index'; -import { tradeToken } from '../../src/runtime/firebase/token/trading'; import { dateToTimestamp } from '../../src/utils/dateTime.utils'; -import { mockWalletReturnValue, wait } from '../../test/controls/common'; -import { testEnv } from '../../test/set-up'; +import { wait } from '../../test/controls/common'; +import { mockWalletReturnValue, testEnv } from '../../test/set-up'; import { Helper } from './Helper'; describe('Token minting', () => { @@ -30,13 +28,13 @@ describe('Token minting', () => { }); it('Should not create sell order, storage deposit unlock condition, also not claimable', async () => { - mockWalletReturnValue(helper.walletSpy, helper.seller!, { + mockWalletReturnValue(helper.seller!, { symbol: helper.token!.symbol, count: 10, price: MIN_IOTA_AMOUNT, type: TokenTradeOrderType.SELL, }); - const sellOrder: Transaction = await testEnv.wrap(tradeToken)({}); + const sellOrder: Transaction = await testEnv.wrap(WEN_FUNC.tradeToken); await helper.walletService!.send(helper.sellerAddress!, sellOrder.payload.targetAddress!, 0, { nativeTokens: [{ amount: BigInt(10), id: helper.token!.mintingData?.tokenId! }], storageDepositReturnAddress: helper.sellerAddress?.bech32, @@ -47,10 +45,10 @@ describe('Token minting', () => { }); const query = build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.CREDIT) + .where('type', '==', PgTransactionType.CREDIT) .where('member', '==', helper.seller); await wait(async () => { - const snap = await query.get(); + const snap = await query.get(); return ( snap.length === 1 && snap[0].ignoreWalletReason === @@ -59,9 +57,10 @@ describe('Token minting', () => { ); }); - const snap = await query.get(); - mockWalletReturnValue(helper.walletSpy, helper.seller!, { transaction: snap[0].uid }); - const order = await testEnv.wrap(creditUnrefundable)({}); + const snap = await query.get(); + mockWalletReturnValue(helper.seller!, { transaction: snap[0].uid }); + let order = await testEnv.wrap(WEN_FUNC.creditUnrefundable); + order = (await build5Db().doc(COL.TRANSACTION, order.uid).get())!; const expiresOn = order.payload.expiresOn!; const isEarlier = dayjs(expiresOn.toDate()).isBefore(dayjs().add(TRANSACTION_AUTO_EXPIRY_MS)); diff --git a/packages/functions/test-tangle/minted-token-trade/minted-token-trade_21.spec.ts b/packages/functions/test-tangle/minted-token-trade/minted-token-trade_21.spec.ts index 1b089bf51e..032758f243 100644 --- a/packages/functions/test-tangle/minted-token-trade/minted-token-trade_21.spec.ts +++ b/packages/functions/test-tangle/minted-token-trade/minted-token-trade_21.spec.ts @@ -1,13 +1,11 @@ -import { build5Db } from '@build-5/database'; +import { PgTokenTradeOrderType, build5Db } from '@build-5/database'; import { COL, MAX_TOTAL_TOKEN_SUPPLY, MIN_IOTA_AMOUNT, Network, TangleRequestType, - TokenTradeOrder, TokenTradeOrderStatus, - TokenTradeOrderType, Transaction, } from '@build-5/interfaces'; import { wait } from '../../test/controls/common'; @@ -52,12 +50,12 @@ describe('Minted toke trading tangle request', () => { const buyQuery = build5Db() .collection(COL.TOKEN_MARKET) .where('owner', '==', tmp.bech32) - .where('type', '==', TokenTradeOrderType.BUY); + .where('type', '==', PgTokenTradeOrderType.BUY); await wait(async () => { - const snap = await buyQuery.get(); + const snap = await buyQuery.get(); return snap.length === 1 && snap[0].status === TokenTradeOrderStatus.SETTLED; }); - const buyOrder = (await buyQuery.get())[0]; + const buyOrder = (await buyQuery.get())[0]; expect(buyOrder.count).toBe(MAX_TOTAL_TOKEN_SUPPLY); expect(buyOrder.fulfilled).toBe(15); @@ -66,8 +64,8 @@ describe('Minted toke trading tangle request', () => { const sellOrders = await build5Db() .collection(COL.TOKEN_MARKET) .where('owner', '==', helper.seller) - .where('type', '==', TokenTradeOrderType.SELL) - .get(); + .where('type', '==', PgTokenTradeOrderType.SELL) + .get(); sellOrders.sort((a, b) => a.price - b.price); expect(sellOrders[0].price).toBe(MIN_IOTA_AMOUNT); diff --git a/packages/functions/test-tangle/minted-token-trade/minted-token-trade_22.spec.ts b/packages/functions/test-tangle/minted-token-trade/minted-token-trade_22.spec.ts index 51f6e72a80..c39dd10f3b 100644 --- a/packages/functions/test-tangle/minted-token-trade/minted-token-trade_22.spec.ts +++ b/packages/functions/test-tangle/minted-token-trade/minted-token-trade_22.spec.ts @@ -1,13 +1,11 @@ -import { build5Db } from '@build-5/database'; +import { PgTokenTradeOrderType, build5Db } from '@build-5/database'; import { COL, MAX_TOTAL_TOKEN_SUPPLY, MIN_IOTA_AMOUNT, Network, TangleRequestType, - TokenTradeOrder, TokenTradeOrderStatus, - TokenTradeOrderType, Transaction, } from '@build-5/interfaces'; import { wait } from '../../test/controls/common'; @@ -47,12 +45,12 @@ describe('Minted toke trading tangle request', () => { const buyQuery = build5Db() .collection(COL.TOKEN_MARKET) .where('owner', '==', tmp.bech32) - .where('type', '==', TokenTradeOrderType.BUY); + .where('type', '==', PgTokenTradeOrderType.BUY); await wait(async () => { - const snap = await buyQuery.get(); + const snap = await buyQuery.get(); return snap.length === 1 && snap[0].fulfilled === 3; }); - const buyOrder = (await buyQuery.get())[0]; + const buyOrder = (await buyQuery.get())[0]; expect(buyOrder.count).toBe(MAX_TOTAL_TOKEN_SUPPLY); expect(buyOrder.fulfilled).toBe(3); @@ -62,8 +60,8 @@ describe('Minted toke trading tangle request', () => { const sellOrders = await build5Db() .collection(COL.TOKEN_MARKET) .where('owner', '==', helper.seller) - .where('type', '==', TokenTradeOrderType.SELL) - .get(); + .where('type', '==', PgTokenTradeOrderType.SELL) + .get(); sellOrders.sort((a, b) => a.price - b.price); expect(sellOrders[0].price).toBe(MIN_IOTA_AMOUNT); diff --git a/packages/functions/test-tangle/minted-token-trade/minted-token-trade_23.spec.ts b/packages/functions/test-tangle/minted-token-trade/minted-token-trade_23.spec.ts index 53d59d6be0..8a8785568e 100644 --- a/packages/functions/test-tangle/minted-token-trade/minted-token-trade_23.spec.ts +++ b/packages/functions/test-tangle/minted-token-trade/minted-token-trade_23.spec.ts @@ -1,13 +1,11 @@ -import { build5Db } from '@build-5/database'; +import { PgTokenTradeOrderType, build5Db } from '@build-5/database'; import { COL, MIN_IOTA_AMOUNT, MIN_PRICE_PER_TOKEN, Network, TangleRequestType, - TokenTradeOrder, TokenTradeOrderStatus, - TokenTradeOrderType, Transaction, } from '@build-5/interfaces'; import { wait } from '../../test/controls/common'; @@ -49,12 +47,12 @@ describe('Minted toke trading tangle request', () => { const sellQuery = build5Db() .collection(COL.TOKEN_MARKET) .where('owner', '==', helper.seller!) - .where('type', '==', TokenTradeOrderType.SELL); + .where('type', '==', PgTokenTradeOrderType.SELL); await wait(async () => { - const snap = await sellQuery.get(); + const snap = await sellQuery.get(); return snap.length === 1 && snap[0].status === TokenTradeOrderStatus.SETTLED; }); - const sellOrder = (await sellQuery.get())[0]; + const sellOrder = (await sellQuery.get())[0]; expect(sellOrder.count).toBe(3); expect(sellOrder.fulfilled).toBe(3); @@ -64,8 +62,8 @@ describe('Minted toke trading tangle request', () => { const buyOrders = await build5Db() .collection(COL.TOKEN_MARKET) .where('owner', '==', helper.buyer!) - .where('type', '==', TokenTradeOrderType.BUY) - .get(); + .where('type', '==', PgTokenTradeOrderType.BUY) + .get(); buyOrders.sort((a, b) => b.price - a.price); expect(buyOrders[0].price).toBe(2 * MIN_IOTA_AMOUNT); diff --git a/packages/functions/test-tangle/minted-token-trade/minted-token-trade_24.spec.ts b/packages/functions/test-tangle/minted-token-trade/minted-token-trade_24.spec.ts index dd2e44f480..931d60730d 100644 --- a/packages/functions/test-tangle/minted-token-trade/minted-token-trade_24.spec.ts +++ b/packages/functions/test-tangle/minted-token-trade/minted-token-trade_24.spec.ts @@ -1,13 +1,5 @@ -import { build5Db } from '@build-5/database'; -import { - COL, - MIN_IOTA_AMOUNT, - Network, - TangleRequestType, - TokenTradeOrder, - TokenTradeOrderType, - Transaction, -} from '@build-5/interfaces'; +import { PgTokenTradeOrderType, build5Db } from '@build-5/database'; +import { COL, MIN_IOTA_AMOUNT, Network, TangleRequestType, Transaction } from '@build-5/interfaces'; import { wait } from '../../test/controls/common'; import { getTangleOrder } from '../common'; import { Helper } from './Helper'; @@ -47,12 +39,12 @@ describe('Minted toke trading tangle request', () => { const sellQuery = build5Db() .collection(COL.TOKEN_MARKET) .where('owner', '==', helper.seller!) - .where('type', '==', TokenTradeOrderType.SELL); + .where('type', '==', PgTokenTradeOrderType.SELL); await wait(async () => { - const snap = await sellQuery.get(); + const snap = await sellQuery.get(); return snap.length === 1 && snap[0].fulfilled === 3; }); - const sellOrder = (await sellQuery.get())[0]; + const sellOrder = (await sellQuery.get())[0]; expect(sellOrder.count).toBe(4); expect(sellOrder.fulfilled).toBe(3); @@ -61,8 +53,8 @@ describe('Minted toke trading tangle request', () => { const buyOrders = await build5Db() .collection(COL.TOKEN_MARKET) .where('owner', '==', helper.buyer!) - .where('type', '==', TokenTradeOrderType.BUY) - .get(); + .where('type', '==', PgTokenTradeOrderType.BUY) + .get(); buyOrders.sort((a, b) => b.price - a.price); expect(buyOrders[0].price).toBe(2 * MIN_IOTA_AMOUNT); diff --git a/packages/functions/test-tangle/minted-token-trade/minted-token-trade_2_b.spec.ts b/packages/functions/test-tangle/minted-token-trade/minted-token-trade_2_b.spec.ts index c7a4c73687..aa696c942c 100644 --- a/packages/functions/test-tangle/minted-token-trade/minted-token-trade_2_b.spec.ts +++ b/packages/functions/test-tangle/minted-token-trade/minted-token-trade_2_b.spec.ts @@ -34,7 +34,7 @@ describe('Token minting', () => { .collection(COL.TOKEN_MARKET) .where('orderTransactionId', '==', buyOrder.uid); await wait(async () => { - const buySnap = await buyQuery.get(); + const buySnap = await buyQuery.get(); return buySnap[0].fulfilled === 99; }); let buy = (await buyQuery.get())[0] as TokenTradeOrder; @@ -48,7 +48,7 @@ describe('Token minting', () => { .collection(COL.TOKEN_MARKET) .where('orderTransactionId', '==', buyOrder2.uid); await wait(async () => { - const buySnap = await buyQuery2.get(); + const buySnap = await buyQuery2.get(); return buySnap[0].fulfilled === 1; }); diff --git a/packages/functions/test-tangle/minted-token-trade/minted-token-trade_3.spec.ts b/packages/functions/test-tangle/minted-token-trade/minted-token-trade_3.spec.ts index 2840f64806..01926e3b16 100644 --- a/packages/functions/test-tangle/minted-token-trade/minted-token-trade_3.spec.ts +++ b/packages/functions/test-tangle/minted-token-trade/minted-token-trade_3.spec.ts @@ -1,6 +1,6 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ -import { build5Db } from '@build-5/database'; +import { build5Db, PgTransactionType } from '@build-5/database'; import { COL, Member, @@ -9,15 +9,14 @@ import { TokenTradeOrder, TokenTradeOrderType, Transaction, - TransactionType, + WEN_FUNC, } from '@build-5/interfaces'; import dayjs from 'dayjs'; import { cancelExpiredSale } from '../../src/cron/token.cron'; -import { tradeToken } from '../../src/runtime/firebase/token/trading'; import { getAddress } from '../../src/utils/address.utils'; import { dateToTimestamp } from '../../src/utils/dateTime.utils'; -import { mockWalletReturnValue, wait } from '../../test/controls/common'; -import { testEnv } from '../../test/set-up'; +import { wait } from '../../test/controls/common'; +import { mockWalletReturnValue, testEnv } from '../../test/set-up'; import { awaitTransactionConfirmationsForToken } from '../common'; import { Helper } from './Helper'; @@ -61,7 +60,7 @@ describe('Token minting', () => { } const member = await build5Db() - .doc(`${COL.MEMBER}/${type === TokenTradeOrderType.SELL ? helper.seller! : helper.buyer!}`) + .doc(COL.MEMBER, type === TokenTradeOrderType.SELL ? helper.seller! : helper.buyer!) .get(); const tradeQuery = build5Db().collection(COL.TOKEN_MARKET).where('owner', '==', member.uid); @@ -73,16 +72,16 @@ describe('Token minting', () => { expect(dayjs(trade.expiresAt.toDate()).isSame(dayjs(expiresAt.toDate()))).toBe(true); await build5Db() - .doc(`${COL.TOKEN_MARKET}/${trade.uid}`) - .update({ expiresAt: dateToTimestamp(dayjs().subtract(1, 'm').toDate()) }); + .doc(COL.TOKEN_MARKET, trade.uid) + .update({ expiresAt: dayjs().subtract(1, 'm').toDate() }); await cancelExpiredSale(); await wait(async () => { const snap = await build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.CREDIT) + .where('type', '==', PgTransactionType.CREDIT) .where('member', '==', member.uid) - .get(); + .get(); return ( snap.length === 1 && snap[0]!.payload.targetAddress === getAddress(member, helper.network) ); @@ -94,16 +93,16 @@ describe('Token minting', () => { const date = dayjs().add(2, 'h').millisecond(0).toDate(); const expiresAt = dateToTimestamp(date) as Timestamp; - mockWalletReturnValue(helper.walletSpy, helper.seller!, { + mockWalletReturnValue(helper.seller!, { symbol: helper.token!.symbol, count: 10, price: MIN_IOTA_AMOUNT, type: TokenTradeOrderType.SELL, }); - const sellOrder: Transaction = await testEnv.wrap(tradeToken)({}); + const sellOrder: Transaction = await testEnv.wrap(WEN_FUNC.tradeToken); await build5Db() - .doc(`${COL.TRANSACTION}/${sellOrder.uid}`) - .update({ 'payload.expiresOn': dateToTimestamp(dayjs().subtract(2, 'h').toDate()) }); + .doc(COL.TRANSACTION, sellOrder.uid) + .update({ payload_expiresOn: dayjs().subtract(2, 'h').toDate() }); await helper.walletService!.send(helper.sellerAddress!, sellOrder.payload.targetAddress!, 0, { nativeTokens: [{ amount: BigInt(10), id: helper.token!.mintingData?.tokenId! }], @@ -118,9 +117,9 @@ describe('Token minting', () => { await wait(async () => { const snap = await build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.CREDIT) + .where('type', '==', PgTransactionType.CREDIT) .where('member', '==', helper.seller) - .get(); + .get(); return ( snap.length === 1 && snap[0]!.payload.walletReference?.confirmed && diff --git a/packages/functions/test-tangle/minted-token-trade/minted-token-trade_4.spec.ts b/packages/functions/test-tangle/minted-token-trade/minted-token-trade_4.spec.ts index ed1b731aaa..f26dd3d85b 100644 --- a/packages/functions/test-tangle/minted-token-trade/minted-token-trade_4.spec.ts +++ b/packages/functions/test-tangle/minted-token-trade/minted-token-trade_4.spec.ts @@ -1,16 +1,14 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ -import { build5Db } from '@build-5/database'; +import { PgTransactionType, build5Db } from '@build-5/database'; import { COL, CreditPaymentReason, TokenTradeOrder, Transaction, - TransactionType, + WEN_FUNC, } from '@build-5/interfaces'; -import { cancelTradeOrder } from '../../src/runtime/firebase/token/trading'; -import { mockWalletReturnValue } from '../../test/controls/common'; -import { testEnv } from '../../test/set-up'; +import { mockWalletReturnValue, testEnv } from '../../test/set-up'; import { awaitTransactionConfirmationsForToken } from '../common'; import { Helper } from './Helper'; @@ -30,13 +28,13 @@ describe('Token minting', () => { const query = build5Db().collection(COL.TOKEN_MARKET).where('owner', '==', helper.seller); const sell = (await query.get())[0]; - mockWalletReturnValue(helper.walletSpy, helper.seller!, { uid: sell.uid }); - await testEnv.wrap(cancelTradeOrder)({}); + mockWalletReturnValue(helper.seller!, { uid: sell.uid }); + await testEnv.wrap(WEN_FUNC.cancelTradeOrder); const sellerCreditSnap = await build5Db() .collection(COL.TRANSACTION) .where('member', '==', helper.seller) - .where('type', '==', TransactionType.CREDIT) + .where('type', '==', PgTransactionType.CREDIT) .get(); expect(sellerCreditSnap.length).toBe(1); const sellerCredit = sellerCreditSnap[0] as Transaction; diff --git a/packages/functions/test-tangle/minted-token-trade/minted-token-trade_5.spec.ts b/packages/functions/test-tangle/minted-token-trade/minted-token-trade_5.spec.ts index 465fe5b1d8..62814a5a09 100644 --- a/packages/functions/test-tangle/minted-token-trade/minted-token-trade_5.spec.ts +++ b/packages/functions/test-tangle/minted-token-trade/minted-token-trade_5.spec.ts @@ -1,17 +1,14 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ -import { build5Db } from '@build-5/database'; +import { PgTransactionType, build5Db } from '@build-5/database'; import { COL, CreditPaymentReason, MIN_IOTA_AMOUNT, TokenTradeOrder, - Transaction, - TransactionType, + WEN_FUNC, } from '@build-5/interfaces'; -import { cancelTradeOrder } from '../../src/runtime/firebase/token/trading'; -import { mockWalletReturnValue } from '../../test/controls/common'; -import { testEnv } from '../../test/set-up'; +import { mockWalletReturnValue, testEnv } from '../../test/set-up'; import { awaitTransactionConfirmationsForToken } from '../common'; import { Helper } from './Helper'; @@ -31,14 +28,14 @@ describe('Token minting', () => { const query = build5Db().collection(COL.TOKEN_MARKET).where('owner', '==', helper.buyer); const buy = (await query.get())[0]; - mockWalletReturnValue(helper.walletSpy, helper.buyer!, { uid: buy.uid }); - await testEnv.wrap(cancelTradeOrder)({}); + mockWalletReturnValue(helper.buyer!, { uid: buy.uid }); + await testEnv.wrap(WEN_FUNC.cancelTradeOrder); const buyerCreditnap = await build5Db() .collection(COL.TRANSACTION) .where('member', '==', helper.buyer) - .where('type', '==', TransactionType.CREDIT) - .get(); + .where('type', '==', PgTransactionType.CREDIT) + .get(); expect(buyerCreditnap.length).toBe(1); expect(buyerCreditnap[0]?.payload?.amount).toBe(10 * MIN_IOTA_AMOUNT); expect(buyerCreditnap[0]?.payload?.reason).toBe(CreditPaymentReason.TRADE_CANCELLED); diff --git a/packages/functions/test-tangle/minted-token-trade/minted-token-trade_6.spec.ts b/packages/functions/test-tangle/minted-token-trade/minted-token-trade_6.spec.ts index 3122747175..04729b6a60 100644 --- a/packages/functions/test-tangle/minted-token-trade/minted-token-trade_6.spec.ts +++ b/packages/functions/test-tangle/minted-token-trade/minted-token-trade_6.spec.ts @@ -1,17 +1,16 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ -import { build5Db } from '@build-5/database'; +import { PgTransactionType, build5Db } from '@build-5/database'; import { COL, CreditPaymentReason, MIN_IOTA_AMOUNT, TokenTradeOrder, Transaction, - TransactionType, + WEN_FUNC, } from '@build-5/interfaces'; -import { cancelTradeOrder } from '../../src/runtime/firebase/token/trading'; -import { mockWalletReturnValue, wait } from '../../test/controls/common'; -import { testEnv } from '../../test/set-up'; +import { wait } from '../../test/controls/common'; +import { mockWalletReturnValue, testEnv } from '../../test/set-up'; import { awaitTransactionConfirmationsForToken } from '../common'; import { Helper } from './Helper'; @@ -37,13 +36,13 @@ describe('Token minting', () => { }); const buy = (await query.get())[0]; - mockWalletReturnValue(helper.walletSpy, helper.buyer!, { uid: buy.uid }); - await testEnv.wrap(cancelTradeOrder)({}); + mockWalletReturnValue(helper.buyer!, { uid: buy.uid }); + await testEnv.wrap(WEN_FUNC.cancelTradeOrder); const billPaymentsQuery = build5Db() .collection(COL.TRANSACTION) - .where('member', 'in', [helper.seller, helper.buyer]) - .where('type', '==', TransactionType.BILL_PAYMENT); + .where('type', '==', PgTransactionType.BILL_PAYMENT) + .whereIn('member', [helper.seller, helper.buyer]); await wait(async () => { const snap = await billPaymentsQuery.get(); return snap.length === 4; @@ -55,7 +54,7 @@ describe('Token minting', () => { )!; expect(paymentToSeller.payload.amount).toBe(4727600); expect(paymentToSeller.payload.sourceAddress).toBe(buyOrder.payload.targetAddress); - expect(paymentToSeller.payload.storageReturn).toBeUndefined(); + expect(paymentToSeller.payload.storageReturn).toEqual({}); const royaltyOnePayment = billPayments.find((bp) => bp.payload.amount === 159300)!; expect(royaltyOnePayment.payload.storageReturn!.address).toBe(helper.sellerAddress!.bech32); @@ -80,7 +79,7 @@ describe('Token minting', () => { const sellerCreditSnap = await build5Db() .collection(COL.TRANSACTION) .where('member', '==', helper.seller) - .where('type', '==', TransactionType.CREDIT) + .where('type', '==', PgTransactionType.CREDIT) .get(); expect(sellerCreditSnap.length).toBe(1); const sellerCredit = sellerCreditSnap.map((d) => d as Transaction)[0]; @@ -89,7 +88,7 @@ describe('Token minting', () => { const buyerCreditSnap = await build5Db() .collection(COL.TRANSACTION) .where('member', '==', helper.buyer) - .where('type', '==', TransactionType.CREDIT) + .where('type', '==', PgTransactionType.CREDIT) .get(); expect(buyerCreditSnap.length).toBe(1); const buyerCredit = buyerCreditSnap.map((d) => d as Transaction)[0]; diff --git a/packages/functions/test-tangle/minted-token-trade/minted-token-trade_7.spec.ts b/packages/functions/test-tangle/minted-token-trade/minted-token-trade_7.spec.ts index 28ec8fc8e3..ee8599fe13 100644 --- a/packages/functions/test-tangle/minted-token-trade/minted-token-trade_7.spec.ts +++ b/packages/functions/test-tangle/minted-token-trade/minted-token-trade_7.spec.ts @@ -1,17 +1,16 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ -import { build5Db } from '@build-5/database'; +import { PgTransactionType, build5Db } from '@build-5/database'; import { COL, CreditPaymentReason, MIN_IOTA_AMOUNT, TokenTradeOrder, Transaction, - TransactionType, + WEN_FUNC, } from '@build-5/interfaces'; -import { cancelTradeOrder } from '../../src/runtime/firebase/token/trading'; -import { mockWalletReturnValue, wait } from '../../test/controls/common'; -import { testEnv } from '../../test/set-up'; +import { wait } from '../../test/controls/common'; +import { mockWalletReturnValue, testEnv } from '../../test/set-up'; import { awaitTransactionConfirmationsForToken } from '../common'; import { Helper } from './Helper'; @@ -38,13 +37,13 @@ describe('Token minting', () => { await awaitTransactionConfirmationsForToken(helper.token!.uid); const sell = (await query.get())[0]; - mockWalletReturnValue(helper.walletSpy, helper.seller!, { uid: sell.uid }); - await testEnv.wrap(cancelTradeOrder)({}); + mockWalletReturnValue(helper.seller!, { uid: sell.uid }); + await testEnv.wrap(WEN_FUNC.cancelTradeOrder); const billPaymentsQuery = build5Db() .collection(COL.TRANSACTION) - .where('member', 'in', [helper.seller, helper.buyer]) - .where('type', '==', TransactionType.BILL_PAYMENT); + .where('type', '==', PgTransactionType.BILL_PAYMENT) + .whereIn('member', [helper.seller, helper.buyer]); await wait(async () => { const snap = await billPaymentsQuery.get(); return snap.length === 4; @@ -56,7 +55,7 @@ describe('Token minting', () => { )!; expect(paymentToSeller.payload.amount).toBe(4727600); expect(paymentToSeller.payload.sourceAddress).toBe(buyOrder.payload.targetAddress); - expect(paymentToSeller.payload.storageReturn).toBeUndefined(); + expect(paymentToSeller.payload.storageReturn).toEqual({}); const royaltyOnePayment = billPayments.find((bp) => bp.payload.amount === 159300)!; expect(royaltyOnePayment.payload.storageReturn!.address).toBe(helper.sellerAddress!.bech32); @@ -81,7 +80,7 @@ describe('Token minting', () => { const sellerCreditSnap = await build5Db() .collection(COL.TRANSACTION) .where('member', '==', helper.seller) - .where('type', '==', TransactionType.CREDIT) + .where('type', '==', PgTransactionType.CREDIT) .get(); expect(sellerCreditSnap.length).toBe(1); const sellerCredit = sellerCreditSnap.map((d) => d as Transaction)[0]; @@ -92,7 +91,7 @@ describe('Token minting', () => { const buyerCreditSnap = await build5Db() .collection(COL.TRANSACTION) .where('member', '==', helper.buyer) - .where('type', '==', TransactionType.CREDIT) + .where('type', '==', PgTransactionType.CREDIT) .get(); expect(buyerCreditSnap.length).toBe(0); diff --git a/packages/functions/test-tangle/minted-token-trade/minted-token-trade_8.spec.ts b/packages/functions/test-tangle/minted-token-trade/minted-token-trade_8.spec.ts index 2c82c047ef..4ef8e8a287 100644 --- a/packages/functions/test-tangle/minted-token-trade/minted-token-trade_8.spec.ts +++ b/packages/functions/test-tangle/minted-token-trade/minted-token-trade_8.spec.ts @@ -1,10 +1,16 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ import { build5Db } from '@build-5/database'; -import { COL, MIN_IOTA_AMOUNT, TokenTradeOrderType, WenError } from '@build-5/interfaces'; -import { tradeToken } from '../../src/runtime/firebase/token/trading'; -import { expectThrow, mockWalletReturnValue } from '../../test/controls/common'; -import { testEnv } from '../../test/set-up'; +import { + COL, + MIN_IOTA_AMOUNT, + TokenTradeOrderType, + Transaction, + WEN_FUNC, + WenError, +} from '@build-5/interfaces'; +import { expectThrow } from '../../test/controls/common'; +import { mockWalletReturnValue, testEnv } from '../../test/set-up'; import { awaitTransactionConfirmationsForToken } from '../common'; import { Helper } from './Helper'; @@ -21,52 +27,50 @@ describe('Token minting', () => { it('Should create sell order, not approved, but public', async () => { // Should throw at sell, not approved, not public - await build5Db() - .doc(`${COL.TOKEN}/${helper.token!.uid}`) - .update({ approved: false, public: false }); - mockWalletReturnValue(helper.walletSpy, helper.seller!, { + await build5Db().doc(COL.TOKEN, helper.token!.uid).update({ approved: false, public: false }); + mockWalletReturnValue(helper.seller!, { symbol: helper.token!.symbol, count: 10, price: MIN_IOTA_AMOUNT, type: TokenTradeOrderType.SELL, }); - await expectThrow(testEnv.wrap(tradeToken)({}), WenError.token_does_not_exist.key); + await expectThrow( + testEnv.wrap(WEN_FUNC.tradeToken), + WenError.token_does_not_exist.key, + ); // Should throw at buy, not approved, not public - await build5Db() - .doc(`${COL.TOKEN}/${helper.token!.uid}`) - .update({ approved: false, public: false }); - mockWalletReturnValue(helper.walletSpy, helper.buyer!, { + await build5Db().doc(COL.TOKEN, helper.token!.uid).update({ approved: false, public: false }); + mockWalletReturnValue(helper.buyer!, { symbol: helper.token!.symbol, count: 5, price: MIN_IOTA_AMOUNT, type: TokenTradeOrderType.BUY, }); - await expectThrow(testEnv.wrap(tradeToken)({}), WenError.token_does_not_exist.key); + await expectThrow( + testEnv.wrap(WEN_FUNC.tradeToken), + WenError.token_does_not_exist.key, + ); // Should create sell order, not approved, but public - await build5Db() - .doc(`${COL.TOKEN}/${helper.token!.uid}`) - .update({ approved: false, public: true }); - mockWalletReturnValue(helper.walletSpy, helper.seller!, { + await build5Db().doc(COL.TOKEN, helper.token!.uid).update({ approved: false, public: true }); + mockWalletReturnValue(helper.seller!, { symbol: helper.token!.symbol, count: 10, price: MIN_IOTA_AMOUNT, type: TokenTradeOrderType.SELL, }); - expect(await testEnv.wrap(tradeToken)({})).toBeDefined(); + expect(await testEnv.wrap(WEN_FUNC.tradeToken)).toBeDefined(); // Should create buy order, not approved, but public' - await build5Db() - .doc(`${COL.TOKEN}/${helper.token!.uid}`) - .update({ approved: false, public: true }); - mockWalletReturnValue(helper.walletSpy, helper.seller!, { + await build5Db().doc(COL.TOKEN, helper.token!.uid).update({ approved: false, public: true }); + mockWalletReturnValue(helper.seller!, { symbol: helper.token!.symbol, count: 10, price: MIN_IOTA_AMOUNT, type: TokenTradeOrderType.BUY, }); - expect(await testEnv.wrap(tradeToken)({})).toBeDefined(); + expect(await testEnv.wrap(WEN_FUNC.tradeToken)).toBeDefined(); await awaitTransactionConfirmationsForToken(helper.token!.uid); }); diff --git a/packages/functions/test-tangle/minted-token-trade/minted-token-trade_9.spec.ts b/packages/functions/test-tangle/minted-token-trade/minted-token-trade_9.spec.ts index 8dc60fc7e6..06a41e7054 100644 --- a/packages/functions/test-tangle/minted-token-trade/minted-token-trade_9.spec.ts +++ b/packages/functions/test-tangle/minted-token-trade/minted-token-trade_9.spec.ts @@ -1,17 +1,16 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ -import { build5Db } from '@build-5/database'; +import { PgTransactionType, build5Db } from '@build-5/database'; import { COL, MIN_IOTA_AMOUNT, TokenTradeOrderType, Transaction, - TransactionType, + WEN_FUNC, } from '@build-5/interfaces'; -import { tradeToken } from '../../src/runtime/firebase/token/trading'; import { packBasicOutput } from '../../src/utils/basic-output.utils'; -import { mockWalletReturnValue, wait } from '../../test/controls/common'; -import { testEnv } from '../../test/set-up'; +import { wait } from '../../test/controls/common'; +import { mockWalletReturnValue, testEnv } from '../../test/set-up'; import { awaitTransactionConfirmationsForToken } from '../common'; import { Helper, MINTED_TOKEN_ID, dummyTokenId, saveToken } from './Helper'; @@ -33,20 +32,20 @@ describe('Token minting', () => { helper.walletService!, dummyTokenId, ); - mockWalletReturnValue(helper.walletSpy, helper.seller!, { + mockWalletReturnValue(helper.seller!, { symbol: dummyToken.symbol, count: 10, price: MIN_IOTA_AMOUNT, type: TokenTradeOrderType.SELL, }); - const sellOrder = await testEnv.wrap(tradeToken)({}); - await helper.walletService!.send(helper.sellerAddress!, sellOrder.payload.targetAddress, 0, { + const sellOrder = await testEnv.wrap(WEN_FUNC.tradeToken); + await helper.walletService!.send(helper.sellerAddress!, sellOrder.payload.targetAddress!, 0, { nativeTokens: [{ amount: BigInt(10), id: helper.token!.mintingData?.tokenId! }], }); const query = build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.CREDIT) + .where('type', '==', PgTransactionType.CREDIT) .where('member', '==', helper.seller); await wait(async () => { const snap = await query.get(); @@ -56,7 +55,7 @@ describe('Token minting', () => { const credit = snap[0]; const output = await packBasicOutput( helper.walletService!, - sellOrder.payload.targetAddress, + sellOrder.payload.targetAddress!, 0, { nativeTokens: [{ amount: BigInt(10), id: helper.token!.mintingData?.tokenId! }], diff --git a/packages/functions/test-tangle/nft-bid/Helper.ts b/packages/functions/test-tangle/nft-bid/Helper.ts index cc4120384f..840d867e0f 100644 --- a/packages/functions/test-tangle/nft-bid/Helper.ts +++ b/packages/functions/test-tangle/nft-bid/Helper.ts @@ -2,8 +2,8 @@ import { build5Db } from '@build-5/database'; import { Access, - Categories, COL, + Categories, Collection, CollectionStatus, CollectionType, @@ -17,27 +17,19 @@ import { Transaction, TransactionType, UnsoldMintingOptions, + WEN_FUNC, } from '@build-5/interfaces'; import dayjs from 'dayjs'; -import { createCollection, mintCollection } from '../../src/runtime/firebase/collection/index'; -import { createNft, orderNft, setForSaleNft } from '../../src/runtime/firebase/nft/index'; import { NftWallet } from '../../src/services/wallet/NftWallet'; import { Wallet } from '../../src/services/wallet/wallet'; import { AddressDetails } from '../../src/services/wallet/wallet.service'; import { serverTime } from '../../src/utils/dateTime.utils'; import * as wallet from '../../src/utils/wallet.utils'; -import { - createMember as createMemberTest, - createSpace, - mockWalletReturnValue, - submitMilestoneFunc, - wait, -} from '../../test/controls/common'; -import { getWallet, MEDIA, testEnv } from '../../test/set-up'; +import { submitMilestoneFunc, wait } from '../../test/controls/common'; +import { MEDIA, getWallet, mockWalletReturnValue, testEnv } from '../../test/set-up'; import { requestFundsFromFaucet } from '../faucet'; export class Helper { - public walletSpy: any = {} as any; public network = Network.RMS; public collection: string = {} as any; public guardian: string = {} as any; @@ -49,47 +41,45 @@ export class Helper { public nft: Nft = {} as any; public beforeAll = async () => { - this.walletSpy = jest.spyOn(wallet, 'decodeAuth'); this.walletService = await getWallet(this.network); this.nftWallet = new NftWallet(this.walletService); }; public beforeEach = async (collectionType = CollectionType.CLASSIC) => { - this.guardian = await createMemberTest(this.walletSpy); - this.member = await createMemberTest(this.walletSpy); - this.space = await createSpace(this.walletSpy, this.guardian); - this.royaltySpace = await createSpace(this.walletSpy, this.guardian); + this.guardian = await testEnv.createMember(); + this.member = await testEnv.createMember(); + this.space = await testEnv.createSpace(this.guardian); + this.royaltySpace = await testEnv.createSpace(this.guardian); mockWalletReturnValue( - this.walletSpy, this.guardian, this.createDummyCollection(this.space.uid, this.royaltySpace.uid, collectionType), ); - this.collection = (await testEnv.wrap(createCollection)({})).uid; + this.collection = (await testEnv.wrap(WEN_FUNC.createCollection)).uid; - await build5Db().doc(`${COL.COLLECTION}/${this.collection}`).update({ approved: true }); + await build5Db().doc(COL.COLLECTION, this.collection).update({ approved: true }); }; public mintCollection = async (expiresAt?: Timestamp) => { - mockWalletReturnValue(this.walletSpy, this.guardian!, { + mockWalletReturnValue(this.guardian!, { collection: this.collection, network: this.network, unsoldMintingOptions: UnsoldMintingOptions.KEEP_PRICE, }); - const collectionMintOrder = await testEnv.wrap(mintCollection)({}); + const collectionMintOrder = await testEnv.wrap(WEN_FUNC.mintCollection); await requestFundsFromFaucet( this.network!, collectionMintOrder.payload.targetAddress, collectionMintOrder.payload.amount, expiresAt, ); - const collectionDocRef = build5Db().doc(`${COL.COLLECTION}/${this.collection}`); + const collectionDocRef = build5Db().doc(COL.COLLECTION, this.collection); await wait(async () => { const data = await collectionDocRef.get(); return data.status === CollectionStatus.MINTED; }); - const nftDocRef = build5Db().doc(`${COL.NFT}/${this.nft?.uid}`); + const nftDocRef = build5Db().doc(COL.NFT, this.nft?.uid); this.nft = await nftDocRef.get(); }; @@ -98,42 +88,40 @@ export class Helper { delete nft.uid; delete nft.status; delete nft.placeholderNft; - mockWalletReturnValue(this.walletSpy, this.guardian!, nft); - nft = await testEnv.wrap(createNft)({}); + mockWalletReturnValue(this.guardian!, nft); + nft = await testEnv.wrap(WEN_FUNC.createNft); await build5Db() - .doc(`${COL.NFT}/${nft.uid}`) + .doc(COL.NFT, nft.uid) .update({ availableFrom: dayjs().subtract(1, 'h').toDate() }); if (shouldOrder) { - mockWalletReturnValue(this.walletSpy, this.guardian!, { + mockWalletReturnValue(this.guardian!, { collection: this.collection, nft: nft.uid, }); - const order = await testEnv.wrap(orderNft)({}); + const order = await testEnv.wrap(WEN_FUNC.orderNft); await submitMilestoneFunc(order); } - this.nft = await build5Db().doc(`${COL.NFT}/${nft.uid}`).get(); + this.nft = await build5Db().doc(COL.NFT, nft.uid).get(); return this.nft; }; public setAvailableForAuction = async (nft?: string) => { const uid = nft || this.nft?.uid!; - mockWalletReturnValue(this.walletSpy, this.guardian!, this.dummyAuctionData(uid)); - await testEnv.wrap(setForSaleNft)({}); + mockWalletReturnValue(this.guardian!, this.dummyAuctionData(uid)); + await testEnv.wrap(WEN_FUNC.setForSaleNft); await wait(async () => { - const docRef = build5Db().doc(`${COL.NFT}/${uid}`); + const docRef = build5Db().doc(COL.NFT, uid); this.nft = await docRef.get(); return this.nft.available === 3; }); }; public setAvailableForSale = async () => { - mockWalletReturnValue(this.walletSpy, this.guardian!, this.dummySaleData(this.nft!.uid)); - await testEnv.wrap(setForSaleNft)({}); - await wait( - async () => (await build5Db().doc(`${COL.NFT}/${this.nft!.uid}`).get())?.available === 1, - ); + mockWalletReturnValue(this.guardian!, this.dummySaleData(this.nft!.uid)); + await testEnv.wrap(WEN_FUNC.setForSaleNft); + await wait(async () => (await build5Db().doc(COL.NFT, this.nft!.uid).get())?.available === 1); }; public createDummyCollection = (space: string, royaltiesSpace: string, type: CollectionType) => ({ @@ -197,7 +185,7 @@ export class Helper { nftId, }, }; - await build5Db().doc(`${COL.TRANSACTION}/${order.uid}`).create(order); + await build5Db().doc(COL.TRANSACTION, order.uid).create(order); return order.uid; }; } diff --git a/packages/functions/test-tangle/nft-bid/nft-bid.otr_1.spec.ts b/packages/functions/test-tangle/nft-bid/nft-bid.otr_1.spec.ts index 09ac011791..87c05138b3 100644 --- a/packages/functions/test-tangle/nft-bid/nft-bid.otr_1.spec.ts +++ b/packages/functions/test-tangle/nft-bid/nft-bid.otr_1.spec.ts @@ -1,20 +1,17 @@ -import { build5Db } from '@build-5/database'; +import { PgTransactionType, build5Db } from '@build-5/database'; import { COL, MIN_IOTA_AMOUNT, Network, - Nft, NftBidTangleRequest, TangleRequestType, Transaction, - TransactionType, } from '@build-5/interfaces'; import { NftOutput } from '@iota/sdk'; import dayjs from 'dayjs'; import { isEmpty } from 'lodash'; import { finalizeAuctions } from '../../src/cron/auction.cron'; import { Bech32AddressHelper } from '../../src/utils/bech32-address.helper'; -import { dateToTimestamp } from '../../src/utils/dateTime.utils'; import { wait } from '../../test/controls/common'; import { getTangleOrder } from '../common'; import { requestFundsFromFaucet } from '../faucet'; @@ -50,15 +47,15 @@ describe('Nft otr bid', () => { }, }); - const nftDocRef = build5Db().doc(`${COL.NFT}/${helper.nft!.uid}`); + const nftDocRef = build5Db().doc(COL.NFT, helper.nft!.uid); await wait(async () => { - const nft = await nftDocRef.get(); + const nft = await nftDocRef.get(); return !isEmpty(nft?.auctionHighestBidder); }); await build5Db() - .doc(`${COL.AUCTION}/${helper.nft!.auction}`) - .update({ auctionTo: dateToTimestamp(dayjs().subtract(1, 'm').toDate()) }); + .doc(COL.AUCTION, helper.nft!.auction!) + .update({ auctionTo: dayjs().subtract(1, 'm').toDate() }); await finalizeAuctions(); @@ -66,9 +63,9 @@ describe('Nft otr bid', () => { const transaction = ( await build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.WITHDRAW_NFT) - .where('payload.nft', '==', helper.nft!.uid) - .get() + .where('type', '==', PgTransactionType.WITHDRAW_NFT) + .where('payload_nft', '==', helper.nft!.uid) + .get() )[0]; return transaction?.payload?.walletReference?.confirmed; }); diff --git a/packages/functions/test-tangle/nft-bid/nft-bid.otr_2.spec.ts b/packages/functions/test-tangle/nft-bid/nft-bid.otr_2.spec.ts index fc3ff949dc..5e072e3dfa 100644 --- a/packages/functions/test-tangle/nft-bid/nft-bid.otr_2.spec.ts +++ b/packages/functions/test-tangle/nft-bid/nft-bid.otr_2.spec.ts @@ -11,7 +11,6 @@ import { import dayjs from 'dayjs'; import { isEmpty } from 'lodash'; import { finalizeAuctions } from '../../src/cron/auction.cron'; -import { dateToTimestamp } from '../../src/utils/dateTime.utils'; import { wait } from '../../test/controls/common'; import { getTangleOrder } from '../common'; import { requestFundsFromFaucet } from '../faucet'; @@ -48,20 +47,20 @@ describe('Nft otr bid', () => { }, }); - const nftDocRef = build5Db().doc(`${COL.NFT}/${helper.nft!.uid}`); + const nftDocRef = build5Db().doc(COL.NFT, helper.nft!.uid); await wait(async () => { - const nft = await nftDocRef.get(); + const nft = await nftDocRef.get(); return !isEmpty(nft?.auctionHighestBidder); }); await build5Db() - .doc(`${COL.AUCTION}/${helper.nft!.auction}`) - .update({ auctionTo: dateToTimestamp(dayjs().subtract(1, 'm').toDate()) }); + .doc(COL.AUCTION, helper.nft!.auction!) + .update({ auctionTo: dayjs().subtract(1, 'm').toDate() }); await finalizeAuctions(); await wait(async () => { - const nft = await build5Db().doc(`${COL.NFT}/${helper.nft!.uid}`).get(); + const nft = await build5Db().doc(COL.NFT, helper.nft!.uid).get(); return nft.owner === address.bech32; }); }); diff --git a/packages/functions/test-tangle/nft-bid/nft-bid.otr_3.spec.ts b/packages/functions/test-tangle/nft-bid/nft-bid.otr_3.spec.ts index c499b3abb8..4de6e75e3f 100644 --- a/packages/functions/test-tangle/nft-bid/nft-bid.otr_3.spec.ts +++ b/packages/functions/test-tangle/nft-bid/nft-bid.otr_3.spec.ts @@ -13,7 +13,6 @@ import { isEmpty } from 'lodash'; import { finalizeAuctions } from '../../src/cron/auction.cron'; import { IotaWallet } from '../../src/services/wallet/IotaWalletService'; import { MnemonicService } from '../../src/services/wallet/mnemonic'; -import { dateToTimestamp } from '../../src/utils/dateTime.utils'; import { wait } from '../../test/controls/common'; import { getWallet } from '../../test/set-up'; import { getTangleOrder } from '../common'; @@ -50,20 +49,20 @@ describe('Nft otr bid', () => { }, }); await MnemonicService.store(atoiAddress.bech32, atoiAddress.mnemonic, Network.RMS); - const nftDocRef = build5Db().doc(`${COL.NFT}/${helper.nft!.uid}`); + const nftDocRef = build5Db().doc(COL.NFT, helper.nft!.uid); await wait(async () => { - const nft = await nftDocRef.get(); + const nft = await nftDocRef.get(); return !isEmpty(nft?.auctionHighestBidder); }); await build5Db() - .doc(`${COL.AUCTION}/${helper.nft!.auction}`) - .update({ auctionTo: dateToTimestamp(dayjs().subtract(1, 'm').toDate()) }); + .doc(COL.AUCTION, helper.nft!.auction!) + .update({ auctionTo: dayjs().subtract(1, 'm').toDate() }); await finalizeAuctions(); await wait(async () => { - const nft = await build5Db().doc(`${COL.NFT}/${helper.nft!.uid}`).get(); + const nft = await build5Db().doc(COL.NFT, helper.nft!.uid).get(); return nft.owner === atoiAddress.bech32; }); }); diff --git a/packages/functions/test-tangle/nft-bid/nft-bid.otr_4.spec.ts b/packages/functions/test-tangle/nft-bid/nft-bid.otr_4.spec.ts index 7fdffd94b0..0d86bfce18 100644 --- a/packages/functions/test-tangle/nft-bid/nft-bid.otr_4.spec.ts +++ b/packages/functions/test-tangle/nft-bid/nft-bid.otr_4.spec.ts @@ -1,4 +1,4 @@ -import { build5Db } from '@build-5/database'; +import { PgTransactionType, build5Db } from '@build-5/database'; import { COL, MIN_IOTA_AMOUNT, @@ -7,11 +7,9 @@ import { NftBidTangleRequest, TangleRequestType, Transaction, - TransactionType, } from '@build-5/interfaces'; import dayjs from 'dayjs'; import { finalizeAuctions } from '../../src/cron/auction.cron'; -import { dateToTimestamp } from '../../src/utils/dateTime.utils'; import { wait } from '../../test/controls/common'; import { getTangleOrder } from '../common'; import { requestFundsFromFaucet } from '../faucet'; @@ -60,15 +58,15 @@ describe('Nft otr bid', () => { }, }); - const nftDocRef = build5Db().doc(`${COL.NFT}/${helper.nft!.uid}`); + const nftDocRef = build5Db().doc(COL.NFT, helper.nft!.uid); await wait(async () => { helper.nft = await nftDocRef.get(); return helper.nft.auctionHighestBidder === address2.bech32; }); await build5Db() - .doc(`${COL.AUCTION}/${helper.nft!.auction}`) - .update({ auctionTo: dateToTimestamp(dayjs().subtract(1, 'm').toDate()) }); + .doc(COL.AUCTION, helper.nft!.auction!) + .update({ auctionTo: dayjs().subtract(1, 'm').toDate() }); await finalizeAuctions(); @@ -79,10 +77,10 @@ describe('Nft otr bid', () => { const creditQuery = build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.CREDIT) + .where('type', '==', PgTransactionType.CREDIT) .where('member', '==', address1.bech32); await wait(async () => { - const snap = await creditQuery.get(); + const snap = await creditQuery.get(); return snap.length === 1 && snap[0]?.payload?.walletReference?.confirmed; }); }); diff --git a/packages/functions/test-tangle/nft-bulk/Helper.ts b/packages/functions/test-tangle/nft-bulk/Helper.ts index 4f19929b9f..b9371e4546 100644 --- a/packages/functions/test-tangle/nft-bulk/Helper.ts +++ b/packages/functions/test-tangle/nft-bulk/Helper.ts @@ -12,23 +12,15 @@ import { NetworkAddress, Nft, Space, + WEN_FUNC, } from '@build-5/interfaces'; import dayjs from 'dayjs'; -import { createCollection } from '../../src/runtime/firebase/collection'; -import { createNft } from '../../src/runtime/firebase/nft'; import { Wallet } from '../../src/services/wallet/wallet'; import { AddressDetails } from '../../src/services/wallet/wallet.service'; import { getAddress } from '../../src/utils/address.utils'; -import * as wallet from '../../src/utils/wallet.utils'; -import { - createMember as createMemberTest, - createSpace, - mockWalletReturnValue, -} from '../../test/controls/common'; -import { getWallet, testEnv } from '../../test/set-up'; +import { getWallet, mockWalletReturnValue, testEnv } from '../../test/set-up'; export class Helper { - public walletSpy: any = {} as any; public member: string = {} as any; public memberAddress: AddressDetails = {} as any; public space: Space = {} as any; @@ -36,28 +28,27 @@ export class Helper { public member2: string = {} as any; public beforeEach = async () => { - this.walletSpy = jest.spyOn(wallet, 'decodeAuth'); - this.member = await createMemberTest(this.walletSpy); - this.member2 = await createMemberTest(this.walletSpy); - this.space = await createSpace(this.walletSpy, this.member); + this.member = await testEnv.createMember(); + this.member2 = await testEnv.createMember(); + this.space = await testEnv.createSpace(this.member); this.walletService = await getWallet(Network.ATOI); - const memberData = await build5Db().doc(`${COL.MEMBER}/${this.member}`).get(); + const memberData = await build5Db().doc(COL.MEMBER, this.member).get(); this.memberAddress = await this.walletService!.getAddressDetails( getAddress(memberData, Network.ATOI), ); }; - public createColletionAndNft = async ( + public createCollectionAndNft = async ( address: NetworkAddress, space: Space, type = CollectionType.CLASSIC, ) => { - mockWalletReturnValue(this.walletSpy, address, this.dummyCollection(space, type)); - const cCollection = await testEnv.wrap(createCollection)({}); + mockWalletReturnValue(address, this.dummyCollection(space, type)); + const cCollection = await testEnv.wrap(WEN_FUNC.createCollection); expect(cCollection?.uid).toBeDefined(); - await build5Db().doc(`${COL.COLLECTION}/${cCollection?.uid}`).update({ approved: true }); + await build5Db().doc(COL.COLLECTION, cCollection?.uid).update({ approved: true }); const collection = cCollection; const nft = await this.createNft(address, collection); @@ -65,8 +56,8 @@ export class Helper { }; public createNft = async (address: NetworkAddress, collection: Collection) => { - mockWalletReturnValue(this.walletSpy, address, this.dummyNft(collection)); - const nft = await testEnv.wrap(createNft)({}); + mockWalletReturnValue(address, this.dummyNft(collection)); + const nft = await testEnv.wrap(WEN_FUNC.createNft); expect(nft?.createdOn).toBeDefined(); return nft; }; diff --git a/packages/functions/test-tangle/nft-bulk/order.bulk_1.spec.ts b/packages/functions/test-tangle/nft-bulk/order.bulk_1.spec.ts index 88831d2ff4..98486bd8a5 100644 --- a/packages/functions/test-tangle/nft-bulk/order.bulk_1.spec.ts +++ b/packages/functions/test-tangle/nft-bulk/order.bulk_1.spec.ts @@ -1,8 +1,7 @@ import { build5Db } from '@build-5/database'; -import { COL, Nft, NftPurchaseBulkRequest, Transaction } from '@build-5/interfaces'; -import { orderNftBulk } from '../../src/runtime/firebase/nft'; -import { mockWalletReturnValue, wait } from '../../test/controls/common'; -import { testEnv } from '../../test/set-up'; +import { COL, Nft, NftPurchaseBulkRequest, Transaction, WEN_FUNC } from '@build-5/interfaces'; +import { wait } from '../../test/controls/common'; +import { mockWalletReturnValue, testEnv } from '../../test/set-up'; import { requestFundsFromFaucet } from '../faucet'; import { Helper } from './Helper'; @@ -14,8 +13,8 @@ describe('Nft bulk order', () => { }); it('Should order 2 nfts', async () => { - const { collection: col1, nft: nft1 } = await h.createColletionAndNft(h.member, h.space); - const { collection: col2, nft: nft2 } = await h.createColletionAndNft(h.member, h.space); + const { collection: col1, nft: nft1 } = await h.createCollectionAndNft(h.member, h.space); + const { collection: col2, nft: nft2 } = await h.createCollectionAndNft(h.member, h.space); const request: NftPurchaseBulkRequest = { orders: [ @@ -23,8 +22,8 @@ describe('Nft bulk order', () => { { collection: col2.uid, nft: nft2.uid }, ], }; - mockWalletReturnValue(h.walletSpy, h.member, request); - const order: Transaction = await testEnv.wrap(orderNftBulk)({}); + mockWalletReturnValue(h.member, request); + const order = await testEnv.wrap(WEN_FUNC.orderNftBulk); await requestFundsFromFaucet( order.network, @@ -32,8 +31,8 @@ describe('Nft bulk order', () => { order.payload.amount!, ); - const nft1DocRef = build5Db().doc(`${COL.NFT}/${nft1.uid}`); - const nft2DocRef = build5Db().doc(`${COL.NFT}/${nft2.uid}`); + const nft1DocRef = build5Db().doc(COL.NFT, nft1.uid); + const nft2DocRef = build5Db().doc(COL.NFT, nft2.uid); await wait(async () => { const nft1 = await nft1DocRef.get(); const nft2 = await nft2DocRef.get(); diff --git a/packages/functions/test-tangle/nft-bulk/order.bulk_2.spec.ts b/packages/functions/test-tangle/nft-bulk/order.bulk_2.spec.ts index bcbd8d94dc..11b8edc1d4 100644 --- a/packages/functions/test-tangle/nft-bulk/order.bulk_2.spec.ts +++ b/packages/functions/test-tangle/nft-bulk/order.bulk_2.spec.ts @@ -1,15 +1,14 @@ -import { build5Db } from '@build-5/database'; +import { PgTransactionType, build5Db } from '@build-5/database'; import { COL, MIN_IOTA_AMOUNT, Nft, NftPurchaseBulkRequest, Transaction, - TransactionType, + WEN_FUNC, } from '@build-5/interfaces'; -import { orderNftBulk } from '../../src/runtime/firebase/nft'; -import { mockWalletReturnValue, wait } from '../../test/controls/common'; -import { testEnv } from '../../test/set-up'; +import { wait } from '../../test/controls/common'; +import { mockWalletReturnValue, testEnv } from '../../test/set-up'; import { requestFundsFromFaucet } from '../faucet'; import { Helper } from './Helper'; @@ -21,8 +20,8 @@ describe('Nft bulk order', () => { }); it('Should order 2 nfts, buy only one', async () => { - const { collection: col1, nft: nft1 } = await h.createColletionAndNft(h.member, h.space); - const { collection: col2, nft: nft2 } = await h.createColletionAndNft(h.member, h.space); + const { collection: col1, nft: nft1 } = await h.createCollectionAndNft(h.member, h.space); + const { collection: col2, nft: nft2 } = await h.createCollectionAndNft(h.member, h.space); const request: NftPurchaseBulkRequest = { orders: [ @@ -30,11 +29,11 @@ describe('Nft bulk order', () => { { collection: col2.uid, nft: nft2.uid }, ], }; - mockWalletReturnValue(h.walletSpy, h.member, request); - const order: Transaction = await testEnv.wrap(orderNftBulk)({}); + mockWalletReturnValue(h.member, request); + const order = await testEnv.wrap(WEN_FUNC.orderNftBulk); - const nft1DocRef = build5Db().doc(`${COL.NFT}/${nft1.uid}`); - const nft2DocRef = build5Db().doc(`${COL.NFT}/${nft2.uid}`); + const nft1DocRef = build5Db().doc(COL.NFT, nft1.uid); + const nft2DocRef = build5Db().doc(COL.NFT, nft2.uid); await nft2DocRef.update({ locked: true }); await requestFundsFromFaucet( @@ -50,13 +49,13 @@ describe('Nft bulk order', () => { const query = build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.CREDIT) + .where('type', '==', PgTransactionType.CREDIT) .where('member', '==', h.member); await wait(async () => { - const snap = await query.get(); + const snap = await query.get(); return snap.length === 1; }); - const snap = await query.get(); + const snap = await query.get(); expect(snap[0].payload.amount).toBe(1 * MIN_IOTA_AMOUNT); }); }); diff --git a/packages/functions/test-tangle/nft-bulk/order.bulk_3.spec.ts b/packages/functions/test-tangle/nft-bulk/order.bulk_3.spec.ts index 51103f1083..dd317ff662 100644 --- a/packages/functions/test-tangle/nft-bulk/order.bulk_3.spec.ts +++ b/packages/functions/test-tangle/nft-bulk/order.bulk_3.spec.ts @@ -22,8 +22,8 @@ describe('Nft bulk order', () => { }); it('Should order 2 nfts with tangle order', async () => { - const { collection: col1, nft: nft1 } = await h.createColletionAndNft(h.member, h.space); - const { collection: col2, nft: nft2 } = await h.createColletionAndNft(h.member, h.space); + const { collection: col1, nft: nft1 } = await h.createCollectionAndNft(h.member, h.space); + const { collection: col2, nft: nft2 } = await h.createCollectionAndNft(h.member, h.space); await requestFundsFromFaucet(Network.ATOI, h.memberAddress.bech32, 2 * MIN_IOTA_AMOUNT); await h.walletService.send( @@ -43,8 +43,8 @@ describe('Nft bulk order', () => { }, ); - const nft1DocRef = build5Db().doc(`${COL.NFT}/${nft1.uid}`); - const nft2DocRef = build5Db().doc(`${COL.NFT}/${nft2.uid}`); + const nft1DocRef = build5Db().doc(COL.NFT, nft1.uid); + const nft2DocRef = build5Db().doc(COL.NFT, nft2.uid); await wait(async () => { const nft1 = await nft1DocRef.get(); diff --git a/packages/functions/test-tangle/nft-bulk/order.bulk_4.spec.ts b/packages/functions/test-tangle/nft-bulk/order.bulk_4.spec.ts index 88b7ece7ad..55b70c7ea9 100644 --- a/packages/functions/test-tangle/nft-bulk/order.bulk_4.spec.ts +++ b/packages/functions/test-tangle/nft-bulk/order.bulk_4.spec.ts @@ -1,8 +1,7 @@ import { build5Db } from '@build-5/database'; -import { COL, CollectionType, Nft, Transaction } from '@build-5/interfaces'; -import { orderNftBulk } from '../../src/runtime/firebase/nft'; -import { mockWalletReturnValue, wait } from '../../test/controls/common'; -import { testEnv } from '../../test/set-up'; +import { COL, CollectionType, Nft, Transaction, WEN_FUNC } from '@build-5/interfaces'; +import { wait } from '../../test/controls/common'; +import { mockWalletReturnValue, testEnv } from '../../test/set-up'; import { requestFundsFromFaucet } from '../faucet'; import { Helper } from './Helper'; @@ -14,9 +13,9 @@ describe('Nft bulk order', () => { }); it('Should order 2 nfts, 2 random', async () => { - const { collection: col1, nft: nft1 } = await h.createColletionAndNft(h.member, h.space); - const { collection: col2, nft: nft2 } = await h.createColletionAndNft(h.member, h.space); - const { collection: col3 } = await h.createColletionAndNft( + const { collection: col1, nft: nft1 } = await h.createCollectionAndNft(h.member, h.space); + const { collection: col2, nft: nft2 } = await h.createCollectionAndNft(h.member, h.space); + const { collection: col3 } = await h.createCollectionAndNft( h.member, h.space, CollectionType.GENERATED, @@ -33,8 +32,8 @@ describe('Nft bulk order', () => { { collection: col3.uid }, ], }; - mockWalletReturnValue(h.walletSpy, h.member, request); - const order: Transaction = await testEnv.wrap(orderNftBulk)({}); + mockWalletReturnValue(h.member, request); + const order = await testEnv.wrap(WEN_FUNC.orderNftBulk); await requestFundsFromFaucet( order.network, order.payload.targetAddress!, @@ -43,7 +42,7 @@ describe('Nft bulk order', () => { await wait(async () => { const promises = order.payload.nftOrders!.map(async (nftOrder) => { - const docRef = build5Db().doc(`${COL.NFT}/${nftOrder.nft}`); + const docRef = build5Db().doc(COL.NFT, nftOrder.nft); return await docRef.get(); }); const nfts = await Promise.all(promises); diff --git a/packages/functions/test-tangle/nft-bulk/order.bulk_5.spec.ts b/packages/functions/test-tangle/nft-bulk/order.bulk_5.spec.ts index fcaf44ea3f..75203578cb 100644 --- a/packages/functions/test-tangle/nft-bulk/order.bulk_5.spec.ts +++ b/packages/functions/test-tangle/nft-bulk/order.bulk_5.spec.ts @@ -1,4 +1,4 @@ -import { build5Db } from '@build-5/database'; +import { PgTransactionType, build5Db } from '@build-5/database'; import { COL, MIN_IOTA_AMOUNT, @@ -6,7 +6,6 @@ import { Nft, TangleRequestType, Transaction, - TransactionType, } from '@build-5/interfaces'; import { MnemonicService } from '../../src/services/wallet/mnemonic'; import { wait } from '../../test/controls/common'; @@ -24,8 +23,8 @@ describe('Nft bulk order', () => { }); it('Should order 2 nfts, buy only one with tangle', async () => { - const { collection: col1, nft: nft1 } = await h.createColletionAndNft(h.member, h.space); - const { collection: col2, nft: nft2 } = await h.createColletionAndNft(h.member, h.space); + const { collection: col1, nft: nft1 } = await h.createCollectionAndNft(h.member, h.space); + const { collection: col2, nft: nft2 } = await h.createCollectionAndNft(h.member, h.space); await requestFundsFromFaucet(Network.ATOI, h.memberAddress.bech32, 3 * MIN_IOTA_AMOUNT); await h.walletService.send( @@ -49,17 +48,17 @@ describe('Nft bulk order', () => { let query = build5Db() .collection(COL.TRANSACTION) .where('member', '==', h.member) - .where('type', '==', TransactionType.CREDIT_TANGLE_REQUEST); + .where('type', '==', PgTransactionType.CREDIT_TANGLE_REQUEST); await wait(async () => { - const snap = await query.get(); + const snap = await query.get(); return snap.length === 1 && snap[0].payload.walletReference?.confirmed; }); - const nft1DocRef = build5Db().doc(`${COL.NFT}/${nft1.uid}`); - const nft2DocRef = build5Db().doc(`${COL.NFT}/${nft2.uid}`); + const nft1DocRef = build5Db().doc(COL.NFT, nft1.uid); + const nft2DocRef = build5Db().doc(COL.NFT, nft2.uid); await nft2DocRef.update({ locked: true }); - const credit = (await query.get())[0]; + const credit = (await query.get())[0]; await h.walletService.send( h.memberAddress, credit.payload.response!.address as string, @@ -74,13 +73,16 @@ describe('Nft bulk order', () => { query = build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.CREDIT) + .where('type', '==', PgTransactionType.CREDIT) .where('member', '==', h.member); + + console.log('nft2.owner', nft2.owner === h.member); await wait(async () => { - const snap = await query.get(); + const snap = await query.get(); + console.log('Nft bulk order', snap, snap.length); return snap.length === 1; }); - const snap = await query.get(); + const snap = await query.get(); expect(snap[0].payload.amount).toBe(1 * MIN_IOTA_AMOUNT); }); }); diff --git a/packages/functions/test-tangle/nft-bulk/order.bulk_6.spec.ts b/packages/functions/test-tangle/nft-bulk/order.bulk_6.spec.ts index 50eec9ae71..1b23924dfe 100644 --- a/packages/functions/test-tangle/nft-bulk/order.bulk_6.spec.ts +++ b/packages/functions/test-tangle/nft-bulk/order.bulk_6.spec.ts @@ -1,4 +1,4 @@ -import { build5Db } from '@build-5/database'; +import { PgTransactionType, build5Db } from '@build-5/database'; import { COL, MIN_IOTA_AMOUNT, @@ -6,7 +6,6 @@ import { Nft, TangleRequestType, Transaction, - TransactionType, } from '@build-5/interfaces'; import { MnemonicService } from '../../src/services/wallet/mnemonic'; import { wait } from '../../test/controls/common'; @@ -24,10 +23,10 @@ describe('Nft bulk order', () => { }); it('Should order 2 nfts, only one available', async () => { - const { collection: col1, nft: nft1 } = await h.createColletionAndNft(h.member, h.space); - const { collection: col2, nft: nft2 } = await h.createColletionAndNft(h.member, h.space); - const nft1DocRef = build5Db().doc(`${COL.NFT}/${nft1.uid}`); - const nft2DocRef = build5Db().doc(`${COL.NFT}/${nft2.uid}`); + const { collection: col1, nft: nft1 } = await h.createCollectionAndNft(h.member, h.space); + const { collection: col2, nft: nft2 } = await h.createCollectionAndNft(h.member, h.space); + const nft1DocRef = build5Db().doc(COL.NFT, nft1.uid); + const nft2DocRef = build5Db().doc(COL.NFT, nft2.uid); await nft2DocRef.update({ locked: true }); await requestFundsFromFaucet(Network.ATOI, h.memberAddress.bech32, 2 * MIN_IOTA_AMOUNT); @@ -52,13 +51,13 @@ describe('Nft bulk order', () => { let query = build5Db() .collection(COL.TRANSACTION) .where('member', '==', h.member) - .where('type', '==', TransactionType.CREDIT_TANGLE_REQUEST); + .where('type', '==', PgTransactionType.CREDIT_TANGLE_REQUEST); await wait(async () => { - const snap = await query.get(); + const snap = await query.get(); return snap.length === 1 && snap[0].payload.walletReference?.confirmed; }); - const credit = (await query.get())[0]; + const credit = (await query.get())[0]; expect(credit.payload.amount).toBe(2 * MIN_IOTA_AMOUNT); expect(credit.payload.response!.amount).toBe(MIN_IOTA_AMOUNT); await h.walletService.send( diff --git a/packages/functions/test-tangle/nft-set-for-sale/Helper.ts b/packages/functions/test-tangle/nft-set-for-sale/Helper.ts index c506f01905..6895beb40b 100644 --- a/packages/functions/test-tangle/nft-set-for-sale/Helper.ts +++ b/packages/functions/test-tangle/nft-set-for-sale/Helper.ts @@ -4,32 +4,26 @@ import { Access, Categories, COL, + Collection, CollectionType, - Member, MIN_IOTA_AMOUNT, Network, Nft, NftAccess, NftStatus, Space, + Transaction, + WEN_FUNC, } from '@build-5/interfaces'; import dayjs from 'dayjs'; -import { createCollection } from '../../src/runtime/firebase/collection/index'; -import { createNft, orderNft } from '../../src/runtime/firebase/nft/index'; import { Wallet } from '../../src/services/wallet/wallet'; import { AddressDetails } from '../../src/services/wallet/wallet.service'; import { getAddress } from '../../src/utils/address.utils'; import * as wallet from '../../src/utils/wallet.utils'; -import { - createMember as createMemberTest, - createSpace, - mockWalletReturnValue, - submitMilestoneFunc, -} from '../../test/controls/common'; -import { getWallet, MEDIA, testEnv } from '../../test/set-up'; +import { submitMilestoneFunc } from '../../test/controls/common'; +import { getWallet, MEDIA, mockWalletReturnValue, testEnv } from '../../test/set-up'; export class Helper { - public walletSpy: any = {} as any; public network = Network.RMS; public collection: string = {} as any; public guardian: string = {} as any; @@ -40,28 +34,26 @@ export class Helper { public nft: Nft = {} as any; public beforeAll = async () => { - this.walletSpy = jest.spyOn(wallet, 'decodeAuth'); this.walletService = await getWallet(this.network); }; public beforeEach = async (collectionType = CollectionType.CLASSIC) => { - this.guardian = await createMemberTest(this.walletSpy); - const guardianDocRef = build5Db().doc(`${COL.MEMBER}/${this.guardian}`); - const guardianData = await guardianDocRef.get(); + this.guardian = await testEnv.createMember(); + const guardianDocRef = build5Db().doc(COL.MEMBER, this.guardian); + const guardianData = await guardianDocRef.get(); const guardianBech32 = getAddress(guardianData, this.network); this.guardianAddress = await this.walletService.getAddressDetails(guardianBech32); - this.space = await createSpace(this.walletSpy, this.guardian); - this.royaltySpace = await createSpace(this.walletSpy, this.guardian); + this.space = await testEnv.createSpace(this.guardian); + this.royaltySpace = await testEnv.createSpace(this.guardian); mockWalletReturnValue( - this.walletSpy, this.guardian, this.createDummyCollection(this.space.uid, this.royaltySpace.uid, collectionType), ); - this.collection = (await testEnv.wrap(createCollection)({})).uid; + this.collection = (await testEnv.wrap(WEN_FUNC.createCollection)).uid; - await build5Db().doc(`${COL.COLLECTION}/${this.collection}`).update({ approved: true }); + await build5Db().doc(COL.COLLECTION, this.collection).update({ approved: true }); }; public createAndOrderNft = async (shouldOrder = true) => { @@ -69,22 +61,22 @@ export class Helper { delete nft.uid; delete nft.status; delete nft.placeholderNft; - mockWalletReturnValue(this.walletSpy, this.guardian!, nft); - nft = await testEnv.wrap(createNft)({}); + mockWalletReturnValue(this.guardian!, nft); + nft = await testEnv.wrap(WEN_FUNC.createNft); await build5Db() - .doc(`${COL.NFT}/${nft.uid}`) + .doc(COL.NFT, nft.uid) .update({ availableFrom: dayjs().subtract(1, 'h').toDate() }); if (shouldOrder) { - mockWalletReturnValue(this.walletSpy, this.guardian!, { + mockWalletReturnValue(this.guardian!, { collection: this.collection, nft: nft.uid, }); - const order = await testEnv.wrap(orderNft)({}); + const order = await testEnv.wrap(WEN_FUNC.orderNft); await submitMilestoneFunc(order); } - this.nft = await build5Db().doc(`${COL.NFT}/${nft.uid}`).get(); + this.nft = await build5Db().doc(COL.NFT, nft.uid).get(); return this.nft; }; diff --git a/packages/functions/test-tangle/nft-set-for-sale/nft-set-for-sale_1.spec.ts b/packages/functions/test-tangle/nft-set-for-sale/nft-set-for-sale_1.spec.ts index 7425d48919..44bcaa8237 100644 --- a/packages/functions/test-tangle/nft-set-for-sale/nft-set-for-sale_1.spec.ts +++ b/packages/functions/test-tangle/nft-set-for-sale/nft-set-for-sale_1.spec.ts @@ -3,7 +3,6 @@ import { COL, MIN_IOTA_AMOUNT, Network, - Nft, NftAvailable, NftSetForSaleTangleRequest, TangleRequestType, @@ -47,9 +46,9 @@ describe('Nft set for sale OTR', () => { }, ); - const nftDocRef = build5Db().doc(`${COL.NFT}/${helper.nft.uid}`); + const nftDocRef = build5Db().doc(COL.NFT, helper.nft.uid); await wait(async () => { - helper.nft = (await nftDocRef.get())!; + helper.nft = (await nftDocRef.get())!; return helper.nft.available === NftAvailable.SALE; }); }); @@ -74,9 +73,9 @@ describe('Nft set for sale OTR', () => { }, ); - const nftDocRef = build5Db().doc(`${COL.NFT}/${helper.nft.uid}`); + const nftDocRef = build5Db().doc(COL.NFT, helper.nft.uid); await wait(async () => { - helper.nft = (await nftDocRef.get())!; + helper.nft = (await nftDocRef.get())!; return helper.nft.available === NftAvailable.AUCTION_AND_SALE; }); }); diff --git a/packages/functions/test-tangle/nft-set-for-sale/nft-set-for-sale_2.spec.ts b/packages/functions/test-tangle/nft-set-for-sale/nft-set-for-sale_2.spec.ts index ca1ecb46cc..f804241068 100644 --- a/packages/functions/test-tangle/nft-set-for-sale/nft-set-for-sale_2.spec.ts +++ b/packages/functions/test-tangle/nft-set-for-sale/nft-set-for-sale_2.spec.ts @@ -1,4 +1,4 @@ -import { build5Db } from '@build-5/database'; +import { PgTransactionType, build5Db } from '@build-5/database'; import { COL, MIN_IOTA_AMOUNT, @@ -6,7 +6,6 @@ import { NftSetForSaleTangleRequest, TangleRequestType, Transaction, - TransactionType, WenError, } from '@build-5/interfaces'; import { wait } from '../../test/controls/common'; @@ -46,13 +45,13 @@ describe('Nft set for sale OTR', () => { const credit = build5Db() .collection(COL.TRANSACTION) .where('member', '==', address.bech32) - .where('type', '==', TransactionType.CREDIT_TANGLE_REQUEST); + .where('type', '==', PgTransactionType.CREDIT_TANGLE_REQUEST); await wait(async () => { - const snap = await credit.get(); + const snap = await credit.get(); return snap.length === 1 && snap[0].payload?.walletReference?.confirmed; }); - const snap = await credit.get(); + const snap = await credit.get(); expect(snap[0].payload.response!['code']).toBe(WenError.you_must_be_the_owner_of_nft.code); }); }); diff --git a/packages/functions/test-tangle/nft-set-for-sale/nft-set-for-sale_3.spec.ts b/packages/functions/test-tangle/nft-set-for-sale/nft-set-for-sale_3.spec.ts index f599bffd40..9cddd65be8 100644 --- a/packages/functions/test-tangle/nft-set-for-sale/nft-set-for-sale_3.spec.ts +++ b/packages/functions/test-tangle/nft-set-for-sale/nft-set-for-sale_3.spec.ts @@ -1,14 +1,12 @@ -import { build5Db } from '@build-5/database'; +import { PgTransactionType, build5Db } from '@build-5/database'; import { COL, MIN_IOTA_AMOUNT, Network, - Nft, NftAvailable, NftSetForSaleTangleRequest, TangleRequestType, Transaction, - TransactionType, WenError, } from '@build-5/interfaces'; import dayjs from 'dayjs'; @@ -56,9 +54,9 @@ describe('Nft set for auction OTR', () => { ); await MnemonicService.store(helper.guardianAddress.bech32, helper.guardianAddress.mnemonic); - const nftDocRef = build5Db().doc(`${COL.NFT}/${helper.nft.uid}`); + const nftDocRef = build5Db().doc(COL.NFT, helper.nft.uid); await wait(async () => { - helper.nft = (await nftDocRef.get())!; + helper.nft = (await nftDocRef.get())!; return helper.nft.available === NftAvailable.AUCTION_AND_SALE; }); @@ -81,14 +79,12 @@ describe('Nft set for auction OTR', () => { const credit = build5Db() .collection(COL.TRANSACTION) .where('member', '==', helper.guardian) - .where('type', '==', TransactionType.CREDIT_TANGLE_REQUEST); + .where('type', '==', PgTransactionType.CREDIT_TANGLE_REQUEST); await wait(async () => { - const snap = await credit.get(); + const snap = await credit.get(); return snap.length === 2; }); - const succeses = (await credit.get()).filter( - (t) => t.payload.response?.status === 'success', - ); + const succeses = (await credit.get()).filter((t) => t.payload.response?.status === 'success'); expect(succeses.length).toBe(2); auctionData = helper.dummyAuctionData(helper.nft.uid); @@ -107,10 +103,10 @@ describe('Nft set for auction OTR', () => { ); await wait(async () => { - const snap = await credit.get(); + const snap = await credit.get(); return snap.length === 3; }); - const snap = await credit.get(); + const snap = await credit.get(); const creditTransction = snap.find( (t) => t.payload.response?.code === WenError.auction_already_in_progress.code, ); diff --git a/packages/functions/test-tangle/nft-staking/Helper.ts b/packages/functions/test-tangle/nft-staking/Helper.ts index 8b0d38bfbe..9c822bddab 100644 --- a/packages/functions/test-tangle/nft-staking/Helper.ts +++ b/packages/functions/test-tangle/nft-staking/Helper.ts @@ -1,5 +1,5 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ -import { build5Db } from '@build-5/database'; +import { PgTransactionPayloadType, PgTransactionType, build5Db } from '@build-5/database'; import { Access, COL, @@ -15,9 +15,8 @@ import { Space, Timestamp, Transaction, - TransactionPayloadType, - TransactionType, UnsoldMintingOptions, + WEN_FUNC, } from '@build-5/interfaces'; import { AddressUnlockCondition, @@ -32,13 +31,6 @@ import { } from '@iota/sdk'; import dayjs from 'dayjs'; import { cloneDeep } from 'lodash'; -import { createCollection, mintCollection } from '../../src/runtime/firebase/collection/index'; -import { - createNft, - orderNft, - setForSaleNft, - withdrawNft, -} from '../../src/runtime/firebase/nft/index'; import { NftWallet } from '../../src/services/wallet/NftWallet'; import { MnemonicService } from '../../src/services/wallet/mnemonic'; import { Wallet } from '../../src/services/wallet/wallet'; @@ -48,15 +40,8 @@ import { mergeOutputs, packBasicOutput } from '../../src/utils/basic-output.util import { createUnlock, packEssence, submitBlock } from '../../src/utils/block.utils'; import { EMPTY_NFT_ID } from '../../src/utils/collection-minting-utils/nft.utils'; import * as wallet from '../../src/utils/wallet.utils'; -import { getRandomEthAddress } from '../../src/utils/wallet.utils'; -import { - createMember as createMemberTest, - createSpace, - mockWalletReturnValue, - submitMilestoneFunc, - wait, -} from '../../test/controls/common'; -import { MEDIA, getWallet, testEnv } from '../../test/set-up'; +import { submitMilestoneFunc, wait } from '../../test/controls/common'; +import { MEDIA, getWallet, mockWalletReturnValue, testEnv } from '../../test/set-up'; import { requestFundsFromFaucet } from '../faucet'; export class Helper { @@ -65,31 +50,28 @@ export class Helper { public guardian: string | undefined; public space: Space | undefined; public walletService: Wallet | undefined; - public walletSpy: any; public nft: Nft | undefined; public guardianAddress: AddressDetails | undefined; public royaltySpace: Space | undefined; public beforeAll = async () => { - this.walletSpy = jest.spyOn(wallet, 'decodeAuth'); this.walletService = await getWallet(this.network); }; public beforeEach = async () => { - this.guardian = await createMemberTest(this.walletSpy); - this.space = await createSpace(this.walletSpy, this.guardian!); - this.royaltySpace = await createSpace(this.walletSpy, this.guardian!); + this.guardian = await testEnv.createMember(); + this.space = await testEnv.createSpace(this.guardian!); + this.royaltySpace = await testEnv.createSpace(this.guardian!); mockWalletReturnValue( - this.walletSpy, this.guardian!, this.createDummyCollection(this.space!.uid, this.royaltySpace!.uid), ); - this.collection = (await testEnv.wrap(createCollection)({})).uid; + this.collection = (await testEnv.wrap(WEN_FUNC.createCollection)).uid; - await build5Db().doc(`${COL.COLLECTION}/${this.collection}`).update({ approved: true }); + await build5Db().doc(COL.COLLECTION, this.collection).update({ approved: true }); - const guardianDocRef = build5Db().doc(`${COL.MEMBER}/${this.guardian}`); + const guardianDocRef = build5Db().doc(COL.MEMBER, this.guardian); const guardianData = await guardianDocRef.get(); const guardianBech32 = getAddress(guardianData, this.network!); this.guardianAddress = await this.walletService?.getAddressDetails(guardianBech32)!; @@ -98,31 +80,31 @@ export class Helper { public createAndOrderNft = async () => { let nft: any = this.createDummyNft(this.collection!); delete nft.uid; - mockWalletReturnValue(this.walletSpy, this.guardian!, nft); - nft = await testEnv.wrap(createNft)({}); + mockWalletReturnValue(this.guardian!, nft); + nft = await testEnv.wrap(WEN_FUNC.createNft); await build5Db() - .doc(`${COL.NFT}/${nft.uid}`) + .doc(COL.NFT, nft.uid) .update({ availableFrom: dayjs().subtract(1, 'h').toDate() }); - mockWalletReturnValue(this.walletSpy, this.guardian!, { + mockWalletReturnValue(this.guardian!, { collection: this.collection, nft: nft.uid, }); - const order = await testEnv.wrap(orderNft)({}); + const order = await testEnv.wrap(WEN_FUNC.orderNft); await submitMilestoneFunc(order); - this.nft = await build5Db().doc(`${COL.NFT}/${nft.uid}`).get(); + this.nft = await build5Db().doc(COL.NFT, nft.uid).get(); return this.nft; }; public mintCollection = async (expiresAt?: Timestamp) => { - mockWalletReturnValue(this.walletSpy, this.guardian!, { + mockWalletReturnValue(this.guardian!, { collection: this.collection!, network: this.network, unsoldMintingOptions: UnsoldMintingOptions.KEEP_PRICE, }); - const collectionMintOrder = await testEnv.wrap(mintCollection)({}); + const collectionMintOrder = await testEnv.wrap(WEN_FUNC.mintCollection); await requestFundsFromFaucet( this.network, this.guardianAddress!.bech32, @@ -131,13 +113,13 @@ export class Helper { ); await this.walletService!.send( this.guardianAddress!, - collectionMintOrder.payload.targetAddress, - collectionMintOrder.payload.amount, + collectionMintOrder.payload.targetAddress!, + collectionMintOrder.payload.amount!, {}, ); await MnemonicService.store(this.guardianAddress!.bech32, this.guardianAddress!.mnemonic); - const collectionDocRef = build5Db().doc(`${COL.COLLECTION}/${this.collection}`); + const collectionDocRef = build5Db().doc(COL.COLLECTION, this.collection!); await wait(async () => { const data = await collectionDocRef.get(); return data.status === CollectionStatus.MINTED; @@ -153,8 +135,8 @@ export class Helper { const ownerChangeTran = ( await build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.MINT_COLLECTION) - .where('payload.type', '==', TransactionPayloadType.SEND_ALIAS_TO_GUARDIAN) + .where('type', '==', PgTransactionType.MINT_COLLECTION) + .where('payload_type', '==', PgTransactionPayloadType.SEND_ALIAS_TO_GUARDIAN) .where('member', '==', this.guardian) .get() ).map((d) => d); @@ -241,37 +223,33 @@ export class Helper { await createUnlock(essence, sourceAddress), ...refUnlocks, ]); - await build5Db().doc(`blocks/${blockId}`).create({ blockId }); + await testEnv.createBlock(blockId); return blockId; }; public withdrawNftAndAwait = async (nft: string) => { - mockWalletReturnValue(this.walletSpy, this.guardian!, { nft }); - await testEnv.wrap(withdrawNft)({}); + mockWalletReturnValue(this.guardian!, { nft }); + await testEnv.wrap(WEN_FUNC.withdrawNft); await wait(async () => { const snap = await build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.WITHDRAW_NFT) - .where('payload.nft', '==', nft) - .get(); + .where('type', '==', PgTransactionType.WITHDRAW_NFT) + .where('payload_nft', '==', nft) + .get(); return snap[0]?.payload?.walletReference?.confirmed; }); }; public setAvailableForAuction = async () => { - mockWalletReturnValue(this.walletSpy, this.guardian!, this.dummyAuctionData(this.nft!.uid)); - await testEnv.wrap(setForSaleNft)({}); - await wait( - async () => (await build5Db().doc(`${COL.NFT}/${this.nft!.uid}`).get())?.available === 3, - ); + mockWalletReturnValue(this.guardian!, this.dummyAuctionData(this.nft!.uid)); + await testEnv.wrap(WEN_FUNC.setForSaleNft); + await wait(async () => (await build5Db().doc(COL.NFT, this.nft!.uid).get())?.available === 3); }; public setAvailableForSale = async () => { - mockWalletReturnValue(this.walletSpy, this.guardian!, this.dummySaleData(this.nft!.uid)); - await testEnv.wrap(setForSaleNft)({}); - await wait( - async () => (await build5Db().doc(`${COL.NFT}/${this.nft!.uid}`).get())?.available === 1, - ); + mockWalletReturnValue(this.guardian!, this.dummySaleData(this.nft!.uid)); + await testEnv.wrap(WEN_FUNC.setForSaleNft); + await wait(async () => (await build5Db().doc(COL.NFT, this.nft!.uid).get())?.available === 1); }; public createDummyCollection = (space: string, royaltiesSpace: string) => ({ @@ -295,7 +273,7 @@ export class Helper { collection, availableFrom: dayjs().add(1, 'hour').toDate(), price: 10 * 1000 * 1000, - uid: getRandomEthAddress(), + uid: wallet.getRandomEthAddress(), media: MEDIA, properties: { custom: { diff --git a/packages/functions/test-tangle/nft-staking/nft-staking_1.spec.ts b/packages/functions/test-tangle/nft-staking/nft-staking_1.spec.ts index d7b01a8738..0704b8702a 100644 --- a/packages/functions/test-tangle/nft-staking/nft-staking_1.spec.ts +++ b/packages/functions/test-tangle/nft-staking/nft-staking_1.spec.ts @@ -7,12 +7,12 @@ import { NftStake, StakeType, Transaction, + WEN_FUNC, } from '@build-5/interfaces'; import dayjs from 'dayjs'; -import { stakeNft } from '../../src/runtime/firebase/nft'; import { dateToTimestamp } from '../../src/utils/dateTime.utils'; -import { mockWalletReturnValue, wait } from '../../test/controls/common'; -import { testEnv } from '../../test/set-up'; +import { wait } from '../../test/controls/common'; +import { mockWalletReturnValue, testEnv } from '../../test/set-up'; import { Helper } from './Helper'; describe('Stake nft', () => { @@ -30,20 +30,20 @@ describe('Stake nft', () => { 'Should stake nft', async (stakeType: StakeType) => { let nft = await helper.createAndOrderNft(); - const nftDocRef = build5Db().doc(`${COL.NFT}/${nft.uid}`); + const nftDocRef = build5Db().doc(COL.NFT, nft.uid); await helper.mintCollection(); await helper.withdrawNftAndAwait(nft.uid); - mockWalletReturnValue(helper.walletSpy, helper.guardian!, { + mockWalletReturnValue(helper.guardian!, { network: Network.RMS, weeks: 25, type: stakeType, }); - let stakeNftOrder = await testEnv.wrap(stakeNft)({}); + let stakeNftOrder = await testEnv.wrap(WEN_FUNC.stakeNft); nft = await nftDocRef.get(); await helper.sendNftToAddress( helper.guardianAddress!, - stakeNftOrder.payload.targetAddress, + stakeNftOrder.payload.targetAddress!, dateToTimestamp(dayjs().add(2, 'd')), nft.mintingData?.nftId, ); @@ -65,11 +65,11 @@ describe('Stake nft', () => { expect(nftStake.expirationProcessed).toBe(false); expect(nftStake.type).toBe(stakeType); - const collectionDocRef = build5Db().doc(`${COL.COLLECTION}/${nftStake.collection}`); + const collectionDocRef = build5Db().doc(COL.COLLECTION, nftStake.collection); const collection = await collectionDocRef.get(); expect(collection.stakedNft).toBe(1); - const stakeNftOrderDocRef = build5Db().doc(`${COL.TRANSACTION}/${stakeNftOrder.uid}`); + const stakeNftOrderDocRef = build5Db().doc(COL.TRANSACTION, stakeNftOrder.uid); stakeNftOrder = await stakeNftOrderDocRef.get(); expect(stakeNftOrder.payload.nft).toBe(nft.uid); expect(stakeNftOrder.payload.collection).toBe(nft.collection); diff --git a/packages/functions/test-tangle/nft-staking/nft-staking_10.spec.ts b/packages/functions/test-tangle/nft-staking/nft-staking_10.spec.ts index c364d173bf..d1cf0f51a3 100644 --- a/packages/functions/test-tangle/nft-staking/nft-staking_10.spec.ts +++ b/packages/functions/test-tangle/nft-staking/nft-staking_10.spec.ts @@ -1,16 +1,15 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ -import { build5Db } from '@build-5/database'; +import { PgTransactionType, build5Db } from '@build-5/database'; import { COL, MIN_IOTA_AMOUNT, Network, StakeType, Transaction, - TransactionType, + WEN_FUNC, } from '@build-5/interfaces'; -import { stakeNft } from '../../src/runtime/firebase/nft/index'; -import { mockWalletReturnValue, wait } from '../../test/controls/common'; -import { testEnv } from '../../test/set-up'; +import { wait } from '../../test/controls/common'; +import { mockWalletReturnValue, testEnv } from '../../test/set-up'; import { requestFundsFromFaucet } from '../faucet'; import { Helper } from './Helper'; @@ -26,20 +25,20 @@ describe('Collection minting', () => { }); it('Should return credits when nft deposit order does not receive nft', async () => { - mockWalletReturnValue(helper.walletSpy, helper.guardian!, { + mockWalletReturnValue(helper.guardian!, { network: Network.RMS, weeks: 25, type: StakeType.DYNAMIC, }); - const order = await testEnv.wrap(stakeNft)({}); + const order = await testEnv.wrap(WEN_FUNC.stakeNft); await requestFundsFromFaucet(Network.RMS, order.payload.targetAddress, MIN_IOTA_AMOUNT); const query = build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.CREDIT) + .where('type', '==', PgTransactionType.CREDIT) .where('member', '==', helper.guardian!); await wait(async () => { - const snap = await query.get(); + const snap = await query.get(); return ( snap.length === 1 && snap[0].payload.walletReference?.confirmed && diff --git a/packages/functions/test-tangle/nft-staking/nft-staking_2.spec.ts b/packages/functions/test-tangle/nft-staking/nft-staking_2.spec.ts index abfeb3854a..7471a4f9d6 100644 --- a/packages/functions/test-tangle/nft-staking/nft-staking_2.spec.ts +++ b/packages/functions/test-tangle/nft-staking/nft-staking_2.spec.ts @@ -1,16 +1,7 @@ -import { build5Db } from '@build-5/database'; -import { - COL, - Network, - Nft, - StakeType, - Transaction, - TransactionType, - WenError, -} from '@build-5/interfaces'; -import { stakeNft } from '../../src/runtime/firebase/nft'; -import { mockWalletReturnValue, wait } from '../../test/controls/common'; -import { testEnv } from '../../test/set-up'; +import { PgTransactionType, build5Db } from '@build-5/database'; +import { COL, Network, Nft, StakeType, Transaction, WEN_FUNC, WenError } from '@build-5/interfaces'; +import { wait } from '../../test/controls/common'; +import { mockWalletReturnValue, testEnv } from '../../test/set-up'; import { Helper } from './Helper'; describe('Stake nft', () => { @@ -26,30 +17,30 @@ describe('Stake nft', () => { it('Should credit nft, not enough base tokens', async () => { let nft = await helper.createAndOrderNft(); - let nftDocRef = build5Db().doc(`${COL.NFT}/${nft.uid}`); + let nftDocRef = build5Db().doc(COL.NFT, nft.uid); await helper.mintCollection(); nft = await nftDocRef.get(); await helper.withdrawNftAndAwait(nft.uid); - mockWalletReturnValue(helper.walletSpy, helper.guardian!, { + mockWalletReturnValue(helper.guardian!, { network: Network.RMS, weeks: 25, type: StakeType.DYNAMIC, }); - const stakeNftOrder = await testEnv.wrap(stakeNft)({}); + const stakeNftOrder = await testEnv.wrap(WEN_FUNC.stakeNft); await helper.sendNftToAddress( helper.guardianAddress!, - stakeNftOrder.payload.targetAddress, + stakeNftOrder.payload.targetAddress!, undefined, nft.mintingData?.nftId, ); const creditQuery = build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.CREDIT_NFT) + .where('type', '==', PgTransactionType.CREDIT_NFT) .where('member', '==', helper.guardian); await wait(async () => { - const snap = await creditQuery.get(); + const snap = await creditQuery.get(); return snap.length === 1 && snap[0]?.payload?.walletReference?.confirmed; }); @@ -61,7 +52,7 @@ describe('Stake nft', () => { nft = await nftDocRef.get(); expect(nft.isOwned).toBe(false); - expect(nft.owner).toBeNull(); + expect(nft.owner).toBeUndefined(); expect(nft.hidden).toBe(true); }); }); diff --git a/packages/functions/test-tangle/nft-staking/nft-staking_2_b.spec.ts b/packages/functions/test-tangle/nft-staking/nft-staking_2_b.spec.ts index e3292c6fd8..d1b20a2981 100644 --- a/packages/functions/test-tangle/nft-staking/nft-staking_2_b.spec.ts +++ b/packages/functions/test-tangle/nft-staking/nft-staking_2_b.spec.ts @@ -1,16 +1,7 @@ -import { build5Db } from '@build-5/database'; -import { - COL, - Network, - Nft, - StakeType, - Transaction, - TransactionType, - WenError, -} from '@build-5/interfaces'; -import { stakeNft } from '../../src/runtime/firebase/nft'; -import { mockWalletReturnValue, wait } from '../../test/controls/common'; -import { testEnv } from '../../test/set-up'; +import { PgTransactionType, build5Db } from '@build-5/database'; +import { COL, Network, Nft, StakeType, Transaction, WEN_FUNC, WenError } from '@build-5/interfaces'; +import { wait } from '../../test/controls/common'; +import { mockWalletReturnValue, testEnv } from '../../test/set-up'; import { Helper } from './Helper'; describe('Stake nft', () => { @@ -26,33 +17,33 @@ describe('Stake nft', () => { it('Should credit nft, not enough base tokens', async () => { let nft = await helper.createAndOrderNft(); - let nftDocRef = build5Db().doc(`${COL.NFT}/${nft.uid}`); + let nftDocRef = build5Db().doc(COL.NFT, nft.uid); await helper.mintCollection(); nft = await nftDocRef.get(); await helper.withdrawNftAndAwait(nft.uid); await nftDocRef.delete(); - await build5Db().doc(`${COL.COLLECTION}/${nft.collection}`).delete(); + await build5Db().doc(COL.COLLECTION, nft.collection).delete(); - mockWalletReturnValue(helper.walletSpy, helper.guardian!, { + mockWalletReturnValue(helper.guardian!, { network: Network.RMS, weeks: 25, type: StakeType.DYNAMIC, }); - const stakeNftOrder = await testEnv.wrap(stakeNft)({}); + const stakeNftOrder = await testEnv.wrap(WEN_FUNC.stakeNft); await helper.sendNftToAddress( helper.guardianAddress!, - stakeNftOrder.payload.targetAddress, + stakeNftOrder.payload.targetAddress!, undefined, nft.mintingData?.nftId, ); const creditQuery = build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.CREDIT_NFT) + .where('type', '==', PgTransactionType.CREDIT_NFT) .where('member', '==', helper.guardian); await wait(async () => { - const snap = await creditQuery.get(); + const snap = await creditQuery.get(); return snap.length === 1 && snap[0]?.payload?.walletReference?.confirmed; }); @@ -62,7 +53,7 @@ describe('Stake nft', () => { expect(credit.payload.response!.message).toBe(WenError.not_enough_base_token.key); expect(credit.payload.response!.requiredAmount).toBeDefined(); - nftDocRef = build5Db().doc(`${COL.NFT}/${nft.mintingData?.nftId}`); + nftDocRef = build5Db().doc(COL.NFT, nft.mintingData?.nftId!); nft = await nftDocRef.get(); expect(nft).toBeUndefined(); }); diff --git a/packages/functions/test-tangle/nft-staking/nft-staking_3.spec.ts b/packages/functions/test-tangle/nft-staking/nft-staking_3.spec.ts index a7678d167f..eaf1aa4ca0 100644 --- a/packages/functions/test-tangle/nft-staking/nft-staking_3.spec.ts +++ b/packages/functions/test-tangle/nft-staking/nft-staking_3.spec.ts @@ -7,14 +7,14 @@ import { NftStake, StakeType, Transaction, + WEN_FUNC, } from '@build-5/interfaces'; import { UnlockConditionType } from '@iota/sdk'; import dayjs from 'dayjs'; -import { stakeNft } from '../../src/runtime/firebase/nft'; import { NftWallet } from '../../src/services/wallet/NftWallet'; import { dateToTimestamp } from '../../src/utils/dateTime.utils'; -import { mockWalletReturnValue, wait } from '../../test/controls/common'; -import { testEnv } from '../../test/set-up'; +import { wait } from '../../test/controls/common'; +import { mockWalletReturnValue, testEnv } from '../../test/set-up'; import { Helper } from './Helper'; describe('Stake nft', () => { @@ -30,23 +30,23 @@ describe('Stake nft', () => { it('Should stake nft minted outside build-5', async () => { let nft = await helper.createAndOrderNft(); - let nftDocRef = build5Db().doc(`${COL.NFT}/${nft.uid}`); + let nftDocRef = build5Db().doc(COL.NFT, nft.uid); await helper.mintCollection(); await helper.withdrawNftAndAwait(nft.uid); nft = await nftDocRef.get(); - await build5Db().doc(`${COL.NFT}/${nft.uid}`).delete(); - await build5Db().doc(`${COL.COLLECTION}/${nft.collection}`).delete(); + await build5Db().doc(COL.NFT, nft.uid).delete(); + await build5Db().doc(COL.COLLECTION, nft.collection).delete(); - mockWalletReturnValue(helper.walletSpy, helper.guardian!, { + mockWalletReturnValue(helper.guardian!, { network: Network.RMS, weeks: 25, type: StakeType.DYNAMIC, }); - let stakeNftOrder = await testEnv.wrap(stakeNft)({}); + let stakeNftOrder = await testEnv.wrap(WEN_FUNC.stakeNft); await helper.sendNftToAddress( helper.guardianAddress!, - stakeNftOrder.payload.targetAddress, + stakeNftOrder.payload.targetAddress!, dateToTimestamp(dayjs().add(2, 'd')), nft.mintingData?.nftId, ); @@ -59,7 +59,7 @@ describe('Stake nft', () => { return snap.length === 1; }); - nftDocRef = build5Db().doc(`${COL.NFT}/${nft.mintingData?.nftId}`); + nftDocRef = build5Db().doc(COL.NFT, nft.mintingData?.nftId!); nft = await nftDocRef.get(); const snap = await stakeQuery.get(); const nftStake = snap[0] as NftStake; @@ -80,11 +80,11 @@ describe('Stake nft', () => { output.unlockConditions.find((uc) => uc.type === UnlockConditionType.Timelock), ).toBeDefined(); - const collectionDocRef = build5Db().doc(`${COL.COLLECTION}/${nftStake.collection}`); + const collectionDocRef = build5Db().doc(COL.COLLECTION, nftStake.collection); const collection = await collectionDocRef.get(); expect(collection.stakedNft).toBe(1); - const stakeNftOrderDocRef = build5Db().doc(`${COL.TRANSACTION}/${stakeNftOrder.uid}`); + const stakeNftOrderDocRef = build5Db().doc(COL.TRANSACTION, stakeNftOrder.uid); stakeNftOrder = await stakeNftOrderDocRef.get(); expect(stakeNftOrder.payload.nft).toBe(nft.uid); }); diff --git a/packages/functions/test-tangle/nft-staking/nft-staking_4.spec.ts b/packages/functions/test-tangle/nft-staking/nft-staking_4.spec.ts index 1a139ce495..8d5163f176 100644 --- a/packages/functions/test-tangle/nft-staking/nft-staking_4.spec.ts +++ b/packages/functions/test-tangle/nft-staking/nft-staking_4.spec.ts @@ -1,16 +1,7 @@ -import { build5Db } from '@build-5/database'; -import { - COL, - Network, - Nft, - StakeType, - Transaction, - TransactionType, - WenError, -} from '@build-5/interfaces'; -import { stakeNft } from '../../src/runtime/firebase/nft'; -import { mockWalletReturnValue, wait } from '../../test/controls/common'; -import { testEnv } from '../../test/set-up'; +import { PgTransactionType, build5Db } from '@build-5/database'; +import { COL, Network, Nft, StakeType, Transaction, WEN_FUNC, WenError } from '@build-5/interfaces'; +import { wait } from '../../test/controls/common'; +import { mockWalletReturnValue, testEnv } from '../../test/set-up'; import { Helper } from './Helper'; describe('Stake nft', () => { @@ -26,35 +17,35 @@ describe('Stake nft', () => { it.each([true, false])('Should credit first then stake', async (migration: boolean) => { let nft = await helper.createAndOrderNft(); - let nftDocRef = build5Db().doc(`${COL.NFT}/${nft.uid}`); + let nftDocRef = build5Db().doc(COL.NFT, nft.uid); await helper.mintCollection(); nft = await nftDocRef.get(); await helper.withdrawNftAndAwait(nft.uid); if (migration) { await nftDocRef.delete(); - await build5Db().doc(`${COL.COLLECTION}/${nft.collection}`).delete(); + await build5Db().doc(COL.COLLECTION, nft.collection).delete(); } - mockWalletReturnValue(helper.walletSpy, helper.guardian!, { + mockWalletReturnValue(helper.guardian!, { network: Network.RMS, weeks: 25, type: StakeType.DYNAMIC, }); - const stakeNftOrder = await testEnv.wrap(stakeNft)({}); + const stakeNftOrder = await testEnv.wrap(WEN_FUNC.stakeNft); await helper.sendNftToAddress( helper.guardianAddress!, - stakeNftOrder.payload.targetAddress, + stakeNftOrder.payload.targetAddress!, undefined, nft.mintingData?.nftId, ); const creditQuery = build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.CREDIT_NFT) + .where('type', '==', PgTransactionType.CREDIT_NFT) .where('member', '==', helper.guardian); await wait(async () => { - const snap = await creditQuery.get(); + const snap = await creditQuery.get(); return snap.length === 1 && snap[0]?.payload?.walletReference?.confirmed; }); @@ -67,7 +58,7 @@ describe('Stake nft', () => { (credit.payload.response!.requiredAmount as number) - nft.mintingData?.storageDeposit!; await helper.sendNftToAddress( helper.guardianAddress!, - stakeNftOrder.payload.targetAddress, + stakeNftOrder.payload.targetAddress!, undefined, nft.mintingData?.nftId, extraRequired, diff --git a/packages/functions/test-tangle/nft-staking/nft-staking_5.spec.ts b/packages/functions/test-tangle/nft-staking/nft-staking_5.spec.ts index ed10c8bffa..79c45f8ac5 100644 --- a/packages/functions/test-tangle/nft-staking/nft-staking_5.spec.ts +++ b/packages/functions/test-tangle/nft-staking/nft-staking_5.spec.ts @@ -1,19 +1,16 @@ -import { build5Db } from '@build-5/database'; +import { PgTransactionPayloadType, build5Db } from '@build-5/database'; import { Award, COL, MIN_IOTA_AMOUNT, Network, - Nft, StakeType, Transaction, - TransactionPayloadType, + WEN_FUNC, } from '@build-5/interfaces'; import dayjs from 'dayjs'; -import { approveAwardParticipant, createAward, fundAward } from '../../src/runtime/firebase/award'; -import { stakeNft } from '../../src/runtime/firebase/nft'; -import { mockWalletReturnValue, wait } from '../../test/controls/common'; -import { MEDIA, testEnv } from '../../test/set-up'; +import { wait } from '../../test/controls/common'; +import { MEDIA, mockWalletReturnValue, testEnv } from '../../test/set-up'; import { saveBaseToken } from '../award/common'; import { requestFundsFromFaucet } from '../faucet'; import { Helper } from './Helper'; @@ -31,47 +28,43 @@ describe('Stake nft', () => { it('Should deposit badge ntt ', async () => { const token = await saveBaseToken(helper.space!.uid, helper.guardian!); - mockWalletReturnValue( - helper.walletSpy, - helper.guardian!, - awardRequest(helper.space!.uid, token.symbol), - ); - let award = await testEnv.wrap(createAward)({}); + mockWalletReturnValue(helper.guardian!, awardRequest(helper.space!.uid, token.symbol)); + let award = await testEnv.wrap(WEN_FUNC.createAward); - mockWalletReturnValue(helper.walletSpy, helper.guardian!, { uid: award.uid }); - const order = await testEnv.wrap(fundAward)({}); + mockWalletReturnValue(helper.guardian!, { uid: award.uid }); + const order = await testEnv.wrap(WEN_FUNC.fundAward); await requestFundsFromFaucet(Network.RMS, order.payload.targetAddress, order.payload.amount); - const awardDocRef = build5Db().doc(`${COL.AWARD}/${award.uid}`); + const awardDocRef = build5Db().doc(COL.AWARD, award.uid); await wait(async () => { award = await awardDocRef.get(); return award.approved && award.funded; }); - mockWalletReturnValue(helper.walletSpy, helper.guardian!, { + mockWalletReturnValue(helper.guardian!, { award: award.uid, members: [helper.guardian!], }); - await testEnv.wrap(approveAwardParticipant)({}); + await testEnv.wrap(WEN_FUNC.approveParticipantAward); const nttQuery = build5Db() .collection(COL.TRANSACTION) .where('member', '==', helper.guardian!) - .where('payload.type', '==', TransactionPayloadType.BADGE); + .where('payload_type', '==', PgTransactionPayloadType.BADGE); await wait(async () => { - const snap = await nttQuery.get(); + const snap = await nttQuery.get(); return snap.length === 1 && snap[0]?.payload?.walletReference?.confirmed; }); - mockWalletReturnValue(helper.walletSpy, helper.guardian!, { + mockWalletReturnValue(helper.guardian!, { network: Network.RMS, weeks: 25, type: StakeType.DYNAMIC, }); - const stakeNftOrder = await testEnv.wrap(stakeNft)({}); + const stakeNftOrder = await testEnv.wrap(WEN_FUNC.stakeNft); await helper.sendNftToAddress( helper.guardianAddress!, - stakeNftOrder.payload.targetAddress, + stakeNftOrder.payload.targetAddress!, undefined, undefined, MIN_IOTA_AMOUNT, @@ -84,7 +77,7 @@ describe('Stake nft', () => { }); const nftQuery = build5Db().collection(COL.NFT).where('space', '==', helper.space?.uid); - const nftSnap = await nftQuery.get(); + const nftSnap = await nftQuery.get(); expect(nftSnap.length).toBe(1); expect(nftSnap[0]?.space).toBe(award.space); }); diff --git a/packages/functions/test-tangle/nft-staking/nft-staking_6.spec.ts b/packages/functions/test-tangle/nft-staking/nft-staking_6.spec.ts index fa0c8e8d2a..2b0b64600b 100644 --- a/packages/functions/test-tangle/nft-staking/nft-staking_6.spec.ts +++ b/packages/functions/test-tangle/nft-staking/nft-staking_6.spec.ts @@ -1,9 +1,16 @@ import { build5Db } from '@build-5/database'; -import { COL, KEY_NAME_TANGLE, Network, Nft, StakeType } from '@build-5/interfaces'; +import { + COL, + KEY_NAME_TANGLE, + Network, + Nft, + StakeType, + Transaction, + WEN_FUNC, +} from '@build-5/interfaces'; import { NftOutput, NftOutputBuilderParams, TagFeature, Utils, utf8ToHex } from '@iota/sdk'; -import { stakeNft } from '../../src/runtime/firebase/nft'; -import { mockWalletReturnValue, wait } from '../../test/controls/common'; -import { testEnv } from '../../test/set-up'; +import { wait } from '../../test/controls/common'; +import { mockWalletReturnValue, testEnv } from '../../test/set-up'; import { Helper } from './Helper'; describe('Stake nft', () => { @@ -19,17 +26,17 @@ describe('Stake nft', () => { it.each([false, true])('Should stake with tag', async (migration: boolean) => { let nft = await helper.createAndOrderNft(); - let nftDocRef = build5Db().doc(`${COL.NFT}/${nft.uid}`); + let nftDocRef = build5Db().doc(COL.NFT, nft.uid); await helper.mintCollection(); nft = await nftDocRef.get(); await helper.withdrawNftAndAwait(nft.uid); if (migration) { await nftDocRef.delete(); - await build5Db().doc(`${COL.COLLECTION}/${nft.collection}`).delete(); + await build5Db().doc(COL.COLLECTION, nft.collection).delete(); } - mockWalletReturnValue(helper.walletSpy, helper.guardian!, { + mockWalletReturnValue(helper.guardian!, { network: Network.RMS, weeks: 25, type: StakeType.DYNAMIC, @@ -47,10 +54,10 @@ describe('Stake nft', () => { helper.walletService!.info.protocol.rentStructure, ); const extraAmount = Number(storageDeposit) - Number(nftOutput.amount); - const stakeNftOrder = await testEnv.wrap(stakeNft)({}); + const stakeNftOrder = await testEnv.wrap(WEN_FUNC.stakeNft); await helper.sendNftToAddress( helper.guardianAddress!, - stakeNftOrder.payload.targetAddress, + stakeNftOrder.payload.targetAddress!, undefined, nft.mintingData?.nftId, extraAmount, diff --git a/packages/functions/test-tangle/nft-staking/nft-staking_7.spec.ts b/packages/functions/test-tangle/nft-staking/nft-staking_7.spec.ts index 3a2ec70576..d7a52e7c3a 100644 --- a/packages/functions/test-tangle/nft-staking/nft-staking_7.spec.ts +++ b/packages/functions/test-tangle/nft-staking/nft-staking_7.spec.ts @@ -1,8 +1,7 @@ -import { build5Db } from '@build-5/database'; -import { COL, Network, Nft, StakeType, Transaction, TransactionType } from '@build-5/interfaces'; -import { stakeNft } from '../../src/runtime/firebase/nft'; -import { mockWalletReturnValue, wait } from '../../test/controls/common'; -import { testEnv } from '../../test/set-up'; +import { PgTransactionType, build5Db } from '@build-5/database'; +import { COL, Network, Nft, StakeType, Transaction, WEN_FUNC } from '@build-5/interfaces'; +import { wait } from '../../test/controls/common'; +import { mockWalletReturnValue, testEnv } from '../../test/set-up'; import { Helper } from './Helper'; describe('Stake nft', () => { @@ -18,42 +17,42 @@ describe('Stake nft', () => { it('Should credit twice', async () => { let nft = await helper.createAndOrderNft(); - let nftDocRef = build5Db().doc(`${COL.NFT}/${nft.uid}`); + let nftDocRef = build5Db().doc(COL.NFT, nft.uid); await helper.mintCollection(); nft = await nftDocRef.get(); await helper.withdrawNftAndAwait(nft.uid); - mockWalletReturnValue(helper.walletSpy, helper.guardian!, { + mockWalletReturnValue(helper.guardian!, { network: Network.RMS, weeks: 25, type: StakeType.DYNAMIC, }); - const stakeNftOrder = await testEnv.wrap(stakeNft)({}); + const stakeNftOrder = await testEnv.wrap(WEN_FUNC.stakeNft); await helper.sendNftToAddress( helper.guardianAddress!, - stakeNftOrder.payload.targetAddress, + stakeNftOrder.payload.targetAddress!, undefined, nft.mintingData?.nftId, ); const creditQuery = build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.CREDIT_NFT) + .where('type', '==', PgTransactionType.CREDIT_NFT) .where('member', '==', helper.guardian); await wait(async () => { - const snap = await creditQuery.get(); + const snap = await creditQuery.get(); return snap.length === 1 && snap[0]?.payload?.walletReference?.confirmed; }); await helper.sendNftToAddress( helper.guardianAddress!, - stakeNftOrder.payload.targetAddress, + stakeNftOrder.payload.targetAddress!, undefined, nft.mintingData?.nftId, ); await wait(async () => { - const snap = await creditQuery.get(); + const snap = await creditQuery.get(); return ( snap.length === 2 && snap[0]?.payload?.walletReference?.confirmed && diff --git a/packages/functions/test-tangle/nft-staking/nft-staking_8.spec.ts b/packages/functions/test-tangle/nft-staking/nft-staking_8.spec.ts index 3ac4e81d7c..9a114f3684 100644 --- a/packages/functions/test-tangle/nft-staking/nft-staking_8.spec.ts +++ b/packages/functions/test-tangle/nft-staking/nft-staking_8.spec.ts @@ -1,18 +1,15 @@ -import { build5Db } from '@build-5/database'; +import { PgIgnoreWalletReason, PgTransactionType, build5Db } from '@build-5/database'; import { COL, - IgnoreWalletReason, MIN_IOTA_AMOUNT, Network, Nft, StakeType, Transaction, - TransactionType, + WEN_FUNC, } from '@build-5/interfaces'; -import { creditUnrefundable } from '../../src/runtime/firebase/credit'; -import { stakeNft } from '../../src/runtime/firebase/nft'; -import { mockWalletReturnValue, wait } from '../../test/controls/common'; -import { testEnv } from '../../test/set-up'; +import { wait } from '../../test/controls/common'; +import { mockWalletReturnValue, testEnv } from '../../test/set-up'; import { requestFundsFromFaucet } from '../faucet'; import { Helper } from './Helper'; @@ -29,20 +26,20 @@ describe('Stake nft', () => { it('Should not stake with storage dep', async () => { let nft = await helper.createAndOrderNft(); - let nftDocRef = build5Db().doc(`${COL.NFT}/${nft.uid}`); + let nftDocRef = build5Db().doc(COL.NFT, nft.uid); await helper.mintCollection(); nft = await nftDocRef.get(); await helper.withdrawNftAndAwait(nft.uid); - mockWalletReturnValue(helper.walletSpy, helper.guardian!, { + mockWalletReturnValue(helper.guardian!, { network: Network.RMS, weeks: 25, type: StakeType.DYNAMIC, }); - const stakeNftOrder = await testEnv.wrap(stakeNft)({}); + const stakeNftOrder = await testEnv.wrap(WEN_FUNC.stakeNft); await helper.sendNftToAddress( helper.guardianAddress!, - stakeNftOrder.payload.targetAddress, + stakeNftOrder.payload.targetAddress!, undefined, nft.mintingData?.nftId, MIN_IOTA_AMOUNT, @@ -52,29 +49,29 @@ describe('Stake nft', () => { let creditQuery = build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.CREDIT_NFT) + .where('type', '==', PgTransactionType.CREDIT_NFT) .where('member', '==', helper.guardian) .where( 'ignoreWalletReason', '==', - IgnoreWalletReason.UNREFUNDABLE_DUE_STORAGE_DEPOSIT_CONDITION, + PgIgnoreWalletReason.UNREFUNDABLE_DUE_STORAGE_DEPOSIT_CONDITION, ); await wait(async () => { - const snap = await creditQuery.get(); + const snap = await creditQuery.get(); return snap.length === 1; }); - const snap = await creditQuery.get(); - mockWalletReturnValue(helper.walletSpy, helper.guardian!, { transaction: snap[0].uid }); - const order = await testEnv.wrap(creditUnrefundable)({}); + const snap = await creditQuery.get(); + mockWalletReturnValue(helper.guardian!, { transaction: snap[0].uid }); + const order = await testEnv.wrap(WEN_FUNC.creditUnrefundable); await requestFundsFromFaucet(Network.RMS, order.payload.targetAddress, order.payload.amount); creditQuery = build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.CREDIT_STORAGE_DEPOSIT_LOCKED) + .where('type', '==', PgTransactionType.CREDIT_STORAGE_DEPOSIT_LOCKED) .where('member', '==', helper.guardian); await wait(async () => { - const snap = await creditQuery.get(); + const snap = await creditQuery.get(); return snap.length === 1 && snap[0].payload.walletReference?.confirmed; }); diff --git a/packages/functions/test-tangle/nft-staking/nft-staking_9.spec.ts b/packages/functions/test-tangle/nft-staking/nft-staking_9.spec.ts index 4e4303ff56..87f918e323 100644 --- a/packages/functions/test-tangle/nft-staking/nft-staking_9.spec.ts +++ b/packages/functions/test-tangle/nft-staking/nft-staking_9.spec.ts @@ -1,21 +1,18 @@ -import { build5Db } from '@build-5/database'; +import { PgIgnoreWalletReason, PgTransactionType, build5Db } from '@build-5/database'; import { COL, - IgnoreWalletReason, MIN_IOTA_AMOUNT, Network, Nft, StakeType, TRANSACTION_AUTO_EXPIRY_MS, Transaction, - TransactionType, + WEN_FUNC, } from '@build-5/interfaces'; import dayjs from 'dayjs'; -import { creditUnrefundable } from '../../src/runtime/firebase/credit'; -import { stakeNft } from '../../src/runtime/firebase/nft'; import { dateToTimestamp } from '../../src/utils/dateTime.utils'; -import { mockWalletReturnValue, wait } from '../../test/controls/common'; -import { testEnv } from '../../test/set-up'; +import { wait } from '../../test/controls/common'; +import { mockWalletReturnValue, testEnv } from '../../test/set-up'; import { Helper } from './Helper'; describe('Stake nft', () => { @@ -31,20 +28,20 @@ describe('Stake nft', () => { it('Should not stake with storage dep and timelock, also should not credit', async () => { let nft = await helper.createAndOrderNft(); - let nftDocRef = build5Db().doc(`${COL.NFT}/${nft.uid}`); + let nftDocRef = build5Db().doc(COL.NFT, nft.uid); await helper.mintCollection(); nft = await nftDocRef.get(); await helper.withdrawNftAndAwait(nft.uid); - mockWalletReturnValue(helper.walletSpy, helper.guardian!, { + mockWalletReturnValue(helper.guardian!, { network: Network.RMS, weeks: 25, type: StakeType.DYNAMIC, }); - const stakeNftOrder = await testEnv.wrap(stakeNft)({}); + const stakeNftOrder = await testEnv.wrap(WEN_FUNC.stakeNft); await helper.sendNftToAddress( helper.guardianAddress!, - stakeNftOrder.payload.targetAddress, + stakeNftOrder.payload.targetAddress!, dateToTimestamp(dayjs().add(1, 'm')), nft.mintingData?.nftId, MIN_IOTA_AMOUNT, @@ -54,22 +51,22 @@ describe('Stake nft', () => { let creditQuery = build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.CREDIT_NFT) + .where('type', '==', PgTransactionType.CREDIT_NFT) .where('member', '==', helper.guardian) .where( 'ignoreWalletReason', '==', - IgnoreWalletReason.UNREFUNDABLE_DUE_STORAGE_DEPOSIT_CONDITION, + PgIgnoreWalletReason.UNREFUNDABLE_DUE_STORAGE_DEPOSIT_CONDITION, ); await wait(async () => { - const snap = await creditQuery.get(); + const snap = await creditQuery.get(); return snap.length === 1; }); - const snap = await creditQuery.get(); - mockWalletReturnValue(helper.walletSpy, helper.guardian!, { transaction: snap[0].uid }); - const order = await testEnv.wrap(creditUnrefundable)({}); - + const snap = await creditQuery.get(); + mockWalletReturnValue(helper.guardian!, { transaction: snap[0].uid }); + let order = await testEnv.wrap(WEN_FUNC.creditUnrefundable); + order = (await build5Db().doc(COL.TRANSACTION, order.uid).get())!; const expiresOn = order.payload.expiresOn!; const isEarlier = dayjs(expiresOn.toDate()).isBefore(dayjs().add(TRANSACTION_AUTO_EXPIRY_MS)); expect(isEarlier).toBe(true); diff --git a/packages/functions/test-tangle/nft-transfer/Helper.ts b/packages/functions/test-tangle/nft-transfer/Helper.ts index e8a0e86bfb..727b3eed83 100644 --- a/packages/functions/test-tangle/nft-transfer/Helper.ts +++ b/packages/functions/test-tangle/nft-transfer/Helper.ts @@ -2,8 +2,8 @@ import { build5Db } from '@build-5/database'; import { Access, - Categories, COL, + Categories, Collection, CollectionStatus, CollectionType, @@ -17,27 +17,19 @@ import { Transaction, TransactionType, UnsoldMintingOptions, + WEN_FUNC, } from '@build-5/interfaces'; import dayjs from 'dayjs'; -import { createCollection, mintCollection } from '../../src/runtime/firebase/collection/index'; -import { createNft, orderNft, setForSaleNft } from '../../src/runtime/firebase/nft/index'; import { NftWallet } from '../../src/services/wallet/NftWallet'; import { Wallet } from '../../src/services/wallet/wallet'; import { AddressDetails } from '../../src/services/wallet/wallet.service'; import { serverTime } from '../../src/utils/dateTime.utils'; import * as wallet from '../../src/utils/wallet.utils'; -import { - createMember as createMemberTest, - createSpace, - mockWalletReturnValue, - submitMilestoneFunc, - wait, -} from '../../test/controls/common'; -import { getWallet, MEDIA, testEnv } from '../../test/set-up'; +import { submitMilestoneFunc, wait } from '../../test/controls/common'; +import { MEDIA, getWallet, mockWalletReturnValue, testEnv } from '../../test/set-up'; import { requestFundsFromFaucet } from '../faucet'; export class Helper { - public spy: any = {} as any; public network = Network.RMS; public collection: string = {} as any; public guardian: string = {} as any; @@ -49,47 +41,45 @@ export class Helper { public nft: Nft = {} as any; public beforeAll = async () => { - this.spy = jest.spyOn(wallet, 'decodeAuth'); this.walletService = await getWallet(this.network); this.nftWallet = new NftWallet(this.walletService); }; public beforeEach = async (collectionType = CollectionType.CLASSIC) => { - this.guardian = await createMemberTest(this.spy); - this.member = await createMemberTest(this.spy); - this.space = await createSpace(this.spy, this.guardian); - this.royaltySpace = await createSpace(this.spy, this.guardian); + this.guardian = await testEnv.createMember(); + this.member = await testEnv.createMember(); + this.space = await testEnv.createSpace(this.guardian); + this.royaltySpace = await testEnv.createSpace(this.guardian); mockWalletReturnValue( - this.spy, this.guardian, this.createDummyCollection(this.space.uid, this.royaltySpace.uid, collectionType), ); - this.collection = (await testEnv.wrap(createCollection)({})).uid; + this.collection = (await testEnv.wrap(WEN_FUNC.createCollection)).uid; - await build5Db().doc(`${COL.COLLECTION}/${this.collection}`).update({ approved: true }); + await build5Db().doc(COL.COLLECTION, this.collection).update({ approved: true }); }; public mintCollection = async (expiresAt?: Timestamp) => { - mockWalletReturnValue(this.spy, this.guardian!, { + mockWalletReturnValue(this.guardian!, { collection: this.collection, network: this.network, unsoldMintingOptions: UnsoldMintingOptions.KEEP_PRICE, }); - const collectionMintOrder = await testEnv.wrap(mintCollection)({}); + const collectionMintOrder = await testEnv.wrap(WEN_FUNC.mintCollection); await requestFundsFromFaucet( this.network!, collectionMintOrder.payload.targetAddress, collectionMintOrder.payload.amount, expiresAt, ); - const collectionDocRef = build5Db().doc(`${COL.COLLECTION}/${this.collection}`); + const collectionDocRef = build5Db().doc(COL.COLLECTION, this.collection); await wait(async () => { const data = await collectionDocRef.get(); return data.status === CollectionStatus.MINTED; }); - const nftDocRef = build5Db().doc(`${COL.NFT}/${this.nft?.uid}`); + const nftDocRef = build5Db().doc(COL.NFT, this.nft?.uid); this.nft = await nftDocRef.get(); }; @@ -98,41 +88,41 @@ export class Helper { delete nft.uid; delete nft.status; delete nft.placeholderNft; - mockWalletReturnValue(this.spy, this.guardian!, nft); - nft = await testEnv.wrap(createNft)({}); + mockWalletReturnValue(this.guardian!, nft); + nft = await testEnv.wrap(WEN_FUNC.createNft); await build5Db() - .doc(`${COL.NFT}/${nft.uid}`) + .doc(COL.NFT, nft.uid) .update({ availableFrom: dayjs().subtract(1, 'h').toDate() }); if (shouldOrder) { - mockWalletReturnValue(this.spy, this.guardian!, { + mockWalletReturnValue(this.guardian!, { collection: this.collection, nft: nft.uid, }); - const order = await testEnv.wrap(orderNft)({}); + const order = await testEnv.wrap(WEN_FUNC.orderNft); await submitMilestoneFunc(order); } - this.nft = await build5Db().doc(`${COL.NFT}/${nft.uid}`).get(); + this.nft = await build5Db().doc(COL.NFT, nft.uid).get(); return this.nft; }; public setAvailableForAuction = async (nft?: string) => { const uid = nft || this.nft?.uid!; - mockWalletReturnValue(this.spy, this.guardian!, this.dummyAuctionData(uid)); - await testEnv.wrap(setForSaleNft)({}); + mockWalletReturnValue(this.guardian!, this.dummyAuctionData(uid)); + await testEnv.wrap(WEN_FUNC.setForSaleNft); await wait(async () => { - const docRef = build5Db().doc(`${COL.NFT}/${uid}`); + const docRef = build5Db().doc(COL.NFT, uid); this.nft = await docRef.get(); return this.nft.available === 3; }); }; public setAvailableForSale = async (nftId: string) => { - mockWalletReturnValue(this.spy, this.guardian!, this.dummySaleData(nftId)); - await testEnv.wrap(setForSaleNft)({}); + mockWalletReturnValue(this.guardian!, this.dummySaleData(nftId)); + await testEnv.wrap(WEN_FUNC.setForSaleNft); await wait(async () => { - const nft = await build5Db().doc(`${COL.NFT}/${nftId}`).get(); + const nft = await build5Db().doc(COL.NFT, nftId).get(); return nft?.available === 1; }); }; @@ -198,7 +188,7 @@ export class Helper { nftId, }, }; - await build5Db().doc(`${COL.TRANSACTION}/${order.uid}`).create(order); + await build5Db().doc(COL.TRANSACTION, order.uid).create(order); return order.uid; }; } diff --git a/packages/functions/test-tangle/nft-transfer/nft-transfer_1.spec.ts b/packages/functions/test-tangle/nft-transfer/nft-transfer_1.spec.ts index 2986de5cce..62860fc005 100644 --- a/packages/functions/test-tangle/nft-transfer/nft-transfer_1.spec.ts +++ b/packages/functions/test-tangle/nft-transfer/nft-transfer_1.spec.ts @@ -1,8 +1,6 @@ -import { build5Db } from '@build-5/database'; -import { COL, Nft, NftTransferRequest, Transaction, TransactionType } from '@build-5/interfaces'; -import { nftTransfer } from '../../src/runtime/firebase/nft'; -import { mockWalletReturnValue } from '../../test/controls/common'; -import { testEnv } from '../../test/set-up'; +import { PgTransactionType, build5Db } from '@build-5/database'; +import { COL, Nft, NftTransferRequest, WEN_FUNC } from '@build-5/interfaces'; +import { mockWalletReturnValue, testEnv } from '../../test/set-up'; import { Helper } from './Helper'; describe('Nft transfer', () => { @@ -28,23 +26,23 @@ describe('Nft transfer', () => { ], }; - mockWalletReturnValue(h.spy, h.guardian, request); - const response: { [key: string]: number } = await testEnv.wrap(nftTransfer)({}); + mockWalletReturnValue(h.guardian, request); + const response: { [key: string]: number } = await testEnv.wrap(WEN_FUNC.nftTransfer); expect(response[nft1.uid]).toBe(200); expect(response[nft2.uid]).toBe(200); const transfers = await build5Db() .collection(COL.TRANSACTION) .where('member', '==', h.guardian) - .where('type', '==', TransactionType.NFT_TRANSFER) - .get(); + .where('type', '==', PgTransactionType.NFT_TRANSFER) + .get(); expect(transfers.length).toBe(2); - const nft1DocRef = build5Db().doc(`${COL.NFT}/${nft1.uid}`); + const nft1DocRef = build5Db().doc(COL.NFT, nft1.uid); nft1 = await nft1DocRef.get(); expect(nft1.owner).toBe(h.member); - const nft2DocRef = build5Db().doc(`${COL.NFT}/${nft2.uid}`); + const nft2DocRef = build5Db().doc(COL.NFT, nft2.uid); nft2 = await nft2DocRef.get(); expect(nft2.owner).toBe(h.member); }); diff --git a/packages/functions/test-tangle/nft-transfer/nft-transfer_2.spec.ts b/packages/functions/test-tangle/nft-transfer/nft-transfer_2.spec.ts index 1a981d9cc9..b57c9e6733 100644 --- a/packages/functions/test-tangle/nft-transfer/nft-transfer_2.spec.ts +++ b/packages/functions/test-tangle/nft-transfer/nft-transfer_2.spec.ts @@ -1,7 +1,5 @@ -import { NftTransferRequest } from '@build-5/interfaces'; -import { nftTransfer } from '../../src/runtime/firebase/nft'; -import { mockWalletReturnValue } from '../../test/controls/common'; -import { testEnv } from '../../test/set-up'; +import { NftTransferRequest, WEN_FUNC } from '@build-5/interfaces'; +import { mockWalletReturnValue, testEnv } from '../../test/set-up'; import { Helper } from './Helper'; describe('Nft transfer', () => { @@ -29,8 +27,8 @@ describe('Nft transfer', () => { ], }; - mockWalletReturnValue(h.spy, h.guardian, request); - const response: { [key: string]: number } = await testEnv.wrap(nftTransfer)({}); + mockWalletReturnValue(h.guardian, request); + const response: { [key: string]: number } = await testEnv.wrap(WEN_FUNC.nftTransfer); expect(response[nft1.uid]).toBe(200); expect(response[nft2.uid]).toBe(2092); }); diff --git a/packages/functions/test-tangle/nft-transfer/nft-transfer_3.spec.ts b/packages/functions/test-tangle/nft-transfer/nft-transfer_3.spec.ts index a0c38dc8c3..a0720d633e 100644 --- a/packages/functions/test-tangle/nft-transfer/nft-transfer_3.spec.ts +++ b/packages/functions/test-tangle/nft-transfer/nft-transfer_3.spec.ts @@ -1,8 +1,6 @@ -import { build5Db } from '@build-5/database'; -import { COL, NftTransferRequest, Transaction, TransactionType } from '@build-5/interfaces'; -import { nftTransfer } from '../../src/runtime/firebase/nft'; -import { mockWalletReturnValue } from '../../test/controls/common'; -import { testEnv } from '../../test/set-up'; +import { PgTransactionType, build5Db } from '@build-5/database'; +import { COL, NftTransferRequest, WEN_FUNC } from '@build-5/interfaces'; +import { mockWalletReturnValue, testEnv } from '../../test/set-up'; import { Helper } from './Helper'; describe('Nft transfer', () => { @@ -28,16 +26,16 @@ describe('Nft transfer', () => { ], }; - mockWalletReturnValue(h.spy, h.member, request); - const response: { [key: string]: number } = await testEnv.wrap(nftTransfer)({}); + mockWalletReturnValue(h.member, request); + const response: { [key: string]: number } = await testEnv.wrap(WEN_FUNC.nftTransfer); expect(response[nft1.uid]).toBe(2066); expect(response[nft2.uid]).toBe(2066); const transfers = await build5Db() .collection(COL.TRANSACTION) .where('member', '==', h.member) - .where('type', '==', TransactionType.NFT_TRANSFER) - .get(); + .where('type', '==', PgTransactionType.NFT_TRANSFER) + .get(); expect(transfers.length).toBe(0); }); }); diff --git a/packages/functions/test-tangle/nft-transfer/nft-transfer_4.spec.ts b/packages/functions/test-tangle/nft-transfer/nft-transfer_4.spec.ts index 32e8788b88..2a47491e4d 100644 --- a/packages/functions/test-tangle/nft-transfer/nft-transfer_4.spec.ts +++ b/packages/functions/test-tangle/nft-transfer/nft-transfer_4.spec.ts @@ -1,13 +1,5 @@ -import { build5Db } from '@build-5/database'; -import { - COL, - MIN_IOTA_AMOUNT, - Member, - Network, - TangleRequestType, - Transaction, - TransactionType, -} from '@build-5/interfaces'; +import { PgTransactionType, build5Db } from '@build-5/database'; +import { COL, MIN_IOTA_AMOUNT, Network, TangleRequestType, Transaction } from '@build-5/interfaces'; import { getAddress } from '../../src/utils/address.utils'; import { wait } from '../../test/controls/common'; import { getTangleOrder } from '../common'; @@ -32,8 +24,8 @@ describe('Nft transfer', () => { const nft2 = await h.createAndOrderNft(); await h.mintCollection(); - const guardianDocRef = build5Db().doc(`${COL.MEMBER}/${h.guardian}`); - const guardian = await guardianDocRef.get(); + const guardianDocRef = build5Db().doc(COL.MEMBER, h.guardian); + const guardian = await guardianDocRef.get(); const bech32 = getAddress(guardian, Network.RMS); const address = await h.walletService.getAddressDetails(bech32); @@ -54,12 +46,12 @@ describe('Nft transfer', () => { const query = build5Db() .collection(COL.TRANSACTION) .where('member', '==', h.guardian) - .where('type', '==', TransactionType.CREDIT_TANGLE_REQUEST); + .where('type', '==', PgTransactionType.CREDIT_TANGLE_REQUEST); await wait(async () => { - const snap = await query.get(); + const snap = await query.get(); return snap.length === 1; }); - const credit = (await query.get())[0]; + const credit = (await query.get())[0]; expect(credit.payload.response![nft1.uid]).toBe(200); expect(credit.payload.response![nft2.uid]).toBe(200); }); diff --git a/packages/functions/test-tangle/nft-transfer/nft-transfer_5.spec.ts b/packages/functions/test-tangle/nft-transfer/nft-transfer_5.spec.ts index 0dd3c0de91..65261ab728 100644 --- a/packages/functions/test-tangle/nft-transfer/nft-transfer_5.spec.ts +++ b/packages/functions/test-tangle/nft-transfer/nft-transfer_5.spec.ts @@ -1,13 +1,5 @@ -import { build5Db } from '@build-5/database'; -import { - COL, - MIN_IOTA_AMOUNT, - Member, - Network, - TangleRequestType, - Transaction, - TransactionType, -} from '@build-5/interfaces'; +import { PgTransactionType, build5Db } from '@build-5/database'; +import { COL, MIN_IOTA_AMOUNT, Network, TangleRequestType, Transaction } from '@build-5/interfaces'; import { getAddress } from '../../src/utils/address.utils'; import { wait } from '../../test/controls/common'; import { getTangleOrder } from '../common'; @@ -34,8 +26,8 @@ describe('Nft transfer', () => { const targetAddress = await h.walletService.getNewIotaAddressDetails(); - const guardianDocRef = build5Db().doc(`${COL.MEMBER}/${h.guardian}`); - const guardian = await guardianDocRef.get(); + const guardianDocRef = build5Db().doc(COL.MEMBER, h.guardian); + const guardian = await guardianDocRef.get(); const bech32 = getAddress(guardian, Network.RMS); const address = await h.walletService.getAddressDetails(bech32); @@ -56,21 +48,21 @@ describe('Nft transfer', () => { let query = build5Db() .collection(COL.TRANSACTION) .where('member', '==', h.guardian) - .where('type', '==', TransactionType.CREDIT_TANGLE_REQUEST); + .where('type', '==', PgTransactionType.CREDIT_TANGLE_REQUEST); await wait(async () => { - const snap = await query.get(); + const snap = await query.get(); return snap.length === 1; }); - const credit = (await query.get())[0]; + const credit = (await query.get())[0]; expect(credit.payload.response![nft1.uid]).toBe(200); expect(credit.payload.response![nft2.uid]).toBe(200); query = build5Db() .collection(COL.TRANSACTION) .where('member', '==', h.guardian) - .where('type', '==', TransactionType.WITHDRAW_NFT); + .where('type', '==', PgTransactionType.WITHDRAW_NFT); await wait(async () => { - const withdraws = await query.get(); + const withdraws = await query.get(); return ( withdraws.length === 2 && withdraws[0].payload.walletReference?.confirmed && diff --git a/packages/functions/test-tangle/nft-transfer/nft-transfer_6.spec.ts b/packages/functions/test-tangle/nft-transfer/nft-transfer_6.spec.ts index 711910d51c..4078b48c87 100644 --- a/packages/functions/test-tangle/nft-transfer/nft-transfer_6.spec.ts +++ b/packages/functions/test-tangle/nft-transfer/nft-transfer_6.spec.ts @@ -1,9 +1,7 @@ -import { build5Db } from '@build-5/database'; -import { COL, NftTransferRequest, Transaction, TransactionType } from '@build-5/interfaces'; -import { nftTransfer } from '../../src/runtime/firebase/nft'; +import { PgTransactionType, build5Db } from '@build-5/database'; +import { COL, NftTransferRequest, WEN_FUNC } from '@build-5/interfaces'; import { getRandomEthAddress } from '../../src/utils/wallet.utils'; -import { mockWalletReturnValue } from '../../test/controls/common'; -import { testEnv } from '../../test/set-up'; +import { mockWalletReturnValue, testEnv } from '../../test/set-up'; import { Helper } from './Helper'; describe('Nft transfer', () => { @@ -29,16 +27,16 @@ describe('Nft transfer', () => { ], }; - mockWalletReturnValue(h.spy, h.guardian, request); - const response: { [key: string]: number } = await testEnv.wrap(nftTransfer)({}); + mockWalletReturnValue(h.guardian, request); + const response: { [key: string]: number } = await testEnv.wrap(WEN_FUNC.nftTransfer); expect(response[nft1.uid]).toBe(200); expect(response[nft2.uid]).toBe(2141); const transfers = await build5Db() .collection(COL.TRANSACTION) .where('member', '==', h.guardian) - .where('type', '==', TransactionType.NFT_TRANSFER) - .get(); + .where('type', '==', PgTransactionType.NFT_TRANSFER) + .get(); expect(transfers.length).toBe(1); }); }); diff --git a/packages/functions/test-tangle/nft-transfer/nft-transfer_7.spec.ts b/packages/functions/test-tangle/nft-transfer/nft-transfer_7.spec.ts index 858339b32f..dbcec2e3a1 100644 --- a/packages/functions/test-tangle/nft-transfer/nft-transfer_7.spec.ts +++ b/packages/functions/test-tangle/nft-transfer/nft-transfer_7.spec.ts @@ -1,8 +1,6 @@ -import { build5Db } from '@build-5/database'; -import { COL, Nft, NftTransferRequest, Transaction, TransactionType } from '@build-5/interfaces'; -import { nftTransfer } from '../../src/runtime/firebase/nft'; -import { mockWalletReturnValue } from '../../test/controls/common'; -import { testEnv } from '../../test/set-up'; +import { PgTransactionType, build5Db } from '@build-5/database'; +import { COL, Nft, NftTransferRequest, WEN_FUNC } from '@build-5/interfaces'; +import { mockWalletReturnValue, testEnv } from '../../test/set-up'; import { Helper } from './Helper'; describe('Nft transfer', () => { @@ -28,27 +26,27 @@ describe('Nft transfer', () => { ], }; - mockWalletReturnValue(h.spy, h.guardian, request); - const response: { [key: string]: number } = await testEnv.wrap(nftTransfer)({}); + mockWalletReturnValue(h.guardian, request); + const response: { [key: string]: number } = await testEnv.wrap(WEN_FUNC.nftTransfer); expect(response[nft1.uid]).toBe(200); expect(response[nft2.uid]).toBe(200); const transfers = await build5Db() .collection(COL.TRANSACTION) .where('member', '==', h.guardian) - .where('type', '==', TransactionType.NFT_TRANSFER) - .get(); + .where('type', '==', PgTransactionType.NFT_TRANSFER) + .get(); expect(transfers.length).toBe(1); - const nft2DocRef = build5Db().doc(`${COL.NFT}/${nft2.uid}`); + const nft2DocRef = build5Db().doc(COL.NFT, nft2.uid); nft2 = await nft2DocRef.get(); expect(nft2.owner).toBe(h.member); const withdraws = await build5Db() .collection(COL.TRANSACTION) .where('member', '==', h.guardian) - .where('type', '==', TransactionType.WITHDRAW_NFT) - .get(); + .where('type', '==', PgTransactionType.WITHDRAW_NFT) + .get(); expect(withdraws.length).toBe(1); }); }); diff --git a/packages/functions/test-tangle/nft-transfer/nft-transfer_8.spec.ts b/packages/functions/test-tangle/nft-transfer/nft-transfer_8.spec.ts index 7891260af2..b964713166 100644 --- a/packages/functions/test-tangle/nft-transfer/nft-transfer_8.spec.ts +++ b/packages/functions/test-tangle/nft-transfer/nft-transfer_8.spec.ts @@ -1,8 +1,6 @@ -import { build5Db } from '@build-5/database'; -import { COL, Nft, NftTransferRequest, Transaction, TransactionType } from '@build-5/interfaces'; -import { nftTransfer } from '../../src/runtime/firebase/nft'; -import { mockWalletReturnValue } from '../../test/controls/common'; -import { testEnv } from '../../test/set-up'; +import { PgTransactionType, build5Db } from '@build-5/database'; +import { COL, Nft, NftTransferRequest, WEN_FUNC } from '@build-5/interfaces'; +import { mockWalletReturnValue, testEnv } from '../../test/set-up'; import { Helper } from './Helper'; describe('Nft transfer', () => { @@ -21,8 +19,8 @@ describe('Nft transfer', () => { let nft2 = await h.createAndOrderNft(); await h.mintCollection(); - const memberDocRef = build5Db().doc(`${COL.MEMBER}/${h.member}`); - await memberDocRef.update({ validatedAddress: {} }); + const memberDocRef = build5Db().doc(COL.MEMBER, h.member); + await memberDocRef.update({ rmsAddress: '', smrAddress: '', iotaAddress: '', atoiAddress: '' }); const request: NftTransferRequest = { transfers: [ @@ -31,23 +29,23 @@ describe('Nft transfer', () => { ], }; - mockWalletReturnValue(h.spy, h.guardian, request); - const response: { [key: string]: number } = await testEnv.wrap(nftTransfer)({}); + mockWalletReturnValue(h.guardian, request); + const response: { [key: string]: number } = await testEnv.wrap(WEN_FUNC.nftTransfer); expect(response[nft1.uid]).toBe(200); expect(response[nft2.uid]).toBe(200); const transfers = await build5Db() .collection(COL.TRANSACTION) .where('member', '==', h.guardian) - .where('type', '==', TransactionType.NFT_TRANSFER) - .get(); + .where('type', '==', PgTransactionType.NFT_TRANSFER) + .get(); expect(transfers.length).toBe(2); - const nft1DocRef = build5Db().doc(`${COL.NFT}/${nft1.uid}`); + const nft1DocRef = build5Db().doc(COL.NFT, nft1.uid); nft1 = await nft1DocRef.get(); expect(nft1.owner).toBe(h.member); - const nft2DocRef = build5Db().doc(`${COL.NFT}/${nft2.uid}`); + const nft2DocRef = build5Db().doc(COL.NFT, nft2.uid); nft2 = await nft2DocRef.get(); expect(nft2.owner).toBe(h.member); }); diff --git a/packages/functions/test-tangle/proposal-tangle/Helper.ts b/packages/functions/test-tangle/proposal-tangle/Helper.ts index e9f518d18b..51f1b45f84 100644 --- a/packages/functions/test-tangle/proposal-tangle/Helper.ts +++ b/packages/functions/test-tangle/proposal-tangle/Helper.ts @@ -1,4 +1,4 @@ -import { build5Db, IQuery } from '@build-5/database'; +import { build5Db, IQuery, PgTransactionType } from '@build-5/database'; import { COL, Member, @@ -9,11 +9,12 @@ import { ProposalType, SOON_PROJECT_ID, Space, + Stake, SUB_COL, TangleRequestType, + Token, TokenStatus, Transaction, - TransactionType, } from '@build-5/interfaces'; import dayjs from 'dayjs'; import { MnemonicService } from '../../src/services/wallet/mnemonic'; @@ -22,22 +23,21 @@ import { AddressDetails } from '../../src/services/wallet/wallet.service'; import { getAddress } from '../../src/utils/address.utils'; import { dateToTimestamp } from '../../src/utils/dateTime.utils'; import * as wallet from '../../src/utils/wallet.utils'; -import { createMember, createSpace, wait } from '../../test/controls/common'; -import { getWallet } from '../../test/set-up'; +import { wait } from '../../test/controls/common'; +import { getWallet, testEnv } from '../../test/set-up'; import { getTangleOrder } from '../common'; import { requestFundsFromFaucet, requestMintedTokenFromFaucet } from '../faucet'; export class Helper { constructor(public readonly type = ProposalType.NATIVE) {} - public walletSpy: any = {} as any; public guardian: string = ''; public space: Space = {} as any; public guardianAddress: AddressDetails = {} as any; public walletService: Wallet = {} as any; public tangleOrder: Transaction = {} as any; public network = Network.RMS; - public guardianCreditQuery: IQuery = {} as any; + public guardianCreditQuery: IQuery = {} as any; public tokenId = ''; public proposalUid = ''; @@ -47,18 +47,17 @@ export class Helper { }; public beforeEach = async () => { - this.walletSpy = jest.spyOn(wallet, 'decodeAuth'); - this.guardian = await createMember(this.walletSpy); - const guardianDocRef = build5Db().doc(`${COL.MEMBER}/${this.guardian}`); + this.guardian = await testEnv.createMember(); + const guardianDocRef = build5Db().doc(COL.MEMBER, this.guardian); const guardianData = await guardianDocRef.get(); const guardianBech32 = getAddress(guardianData, this.network); this.guardianAddress = await this.walletService.getAddressDetails(guardianBech32); - this.space = await createSpace(this.walletSpy, this.guardian); + this.space = await testEnv.createSpace(this.guardian); this.tokenId = wallet.getRandomEthAddress(); await build5Db() - .doc(`${COL.TOKEN}/${this.tokenId}`) + .doc(COL.TOKEN, this.tokenId) .create({ project: SOON_PROJECT_ID, uid: this.tokenId, @@ -66,18 +65,19 @@ export class Helper { status: TokenStatus.MINTED, mintingData: { tokenId: MINTED_TOKEN_ID }, approved: true, - }); + } as Token); - const distributionDocRef = build5Db() - .collection(COL.TOKEN) - .doc(this.tokenId) - .collection(SUB_COL.DISTRIBUTION) - .doc(this.guardian); - await distributionDocRef.create({}); + const distributionDocRef = build5Db().doc( + COL.TOKEN, + this.tokenId, + SUB_COL.DISTRIBUTION, + this.guardian, + ); + await distributionDocRef.create({ parentId: this.tokenId, parentCol: COL.TOKEN }); this.guardianCreditQuery = build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.CREDIT_TANGLE_REQUEST) + .where('type', '==', PgTransactionType.CREDIT_TANGLE_REQUEST) .where('member', '==', this.guardian); await requestFundsFromFaucet(Network.RMS, this.guardianAddress.bech32, 5 * MIN_IOTA_AMOUNT); @@ -135,13 +135,13 @@ export class Helper { uid: wallet.getRandomEthAddress(), token: this.tokenId, expirationProcessed: false, - }; - const docRef = build5Db().doc(`${COL.STAKE}/${stake.uid}`); + } as Stake; + const docRef = build5Db().doc(COL.STAKE, stake.uid); await docRef.create(stake); }; public assertProposalWeights = async (total: number, voted: number) => { - const proposalDocRef = build5Db().doc(`${COL.PROPOSAL}/${this.proposalUid}`); + const proposalDocRef = build5Db().doc(COL.PROPOSAL, this.proposalUid); const proposal = await proposalDocRef.get(); expect(+proposal.results?.total.toFixed(0)).toBe(total); expect(+proposal.results?.voted.toFixed(0)).toBe(voted); @@ -152,35 +152,30 @@ export class Helper { weight: number, answer: number, ) => { - const proposalDocRef = build5Db().doc(`${COL.PROPOSAL}/${this.proposalUid}`); - const proposalMemberDocRef = proposalDocRef.collection(SUB_COL.MEMBERS).doc(member); + const proposalMemberDocRef = build5Db().doc( + COL.PROPOSAL, + this.proposalUid, + SUB_COL.MEMBERS, + member, + ); const proposalMember = await proposalMemberDocRef.get(); expect(+proposalMember.weightPerAnswer![answer].toFixed(0)).toBe(weight); }; public updatePropoasalDates = (startDate: dayjs.Dayjs, endDate: dayjs.Dayjs) => - build5Db() - .doc(`${COL.PROPOSAL}/${this.proposalUid}`) - .set( - { - settings: { - startDate: dateToTimestamp(startDate), - endDate: dateToTimestamp(endDate), - }, - }, - true, - ); + build5Db().doc(COL.PROPOSAL, this.proposalUid).upsert({ + settings_startDate: startDate.toDate(), + settings_endDate: endDate.toDate(), + }); public updateVoteTranCreatedOn = (voteTransactionId: string, createdOn: dayjs.Dayjs) => - build5Db() - .doc(`${COL.TRANSACTION}/${voteTransactionId}`) - .update({ createdOn: dateToTimestamp(createdOn) }); + build5Db().doc(COL.TRANSACTION, voteTransactionId).update({ createdOn: createdOn.toDate() }); public getVoteTransactionForCredit = async (creditId: string) => { const query = build5Db() .collection(COL.TRANSACTION) - .where('payload.creditId', '==', creditId) - .where('type', '==', TransactionType.VOTE); + .where('payload_creditId', '==', creditId) + .where('type', '==', PgTransactionType.VOTE); const voteTranSnap = await query.get(); return voteTranSnap[0] as Transaction; }; diff --git a/packages/functions/test-tangle/proposal-tangle/proposal.approval.spec.ts b/packages/functions/test-tangle/proposal-tangle/proposal.approval.spec.ts index 3ec213b28e..99eb6ae0c8 100644 --- a/packages/functions/test-tangle/proposal-tangle/proposal.approval.spec.ts +++ b/packages/functions/test-tangle/proposal-tangle/proposal.approval.spec.ts @@ -41,7 +41,7 @@ describe('Proposal approval via tangle request', () => { return snap.length === 2; }); - const proposalDocRef = build5Db().doc(`${COL.PROPOSAL}/${proposalUid}`); + const proposalDocRef = build5Db().doc(COL.PROPOSAL, proposalUid); const proposal = await proposalDocRef.get(); expect(approve ? proposal.approved : proposal.rejected).toBe(true); diff --git a/packages/functions/test-tangle/proposal-tangle/proposal.simple.vote.spec.ts b/packages/functions/test-tangle/proposal-tangle/proposal.simple.vote.spec.ts index 04208da99c..522a2c1232 100644 --- a/packages/functions/test-tangle/proposal-tangle/proposal.simple.vote.spec.ts +++ b/packages/functions/test-tangle/proposal-tangle/proposal.simple.vote.spec.ts @@ -5,11 +5,11 @@ import { Proposal, ProposalType, TangleRequestType, + WEN_FUNC, } from '@build-5/interfaces'; -import { approveProposal } from '../../src/runtime/firebase/proposal'; import { MnemonicService } from '../../src/services/wallet/mnemonic'; -import { mockWalletReturnValue, wait } from '../../test/controls/common'; -import { testEnv } from '../../test/set-up'; +import { wait } from '../../test/controls/common'; +import { mockWalletReturnValue, testEnv } from '../../test/set-up'; import { Helper } from './Helper'; describe('Create proposal via tangle request', () => { @@ -26,8 +26,8 @@ describe('Create proposal via tangle request', () => { it('Should create proposal and vote', async () => { const proposalUid = await helper.sendCreateProposalRequest(); - mockWalletReturnValue(helper.walletSpy, helper.guardian, { uid: proposalUid }); - await testEnv.wrap(approveProposal)({}); + mockWalletReturnValue(helper.guardian, { uid: proposalUid }); + await testEnv.wrap(WEN_FUNC.approveProposal); await helper.walletService.send( helper.guardianAddress, @@ -49,7 +49,7 @@ describe('Create proposal via tangle request', () => { return snap.length === 2; }); - let proposalDocRef = build5Db().doc(`${COL.PROPOSAL}/${proposalUid}`); + let proposalDocRef = build5Db().doc(COL.PROPOSAL, proposalUid); let proposal = await proposalDocRef.get(); expect(proposal.results.answers[1]).toBe(1); @@ -73,7 +73,7 @@ describe('Create proposal via tangle request', () => { return snap.length === 3; }); - proposalDocRef = build5Db().doc(`${COL.PROPOSAL}/${proposalUid}`); + proposalDocRef = build5Db().doc(COL.PROPOSAL, proposalUid); proposal = await proposalDocRef.get(); expect(proposal.results.answers[2]).toBe(1); expect(proposal.results.answers[1]).toBe(0); diff --git a/packages/functions/test-tangle/proposal-tangle/proposal.stake.voting.spec.ts b/packages/functions/test-tangle/proposal-tangle/proposal.stake.voting.spec.ts index e193fff0ea..161c1029b7 100644 --- a/packages/functions/test-tangle/proposal-tangle/proposal.stake.voting.spec.ts +++ b/packages/functions/test-tangle/proposal-tangle/proposal.stake.voting.spec.ts @@ -1,10 +1,15 @@ import { build5Db } from '@build-5/database'; -import { COL, MIN_IOTA_AMOUNT, TangleRequestType, Transaction } from '@build-5/interfaces'; +import { + COL, + MIN_IOTA_AMOUNT, + TangleRequestType, + Transaction, + WEN_FUNC, +} from '@build-5/interfaces'; import dayjs from 'dayjs'; import { isEmpty } from 'lodash'; -import { approveProposal } from '../../src/runtime/firebase/proposal'; -import { mockWalletReturnValue, wait } from '../../test/controls/common'; -import { testEnv } from '../../test/set-up'; +import { wait } from '../../test/controls/common'; +import { mockWalletReturnValue, testEnv } from '../../test/set-up'; import { Helper } from './Helper'; describe('Create proposal via tangle request', () => { @@ -20,8 +25,8 @@ describe('Create proposal via tangle request', () => { proposalUid = await helper.sendCreateProposalRequest(); - mockWalletReturnValue(helper.walletSpy, helper.guardian, { uid: proposalUid }); - await testEnv.wrap(approveProposal)({}); + mockWalletReturnValue(helper.guardian, { uid: proposalUid }); + await testEnv.wrap(WEN_FUNC.approveProposal); }); it('Should create proposal and vote with staked tokens', async () => { @@ -49,12 +54,13 @@ describe('Create proposal via tangle request', () => { return snap.length === 2; }); - const snap = await helper.guardianCreditQuery.get(); + const snap = await helper.guardianCreditQuery.get(); const credit = snap.find((c) => !isEmpty(c?.payload?.response?.voteTransaction))!; expect(credit.payload.amount).toBe(MIN_IOTA_AMOUNT); const voteTransactionDocRef = build5Db().doc( - `${COL.TRANSACTION}/${credit.payload.response!.voteTransaction}`, + COL.TRANSACTION, + credit.payload.response!.voteTransaction, ); const voteTransaction = await voteTransactionDocRef.get(); expect(+voteTransaction.payload.weight!.toFixed(0)).toBe(150); diff --git a/packages/functions/test-tangle/proposal-tangle/proposal.token.voting.spec.ts b/packages/functions/test-tangle/proposal-tangle/proposal.token.voting.spec.ts index 67ea1458e7..cb8a924e02 100644 --- a/packages/functions/test-tangle/proposal-tangle/proposal.token.voting.spec.ts +++ b/packages/functions/test-tangle/proposal-tangle/proposal.token.voting.spec.ts @@ -1,16 +1,9 @@ -import { build5Db } from '@build-5/database'; -import { - COL, - MIN_IOTA_AMOUNT, - TangleRequestType, - Transaction, - TransactionType, -} from '@build-5/interfaces'; +import { PgTransactionType, build5Db } from '@build-5/database'; +import { COL, MIN_IOTA_AMOUNT, TangleRequestType, WEN_FUNC } from '@build-5/interfaces'; import dayjs from 'dayjs'; -import { approveProposal } from '../../src/runtime/firebase/proposal'; import { MnemonicService } from '../../src/services/wallet/mnemonic'; -import { mockWalletReturnValue, wait } from '../../test/controls/common'; -import { testEnv } from '../../test/set-up'; +import { wait } from '../../test/controls/common'; +import { mockWalletReturnValue, testEnv } from '../../test/set-up'; import { Helper, MINTED_TOKEN_ID } from './Helper'; describe('Create proposal via tangle request', () => { @@ -27,8 +20,8 @@ describe('Create proposal via tangle request', () => { proposalUid = await helper.sendCreateProposalRequest(); - mockWalletReturnValue(helper.walletSpy, helper.guardian, { uid: proposalUid }); - await testEnv.wrap(approveProposal)({}); + mockWalletReturnValue(helper.guardian, { uid: proposalUid }); + await testEnv.wrap(WEN_FUNC.approveProposal); }); it('Should vote full, then 50%', async () => { @@ -51,30 +44,24 @@ describe('Create proposal via tangle request', () => { const orderQuery = build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.VOTE) + .where('type', '==', PgTransactionType.VOTE) .where('member', '==', helper.guardian); - console.log('asd', 1); await wait(async () => { const snap = await orderQuery.get(); return snap.length === 1; }); - console.log('asd', 2); - const snap = await orderQuery.get(); + const snap = await orderQuery.get(); const voteTransaction = snap[0]; - console.log('asd', helper.guardianAddress.bech32); await wait(async () => { const { amount } = await helper.walletService.getBalance(helper.guardianAddress.bech32); - console.log(amount); return amount === 6 * MIN_IOTA_AMOUNT; }); - console.log('asd', 4); await helper.assertProposalWeights(10, 10); await helper.assertProposalMemberWeightsPerAnser(helper.guardian, 10, 1); - console.log('asd', 5); await helper.updatePropoasalDates(dayjs().subtract(2, 'd'), dayjs().add(2, 'd')); await helper.updateVoteTranCreatedOn(voteTransaction.uid, dayjs().subtract(3, 'd')); }); diff --git a/packages/functions/test-tangle/soon.snapshot.only.spec.ts b/packages/functions/test-tangle/soon.snapshot.only.spec.ts deleted file mode 100644 index 67e1df265a..0000000000 --- a/packages/functions/test-tangle/soon.snapshot.only.spec.ts +++ /dev/null @@ -1,585 +0,0 @@ -import { build5App, build5Db } from '@build-5/database'; -import { - COL, - MIN_IOTA_AMOUNT, - Network, - SOON_PROJECT_ID, - SUB_COL, - SoonSnap, - TangleRequestType, - Token, - TokenDrop, - TokenDropStatus, - TokenStatus, - Transaction, - TransactionType, - getMilestoneCol, -} from '@build-5/interfaces'; -import { - AddressUnlockCondition, - AliasOutputBuilderParams, - Ed25519Address, - GovernorAddressUnlockCondition, - IssuerFeature, - NftOutputBuilderParams, - ReferenceUnlock, - StateControllerAddressUnlockCondition, - UTXOInput, - Unlock, - Utils, -} from '@iota/sdk'; -import dayjs from 'dayjs'; -import admin from 'firebase-admin'; -import { cloneDeep } from 'lodash'; -import { soonSnapshot } from '../scripts/dbUpgrades/2.1/soon.snapshot'; -import { airdropMintedToken } from '../src/runtime/firebase/token/minting'; -import { MnemonicService } from '../src/services/wallet/mnemonic'; -import { Wallet } from '../src/services/wallet/wallet'; -import { AddressDetails } from '../src/services/wallet/wallet.service'; -import { mergeOutputs } from '../src/utils/basic-output.utils'; -import { createUnlock, packEssence, submitBlock } from '../src/utils/block.utils'; -import { EMPTY_NFT_ID } from '../src/utils/collection-minting-utils/nft.utils'; -import { dateToTimestamp } from '../src/utils/dateTime.utils'; -import { EMPTY_ALIAS_ID } from '../src/utils/token-minting-utils/alias.utils'; -import * as walletUtils from '../src/utils/wallet.utils'; -import { - createMember, - createSpace, - getRandomSymbol, - mockWalletReturnValue, - wait, -} from '../test/controls/common'; -import { getWallet, testEnv } from '../test/set-up'; -import { awaitTransactionConfirmationsForToken, getTangleOrder } from './common'; -import { requestFundsFromFaucet, requestMintedTokenFromFaucet } from './faucet'; - -const tokenId = '0x08e232e6541a81d2b2c0df252e90d8ba4e6fc6680f668fc266b1e43fc3cc01f4830100000000'; -const vaultAddress = 'rms1qpukey66jkfnpvyf968ewld9df5ymfudaw7hfrry4ad3jgaxg7kp2qsz5uv'; -const vaultMnemonic = - 'slender bag negative song swallow can inform used grocery old camp scatter develop surface lock clutch year hat oyster crack obvious first member dog'; - -describe('Soon snapshot test', () => { - const network = Network.RMS; - let guardian: string; - let wallet: Wallet; - let address: AddressDetails; - let targetAddress: AddressDetails; - let currentSoonTotal: number; - let walletSpy: any; - let token: Token; - let tangleOrder: Transaction; - - beforeAll(async () => { - wallet = await getWallet(network); - tangleOrder = await getTangleOrder(Network.RMS); - }); - - beforeEach(async () => { - walletSpy = jest.spyOn(walletUtils, 'decodeAuth'); - - address = await wallet.getNewIotaAddressDetails(); - targetAddress = await wallet.getNewIotaAddressDetails(); - - guardian = await createMember(walletSpy); - await build5Db() - .doc(`${COL.MEMBER}/${guardian}`) - .update({ [`validatedAddress.${network}`]: address.bech32 }); - const space = await createSpace(walletSpy, guardian); - - const db = (build5App.getInstance() as admin.app.App).firestore(); - let snap = await db.collectionGroup(SUB_COL.TRANSACTIONS).get(); - await Promise.all(snap.docs.map((d) => d.ref.delete())); - snap = await db.collection(getMilestoneCol(network)).get(); - await Promise.all(snap.docs.map((d) => d.ref.delete())); - - currentSoonTotal = (await wallet.getBalance(vaultAddress)).nativeTokens[tokenId]; - currentSoonTotal -= 100; - - await requestFundsFromFaucet(network, address.bech32, 5 * MIN_IOTA_AMOUNT); - - const blockId = await requestMintedTokenFromFaucet( - wallet, - address, - tokenId, - vaultMnemonic, - 100, - ); - await blockInDd(blockId); - - token = { - project: SOON_PROJECT_ID, - createdBy: guardian, - symbol: getRandomSymbol(), - uid: tokenId, - space: space.uid, - status: TokenStatus.MINTED, - mintingData: { - tokenId, - network, - }, - approved: true, - } as Token; - await build5Db().doc(`${COL.TOKEN}/${tokenId}`).set(token); - }); - - it('Should get 100 token from vault and claim it', async () => { - const tokensPerMember = await soonSnapshot(build5App, tokenId, network); - expect(tokensPerMember[vaultAddress]).toBe(currentSoonTotal); - expect(tokensPerMember[address.bech32]).toBe(100); - - let snapshot = await build5Db().doc(`${COL.SOON_SNAP}/${vaultAddress}`).get(); - expect(snapshot?.uid).toBe(vaultAddress); - expect(snapshot?.count).toBe(currentSoonTotal); - expect(snapshot?.paidOut).toBe(0); - expect(snapshot?.ethAddress).toBe(''); - expect(snapshot?.ethAddressVerified).toBe(false); - - snapshot = await build5Db().doc(`${COL.SOON_SNAP}/${address.bech32}`).get(); - expect(snapshot?.uid).toBe(address.bech32); - expect(snapshot?.count).toBe(100); - expect(snapshot?.paidOut).toBe(0); - expect(snapshot?.ethAddress).toBe(''); - expect(snapshot?.ethAddressVerified).toBe(false); - - const ethAddress = '0x69252ebdc3b77624c6e640a81a086aaa720734d3'; - await wallet.send(address, tangleOrder.payload.targetAddress!, MIN_IOTA_AMOUNT, { - customMetadata: { - request: { requestType: TangleRequestType.VERIFY_ETH_ADDRESS, ethAddress }, - }, - }); - await MnemonicService.store(address.bech32, address.mnemonic); - - const creditQuery = build5Db() - .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.CREDIT_TANGLE_REQUEST) - .where('member', '==', guardian); - await wait(async () => { - const snap = await creditQuery.get(); - return snap.length === 1 && snap[0].payload.walletReference?.confirmed; - }); - - const docRef = build5Db().doc(`${COL.SOON_SNAP}/${address.bech32}`); - snapshot = await docRef.get(); - expect(snapshot?.uid).toBe(address.bech32); - expect(snapshot?.count).toBe(100); - expect(snapshot?.paidOut).toBe(0); - expect(snapshot?.ethAddress).toBe(ethAddress); - expect(snapshot?.ethAddressVerified).toBe(true); - await docRef.update({ paidOut: snapshot!.count }); - - await wallet.send(address, tangleOrder.payload.targetAddress!, MIN_IOTA_AMOUNT, { - customMetadata: { - request: { requestType: TangleRequestType.VERIFY_ETH_ADDRESS, ethAddress }, - }, - }); - - await wait(async () => { - const snap = await creditQuery.get(); - return snap.length === 2; - }); - - snapshot = await docRef.get(); - expect(snapshot?.uid).toBe(address.bech32); - expect(snapshot?.count).toBe(100); - expect(snapshot?.paidOut).toBe(100); - expect(snapshot?.ethAddress).toBe(ethAddress); - expect(snapshot?.ethAddressVerified).toBe(true); - }); - - it('Should get 100 token from vault, can not claim, not following', async () => { - const tokensPerMember = await soonSnapshot(build5App, tokenId, network); - expect(tokensPerMember[vaultAddress]).toBe(currentSoonTotal); - expect(tokensPerMember[address.bech32]).toBe(100); - - let snapshot = await build5Db().doc(`${COL.SOON_SNAP}/${vaultAddress}`).get(); - expect(snapshot?.uid).toBe(vaultAddress); - expect(snapshot?.count).toBe(currentSoonTotal); - expect(snapshot?.paidOut).toBe(0); - expect(snapshot?.ethAddress).toBe(''); - expect(snapshot?.ethAddressVerified).toBe(false); - - snapshot = await build5Db().doc(`${COL.SOON_SNAP}/${address.bech32}`).get(); - expect(snapshot?.uid).toBe(address.bech32); - expect(snapshot?.count).toBe(100); - expect(snapshot?.paidOut).toBe(0); - expect(snapshot?.ethAddress).toBe(''); - expect(snapshot?.ethAddressVerified).toBe(false); - - const ethAddress = walletUtils.getRandomEthAddress(); - await wallet.send(address, tangleOrder.payload.targetAddress!, MIN_IOTA_AMOUNT, { - customMetadata: { - request: { requestType: TangleRequestType.VERIFY_ETH_ADDRESS, ethAddress }, - }, - }); - - const creditQuery = build5Db() - .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.CREDIT_TANGLE_REQUEST) - .where('member', '==', guardian); - await wait(async () => { - const snap = await creditQuery.get(); - return snap.length === 1 && snap[0].payload.walletReference?.confirmed; - }); - const credit = (await creditQuery.get())[0]; - expect(credit.payload.response?.message).toBe('Must follow JustBuild'); - - const docRef = build5Db().doc(`${COL.SOON_SNAP}/${address.bech32}`); - snapshot = await docRef.get(); - expect(snapshot?.uid).toBe(address.bech32); - expect(snapshot?.count).toBe(100); - expect(snapshot?.paidOut).toBe(0); - expect(snapshot?.ethAddress).toBe(''); - expect(snapshot?.ethAddressVerified).toBe(false); - }); - - it('Should send 50 to random user, keep 50', async () => { - const blockId = await wallet.send(address, targetAddress.bech32, MIN_IOTA_AMOUNT / 2, { - nativeTokens: [{ id: tokenId, amount: BigInt(50) }], - }); - await blockInDd(blockId); - - const tokensPerMember = await soonSnapshot(build5App, tokenId, network); - expect(tokensPerMember[vaultAddress]).toBe(currentSoonTotal); - expect(tokensPerMember[address.bech32]).toBe(50); - expect(tokensPerMember[targetAddress.bech32]).toBe(50); - - await requestFundsFromFaucet(network, targetAddress.bech32, MIN_IOTA_AMOUNT); - const ethAddress = '0x69252ebdc3b77624c6e640a81a086aaa720734d3'; - await wallet.send(targetAddress, tangleOrder.payload.targetAddress!, MIN_IOTA_AMOUNT, { - customMetadata: { - request: { requestType: TangleRequestType.VERIFY_ETH_ADDRESS, ethAddress }, - }, - }); - const creditQuery = build5Db() - .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.CREDIT_TANGLE_REQUEST) - .where('member', '==', targetAddress.bech32); - await wait(async () => { - const snap = await creditQuery.get(); - return snap.length === 1 && snap[0].payload.walletReference?.confirmed; - }); - - const snapshot = await build5Db() - .doc(`${COL.SOON_SNAP}/${targetAddress.bech32}`) - .get(); - expect(snapshot?.uid).toBe(targetAddress.bech32); - expect(snapshot?.count).toBe(50); - expect(snapshot?.paidOut).toBe(0); - expect(snapshot?.ethAddress).toBe(ethAddress); - expect(snapshot?.ethAddressVerified).toBe(true); - }); - - it('Receive 25 back locked', async () => { - let blockId = await wallet.send(address, targetAddress.bech32, MIN_IOTA_AMOUNT / 2, { - nativeTokens: [{ id: tokenId, amount: BigInt(50) }], - }); - await blockInDd(blockId); - - blockId = await wallet.send(targetAddress, address.bech32, 0, { - nativeTokens: [{ id: tokenId, amount: BigInt(25) }], - vestingAt: dateToTimestamp(dayjs().add(100, 'd')), - }); - await blockInDd(blockId); - - const tokensPerMember = await soonSnapshot(build5App, tokenId, network); - expect(tokensPerMember[vaultAddress]).toBe(currentSoonTotal); - expect(tokensPerMember[address.bech32]).toBe(75); - expect(tokensPerMember[targetAddress.bech32]).toBe(25); - }); - - it('Receive 10 back with expiration', async () => { - let blockId = await wallet.send(address, targetAddress.bech32, MIN_IOTA_AMOUNT / 2, { - nativeTokens: [{ id: tokenId, amount: BigInt(50) }], - }); - await blockInDd(blockId); - - blockId = await wallet.send(targetAddress, address.bech32, 0, { - nativeTokens: [{ id: tokenId, amount: BigInt(10) }], - expiration: { - expiresAt: dateToTimestamp(dayjs().add(100, 'd')), - returnAddressBech32: targetAddress.bech32, - }, - }); - await blockInDd(blockId); - - const tokensPerMember = await soonSnapshot(build5App, tokenId, network); - expect(tokensPerMember[vaultAddress]).toBe(currentSoonTotal); - expect(tokensPerMember[address.bech32]).toBe(60); - expect(tokensPerMember[targetAddress.bech32]).toBe(40); - }); - - it('Mint nft and store native tokens', async () => { - const outputs = await wallet.getOutputs(address.bech32, undefined, undefined, false); - const output = mergeOutputs(cloneDeep(Object.values(outputs))); - - const issuerAddress = new Ed25519Address(address.hex); - const ownerAddress = new Ed25519Address(targetAddress.hex); - - const nftOutputParams: NftOutputBuilderParams = { - nftId: EMPTY_NFT_ID, - immutableFeatures: [new IssuerFeature(issuerAddress)], - unlockConditions: [new AddressUnlockCondition(ownerAddress)], - nativeTokens: [{ id: tokenId, amount: BigInt(10) }], - }; - const nftOutput = await wallet.client.buildNftOutput(nftOutputParams); - - output.amount = (Number(output.amount!) - Number(nftOutput.amount)).toString(); - output.nativeTokens = [ - { id: tokenId, amount: BigInt(Number(output.nativeTokens![0].amount) - 10) }, - ]; - - const inputs = Object.keys(outputs).map(UTXOInput.fromOutputId); - const inputsCommitment = Utils.computeInputsCommitment(Object.values(outputs)); - - const essence = await packEssence( - wallet, - inputs, - inputsCommitment, - [await wallet.client.buildBasicOutput(output), nftOutput], - {}, - ); - const fromUnlock = await createUnlock(essence, address); - const unlocks: Unlock[] = Object.values(outputs).map((_, index) => - index ? new ReferenceUnlock(0) : fromUnlock, - ); - const blockId = await submitBlock(wallet, essence, unlocks); - await build5Db().doc(`blocks/${blockId}`).create({ blockId }); - await blockInDd(blockId); - - const tokensPerMember = await soonSnapshot(build5App, tokenId, network); - expect(tokensPerMember[vaultAddress]).toBe(currentSoonTotal); - expect(tokensPerMember[address.bech32]).toBe(90); - expect(tokensPerMember[targetAddress.bech32]).toBe(10); - }); - - it('Mint alias and store 10 tokens', async () => { - const outputs = await wallet.getOutputs(address.bech32, undefined, undefined, false); - const output = mergeOutputs(cloneDeep(Object.values(outputs))); - - const issuerAddress = new Ed25519Address(address.hex); - const governorAddress = new Ed25519Address(targetAddress.hex); - - const aliasOutputParams: AliasOutputBuilderParams = { - aliasId: EMPTY_ALIAS_ID, - stateIndex: 0, - foundryCounter: 0, - immutableFeatures: [new IssuerFeature(issuerAddress)], - unlockConditions: [ - new StateControllerAddressUnlockCondition(governorAddress), - new GovernorAddressUnlockCondition(governorAddress), - ], - nativeTokens: [{ id: tokenId, amount: BigInt(10) }], - }; - const aliasOutput = await wallet.client.buildAliasOutput(aliasOutputParams); - - output.amount = (Number(output.amount!) - Number(aliasOutput.amount)).toString(); - output.nativeTokens = [ - { id: tokenId, amount: BigInt(Number(output.nativeTokens![0].amount) - 10) }, - ]; - - const inputs = Object.keys(outputs).map(UTXOInput.fromOutputId); - const inputsCommitment = Utils.computeInputsCommitment(Object.values(outputs)); - - const essence = await packEssence( - wallet, - inputs, - inputsCommitment, - [await wallet.client.buildBasicOutput(output), aliasOutput], - {}, - ); - const fromUnlock = await createUnlock(essence, address); - const unlocks: Unlock[] = Object.values(outputs).map((_, index) => - index ? new ReferenceUnlock(0) : fromUnlock, - ); - const blockId = await submitBlock(wallet, essence, unlocks); - await build5Db().doc(`blocks/${blockId}`).create({ blockId }); - await blockInDd(blockId); - - const tokensPerMember = await soonSnapshot(build5App, tokenId, network); - expect(tokensPerMember[vaultAddress]).toBe(currentSoonTotal); - expect(tokensPerMember[address.bech32]).toBe(90); - expect(tokensPerMember[targetAddress.bech32]).toBe(10); - }); - - it('Airdrop 2 * 10 token, unclaimed', async () => { - const drops = [ - { - count: 10, - recipient: targetAddress.bech32, - vestingAt: dayjs().subtract(1, 'm').toDate(), - }, - { count: 10, recipient: targetAddress.bech32, vestingAt: dayjs().add(2, 'M').toDate() }, - ]; - mockWalletReturnValue(walletSpy, guardian, { token: tokenId, drops }); - let order = await testEnv.wrap(airdropMintedToken)({}); - const blockId = await wallet.send(address, order.payload.targetAddress, 0, { - nativeTokens: [{ id: tokenId, amount: BigInt(20) }], - }); - await MnemonicService.store(address.bech32, address.mnemonic); - await blockInDd(blockId); - - mockWalletReturnValue(walletSpy, guardian, { token: tokenId, drops }); - order = await testEnv.wrap(airdropMintedToken)({}); - await wallet.send(address, order.payload.targetAddress, 0, { - nativeTokens: [{ id: tokenId, amount: BigInt(20) }], - }); - - await wait(async () => { - const snap = await build5Db() - .collection(COL.AIRDROP) - .where('member', '==', targetAddress.bech32) - .get(); - const status = snap.reduce( - (acc, act) => acc && act.status === TokenDropStatus.UNCLAIMED, - true, - ); - return snap.length === 4 && status; - }); - - const tokensPerMember = await soonSnapshot(build5App, tokenId, network); - expect(tokensPerMember[vaultAddress]).toBe(currentSoonTotal); - expect(tokensPerMember[address.bech32]).toBe(60); - expect(tokensPerMember[targetAddress.bech32]).toBe(40); - }); - - it('Airdrop 2 * 10 token, claim half, do not count twice', async () => { - const tmp = await wallet.getNewIotaAddressDetails(); - const drops = [ - { - count: 10, - recipient: targetAddress.bech32, - vestingAt: dayjs().subtract(1, 'm').toDate(), - }, - { count: 10, recipient: tmp.bech32, vestingAt: dayjs().add(2, 'M').toDate() }, - ]; - mockWalletReturnValue(walletSpy, guardian, { token: tokenId, drops }); - let order = await testEnv.wrap(airdropMintedToken)({}); - const blockId = await wallet.send(address, order.payload.targetAddress, 0, { - nativeTokens: [{ id: tokenId, amount: BigInt(20) }], - }); - await MnemonicService.store(address.bech32, address.mnemonic); - await blockInDd(blockId); - - await requestFundsFromFaucet(network, tmp.bech32, MIN_IOTA_AMOUNT); - await wallet.send(tmp, tangleOrder.payload.targetAddress!, MIN_IOTA_AMOUNT, { - customMetadata: { - request: { - requestType: TangleRequestType.CLAIM_MINTED_AIRDROPS, - symbol: token.symbol, - }, - }, - }); - await MnemonicService.store(tmp.bech32, tmp.mnemonic); - - const orderQuery = build5Db() - .collection(COL.TRANSACTION) - .where('member', '==', tmp.bech32) - .where('type', '==', TransactionType.CREDIT_TANGLE_REQUEST); - - await wait(async () => { - const snap = await orderQuery.get(); - return snap.length === 1 && snap[0].payload.walletReference?.confirmed; - }); - - const claimOrder = (await orderQuery.get())[0]; - await wallet.send( - tmp, - claimOrder.payload.response!.address as string, - claimOrder.payload.response!.amount as number, - {}, - ); - - mockWalletReturnValue(walletSpy, guardian, { token: tokenId, drops }); - order = await testEnv.wrap(airdropMintedToken)({}); - await wallet.send(address, order.payload.targetAddress, 0, { - nativeTokens: [{ id: tokenId, amount: BigInt(20) }], - }); - - await wait(async () => { - const snap = await build5Db() - .collection(COL.AIRDROP) - .where('member', 'in', [targetAddress.bech32, tmp.bech32]) - .get(); - const claimed = snap.filter((s) => s.status === TokenDropStatus.CLAIMED); - const unclaimed = snap.filter((s) => s.status === TokenDropStatus.UNCLAIMED); - return snap.length === 4 && claimed.length === 1 && unclaimed.length === 3; - }); - - await awaitTransactionConfirmationsForToken(tokenId); - - const tokensPerMember = await soonSnapshot(build5App, tokenId, network); - expect(tokensPerMember[vaultAddress]).toBe(currentSoonTotal); - expect(tokensPerMember[address.bech32]).toBe(60); - expect(tokensPerMember[targetAddress.bech32]).toBe(20); - expect(tokensPerMember[tmp.bech32]).toBe(20); - - let snapshot = await build5Db().doc(`${COL.SOON_SNAP}/${vaultAddress}`).get(); - expect(snapshot?.count).toBe(currentSoonTotal); - snapshot = await build5Db().doc(`${COL.SOON_SNAP}/${address.bech32}`).get(); - expect(snapshot?.count).toBe(60); - snapshot = await build5Db().doc(`${COL.SOON_SNAP}/${targetAddress.bech32}`).get(); - expect(snapshot?.count).toBe(20); - snapshot = await build5Db().doc(`${COL.SOON_SNAP}/${tmp.bech32}`).get(); - expect(snapshot?.count).toBe(20); - }); - - it('Airdrop to member with no validated address', async () => { - const member = '0x69252ebdc3b77624c6e640a81a086aaa720734d3'; - await build5Db().doc(`${COL.MEMBER}/${member}`).set({ uid: member, validatedAddress: {} }); - const drops = [{ count: 10, recipient: member, vestingAt: dayjs().add(2, 'M').toDate() }]; - - mockWalletReturnValue(walletSpy, guardian, { token: tokenId, drops }); - let order = await testEnv.wrap(airdropMintedToken)({}); - const blockId = await wallet.send(address, order.payload.targetAddress, 0, { - nativeTokens: [{ id: tokenId, amount: BigInt(10) }], - }); - await MnemonicService.store(address.bech32, address.mnemonic); - await blockInDd(blockId); - - await wait(async () => { - const snap = await build5Db() - .collection(COL.AIRDROP) - .where('member', '==', member) - .where('status', '==', TokenDropStatus.UNCLAIMED) - .get(); - return snap.length === 1; - }); - - const tokensPerMember = await soonSnapshot(build5App, tokenId, network); - expect(tokensPerMember[vaultAddress]).toBe(currentSoonTotal); - expect(tokensPerMember[address.bech32]).toBe(90); - expect(tokensPerMember[member]).toBe(10); - - const tmp = await wallet.getNewIotaAddressDetails(); - await requestFundsFromFaucet(network, tmp.bech32, MIN_IOTA_AMOUNT); - await wallet.send(tmp, tangleOrder.payload.targetAddress!, MIN_IOTA_AMOUNT, { - customMetadata: { - request: { requestType: TangleRequestType.VERIFY_ETH_ADDRESS, ethAddress: member }, - }, - }); - - const creditQuery = build5Db() - .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.CREDIT_TANGLE_REQUEST) - .where('member', '==', tmp.bech32); - await wait(async () => { - const snap = await creditQuery.get(); - return snap.length === 1 && snap[0].payload.walletReference?.confirmed; - }); - - const snapshot = await build5Db().doc(`${COL.SOON_SNAP}/${member}`).get(); - expect(snapshot?.uid).toBe(member); - expect(snapshot?.count).toBe(10); - expect(snapshot?.paidOut).toBe(0); - expect(snapshot?.ethAddress).toBe(member); - expect(snapshot?.ethAddressVerified).toBe(true); - }); -}); - -const blockInDd = async (blockId: string) => { - await wait(async () => { - const snap = await build5Db().collectionGroup(SUB_COL.TRANSACTIONS).get(); - const blockIds = snap.map((s) => s.blockId); - return blockIds.includes(blockId); - }); -}; diff --git a/packages/functions/test-tangle/space-tangle/Helper.ts b/packages/functions/test-tangle/space-tangle/Helper.ts index 4a32119719..6746f6fd08 100644 --- a/packages/functions/test-tangle/space-tangle/Helper.ts +++ b/packages/functions/test-tangle/space-tangle/Helper.ts @@ -1,15 +1,12 @@ -import { IQuery, build5Db } from '@build-5/database'; -import { COL, Member, Network, Space, Transaction, TransactionType } from '@build-5/interfaces'; +import { IQuery, PgTransactionType, build5Db } from '@build-5/database'; +import { COL, Member, Network, Space, Transaction } from '@build-5/interfaces'; import { Wallet } from '../../src/services/wallet/wallet'; import { AddressDetails } from '../../src/services/wallet/wallet.service'; import { getAddress } from '../../src/utils/address.utils'; -import * as wallet from '../../src/utils/wallet.utils'; -import { createMember, createSpace } from '../../test/controls/common'; -import { getWallet } from '../../test/set-up'; +import { getWallet, testEnv } from '../../test/set-up'; import { getTangleOrder } from '../common'; export class Helper { - public walletSpy: any = {} as any; public guardian: string = ''; public member: string = ''; public space: Space = {} as any; @@ -17,8 +14,8 @@ export class Helper { public walletService: Wallet = {} as any; public network = Network.RMS; public tangleOrder: Transaction = {} as any; - public memberCreditQuery: IQuery = {} as any; - public guardianCreditQuery: IQuery = {} as any; + public memberCreditQuery: IQuery = {} as any; + public guardianCreditQuery: IQuery = {} as any; public guardianAddress: AddressDetails = {} as any; public beforeAll = async () => { @@ -27,29 +24,28 @@ export class Helper { }; public beforeEach = async () => { - this.walletSpy = jest.spyOn(wallet, 'decodeAuth'); - this.guardian = await createMember(this.walletSpy); - this.member = await createMember(this.walletSpy); - this.space = await createSpace(this.walletSpy, this.guardian); + this.guardian = await testEnv.createMember(); + this.member = await testEnv.createMember(); + this.space = await testEnv.createSpace(this.guardian); - const memberDocRef = build5Db().doc(`${COL.MEMBER}/${this.member}`); + const memberDocRef = build5Db().doc(COL.MEMBER, this.member); const memberData = await memberDocRef.get(); const memberBech32 = getAddress(memberData, this.network); this.memberAddress = await this.walletService.getAddressDetails(memberBech32); - const guardianDocRef = build5Db().doc(`${COL.MEMBER}/${this.guardian}`); + const guardianDocRef = build5Db().doc(COL.MEMBER, this.guardian); const guardianData = await guardianDocRef.get(); const guardianBech32 = getAddress(guardianData, this.network); this.guardianAddress = await this.walletService.getAddressDetails(guardianBech32); this.memberCreditQuery = build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.CREDIT_TANGLE_REQUEST) + .where('type', '==', PgTransactionType.CREDIT_TANGLE_REQUEST) .where('member', '==', this.member); this.guardianCreditQuery = build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.CREDIT_TANGLE_REQUEST) + .where('type', '==', PgTransactionType.CREDIT_TANGLE_REQUEST) .where('member', '==', this.guardian); }; } diff --git a/packages/functions/test-tangle/space-tangle/space.accept.member.spec.ts b/packages/functions/test-tangle/space-tangle/space.accept.member.spec.ts index 58fcd78ddf..330096004b 100644 --- a/packages/functions/test-tangle/space-tangle/space.accept.member.spec.ts +++ b/packages/functions/test-tangle/space-tangle/space.accept.member.spec.ts @@ -23,7 +23,7 @@ describe('Join space', () => { }); it('Should join space via tangle request', async () => { - const spaceDocRef = build5Db().doc(`${COL.SPACE}/${helper.space.uid}`); + const spaceDocRef = build5Db().doc(COL.SPACE, helper.space.uid); await spaceDocRef.update({ open: false }); await requestFundsFromFaucet(Network.RMS, helper.memberAddress.bech32, MIN_IOTA_AMOUNT); @@ -42,7 +42,7 @@ describe('Join space', () => { ); await wait(async () => { - const snap = await helper.memberCreditQuery.get(); + const snap = await helper.memberCreditQuery.get(); return snap.length === 1 && snap[0]?.payload?.walletReference?.confirmed; }); let snap = await helper.memberCreditQuery.get(); @@ -70,7 +70,7 @@ describe('Join space', () => { ); await wait(async () => { - const snap = await helper.guardianCreditQuery.get(); + const snap = await helper.guardianCreditQuery.get(); return snap.length === 1 && snap[0]?.payload?.walletReference?.confirmed; }); snap = await helper.guardianCreditQuery.get(); diff --git a/packages/functions/test-tangle/space-tangle/space.block.member.spec.ts b/packages/functions/test-tangle/space-tangle/space.block.member.spec.ts index ae421f1a90..c5d822e830 100644 --- a/packages/functions/test-tangle/space-tangle/space.block.member.spec.ts +++ b/packages/functions/test-tangle/space-tangle/space.block.member.spec.ts @@ -6,11 +6,10 @@ import { SUB_COL, Space, TangleRequestType, - Transaction, + WEN_FUNC, } from '@build-5/interfaces'; -import { joinSpace } from '../../src/runtime/firebase/space'; -import { mockWalletReturnValue, wait } from '../../test/controls/common'; -import { testEnv } from '../../test/set-up'; +import { wait } from '../../test/controls/common'; +import { mockWalletReturnValue, testEnv } from '../../test/set-up'; import { requestFundsFromFaucet } from '../faucet'; import { Helper } from './Helper'; @@ -26,8 +25,8 @@ describe('Block space member', () => { }); it('Should block member', async () => { - mockWalletReturnValue(helper.walletSpy, helper.member, { uid: helper.space.uid }); - await testEnv.wrap(joinSpace)({}); + mockWalletReturnValue(helper.member, { uid: helper.space.uid }); + await testEnv.wrap(WEN_FUNC.joinSpace); await requestFundsFromFaucet(Network.RMS, helper.guardianAddress.bech32, MIN_IOTA_AMOUNT); await helper.walletService.send( @@ -46,19 +45,21 @@ describe('Block space member', () => { ); await wait(async () => { - const snap = await helper.guardianCreditQuery.get(); + const snap = await helper.guardianCreditQuery.get(); return snap.length === 1 && snap[0]?.payload?.walletReference?.confirmed; }); - const spaceDocRef = build5Db().doc(`${COL.SPACE}/${helper.space.uid}`); + const spaceDocRef = build5Db().doc(COL.SPACE, helper.space.uid); helper.space = await spaceDocRef.get(); expect(helper.space.totalMembers).toBe(1); expect(helper.space.totalGuardians).toBe(1); - const guardianCount = await spaceDocRef.collection(SUB_COL.GUARDIANS).count(); - expect(guardianCount).toBe(1); + const guardians = await build5Db() + .collection(COL.SPACE, helper.space.uid, SUB_COL.GUARDIANS) + .get(); + expect(guardians.length).toBe(1); - const memberCount = await spaceDocRef.collection(SUB_COL.MEMBERS).count(); - expect(memberCount).toBe(1); + const members = await build5Db().collection(COL.SPACE, helper.space.uid, SUB_COL.MEMBERS).get(); + expect(members.length).toBe(1); }); }); diff --git a/packages/functions/test-tangle/space-tangle/space.create.spec.ts b/packages/functions/test-tangle/space-tangle/space.create.spec.ts index 0e2193ed0c..31d91577ea 100644 --- a/packages/functions/test-tangle/space-tangle/space.create.spec.ts +++ b/packages/functions/test-tangle/space-tangle/space.create.spec.ts @@ -41,12 +41,12 @@ describe('Create space', () => { ); await wait(async () => { - const snap = await helper.memberCreditQuery.get(); + const snap = await helper.memberCreditQuery.get(); return snap.length === 1 && snap[0]?.payload?.walletReference?.confirmed; }); const snap = await helper.memberCreditQuery.get(); const credit = snap[0] as Transaction; - const spaceDocRef = build5Db().doc(`${COL.SPACE}/${credit.payload.response!.space}`); + const spaceDocRef = build5Db().doc(COL.SPACE, credit.payload.response!.space as string); const space = await spaceDocRef.get(); expect(space.name).toBe('Space A'); }); diff --git a/packages/functions/test-tangle/space-tangle/space.decline.member.spec.ts b/packages/functions/test-tangle/space-tangle/space.decline.member.spec.ts index 3644240489..d34db62cda 100644 --- a/packages/functions/test-tangle/space-tangle/space.decline.member.spec.ts +++ b/packages/functions/test-tangle/space-tangle/space.decline.member.spec.ts @@ -5,11 +5,10 @@ import { Network, Space, TangleRequestType, - Transaction, + WEN_FUNC, } from '@build-5/interfaces'; -import { joinSpace } from '../../src/runtime/firebase/space'; -import { mockWalletReturnValue, wait } from '../../test/controls/common'; -import { testEnv } from '../../test/set-up'; +import { wait } from '../../test/controls/common'; +import { mockWalletReturnValue, testEnv } from '../../test/set-up'; import { requestFundsFromFaucet } from '../faucet'; import { Helper } from './Helper'; @@ -25,11 +24,11 @@ describe('Block space member', () => { }); it('Should block member', async () => { - const spaceDocRef = build5Db().doc(`${COL.SPACE}/${helper.space.uid}`); + const spaceDocRef = build5Db().doc(COL.SPACE, helper.space.uid); await spaceDocRef.update({ open: false }); - mockWalletReturnValue(helper.walletSpy, helper.member, { uid: helper.space.uid }); - await testEnv.wrap(joinSpace)({}); + mockWalletReturnValue(helper.member, { uid: helper.space.uid }); + await testEnv.wrap(WEN_FUNC.joinSpace); helper.space = await spaceDocRef.get(); expect(helper.space.totalMembers).toBe(1); @@ -52,7 +51,7 @@ describe('Block space member', () => { ); await wait(async () => { - const snap = await helper.guardianCreditQuery.get(); + const snap = await helper.guardianCreditQuery.get(); return snap.length === 1 && snap[0]?.payload?.walletReference?.confirmed; }); diff --git a/packages/functions/test-tangle/space-tangle/space.edit.guardian.spec.ts b/packages/functions/test-tangle/space-tangle/space.edit.guardian.spec.ts index 84a261d5f5..95004a62c6 100644 --- a/packages/functions/test-tangle/space-tangle/space.edit.guardian.spec.ts +++ b/packages/functions/test-tangle/space-tangle/space.edit.guardian.spec.ts @@ -7,10 +7,10 @@ import { ProposalType, TangleRequestType, Transaction, + WEN_FUNC, } from '@build-5/interfaces'; -import { joinSpace } from '../../src/runtime/firebase/space'; -import { addGuardianToSpace, mockWalletReturnValue, wait } from '../../test/controls/common'; -import { testEnv } from '../../test/set-up'; +import { addGuardianToSpace, wait } from '../../test/controls/common'; +import { mockWalletReturnValue, testEnv } from '../../test/set-up'; import { requestFundsFromFaucet } from '../faucet'; import { Helper } from './Helper'; @@ -28,8 +28,8 @@ describe('Edit guardian space', () => { it.each([TangleRequestType.SPACE_ADD_GUARDIAN, TangleRequestType.SPACE_REMOVE_GUARDIAN])( 'Should add/remove guardian', async (requestType: TangleRequestType) => { - mockWalletReturnValue(helper.walletSpy, helper.member, { uid: helper.space.uid }); - await testEnv.wrap(joinSpace)({}); + mockWalletReturnValue(helper.member, { uid: helper.space.uid }); + await testEnv.wrap(WEN_FUNC.joinSpace); if (requestType === TangleRequestType.SPACE_REMOVE_GUARDIAN) { await addGuardianToSpace(helper.space.uid, helper.member); @@ -52,14 +52,14 @@ describe('Edit guardian space', () => { ); await wait(async () => { - const snap = await helper.guardianCreditQuery.get(); + const snap = await helper.guardianCreditQuery.get(); return snap.length === 1 && snap[0]?.payload?.walletReference?.confirmed; }); const snap = await helper.guardianCreditQuery.get(); const credit = snap[0] as Transaction; - const proposalId = credit.payload.response!.proposal; + const proposalId = credit.payload.response!.proposal as string; - const proposalDocRef = build5Db().doc(`${COL.PROPOSAL}/${proposalId}`); + const proposalDocRef = build5Db().doc(COL.PROPOSAL, proposalId); const proposal = await proposalDocRef.get(); expect(proposal.type).toBe( requestType === TangleRequestType.SPACE_ADD_GUARDIAN diff --git a/packages/functions/test-tangle/space-tangle/space.join.spec.ts b/packages/functions/test-tangle/space-tangle/space.join.spec.ts index 24c9b26070..71dde979b8 100644 --- a/packages/functions/test-tangle/space-tangle/space.join.spec.ts +++ b/packages/functions/test-tangle/space-tangle/space.join.spec.ts @@ -3,9 +3,9 @@ import { COL, MIN_IOTA_AMOUNT, Network, + SUB_COL, Space, SpaceMember, - SUB_COL, TangleRequestType, Transaction, } from '@build-5/interfaces'; @@ -41,18 +41,23 @@ describe('Join space', () => { ); await wait(async () => { - const snap = await helper.memberCreditQuery.get(); + const snap = await helper.memberCreditQuery.get(); return snap.length === 1 && snap[0]?.payload?.walletReference?.confirmed; }); const snap = await helper.memberCreditQuery.get(); const credit = snap[0] as Transaction; expect(credit.payload.response!.status).toBe('success'); - const spaceDocRef = build5Db().doc(`${COL.SPACE}/${helper.space.uid}`); + const spaceDocRef = build5Db().doc(COL.SPACE, helper.space.uid); helper.space = await spaceDocRef.get(); expect(helper.space.totalMembers).toBe(2); - const spaceMemberDocRef = spaceDocRef.collection(SUB_COL.MEMBERS).doc(helper.member); + const spaceMemberDocRef = build5Db().doc( + COL.SPACE, + helper.space.uid, + SUB_COL.MEMBERS, + helper.member, + ); const spaceMember = await spaceMemberDocRef.get(); expect(spaceMember).toBeDefined(); }); diff --git a/packages/functions/test-tangle/space-tangle/space.leave.spec.ts b/packages/functions/test-tangle/space-tangle/space.leave.spec.ts index 6bfe4d0d26..b8bb2e2550 100644 --- a/packages/functions/test-tangle/space-tangle/space.leave.spec.ts +++ b/packages/functions/test-tangle/space-tangle/space.leave.spec.ts @@ -6,10 +6,10 @@ import { Space, TangleRequestType, Transaction, + WEN_FUNC, } from '@build-5/interfaces'; -import { joinSpace } from '../../src/runtime/firebase/space'; -import { mockWalletReturnValue, wait } from '../../test/controls/common'; -import { testEnv } from '../../test/set-up'; +import { wait } from '../../test/controls/common'; +import { mockWalletReturnValue, testEnv } from '../../test/set-up'; import { requestFundsFromFaucet } from '../faucet'; import { Helper } from './Helper'; @@ -25,10 +25,10 @@ describe('Join space', () => { }); it('Should leave space via tangle request', async () => { - mockWalletReturnValue(helper.walletSpy, helper.member, { uid: helper.space.uid }); - await testEnv.wrap(joinSpace)({}); + mockWalletReturnValue(helper.member, { uid: helper.space.uid }); + await testEnv.wrap(WEN_FUNC.joinSpace); - const spaceDocRef = build5Db().doc(`${COL.SPACE}/${helper.space.uid}`); + const spaceDocRef = build5Db().doc(COL.SPACE, helper.space.uid); helper.space = await spaceDocRef.get(); expect(helper.space.totalMembers).toBe(2); @@ -48,7 +48,7 @@ describe('Join space', () => { ); await wait(async () => { - const snap = await helper.memberCreditQuery.get(); + const snap = await helper.memberCreditQuery.get(); return snap.length === 1 && snap[0]?.payload?.walletReference?.confirmed; }); let snap = await helper.memberCreditQuery.get(); diff --git a/packages/functions/test-tangle/staking/Helper.ts b/packages/functions/test-tangle/staking/Helper.ts index 647e505a17..55c0b0ab42 100644 --- a/packages/functions/test-tangle/staking/Helper.ts +++ b/packages/functions/test-tangle/staking/Helper.ts @@ -17,25 +17,19 @@ import { TokenStatus, Transaction, TransactionPayloadType, + WEN_FUNC, calcStakedMultiplier, } from '@build-5/interfaces'; import dayjs from 'dayjs'; -import { isEmpty } from 'lodash'; -import { depositStake } from '../../src/runtime/firebase/stake'; +import { isEmpty, set } from 'lodash'; import { MnemonicService } from '../../src/services/wallet/mnemonic'; import { Wallet } from '../../src/services/wallet/wallet'; import { AddressDetails } from '../../src/services/wallet/wallet.service'; import { getAddress } from '../../src/utils/address.utils'; import { dateToTimestamp, serverTime } from '../../src/utils/dateTime.utils'; import * as wallet from '../../src/utils/wallet.utils'; -import { - createMember, - createSpace, - getRandomSymbol, - mockWalletReturnValue, - wait, -} from '../../test/controls/common'; -import { MEDIA, getWallet, testEnv } from '../../test/set-up'; +import { getRandomSymbol, wait } from '../../test/controls/common'; +import { MEDIA, getWallet, mockWalletReturnValue, testEnv } from '../../test/set-up'; import { requestFundsFromFaucet, requestMintedTokenFromFaucet } from '../faucet'; export class Helper { @@ -48,27 +42,23 @@ export class Helper { public memberAddress: AddressDetails | undefined; public space: Space | undefined; public walletService: Wallet | undefined; - public walletSpy: any; public network = Network.RMS; public token: Token | undefined; public tokenStats: TokenStats | undefined; public beforeAll = async () => { - this.walletSpy = jest.spyOn(wallet, 'decodeAuth'); this.walletService = await getWallet(this.network); }; public beforeEach = async () => { - const memberId = await createMember(this.walletSpy); - this.member = await build5Db().doc(`${COL.MEMBER}/${memberId}`).get(); + const memberId = await testEnv.createMember(); + this.member = await build5Db().doc(COL.MEMBER, memberId).get(); this.memberAddress = await this.walletService?.getNewIotaAddressDetails(); - this.space = await createSpace(this.walletSpy, memberId); + this.space = await testEnv.createSpace(memberId); this.token = await this.saveToken(this.space!.uid, this.member!.uid); this.tokenStats = ( - await build5Db() - .doc(`${COL.TOKEN}/${this.token.uid}/${SUB_COL.STATS}/${this.token.uid}`) - .get() + await build5Db().doc(COL.TOKEN, this.token.uid, SUB_COL.STATS, this.token.uid).get() ); await requestFundsFromFaucet(this.network, this.memberAddress!.bech32, 10 * MIN_IOTA_AMOUNT); await requestMintedTokenFromFaucet( @@ -100,9 +90,9 @@ export class Helper { }, access: 0, icon: MEDIA, - }; - await build5Db().doc(`${COL.TOKEN}/${token.uid}`).set(token); - return token; + } as Token; + await build5Db().doc(COL.TOKEN, token.uid).create(token); + return token; }; public stakeAmount = async ( @@ -114,19 +104,23 @@ export class Helper { memberUid?: string, ) => { const member = await build5Db() - .doc(`${COL.MEMBER}/${memberUid || this.member?.uid}`) + .doc(COL.MEMBER, memberUid || this.member?.uid!) .get(); - mockWalletReturnValue(this.walletSpy, member.uid, { + + const body = { symbol: this.token?.symbol, weeks, type: type || StakeType.DYNAMIC, - customMetadata, - }); - const order = await testEnv.wrap(depositStake)({}); + }; + if (!isEmpty(customMetadata)) { + set(body, 'customMetadata', customMetadata); + } + mockWalletReturnValue(member.uid, body); + const order = await testEnv.wrap(WEN_FUNC.depositStake); const address = memberUid ? await this.walletService!.getAddressDetails(getAddress(member, Network.RMS)) : this.memberAddress!; - await this.walletService!.send(address, order.payload.targetAddress, order.payload.amount, { + await this.walletService!.send(address, order.payload.targetAddress!, order.payload.amount!, { expiration: expiresAt ? { expiresAt, returnAddressBech32: this.memberAddress!.bech32 } : undefined, @@ -149,9 +143,7 @@ export class Helper { await wait(async () => { const currTokenStats = ( - await build5Db() - .doc(`${COL.TOKEN}/${this.token?.uid}/${SUB_COL.STATS}/${this.token?.uid}`) - .get() + await build5Db().doc(COL.TOKEN, this.token?.uid!, SUB_COL.STATS, this.token?.uid).get() ); return ( (currTokenStats?.stakes || {})[type || StakeType.DYNAMIC]?.totalAmount !== @@ -159,7 +151,7 @@ export class Helper { ); }); - const billPaymentDocRef = build5Db().doc(`${COL.TRANSACTION}/${stake.billPaymentId}`); + const billPaymentDocRef = build5Db().doc(COL.TRANSACTION, stake.billPaymentId); await wait(async () => { const billPayment = await billPaymentDocRef.get(); return billPayment.payload.walletReference?.confirmed; @@ -183,9 +175,7 @@ export class Helper { membersCount: number, ) => { this.tokenStats = ( - await build5Db() - .doc(`${COL.TOKEN}/${this.token!.uid}/${SUB_COL.STATS}/${this.token?.uid}`) - .get() + await build5Db().doc(COL.TOKEN, this.token!.uid, SUB_COL.STATS, this.token?.uid).get() ); expect(this.tokenStats.stakes![type].amount).toBe(stakeAmount); expect(this.tokenStats.stakes![type].totalAmount).toBe(stakeTotalAmount); @@ -203,7 +193,7 @@ export class Helper { member?: string, ) => { const distribution = await build5Db() - .doc(`${COL.TOKEN}/${this.token!.uid}/${SUB_COL.DISTRIBUTION}/${member || this.member!.uid}`) + .doc(COL.TOKEN, this.token!.uid, SUB_COL.DISTRIBUTION, member || this.member!.uid) .get(); expect(distribution.stakes![type].amount).toBe(stakeAmount); expect(distribution.stakes![type].totalAmount).toBe(stakeTotalAmount); @@ -213,35 +203,40 @@ export class Helper { public assertDistributionStakeExpiry = async (stake: Stake) => { const distributionDocRef = build5Db().doc( - `${COL.TOKEN}/${this.token?.uid}/${SUB_COL.DISTRIBUTION}/${this.member!.uid}`, + COL.TOKEN, + this.token?.uid!, + SUB_COL.DISTRIBUTION, + this.member!.uid, ); const distirbution = await distributionDocRef.get(); expect(distirbution.stakeExpiry![stake.type][stake.expiresAt.toMillis()]).toBe(stake.value); }; public updateStakeExpiresAt = async (stake: Stake, expiresAt: dayjs.Dayjs) => { - await build5Db() - .doc(`${COL.STAKE}/${stake.uid}`) - .update({ expiresAt: dateToTimestamp(expiresAt.toDate()) }); + await build5Db().doc(COL.STAKE, stake.uid).update({ expiresAt: expiresAt.toDate() }); const distributionDocRef = build5Db().doc( - `${COL.TOKEN}/${this.token?.uid}/${SUB_COL.DISTRIBUTION}/${this.member!.uid}`, + COL.TOKEN, + this.token?.uid!, + SUB_COL.DISTRIBUTION, + this.member!.uid, ); - await distributionDocRef.set( - { - stakeExpiry: { - [stake.type]: { - [stake.expiresAt.toMillis()]: build5Db().deleteField(), - [dateToTimestamp(expiresAt.toDate()).toMillis()]: stake.value, - }, - }, + + await distributionDocRef.update({ + stakeExpiry: { [stake.type]: { [stake.expiresAt.toMillis()]: null } }, + }); + await distributionDocRef.update({ + stakeExpiry: { + [stake.type]: { [dateToTimestamp(expiresAt.toDate()).toMillis()]: stake.value }, }, - true, - ); + }); }; public assertStakeExpiryCleared = async (type: StakeType) => { const distributionDocRef = build5Db().doc( - `${COL.TOKEN}/${this.token?.uid}/${SUB_COL.DISTRIBUTION}/${this.member!.uid}`, + COL.TOKEN, + this.token?.uid!, + SUB_COL.DISTRIBUTION, + this.member!.uid, ); const distribution = await distributionDocRef.get(); expect(isEmpty(distribution.stakeExpiry![type])).toBe(true); diff --git a/packages/functions/test-tangle/staking/staking_1.spec.ts b/packages/functions/test-tangle/staking/staking_1.spec.ts index 3ac23d42b4..699c0d815c 100644 --- a/packages/functions/test-tangle/staking/staking_1.spec.ts +++ b/packages/functions/test-tangle/staking/staking_1.spec.ts @@ -1,4 +1,4 @@ -import { build5Db } from '@build-5/database'; +import { build5Db, PgTransactionType } from '@build-5/database'; import { calcStakedMultiplier, COL, @@ -7,23 +7,16 @@ import { StakeType, SUB_COL, Transaction, - TransactionType, + WEN_FUNC, WenError, } from '@build-5/interfaces'; import { UnlockConditionType } from '@iota/sdk'; import dayjs from 'dayjs'; import { removeExpiredStakesFromSpace } from '../../src/cron/stake.cron'; -import { depositStake } from '../../src/runtime/firebase/stake'; import { MnemonicService } from '../../src/services/wallet/mnemonic'; import { dateToTimestamp } from '../../src/utils/dateTime.utils'; -import { - addGuardianToSpace, - createMember, - expectThrow, - mockWalletReturnValue, - wait, -} from '../../test/controls/common'; -import { testEnv } from '../../test/set-up'; +import { addGuardianToSpace, expectThrow, wait } from '../../test/controls/common'; +import { mockWalletReturnValue, testEnv } from '../../test/set-up'; import { Helper } from './Helper'; describe('Staking test', () => { @@ -52,13 +45,19 @@ describe('Staking test', () => { type: StakeType.STATIC, customMetadata, }; - mockWalletReturnValue(helper.walletSpy, helper.member!.uid, data); - await expectThrow(testEnv.wrap(depositStake)({}), WenError.invalid_params.key); + mockWalletReturnValue(helper.member!.uid, data); + await expectThrow( + testEnv.wrap(WEN_FUNC.depositStake), + WenError.invalid_params.key, + ); delete customMetadata.key6; customMetadata.key5 = 12; - mockWalletReturnValue(helper.walletSpy, helper.member!.uid, { ...data, customMetadata }); - await expectThrow(testEnv.wrap(depositStake)({}), WenError.invalid_params.key); + mockWalletReturnValue(helper.member!.uid, { ...data, customMetadata }); + await expectThrow( + testEnv.wrap(WEN_FUNC.depositStake), + WenError.invalid_params.key, + ); }); it('Should throw, invalid weeks', async () => { @@ -67,11 +66,17 @@ describe('Staking test', () => { weeks: 0, type: StakeType.STATIC, }; - mockWalletReturnValue(helper.walletSpy, helper.member!.uid, data); - await expectThrow(testEnv.wrap(depositStake)({}), WenError.invalid_params.key); + mockWalletReturnValue(helper.member!.uid, data); + await expectThrow( + testEnv.wrap(WEN_FUNC.depositStake), + WenError.invalid_params.key, + ); - mockWalletReturnValue(helper.walletSpy, helper.member!.uid, { ...data, weeks: 53 }); - await expectThrow(testEnv.wrap(depositStake)({}), WenError.invalid_params.key); + mockWalletReturnValue(helper.member!.uid, { ...data, weeks: 53 }); + await expectThrow( + testEnv.wrap(WEN_FUNC.depositStake), + WenError.invalid_params.key, + ); }); it.each([ @@ -79,22 +84,16 @@ describe('Staking test', () => { { expiration: false, type: StakeType.STATIC }, { expiration: true, type: StakeType.DYNAMIC }, ])('Should set stake amount and remove it once expired', async ({ expiration, type }) => { - const secondGuardian = await createMember(helper.walletSpy!); + const secondGuardian = await testEnv.createMember(); await addGuardianToSpace(helper.space?.uid!, secondGuardian); await build5Db() - .doc(`${COL.TOKEN}/${helper.token?.uid!}/${SUB_COL.DISTRIBUTION}/${secondGuardian}`) - .set({ + .doc(COL.TOKEN, helper.token?.uid!, SUB_COL.DISTRIBUTION, secondGuardian) + .upsert({ parentId: helper.token?.uid!, - parentCol: COL.TOKEN, - uid: secondGuardian, - stakes: { - [StakeType.DYNAMIC]: { - amount: 10, - totalAmount: 10, - value: 10, - totalValue: 10, - }, - }, + stakes_dynamic_amount: 10, + stakes_dynamic_totalAmount: 10, + stakes_dynamic_value: 10, + stakes_dynamic_totalValue: 10, }); const expiresAt = expiration ? dateToTimestamp(dayjs().add(1, 'h').toDate()) : undefined; @@ -104,7 +103,7 @@ describe('Staking test', () => { await helper.validateMemberStakeAmount(10, 10, 14, 14, type); await helper.assertDistributionStakeExpiry(stake1); - const spaceDocRef = build5Db().doc(`${COL.SPACE}/${helper.space?.uid}`); + const spaceDocRef = build5Db().doc(COL.SPACE, helper.space?.uid!); await spaceDocRef.update({ tokenBased: true, minStakedValue: 10 }); const stake2 = await helper.stakeAmount(20, 26, expiresAt, type); @@ -163,17 +162,17 @@ describe('Staking test', () => { it('Should credit invalid stake payment', async () => { const expiresAt = dateToTimestamp(dayjs().add(1, 'h').toDate()); - mockWalletReturnValue(helper.walletSpy, helper.member!.uid, { + mockWalletReturnValue(helper.member!.uid, { symbol: helper.token?.symbol, weeks: 26, type: StakeType.DYNAMIC, }); - const order = await testEnv.wrap(depositStake)({}); + const order = await testEnv.wrap(WEN_FUNC.depositStake); await helper.walletService!.send( helper.memberAddress!, - order.payload.targetAddress, - order.payload.amount, + order.payload.targetAddress!, + order.payload.amount!, { expiration: { expiresAt, returnAddressBech32: helper.memberAddress!.bech32 }, nativeTokens: [{ id: helper.MINTED_TOKEN_ID, amount: BigInt(10) }], @@ -188,13 +187,13 @@ describe('Staking test', () => { async () => { const snap = await build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.UNLOCK) + .where('type', '==', PgTransactionType.UNLOCK) .where('member', '==', helper.member?.uid) .get(); if (snap.length) { await build5Db() - .doc(`${COL.TRANSACTION}/${order.uid}`) - .update({ 'payload.expiresOn': dateToTimestamp(dayjs().subtract(1, 'd')) }); + .doc(COL.TRANSACTION, order.uid) + .update({ payload_expiresOn: dayjs().subtract(1, 'd').toDate() }); } return snap.length > 0; }, @@ -204,13 +203,13 @@ describe('Staking test', () => { const creditQuery = build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.CREDIT) + .where('type', '==', PgTransactionType.CREDIT) .where('member', '==', helper.member?.uid); await wait(async () => { const snap = await creditQuery.get(); return snap.length > 0; }); - const credits = await creditQuery.get(); + const credits = await creditQuery.get(); expect(credits.length).toBe(1); expect(credits[0]?.payload.targetAddress).toBe(helper.memberAddress?.bech32); }); diff --git a/packages/functions/test-tangle/staking/staking_2.spec.ts b/packages/functions/test-tangle/staking/staking_2.spec.ts index fea3cdfa81..3dab3194d6 100644 --- a/packages/functions/test-tangle/staking/staking_2.spec.ts +++ b/packages/functions/test-tangle/staking/staking_2.spec.ts @@ -3,7 +3,6 @@ import { COL, Space, StakeType } from '@build-5/interfaces'; import { FeatureType, MetadataFeature, UnlockConditionType, hexToUtf8 } from '@iota/sdk'; import dayjs from 'dayjs'; import { removeExpiredStakesFromSpace } from '../../src/cron/stake.cron'; -import { dateToTimestamp } from '../../src/utils/dateTime.utils'; import { Helper } from './Helper'; describe('Staking test', () => { @@ -21,7 +20,7 @@ describe('Staking test', () => { const type = StakeType.DYNAMIC; const customMetadata = { name: 'random name', - asd: 'true', + isOld: 'true', }; await helper.stakeAmount(10, 26, undefined, type, customMetadata); await helper.validateStatsStakeAmount(10, 10, 14, 14, type, 1); @@ -40,13 +39,13 @@ describe('Staking test', () => { ); const decoded = JSON.parse(hexToUtf8(hexMetadata.data)); expect(decoded.name).toBe(customMetadata.name); - expect(decoded.asd).toBe(customMetadata.asd); + expect(decoded.isOld).toBe(customMetadata.isOld); }); it.each([StakeType.DYNAMIC, StakeType.STATIC])( 'Should set stake amount and remove it once expired, 52 weeks', async (type: StakeType) => { - const spaceDocRef = build5Db().doc(`${COL.SPACE}/${helper.space?.uid}`); + const spaceDocRef = build5Db().doc(COL.SPACE, helper.space?.uid!); await spaceDocRef.update({ tokenBased: true, minStakedValue: 10 }); let space = await spaceDocRef.get(); expect(space.totalMembers).toBe(1); @@ -65,15 +64,15 @@ describe('Staking test', () => { await helper.validateMemberStakeAmount(30, 30, 60, 60, type); await build5Db() - .doc(`${COL.STAKE}/${stake2.uid}`) - .update({ expiresAt: dateToTimestamp(dayjs().subtract(1, 'm').toDate()) }); + .doc(COL.STAKE, stake2.uid) + .update({ expiresAt: dayjs().subtract(1, 'm').toDate() }); await removeExpiredStakesFromSpace(); await helper.validateStatsStakeAmount(10, 30, 20, 60, type, 1); await helper.validateMemberStakeAmount(10, 30, 20, 60, type); await build5Db() - .doc(`${COL.STAKE}/${stake1.uid}`) - .update({ expiresAt: dateToTimestamp(dayjs().subtract(1, 'm').toDate()) }); + .doc(COL.STAKE, stake1.uid) + .update({ expiresAt: dayjs().subtract(1, 'm').toDate() }); await removeExpiredStakesFromSpace(); await helper.validateStatsStakeAmount(0, 30, 0, 60, type, 0); await helper.validateMemberStakeAmount(0, 30, 0, 60, type); diff --git a/packages/functions/test-tangle/staking/staking_3.spec.ts b/packages/functions/test-tangle/staking/staking_3.spec.ts index a765b49bfc..d0ca2b8841 100644 --- a/packages/functions/test-tangle/staking/staking_3.spec.ts +++ b/packages/functions/test-tangle/staking/staking_3.spec.ts @@ -2,7 +2,6 @@ import { build5Db } from '@build-5/database'; import { COL, Member, MIN_IOTA_AMOUNT, Stake, StakeType } from '@build-5/interfaces'; import dayjs from 'dayjs'; import { removeExpiredStakesFromSpace } from '../../src/cron/stake.cron'; -import { dateToTimestamp } from '../../src/utils/dateTime.utils'; import { setProdTiers, setTestTiers, wait } from '../../test/controls/common'; import { requestMintedTokenFromFaucet } from '../faucet'; import { Helper } from './Helper'; @@ -21,15 +20,15 @@ describe('Staking test', () => { const validateMemberTradingFee = async (expected: number) => { await wait(async () => { - helper.member = await build5Db().doc(`${COL.MEMBER}/${helper.member?.uid}`).get(); - return helper.member.tokenTradingFeePercentage === expected; + helper.member = await build5Db().doc(COL.MEMBER, helper.member?.uid!).get(); + return (helper.member.tokenTradingFeePercentage || 0) === expected; }); }; const expireStakeAndValidateFee = async (stake: Stake, expectedFee: number) => { await build5Db() - .doc(`${COL.STAKE}/${stake.uid}`) - .update({ expiresAt: dateToTimestamp(dayjs().subtract(1, 'm').toDate()) }); + .doc(COL.STAKE, stake.uid) + .update({ expiresAt: dayjs().subtract(1, 'm').toDate() }); await removeExpiredStakesFromSpace(); await validateMemberTradingFee(expectedFee); }; diff --git a/packages/functions/test-tangle/staking/staking_4.spec.ts b/packages/functions/test-tangle/staking/staking_4.spec.ts index 8493be328b..b3f961bac3 100644 --- a/packages/functions/test-tangle/staking/staking_4.spec.ts +++ b/packages/functions/test-tangle/staking/staking_4.spec.ts @@ -1,7 +1,11 @@ -import { build5Db } from '@build-5/database'; +import { + PgIgnoreWalletReason, + PgStakeRewardStatus, + PgTransactionType, + build5Db, +} from '@build-5/database'; import { COL, - IgnoreWalletReason, MIN_IOTA_AMOUNT, Member, Network, @@ -13,18 +17,17 @@ import { TokenDistribution, TokenDrop, Transaction, - TransactionType, + WEN_FUNC, } from '@build-5/interfaces'; import dayjs from 'dayjs'; import { isEmpty } from 'lodash'; import { onStakeRewardExpired } from '../../src/cron/stakeReward.cron'; import { retryWallet } from '../../src/cron/wallet.cron'; -import { claimMintedTokenOrder } from '../../src/runtime/firebase/token/minting'; import { getAddress } from '../../src/utils/address.utils'; import { dateToTimestamp, serverTime } from '../../src/utils/dateTime.utils'; import { getRandomEthAddress } from '../../src/utils/wallet.utils'; -import { createMember, mockWalletReturnValue, wait } from '../../test/controls/common'; -import { testEnv } from '../../test/set-up'; +import { wait } from '../../test/controls/common'; +import { mockWalletReturnValue, testEnv } from '../../test/set-up'; import { awaitTransactionConfirmationsForToken } from '../common'; import { requestFundsFromFaucet, requestMintedTokenFromFaucet } from '../faucet'; import { Helper } from './Helper'; @@ -56,7 +59,10 @@ describe('Stake reward test test', () => { true, ); const distributionDocRef = build5Db().doc( - `${COL.TOKEN}/${helper.token!.uid}/${SUB_COL.DISTRIBUTION}/${member}`, + COL.TOKEN, + helper.token!.uid, + SUB_COL.DISTRIBUTION, + member, ); const distribution = await distributionDocRef.get(); expect(distribution.stakeRewards).toBe(count); @@ -74,7 +80,7 @@ describe('Stake reward test test', () => { token: helper.token?.uid!, status: StakeRewardStatus.UNPROCESSED, }; - const stakeRewardDocRef = build5Db().doc(`${COL.STAKE_REWARD}/${stakeReward.uid}`); + const stakeRewardDocRef = build5Db().doc(COL.STAKE_REWARD, stakeReward.uid); await stakeRewardDocRef.create(stakeReward); await onStakeRewardExpired(); @@ -95,8 +101,8 @@ describe('Stake reward test test', () => { await helper.stakeAmount(1000, 26); await helper.validateStatsStakeAmount(1000, 1000, 1490, 1490, StakeType.DYNAMIC, 1); - const member2Uid = await createMember(helper.walletSpy); - const member2 = await build5Db().doc(`${COL.MEMBER}/${member2Uid}`).get(); + const member2Uid = await testEnv.createMember(); + const member2 = await build5Db().doc(COL.MEMBER, member2Uid).get(); const member2Address = await helper.walletService?.getAddressDetails( getAddress(member2, helper.network)!, )!; @@ -122,7 +128,7 @@ describe('Stake reward test test', () => { token: helper.token?.uid!, status: StakeRewardStatus.UNPROCESSED, }; - const stakeRewardDocRef = build5Db().doc(`${COL.STAKE_REWARD}/${stakeReward.uid}`); + const stakeRewardDocRef = build5Db().doc(COL.STAKE_REWARD, stakeReward.uid); await stakeRewardDocRef.create(stakeReward); await onStakeRewardExpired(); @@ -162,16 +168,16 @@ describe('Stake reward test test', () => { token: helper.token?.uid!, status: StakeRewardStatus.UNPROCESSED, }; - const stakeRewardDocRef = build5Db().doc(`${COL.STAKE_REWARD}/${stakeReward.uid}`); + const stakeRewardDocRef = build5Db().doc(COL.STAKE_REWARD, stakeReward.uid); await stakeRewardDocRef.create(stakeReward); await onStakeRewardExpired(); await verifyMemberAirdrop(helper.member!.uid, 149); - mockWalletReturnValue(helper.walletSpy, helper.member!.uid, { + mockWalletReturnValue(helper.member!.uid, { symbol: helper.token!.symbol, }); - const claimOrder = await testEnv.wrap(claimMintedTokenOrder)({}); + const claimOrder = await testEnv.wrap(WEN_FUNC.claimMintedTokenOrder); await requestFundsFromFaucet( helper.network, claimOrder.payload.targetAddress, @@ -182,14 +188,14 @@ describe('Stake reward test test', () => { const snap = await build5Db() .collection(COL.TRANSACTION) .where('member', '==', helper.member!.uid) - .where('type', '==', TransactionType.BILL_PAYMENT) + .where('type', '==', PgTransactionType.BILL_PAYMENT) .get(); return snap.length === 2; }); await awaitTransactionConfirmationsForToken(helper.token?.uid!); - const member = await build5Db().doc(`${COL.MEMBER}/${helper.member?.uid}`).get(); + const member = await build5Db().doc(COL.MEMBER, helper.member?.uid!).get(); for (const address of [helper.memberAddress?.bech32!, getAddress(member, Network.RMS)]) { const outputs = await helper.walletService!.getOutputs(address, [], false, true); const nativeTokens = Object.values(outputs).reduce( @@ -200,7 +206,10 @@ describe('Stake reward test test', () => { } const distributionDocRef = build5Db().doc( - `${COL.TOKEN}/${helper.token?.uid}/${SUB_COL.DISTRIBUTION}/${helper.member?.uid}`, + COL.TOKEN, + helper.token?.uid!, + SUB_COL.DISTRIBUTION, + helper.member?.uid, ); await wait(async () => { const distribution = await distributionDocRef.get(); @@ -225,16 +234,16 @@ describe('Stake reward test test', () => { token: helper.token?.uid!, status: StakeRewardStatus.UNPROCESSED, }; - const stakeRewardDocRef = build5Db().doc(`${COL.STAKE_REWARD}/${stakeReward.uid}`); + const stakeRewardDocRef = build5Db().doc(COL.STAKE_REWARD, stakeReward.uid); await stakeRewardDocRef.create(stakeReward); await onStakeRewardExpired(); await verifyMemberAirdrop(helper.member!.uid, 149); - mockWalletReturnValue(helper.walletSpy, helper.member!.uid, { + mockWalletReturnValue(helper.member!.uid, { symbol: helper.token!.symbol, }); - const claimOrder = await testEnv.wrap(claimMintedTokenOrder)({}); + const claimOrder = await testEnv.wrap(WEN_FUNC.claimMintedTokenOrder); await requestFundsFromFaucet( helper.network, claimOrder.payload.targetAddress, @@ -244,10 +253,10 @@ describe('Stake reward test test', () => { const query = build5Db() .collection(COL.TRANSACTION) .where('member', '==', helper.member!.uid) - .where('type', '==', TransactionType.BILL_PAYMENT); + .where('type', '==', PgTransactionType.BILL_PAYMENT); let failed: any; await wait(async () => { - const snap = await query.get(); + const snap = await query.get(); failed = snap.find((d) => d?.payload?.walletReference?.count === 5); return snap.length === 2 && failed !== undefined; }); @@ -267,17 +276,17 @@ describe('Stake reward test test', () => { }); if (failed) { - const docRef = build5Db().doc(`${COL.TRANSACTION}/${failed.uid}`); + const docRef = build5Db().doc(COL.TRANSACTION, failed.uid); await docRef.update({ - 'payload.walletReference.count': 4, - 'payload.walletReference.processedOn': dateToTimestamp(dayjs().subtract(1, 'h')), + payload_walletReference_count: 4, + payload_walletReference_processedOn: dayjs().subtract(1, 'h').toDate(), }); } await retryWallet(); await awaitTransactionConfirmationsForToken(helper.token?.uid!); - const member = await build5Db().doc(`${COL.MEMBER}/${helper.member?.uid}`).get(); + const member = await build5Db().doc(COL.MEMBER, helper.member?.uid!).get(); for (const address of [helper.memberAddress?.bech32!, getAddress(member, Network.RMS)]) { const outputs = await helper.walletService!.getOutputs(address, [], false, true); const nativeTokens = Object.values(outputs).reduce( @@ -303,17 +312,17 @@ describe('Stake reward test test', () => { await helper.stakeAmount(25, 26); const stake = await helper.stakeAmount(12, 26); await build5Db() - .doc(`${COL.STAKE}/${stake.uid}`) + .doc(COL.STAKE, stake.uid) .update({ - createdOn: dateToTimestamp(dayjs().subtract(3, 'h')), - expiresAt: dateToTimestamp(dayjs().subtract(2, 'h')), + createdOn: dayjs().subtract(3, 'h').toDate(), + expiresAt: dayjs().subtract(2, 'h').toDate(), }); const stake2 = await helper.stakeAmount(13, 26); await build5Db() - .doc(`${COL.STAKE}/${stake2.uid}`) + .doc(COL.STAKE, stake2.uid) .update({ - createdOn: dateToTimestamp(dayjs().add(2, 'h')), - expiresAt: dateToTimestamp(dayjs().add(3, 'h')), + createdOn: dayjs().add(2, 'h').toDate(), + expiresAt: dayjs().add(3, 'h').toDate(), }); let stakeReward: StakeReward = { @@ -327,7 +336,7 @@ describe('Stake reward test test', () => { token: helper.token?.uid!, status: StakeRewardStatus.UNPROCESSED, }; - const stakeRewardDocRef = build5Db().doc(`${COL.STAKE_REWARD}/${stakeReward.uid}`); + const stakeRewardDocRef = build5Db().doc(COL.STAKE_REWARD, stakeReward.uid); await stakeRewardDocRef.create(stakeReward); await onStakeRewardExpired(); @@ -343,9 +352,12 @@ describe('Stake reward test test', () => { it('Should claim extras properly', async () => { const distributionDocRef = build5Db().doc( - `${COL.TOKEN}/${helper.token?.uid!}/${SUB_COL.DISTRIBUTION}/${helper.member?.uid}`, + COL.TOKEN, + helper.token?.uid!, + SUB_COL.DISTRIBUTION, + helper.member?.uid, ); - await distributionDocRef.set({ extraStakeRewards: 400 }, true); + await distributionDocRef.upsert({ extraStakeRewards: 400 }); const vaultAddress = await helper.walletService!.getAddressDetails(helper.space?.vaultAddress!); await requestFundsFromFaucet(helper.network, vaultAddress.bech32, MIN_IOTA_AMOUNT); @@ -370,36 +382,36 @@ describe('Stake reward test test', () => { token: helper.token?.uid!, status: StakeRewardStatus.UNPROCESSED, }; - const stakeRewardDocRef = build5Db().doc(`${COL.STAKE_REWARD}/${stakeReward.uid}`); + const stakeRewardDocRef = build5Db().doc(COL.STAKE_REWARD, stakeReward.uid); await stakeRewardDocRef.create(stakeReward); const billPaymentQuery = build5Db() .collection(COL.TRANSACTION) .where('member', '==', helper.member?.uid) - .where('ignoreWalletReason', '==', IgnoreWalletReason.EXTRA_STAKE_REWARD); + .where('ignoreWalletReason', '==', PgIgnoreWalletReason.EXTRA_STAKE_REWARD); // No reward, 149 reduction await onStakeRewardExpired(); - let snap = await billPaymentQuery.get(); + let snap = await billPaymentQuery.get(); expect(snap.length).toBe(1); - await stakeRewardDocRef.update({ status: StakeRewardStatus.UNPROCESSED }); + await stakeRewardDocRef.update({ status: PgStakeRewardStatus.UNPROCESSED }); let distribution = await distributionDocRef.get(); expect(distribution.extraStakeRewards).toBe(251); - snap = await billPaymentQuery.get(); + snap = await billPaymentQuery.get(); expect(snap[0]?.payload.nativeTokens![0]?.amount).toBe(149); // No reward, 149 reduction await onStakeRewardExpired(); snap = await billPaymentQuery.get(); expect(snap.length).toBe(2); - await stakeRewardDocRef.update({ status: StakeRewardStatus.UNPROCESSED }); + await stakeRewardDocRef.update({ status: PgStakeRewardStatus.UNPROCESSED }); distribution = await distributionDocRef.get(); expect(distribution.extraStakeRewards).toBe(102); await onStakeRewardExpired(); snap = await billPaymentQuery.get(); expect(snap.length).toBe(3); - await stakeRewardDocRef.update({ status: StakeRewardStatus.UNPROCESSED }); + await stakeRewardDocRef.update({ status: PgStakeRewardStatus.UNPROCESSED }); distribution = await distributionDocRef.get(); expect(distribution.extraStakeRewards).toBe(-47); diff --git a/packages/functions/test-tangle/staking/staking_5.spec.ts b/packages/functions/test-tangle/staking/staking_5.spec.ts index f693cea0f8..cb9c9ea316 100644 --- a/packages/functions/test-tangle/staking/staking_5.spec.ts +++ b/packages/functions/test-tangle/staking/staking_5.spec.ts @@ -3,8 +3,8 @@ import { COL, MIN_IOTA_AMOUNT, Network, - StakeType, SUB_COL, + StakeType, TangleRequestType, TokenDistribution, Transaction, @@ -54,11 +54,14 @@ describe('Stake reward test test', () => { }, }, }); - await build5Db().doc(`${COL.MNEMONIC}/${tmp.bech32}`).update({ consumedOutputIds: [] }); + await build5Db().doc(COL.MNEMONIC, tmp.bech32).update({ consumedOutputIds: [] }); await wait(async () => { const distributionDocRef = build5Db().doc( - `${COL.TOKEN}/${helper.token!.uid}/${SUB_COL.DISTRIBUTION}/${tmp.bech32}`, + COL.TOKEN, + helper.token!.uid, + SUB_COL.DISTRIBUTION, + tmp.bech32, ); const distribution = await distributionDocRef.get(); return (distribution?.stakes || {})[type]?.value === 200; diff --git a/packages/functions/test-tangle/stamp-tangle/Helper.ts b/packages/functions/test-tangle/stamp-tangle/Helper.ts index 2ceab6bcfe..f5b13f18e0 100644 --- a/packages/functions/test-tangle/stamp-tangle/Helper.ts +++ b/packages/functions/test-tangle/stamp-tangle/Helper.ts @@ -1,4 +1,4 @@ -import { build5Db, build5Storage } from '@build-5/database'; +import { PgTransactionType, build5Db, build5Storage } from '@build-5/database'; import { Bucket, COL, @@ -7,7 +7,6 @@ import { StampTangleRequest, TangleRequestType, Transaction, - TransactionType, } from '@build-5/interfaces'; import crypto from 'crypto'; import fs from 'fs'; @@ -53,13 +52,13 @@ export class Helper { const query = build5Db() .collection(COL.TRANSACTION) .where('member', '==', this.address.bech32) - .where('type', '==', TransactionType.CREDIT_TANGLE_REQUEST); + .where('type', '==', PgTransactionType.CREDIT_TANGLE_REQUEST); await wait(async () => { - const snap = await query.get(); + const snap = await query.get(); return snap.length === 1 && snap[0].payload.walletReference?.confirmed === true; }); - const credit = (await query.get())[0]; + const credit = (await query.get())[0]; return credit.payload.response!; }; } diff --git a/packages/functions/test-tangle/stamp-tangle/stamp-tangle_1_a.spec.ts b/packages/functions/test-tangle/stamp-tangle/stamp-tangle_1_a.spec.ts index 732aeabce8..297078dc80 100644 --- a/packages/functions/test-tangle/stamp-tangle/stamp-tangle_1_a.spec.ts +++ b/packages/functions/test-tangle/stamp-tangle/stamp-tangle_1_a.spec.ts @@ -1,12 +1,5 @@ -import { build5Db } from '@build-5/database'; -import { - COL, - KEY_NAME_TANGLE, - MediaStatus, - Stamp, - Transaction, - TransactionType, -} from '@build-5/interfaces'; +import { PgTransactionType, build5Db } from '@build-5/database'; +import { COL, KEY_NAME_TANGLE, MediaStatus, Stamp } from '@build-5/interfaces'; import { NftOutput } from '@iota/sdk'; import dayjs from 'dayjs'; import { uploadMediaToWeb3 } from '../../src/cron/media.cron'; @@ -23,7 +16,7 @@ describe('Stamp tangle test', () => { beforeEach(helper.beforeEach); it('Should create and mint stamp', async () => { - const fiftyDayCost = 2124 * 50 + 53700 + 108000; + const fiftyDayCost = 2124 * 50 + 53700 + 104500; await helper.wallet!.send( helper.address, @@ -35,10 +28,10 @@ describe('Stamp tangle test', () => { const query = build5Db().collection(COL.STAMP).where('createdBy', '==', helper.address.bech32); await wait(async () => { - const snap = await query.get(); + const snap = await query.get(); return snap.length === 1 && snap[0].funded; }); - let stamp = (await query.get())[0]; + let stamp = (await query.get())[0]; expect(stamp?.mediaStatus).toBe(MediaStatus.PENDING_UPLOAD); expect(stamp?.ipfsMedia).toBeDefined(); @@ -48,12 +41,12 @@ describe('Stamp tangle test', () => { expect(expiresBefore51Days).toBe(true); await uploadMediaToWeb3(); - const stampDocRef = build5Db().doc(`${COL.STAMP}/${stamp.uid}`); + const stampDocRef = build5Db().doc(COL.STAMP, stamp.uid); await wait(async () => { - const stamp = await stampDocRef.get(); + const stamp = await stampDocRef.get(); return stamp?.mediaStatus === MediaStatus.UPLOADED; }); - const uploadedMediaStamp = await stampDocRef.get(); + const uploadedMediaStamp = await stampDocRef.get(); expect(uploadedMediaStamp?.ipfsMedia).toBe(stamp?.ipfsMedia); await wait(async () => { @@ -73,9 +66,9 @@ describe('Stamp tangle test', () => { const billPayment = await build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.BILL_PAYMENT) - .where('payload.stamp', '==', stamp?.uid) - .get(); + .where('type', '==', PgTransactionType.BILL_PAYMENT) + .where('payload_stamp', '==', stamp?.uid) + .get(); expect(billPayment.length).toBe(1); }); }); diff --git a/packages/functions/test-tangle/stamp-tangle/stamp-tangle_1_b.spec.ts b/packages/functions/test-tangle/stamp-tangle/stamp-tangle_1_b.spec.ts index ab60c89f62..f390416424 100644 --- a/packages/functions/test-tangle/stamp-tangle/stamp-tangle_1_b.spec.ts +++ b/packages/functions/test-tangle/stamp-tangle/stamp-tangle_1_b.spec.ts @@ -1,13 +1,5 @@ -import { build5Db } from '@build-5/database'; -import { - COL, - KEY_NAME_TANGLE, - MIN_IOTA_AMOUNT, - MediaStatus, - Stamp, - Transaction, - TransactionType, -} from '@build-5/interfaces'; +import { PgTransactionType, build5Db } from '@build-5/database'; +import { COL, KEY_NAME_TANGLE, MIN_IOTA_AMOUNT, MediaStatus, Stamp } from '@build-5/interfaces'; import { NftOutput } from '@iota/sdk'; import dayjs from 'dayjs'; import { uploadMediaToWeb3 } from '../../src/cron/media.cron'; @@ -34,10 +26,10 @@ describe('Stamp tangle test', () => { const query = build5Db().collection(COL.STAMP).where('createdBy', '==', helper.address.bech32); await wait(async () => { - const snap = await query.get(); + const snap = await query.get(); return snap.length === 1 && snap[0].funded; }); - let stamp = (await query.get())[0]; + let stamp = (await query.get())[0]; expect(stamp?.mediaStatus).toBe(MediaStatus.PENDING_UPLOAD); expect(stamp?.ipfsMedia).toBeDefined(); @@ -47,12 +39,12 @@ describe('Stamp tangle test', () => { expect(expiresAfter30Days).toBe(true); await uploadMediaToWeb3(); - const stampDocRef = build5Db().doc(`${COL.STAMP}/${stamp.uid}`); + const stampDocRef = build5Db().doc(COL.STAMP, stamp.uid); await wait(async () => { - const stamp = await stampDocRef.get(); + const stamp = await stampDocRef.get(); return stamp?.mediaStatus === MediaStatus.UPLOADED; }); - const uploadedMediaStamp = await stampDocRef.get(); + const uploadedMediaStamp = await stampDocRef.get(); expect(uploadedMediaStamp?.ipfsMedia).toBe(stamp?.ipfsMedia); await wait(async () => { @@ -72,9 +64,9 @@ describe('Stamp tangle test', () => { const billPayment = await build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.BILL_PAYMENT) - .where('payload.stamp', '==', stamp?.uid) - .get(); + .where('type', '==', PgTransactionType.BILL_PAYMENT) + .where('payload_stamp', '==', stamp?.uid) + .get(); expect(billPayment.length).toBe(1); }); }); diff --git a/packages/functions/test-tangle/stamp-tangle/stamp-tangle_2.spec.ts b/packages/functions/test-tangle/stamp-tangle/stamp-tangle_2.spec.ts index b66e1f72fe..272b41b492 100644 --- a/packages/functions/test-tangle/stamp-tangle/stamp-tangle_2.spec.ts +++ b/packages/functions/test-tangle/stamp-tangle/stamp-tangle_2.spec.ts @@ -1,5 +1,5 @@ import { build5Db } from '@build-5/database'; -import { COL, MIN_IOTA_AMOUNT, Stamp } from '@build-5/interfaces'; +import { COL, MIN_IOTA_AMOUNT } from '@build-5/interfaces'; import { isEmpty } from 'lodash'; import { MnemonicService } from '../../src/services/wallet/mnemonic'; import { EMPTY_ALIAS_ID } from '../../src/utils/token-minting-utils/alias.utils'; @@ -23,10 +23,10 @@ describe('Stamp tangle test', () => { let query = build5Db().collection(COL.STAMP).where('createdBy', '==', helper.address.bech32); await wait(async () => { - const snap = await query.get(); + const snap = await query.get(); return snap.length === 1 && snap[0].aliasId !== EMPTY_ALIAS_ID; }); - const stamp = (await query.get())[0]; + const stamp = (await query.get())[0]; await helper.wallet!.send( helper.address, @@ -37,15 +37,15 @@ describe('Stamp tangle test', () => { await MnemonicService.store(helper.address.bech32, helper.address.mnemonic); await wait(async () => { - const snap = await query.get(); + const snap = await query.get(); return snap.length === 2 && snap[0].aliasId === snap[1].aliasId; }); await wait(async () => { - const snap = await query.get(); + const snap = await query.get(); return snap.reduce((acc, act) => acc && !isEmpty(act.nftId), true); }); - const stamps = await query.get(); + const stamps = await query.get(); expect(stamps.length).toBe(2); expect(stamps[0].aliasId).toBe(stamps[1].aliasId); expect(stamps[0].nftId).not.toBe(stamps[1].nftId); diff --git a/packages/functions/test-tangle/stamp-tangle/stamp-tangle_3.spec.ts b/packages/functions/test-tangle/stamp-tangle/stamp-tangle_3.spec.ts index 9f66919cc9..bd46430358 100644 --- a/packages/functions/test-tangle/stamp-tangle/stamp-tangle_3.spec.ts +++ b/packages/functions/test-tangle/stamp-tangle/stamp-tangle_3.spec.ts @@ -1,11 +1,5 @@ -import { build5Db } from '@build-5/database'; -import { - COL, - Stamp, - Transaction, - TransactionPayloadType, - TransactionType, -} from '@build-5/interfaces'; +import { PgTransactionPayloadType, PgTransactionType, build5Db } from '@build-5/database'; +import { COL, Stamp, Transaction } from '@build-5/interfaces'; import dayjs from 'dayjs'; import { updateExpiredStamp } from '../../src/cron/stamp.cron'; import { MnemonicService } from '../../src/services/wallet/mnemonic'; @@ -20,7 +14,7 @@ describe('Stamp tangle test', () => { it('Should extend stamp', async () => { const now = dayjs(); - const fiftyDayCost = 2124 * 50 + 53700 + 108000; + const fiftyDayCost = 2124 * 50 + 53700 + 104500; await helper.wallet!.send( helper.address, helper.tangleOrder.payload.targetAddress!, @@ -31,21 +25,21 @@ describe('Stamp tangle test', () => { const query = build5Db().collection(COL.STAMP).where('createdBy', '==', helper.address.bech32); await wait(async () => { - const snap = await query.get(); + const snap = await query.get(); return snap.length === 1 && snap[0].nftId !== undefined; }); - let stamp = (await query.get())[0]; + let stamp = (await query.get())[0]; const expiresAfter50Days = dayjs(stamp?.expiresAt.toDate()).isAfter(dayjs().add(4.32e9)); expect(expiresAfter50Days).toBe(true); - const orderDocRef = build5Db().doc(`${COL.TRANSACTION}/${stamp.order}`); + const orderDocRef = build5Db().doc(COL.TRANSACTION, stamp.order); const order = await orderDocRef.get(); await helper.wallet!.send(helper.address, order.payload.targetAddress!, fiftyDayCost, {}); await MnemonicService.store(helper.address.bech32, helper.address.mnemonic); await wait(async () => { - const stamp = (await query.get())[0]; + const stamp = (await query.get())[0]; const expiresAfter100Days = dayjs(stamp?.expiresAt.toDate()).isAfter(now.add(2 * 4.32e9)); return expiresAfter100Days; }); @@ -55,11 +49,11 @@ describe('Stamp tangle test', () => { const snap = await build5Db() .collection(COL.TRANSACTION) .where('member', '==', helper.address.bech32) - .where('type', '==', TransactionType.STAMP) + .where('type', '==', PgTransactionType.STAMP) .get(); expect(snap.length).toBe(2); - const stampDocRef = build5Db().doc(`${COL.STAMP}/${stamp.uid}`); + const stampDocRef = build5Db().doc(COL.STAMP, stamp.uid); await stampDocRef.update({ expiresAt: dayjs().subtract(1, 'h').toDate() }); await updateExpiredStamp(); stamp = await stampDocRef.get(); @@ -72,8 +66,8 @@ describe('Stamp tangle test', () => { const creditSnap = await build5Db() .collection(COL.TRANSACTION) .where('member', '==', helper.address.bech32) - .where('type', '==', TransactionType.CREDIT) - .where('payload.type', '==', TransactionPayloadType.INVALID_PAYMENT) + .where('type', '==', PgTransactionType.CREDIT) + .where('payload_type', '==', PgTransactionPayloadType.INVALID_PAYMENT) .get(); return creditSnap.length === 1; }); diff --git a/packages/functions/test-tangle/stamp-tangle/stamp-tangle_4.spec.ts b/packages/functions/test-tangle/stamp-tangle/stamp-tangle_4.spec.ts index 99e630552f..375bfdcd56 100644 --- a/packages/functions/test-tangle/stamp-tangle/stamp-tangle_4.spec.ts +++ b/packages/functions/test-tangle/stamp-tangle/stamp-tangle_4.spec.ts @@ -1,5 +1,5 @@ -import { build5Db } from '@build-5/database'; -import { COL, Transaction, TransactionType } from '@build-5/interfaces'; +import { PgTransactionType, build5Db } from '@build-5/database'; +import { COL } from '@build-5/interfaces'; import { MnemonicService } from '../../src/services/wallet/mnemonic'; import { wait } from '../../test/controls/common'; import { Helper } from './Helper'; @@ -23,12 +23,12 @@ describe('Stamp tangle test', () => { const query = build5Db() .collection(COL.TRANSACTION) .where('member', '==', helper.address.bech32) - .where('type', '==', TransactionType.CREDIT_TANGLE_REQUEST); + .where('type', '==', PgTransactionType.CREDIT_TANGLE_REQUEST); await wait(async () => { const snap = await query.get(); return snap.length === 1; }); - const credit = (await query.get())[0]; + const credit = (await query.get())[0]; expect(credit.payload.response!.address).toBeDefined(); }); }); diff --git a/packages/functions/test-tangle/stamp-tangle/stamp-tangle_5.spec.ts b/packages/functions/test-tangle/stamp-tangle/stamp-tangle_5.spec.ts index 9c730ea01d..0a826a7a69 100644 --- a/packages/functions/test-tangle/stamp-tangle/stamp-tangle_5.spec.ts +++ b/packages/functions/test-tangle/stamp-tangle/stamp-tangle_5.spec.ts @@ -1,5 +1,5 @@ import { build5Db, build5Storage } from '@build-5/database'; -import { Bucket, COL, MIN_IOTA_AMOUNT, MediaStatus, Stamp } from '@build-5/interfaces'; +import { Bucket, COL, MIN_IOTA_AMOUNT, MediaStatus } from '@build-5/interfaces'; import { uploadMediaToWeb3 } from '../../src/cron/media.cron'; import { MnemonicService } from '../../src/services/wallet/mnemonic'; import { EMPTY_ALIAS_ID } from '../../src/utils/token-minting-utils/alias.utils'; @@ -29,23 +29,23 @@ describe('Stamp tangle test', () => { const query = build5Db().collection(COL.STAMP).where('createdBy', '==', helper.address.bech32); await wait(async () => { - const snap = await query.get(); + const snap = await query.get(); return snap.length === 1 && snap[0].funded; }); - const stamp = (await query.get())[0]; + const stamp = (await query.get())[0]; expect(stamp?.mediaStatus).toBe(MediaStatus.PENDING_UPLOAD); expect(stamp?.ipfsMedia).toBeDefined(); await uploadMediaToWeb3(); await wait(async () => { - const stamp = (await query.get())[0]; + const stamp = (await query.get())[0]; return stamp?.mediaStatus === MediaStatus.UPLOADED; }); - const uploadedMediaStamp = (await query.get())[0]; + const uploadedMediaStamp = (await query.get())[0]; expect(uploadedMediaStamp?.ipfsMedia).toBe(stamp?.ipfsMedia); await wait(async () => { - const stamp = (await query.get())[0]; + const stamp = (await query.get())[0]; return stamp?.aliasId !== EMPTY_ALIAS_ID && stamp?.nftId !== undefined; }); }); diff --git a/packages/functions/test-tangle/stamp-tangle/stamp-tangle_6.spec.ts b/packages/functions/test-tangle/stamp-tangle/stamp-tangle_6.spec.ts index 1f43f59a3e..c2f2495603 100644 --- a/packages/functions/test-tangle/stamp-tangle/stamp-tangle_6.spec.ts +++ b/packages/functions/test-tangle/stamp-tangle/stamp-tangle_6.spec.ts @@ -1,13 +1,5 @@ -import { build5Db } from '@build-5/database'; -import { - COL, - KEY_NAME_TANGLE, - MIN_IOTA_AMOUNT, - MediaStatus, - Stamp, - Transaction, - TransactionType, -} from '@build-5/interfaces'; +import { PgTransactionType, build5Db } from '@build-5/database'; +import { COL, KEY_NAME_TANGLE, MIN_IOTA_AMOUNT, MediaStatus } from '@build-5/interfaces'; import { NftOutput } from '@iota/sdk'; import { uploadMediaToWeb3 } from '../../src/cron/media.cron'; import { MnemonicService } from '../../src/services/wallet/mnemonic'; @@ -36,10 +28,10 @@ describe('Stamp tangle test', () => { const query = build5Db().collection(COL.STAMP).where('createdBy', '==', helper.address.bech32); await wait(async () => { - const snap = await query.get(); + const snap = await query.get(); return snap.length === 1 && snap[0].funded; }); - let stamp = (await query.get())[0]; + let stamp = (await query.get())[0]; expect(stamp?.mediaStatus).toBe(MediaStatus.PENDING_UPLOAD); expect(stamp?.ipfsMedia).toBeDefined(); const ipfsMedia = stamp.ipfsMedia; @@ -47,17 +39,17 @@ describe('Stamp tangle test', () => { await uploadMediaToWeb3(); await wait(async () => { - stamp = (await query.get())[0]; + stamp = (await query.get())[0]; return stamp?.mediaStatus === MediaStatus.UPLOADED; }); expect(stamp?.ipfsMedia).toBe(ipfsMedia); await wait(async () => { - stamp = (await query.get())[0]; + stamp = (await query.get())[0]; return stamp?.aliasId !== EMPTY_ALIAS_ID && stamp?.nftId !== undefined; }); - stamp = (await query.get())[0]; + stamp = (await query.get())[0]; const nftOutputId = await helper.wallet.client.nftOutputId(stamp?.nftId!); const nftOutput = (await helper.wallet.client.getOutput(nftOutputId)).output as NftOutput; const metadata = getNftMetadata(nftOutput); @@ -67,9 +59,9 @@ describe('Stamp tangle test', () => { const billPayment = await build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.BILL_PAYMENT) - .where('payload.stamp', '==', stamp?.uid) - .get(); + .where('type', '==', PgTransactionType.BILL_PAYMENT) + .where('payload_stamp', '==', stamp?.uid) + .get(); expect(billPayment.length).toBe(1); }); }); diff --git a/packages/functions/test-tangle/swap/Helper.ts b/packages/functions/test-tangle/swap/Helper.ts index a195c91dbf..e1df7f54b0 100644 --- a/packages/functions/test-tangle/swap/Helper.ts +++ b/packages/functions/test-tangle/swap/Helper.ts @@ -1,4 +1,4 @@ -import { build5Db } from '@build-5/database'; +import { PgTransactionPayloadType, PgTransactionType, build5Db } from '@build-5/database'; import { Access, COL, @@ -14,29 +14,20 @@ import { SOON_PROJECT_ID, Space, Transaction, - TransactionPayloadType, TransactionType, UnsoldMintingOptions, + WEN_FUNC, } from '@build-5/interfaces'; import dayjs from 'dayjs'; import { set } from 'lodash'; -import { mintCollection } from '../../src/runtime/firebase/collection'; -import { createNft, openBid, orderNft, setForSaleNft } from '../../src/runtime/firebase/nft'; import { Wallet } from '../../src/services/wallet/wallet'; import { AddressDetails } from '../../src/services/wallet/wallet.service'; import * as wallet from '../../src/utils/wallet.utils'; -import { - createMember as createMemberTest, - createSpace, - mockWalletReturnValue, - submitMilestoneFunc, - wait, -} from '../../test/controls/common'; -import { MEDIA, getWallet, testEnv } from '../../test/set-up'; +import { submitMilestoneFunc, wait } from '../../test/controls/common'; +import { MEDIA, getWallet, mockWalletReturnValue, testEnv } from '../../test/set-up'; import { requestFundsFromFaucet } from '../faucet'; export class Helper { - public spy: any = {} as any; public network = Network.RMS; public guardian: string = {} as any; public member: string = {} as any; @@ -45,14 +36,13 @@ export class Helper { public space: Space = {} as any; public beforeAll = async () => { - this.spy = jest.spyOn(wallet, 'decodeAuth'); this.wallet = await getWallet(this.network); }; public beforeEach = async () => { - this.guardian = await createMemberTest(this.spy); - this.space = await createSpace(this.spy, this.guardian); - this.member = await createMemberTest(this.spy); + this.guardian = await testEnv.createMember(); + this.space = await testEnv.createSpace(this.guardian); + this.member = await testEnv.createMember(); }; public createDummyNft = (collection: string, description = 'babba') => ({ @@ -106,14 +96,14 @@ export class Helper { if (unsoldMintingOptions === UnsoldMintingOptions.SET_NEW_PRICE) { set(request, 'price', price); } - mockWalletReturnValue(this.spy, this.guardian!, request); - const collectionMintOrder = await testEnv.wrap(mintCollection)({}); + mockWalletReturnValue(this.guardian!, request); + const collectionMintOrder = await testEnv.wrap(WEN_FUNC.mintCollection); await requestFundsFromFaucet( this.network!, collectionMintOrder.payload.targetAddress, collectionMintOrder.payload.amount, ); - const collectionDocRef = build5Db().doc(`${COL.COLLECTION}/${this.collection}`); + const collectionDocRef = build5Db().doc(COL.COLLECTION, this.collection); await wait(async () => { const data = await collectionDocRef.get(); return data.status === CollectionStatus.MINTED; @@ -129,8 +119,8 @@ export class Helper { const ownerChangeTran = ( await build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.MINT_COLLECTION) - .where('payload.type', '==', TransactionPayloadType.SEND_ALIAS_TO_GUARDIAN) + .where('type', '==', PgTransactionType.MINT_COLLECTION) + .where('payload_type', '==', PgTransactionPayloadType.SEND_ALIAS_TO_GUARDIAN) .where('member', '==', this.guardian) .get() ).map((d) => d); @@ -144,34 +134,32 @@ export class Helper { delete nft.uid; delete nft.status; delete nft.placeholderNft; - mockWalletReturnValue(this.spy, this.guardian!, nft); - nft = await testEnv.wrap(createNft)({}); + mockWalletReturnValue(this.guardian!, nft); + nft = await testEnv.wrap(WEN_FUNC.createNft); if (buyAndAuctionId) { await build5Db() - .doc(`${COL.NFT}/${nft.uid}`) + .doc(COL.NFT, nft.uid) .update({ availableFrom: dayjs().subtract(1, 'h').toDate() }); - mockWalletReturnValue(this.spy, this.guardian!, { + mockWalletReturnValue(this.guardian!, { collection: this.collection, nft: nft.uid, }); - const order = await testEnv.wrap(orderNft)({}); + const order = await testEnv.wrap(WEN_FUNC.orderNft); await submitMilestoneFunc(order); - mockWalletReturnValue(this.spy, this.guardian!, this.dummyAuctionData(nft.uid)); - await testEnv.wrap(setForSaleNft)({}); - await wait( - async () => (await build5Db().doc(`${COL.NFT}/${nft.uid}`).get())?.available === 3, - ); + mockWalletReturnValue(this.guardian!, this.dummyAuctionData(nft.uid)); + await testEnv.wrap(WEN_FUNC.setForSaleNft); + await wait(async () => (await build5Db().doc(COL.NFT, nft.uid).get())?.available === 3); if (shouldBid) { - mockWalletReturnValue(this.spy, this.member!, { nft: nft.uid }); - const bidOrder = await testEnv.wrap(openBid)({}); + mockWalletReturnValue(this.member!, { nft: nft.uid }); + const bidOrder = await testEnv.wrap(WEN_FUNC.openBid); await submitMilestoneFunc(bidOrder, 2 * MIN_IOTA_AMOUNT); } } - return await build5Db().doc(`${COL.NFT}/${nft.uid}`).get(); + return await build5Db().doc(COL.NFT, nft.uid).get(); }; public dummyAuctionData = (uid: string) => ({ @@ -201,7 +189,7 @@ export class Helper { nftId, }, }; - await build5Db().doc(`${COL.TRANSACTION}/${order.uid}`).create(order); + await build5Db().doc(COL.TRANSACTION, order.uid).create(order); return order.uid; }; } diff --git a/packages/functions/test-tangle/swap/swap_1.spec.ts b/packages/functions/test-tangle/swap/swap_1.spec.ts index 04d921b1b3..6c20a95023 100644 --- a/packages/functions/test-tangle/swap/swap_1.spec.ts +++ b/packages/functions/test-tangle/swap/swap_1.spec.ts @@ -1,17 +1,16 @@ -import { build5Db } from '@build-5/database'; +import { PgTransactionType, build5Db } from '@build-5/database'; import { COL, MIN_IOTA_AMOUNT, Swap, SwapStatus, Transaction, - TransactionType, + WEN_FUNC, WenError, } from '@build-5/interfaces'; -import { createSwap, setSwapFunded } from '../../src/runtime/firebase/swap'; import { MnemonicService } from '../../src/services/wallet/mnemonic'; -import { expectThrow, mockWalletReturnValue, wait } from '../../test/controls/common'; -import { testEnv } from '../../test/set-up'; +import { expectThrow, wait } from '../../test/controls/common'; +import { mockWalletReturnValue, testEnv } from '../../test/set-up'; import { awaitLedgerInclusionState, requestFundsFromFaucet, @@ -37,18 +36,18 @@ describe('Swap control test', () => { }); it('Should create, offer minted tokens, request base token', async () => { - mockWalletReturnValue(h.spy, h.guardian, { + mockWalletReturnValue(h.guardian, { network: h.network, baseTokenAmount: MIN_IOTA_AMOUNT, recipient: h.member, }); - const swapOrder: Transaction = await testEnv.wrap(createSwap)({}); + const swapOrder = await testEnv.wrap(WEN_FUNC.createSwap); - const swapDocRef = build5Db().doc(`${COL.SWAP}/${swapOrder.payload.swap}`); + const swapDocRef = build5Db().doc(COL.SWAP, swapOrder.payload.swap!); let swap = await swapDocRef.get(); - mockWalletReturnValue(h.spy, h.guardian, { uid: swap.uid }); - await expectThrow(testEnv.wrap(setSwapFunded)({}), WenError.swap_must_be_funded.key); + mockWalletReturnValue(h.guardian, { uid: swap.uid }); + await expectThrow(testEnv.wrap(WEN_FUNC.setSwapFunded), WenError.swap_must_be_funded.key); const source = await h.wallet.getNewIotaAddressDetails(); await requestFundsFromFaucet(h.network, source.bech32, 10 * MIN_IOTA_AMOUNT); @@ -77,10 +76,10 @@ describe('Swap control test', () => { ]); expect(swap.bidOutputs!.map((nt) => nt.nativeTokens![0].amount!)).toEqual(['0x5', '0x5']); - mockWalletReturnValue(h.spy, h.member, { uid: swap.uid }); - await expectThrow(testEnv.wrap(setSwapFunded)({}), WenError.not_swap_owner.key); - mockWalletReturnValue(h.spy, h.guardian, { uid: swap.uid }); - await testEnv.wrap(setSwapFunded)({}); + mockWalletReturnValue(h.member, { uid: swap.uid }); + await expectThrow(testEnv.wrap(WEN_FUNC.setSwapFunded), WenError.not_swap_owner.key); + mockWalletReturnValue(h.guardian, { uid: swap.uid }); + await testEnv.wrap(WEN_FUNC.setSwapFunded); swap = await swapDocRef.get(); expect(swap.status).toBe(SwapStatus.FUNDED); @@ -93,10 +92,10 @@ describe('Swap control test', () => { let query = build5Db() .collection(COL.TRANSACTION) - .where('payload.swap', '==', swap.uid) - .where('type', '==', TransactionType.BILL_PAYMENT); + .where('payload_swap', '==', swap.uid) + .where('type', '==', PgTransactionType.BILL_PAYMENT); await wait(async () => { - const snap = await query.get(); + const snap = await query.get(); return ( snap.length === 3 && snap.reduce((acc, act) => (acc && act.payload.walletReference?.confirmed) || false, true) @@ -106,8 +105,8 @@ describe('Swap control test', () => { query = build5Db() .collection(COL.TRANSACTION) .where('member', '==', h.guardian) - .where('type', '==', TransactionType.BILL_PAYMENT); - let billPayments = await query.get(); + .where('type', '==', PgTransactionType.BILL_PAYMENT); + let billPayments = await query.get(); expect(billPayments.length).toBe(1); expect(billPayments[0].payload.amount).toBe(MIN_IOTA_AMOUNT); expect(billPayments[0].payload.nativeTokens).toEqual([]); @@ -116,8 +115,8 @@ describe('Swap control test', () => { query = build5Db() .collection(COL.TRANSACTION) .where('member', '==', h.member) - .where('type', '==', TransactionType.BILL_PAYMENT); - billPayments = await query.get(); + .where('type', '==', PgTransactionType.BILL_PAYMENT); + billPayments = await query.get(); expect(billPayments.length).toBe(2); expect(billPayments.map((b) => b.payload.nativeTokens![0].id).sort()).toEqual( [MINTED_TOKEN_ID_1, MINTED_TOKEN_ID_2].sort(), diff --git a/packages/functions/test-tangle/swap/swap_2.spec.ts b/packages/functions/test-tangle/swap/swap_2.spec.ts index 466118c893..c40c230af5 100644 --- a/packages/functions/test-tangle/swap/swap_2.spec.ts +++ b/packages/functions/test-tangle/swap/swap_2.spec.ts @@ -1,16 +1,8 @@ -import { build5Db } from '@build-5/database'; -import { - COL, - MIN_IOTA_AMOUNT, - Swap, - SwapStatus, - Transaction, - TransactionType, -} from '@build-5/interfaces'; -import { createSwap, setSwapFunded } from '../../src/runtime/firebase/swap'; +import { PgTransactionType, build5Db } from '@build-5/database'; +import { COL, MIN_IOTA_AMOUNT, Swap, SwapStatus, Transaction, WEN_FUNC } from '@build-5/interfaces'; import { MnemonicService } from '../../src/services/wallet/mnemonic'; -import { mockWalletReturnValue, wait } from '../../test/controls/common'; -import { testEnv } from '../../test/set-up'; +import { wait } from '../../test/controls/common'; +import { mockWalletReturnValue, testEnv } from '../../test/set-up'; import { awaitLedgerInclusionState, requestFundsFromFaucet, @@ -36,7 +28,7 @@ describe('Swap control test', () => { }); it('Should create, offer base token, request minted tokens, ', async () => { - mockWalletReturnValue(h.spy, h.guardian, { + mockWalletReturnValue(h.guardian, { network: h.network, nativeTokens: [ { id: MINTED_TOKEN_ID_1, amount: 5 }, @@ -44,9 +36,9 @@ describe('Swap control test', () => { ], recipient: h.member, }); - const swapOrder: Transaction = await testEnv.wrap(createSwap)({}); + const swapOrder = await testEnv.wrap(WEN_FUNC.createSwap); - const swapDocRef = build5Db().doc(`${COL.SWAP}/${swapOrder.payload.swap}`); + const swapDocRef = build5Db().doc(COL.SWAP, swapOrder.payload.swap!); let swap = await swapDocRef.get(); await requestFundsFromFaucet(h.network, swapOrder.payload.targetAddress!, MIN_IOTA_AMOUNT); @@ -55,8 +47,8 @@ describe('Swap control test', () => { return swap.bidOutputs?.length === 1; }); - mockWalletReturnValue(h.spy, h.guardian, { uid: swap.uid }); - await testEnv.wrap(setSwapFunded)({}); + mockWalletReturnValue(h.guardian, { uid: swap.uid }); + await testEnv.wrap(WEN_FUNC.setSwapFunded); swap = await swapDocRef.get(); expect(swap.status).toBe(SwapStatus.FUNDED); @@ -94,10 +86,10 @@ describe('Swap control test', () => { let query = build5Db() .collection(COL.TRANSACTION) - .where('payload.swap', '==', swap.uid) - .where('type', '==', TransactionType.BILL_PAYMENT); + .where('payload_swap', '==', swap.uid) + .where('type', '==', PgTransactionType.BILL_PAYMENT); await wait(async () => { - const snap = await query.get(); + const snap = await query.get(); return ( snap.length === 3 && snap.reduce((acc, act) => (acc && act.payload.walletReference?.confirmed) || false, true) @@ -107,8 +99,8 @@ describe('Swap control test', () => { query = build5Db() .collection(COL.TRANSACTION) .where('member', '==', h.member) - .where('type', '==', TransactionType.BILL_PAYMENT); - let billPayments = await query.get(); + .where('type', '==', PgTransactionType.BILL_PAYMENT); + let billPayments = await query.get(); expect(billPayments.length).toBe(1); expect(billPayments[0].payload.amount).toBe(MIN_IOTA_AMOUNT); expect(billPayments[0].payload.nativeTokens).toEqual([]); @@ -117,8 +109,8 @@ describe('Swap control test', () => { query = build5Db() .collection(COL.TRANSACTION) .where('member', '==', h.guardian) - .where('type', '==', TransactionType.BILL_PAYMENT); - billPayments = await query.get(); + .where('type', '==', PgTransactionType.BILL_PAYMENT); + billPayments = await query.get(); expect(billPayments.length).toBe(2); const nativeTokens = billPayments.map((b) => b.payload.nativeTokens![0].id).sort(); expect(nativeTokens).toEqual([MINTED_TOKEN_ID_1, MINTED_TOKEN_ID_2].sort()); diff --git a/packages/functions/test-tangle/swap/swap_3_a.spec.ts b/packages/functions/test-tangle/swap/swap_3_a.spec.ts index 3f0624b816..3496543398 100644 --- a/packages/functions/test-tangle/swap/swap_3_a.spec.ts +++ b/packages/functions/test-tangle/swap/swap_3_a.spec.ts @@ -1,21 +1,19 @@ -import { build5Db } from '@build-5/database'; +import { PgTransactionType, build5Db } from '@build-5/database'; import { COL, + Collection, MIN_IOTA_AMOUNT, Member, Nft, Swap, SwapStatus, Transaction, - TransactionType, + WEN_FUNC, WenError, } from '@build-5/interfaces'; -import { createCollection } from '../../src/runtime/firebase/collection'; -import { withdrawNft } from '../../src/runtime/firebase/nft'; -import { createSwap, rejectSwap, setSwapFunded } from '../../src/runtime/firebase/swap'; import { getAddress } from '../../src/utils/address.utils'; -import { expectThrow, mockWalletReturnValue, wait } from '../../test/controls/common'; -import { testEnv } from '../../test/set-up'; +import { expectThrow, wait } from '../../test/controls/common'; +import { mockWalletReturnValue, testEnv } from '../../test/set-up'; import { requestFundsFromFaucet, requestMintedTokenFromFaucet } from '../faucet'; import { Helper, MINTED_TOKEN_ID_1, VAULT_MNEMONIC_1 } from './Helper'; @@ -30,30 +28,30 @@ describe('Swap control test', () => { beforeEach(async () => { await h.beforeEach(); - mockWalletReturnValue(h.spy, h.guardian, h.createDummyCollection(h.space.uid, h.space.uid)); - h.collection = (await testEnv.wrap(createCollection)({})).uid; + mockWalletReturnValue(h.guardian, h.createDummyCollection(h.space.uid, h.space.uid)); + h.collection = (await testEnv.wrap(WEN_FUNC.createCollection)).uid; nfts = [(await h.createAndOrderNft(true)).uid, (await h.createAndOrderNft(true)).uid]; await h.mintCollection(); - mockWalletReturnValue(h.spy, h.guardian!, { nft: nfts[0] }); - await testEnv.wrap(withdrawNft)({}); + mockWalletReturnValue(h.guardian!, { nft: nfts[0] }); + await testEnv.wrap(WEN_FUNC.withdrawNft); - mockWalletReturnValue(h.spy, h.guardian!, { nft: nfts[1] }); - await testEnv.wrap(withdrawNft)({}); + mockWalletReturnValue(h.guardian!, { nft: nfts[1] }); + await testEnv.wrap(WEN_FUNC.withdrawNft); }); it('Should create, offer base token, request nft', async () => { - mockWalletReturnValue(h.spy, h.member, { + mockWalletReturnValue(h.member, { network: h.network, nativeTokens: [{ id: MINTED_TOKEN_ID_1, amount: 5 }], nfts, recipient: h.guardian, }); - const swapOrder: Transaction = await testEnv.wrap(createSwap)({}); + const swapOrder = await testEnv.wrap(WEN_FUNC.createSwap); - const swapDocRef = build5Db().doc(`${COL.SWAP}/${swapOrder.payload.swap}`); + const swapDocRef = build5Db().doc(COL.SWAP, swapOrder.payload.swap!); let swap = await swapDocRef.get(); await requestFundsFromFaucet(h.network, swapOrder.payload.targetAddress!, MIN_IOTA_AMOUNT); @@ -61,12 +59,12 @@ describe('Swap control test', () => { swap = await swapDocRef.get(); return swap.bidOutputs?.length === 1; }); - mockWalletReturnValue(h.spy, h.member, { uid: swap.uid }); - await testEnv.wrap(setSwapFunded)({}); + mockWalletReturnValue(h.member, { uid: swap.uid }); + await testEnv.wrap(WEN_FUNC.setSwapFunded); swap = await swapDocRef.get(); expect(swap.status).toBe(SwapStatus.FUNDED); - const guardianDocRef = build5Db().doc(`${COL.MEMBER}/${h.guardian}`); + const guardianDocRef = build5Db().doc(COL.MEMBER, h.guardian); const guardianData = await guardianDocRef.get(); const sourceAddress = await h.wallet.getAddressDetails(getAddress(guardianData, h.network)); @@ -75,7 +73,7 @@ describe('Swap control test', () => { return result.items.length === 2; }); for (const nftUid of nfts) { - const docRef = build5Db().doc(`${COL.NFT}/${nftUid}`); + const docRef = build5Db().doc(COL.NFT, nftUid); const nft = await docRef.get(); await h.sendNftToAddress(sourceAddress, swap.address, nft.mintingData?.nftId!); } @@ -95,20 +93,20 @@ describe('Swap control test', () => { let query = build5Db() .collection(COL.TRANSACTION) .where('member', '==', h.member) - .where('type', '==', TransactionType.BILL_PAYMENT) - .where('payload.swap', '==', swap.uid); + .where('type', '==', PgTransactionType.BILL_PAYMENT) + .where('payload_swap', '==', swap.uid); await wait(async () => { - const snap = await query.get(); + const snap = await query.get(); return snap.length === 1 && (snap[0].payload.walletReference?.confirmed || false); }); query = build5Db() .collection(COL.TRANSACTION) .where('member', '==', h.member) - .where('type', '==', TransactionType.WITHDRAW_NFT) - .where('payload.swap', '==', swap.uid); + .where('type', '==', PgTransactionType.WITHDRAW_NFT) + .where('payload_swap', '==', swap.uid); await wait(async () => { - const snap = await query.get(); + const snap = await query.get(); return ( snap.length === 2 && (snap[0].payload.walletReference?.confirmed || false) && @@ -116,7 +114,7 @@ describe('Swap control test', () => { ); }); - const memberDocRef = build5Db().doc(`${COL.MEMBER}/${h.member}`); + const memberDocRef = build5Db().doc(COL.MEMBER, h.member); const member = await memberDocRef.get(); const response = await h.wallet.client.nftOutputIds([ { address: getAddress(member, h.network) }, @@ -126,14 +124,14 @@ describe('Swap control test', () => { query = build5Db() .collection(COL.TRANSACTION) .where('member', '==', h.guardian) - .where('type', '==', TransactionType.BILL_PAYMENT) - .where('payload.swap', '==', swap.uid); + .where('type', '==', PgTransactionType.BILL_PAYMENT) + .where('payload_swap', '==', swap.uid); await wait(async () => { - const snap = await query.get(); + const snap = await query.get(); return snap.length === 1 && (snap[0].payload.walletReference?.confirmed || false); }); - mockWalletReturnValue(h.spy, h.member, { uid: swap.uid }); - await expectThrow(testEnv.wrap(rejectSwap)({}), WenError.swap_already_fulfilled.key); + mockWalletReturnValue(h.member, { uid: swap.uid }); + await expectThrow(testEnv.wrap(WEN_FUNC.rejectSwap), WenError.swap_already_fulfilled.key); }); }); diff --git a/packages/functions/test-tangle/swap/swap_3_b.spec.ts b/packages/functions/test-tangle/swap/swap_3_b.spec.ts index 2af09e2879..06b6b4f5f9 100644 --- a/packages/functions/test-tangle/swap/swap_3_b.spec.ts +++ b/packages/functions/test-tangle/swap/swap_3_b.spec.ts @@ -1,21 +1,19 @@ -import { build5Db } from '@build-5/database'; +import { PgTransactionType, build5Db } from '@build-5/database'; import { COL, + Collection, MIN_IOTA_AMOUNT, Member, Nft, Swap, SwapStatus, Transaction, - TransactionType, + WEN_FUNC, WenError, } from '@build-5/interfaces'; -import { createCollection } from '../../src/runtime/firebase/collection'; -import { withdrawNft } from '../../src/runtime/firebase/nft'; -import { createSwap, rejectSwap, setSwapFunded } from '../../src/runtime/firebase/swap'; import { getAddress } from '../../src/utils/address.utils'; -import { expectThrow, mockWalletReturnValue, wait } from '../../test/controls/common'; -import { testEnv } from '../../test/set-up'; +import { expectThrow, wait } from '../../test/controls/common'; +import { mockWalletReturnValue, testEnv } from '../../test/set-up'; import { requestFundsFromFaucet, requestMintedTokenFromFaucet } from '../faucet'; import { Helper, MINTED_TOKEN_ID_1, VAULT_MNEMONIC_1 } from './Helper'; @@ -30,30 +28,30 @@ describe('Swap control test', () => { beforeEach(async () => { await h.beforeEach(); - mockWalletReturnValue(h.spy, h.guardian, h.createDummyCollection(h.space.uid, h.space.uid)); - h.collection = (await testEnv.wrap(createCollection)({})).uid; + mockWalletReturnValue(h.guardian, h.createDummyCollection(h.space.uid, h.space.uid)); + h.collection = (await testEnv.wrap(WEN_FUNC.createCollection)).uid; nfts = [(await h.createAndOrderNft(true)).uid, (await h.createAndOrderNft(true)).uid]; await h.mintCollection(); - mockWalletReturnValue(h.spy, h.guardian!, { nft: nfts[0] }); - await testEnv.wrap(withdrawNft)({}); + mockWalletReturnValue(h.guardian!, { nft: nfts[0] }); + await testEnv.wrap(WEN_FUNC.withdrawNft); - mockWalletReturnValue(h.spy, h.guardian!, { nft: nfts[1] }); - await testEnv.wrap(withdrawNft)({}); + mockWalletReturnValue(h.guardian!, { nft: nfts[1] }); + await testEnv.wrap(WEN_FUNC.withdrawNft); }); it('Should create, offer base token, request nft', async () => { - mockWalletReturnValue(h.spy, h.member, { + mockWalletReturnValue(h.member, { network: h.network, nativeTokens: [{ id: MINTED_TOKEN_ID_1, amount: 5 }], nfts, recipient: h.guardian, }); - const swapOrder: Transaction = await testEnv.wrap(createSwap)({}); + const swapOrder = await testEnv.wrap(WEN_FUNC.createSwap); - const swapDocRef = build5Db().doc(`${COL.SWAP}/${swapOrder.payload.swap}`); + const swapDocRef = build5Db().doc(COL.SWAP, swapOrder.payload.swap!); let swap = await swapDocRef.get(); await requestFundsFromFaucet(h.network, swapOrder.payload.targetAddress!, MIN_IOTA_AMOUNT); @@ -62,7 +60,7 @@ describe('Swap control test', () => { return swap.bidOutputs?.length === 1; }); - const guardianDocRef = build5Db().doc(`${COL.MEMBER}/${h.guardian}`); + const guardianDocRef = build5Db().doc(COL.MEMBER, h.guardian); const guardianData = await guardianDocRef.get(); const sourceAddress = await h.wallet.getAddressDetails(getAddress(guardianData, h.network)); await wait(async () => { @@ -70,7 +68,7 @@ describe('Swap control test', () => { return result.items.length === 2; }); for (const nftUid of nfts) { - const docRef = build5Db().doc(`${COL.NFT}/${nftUid}`); + const docRef = build5Db().doc(COL.NFT, nftUid); const nft = await docRef.get(); await h.sendNftToAddress(sourceAddress, swap.address, nft.mintingData?.nftId!); } @@ -87,28 +85,28 @@ describe('Swap control test', () => { return swap.askOutputs?.length === 3 && swap.bidOutputs?.length === 1; }); - mockWalletReturnValue(h.spy, h.member, { uid: swap.uid }); - await testEnv.wrap(setSwapFunded)({}); + mockWalletReturnValue(h.member, { uid: swap.uid }); + await testEnv.wrap(WEN_FUNC.setSwapFunded); swap = await swapDocRef.get(); expect(swap.status).toBe(SwapStatus.FULFILLED); let query = build5Db() .collection(COL.TRANSACTION) .where('member', '==', h.member) - .where('type', '==', TransactionType.BILL_PAYMENT) - .where('payload.swap', '==', swap.uid); + .where('type', '==', PgTransactionType.BILL_PAYMENT) + .where('payload_swap', '==', swap.uid); await wait(async () => { - const snap = await query.get(); + const snap = await query.get(); return snap.length === 1 && (snap[0].payload.walletReference?.confirmed || false); }); query = build5Db() .collection(COL.TRANSACTION) .where('member', '==', h.member) - .where('type', '==', TransactionType.WITHDRAW_NFT) - .where('payload.swap', '==', swap.uid); + .where('type', '==', PgTransactionType.WITHDRAW_NFT) + .where('payload_swap', '==', swap.uid); await wait(async () => { - const snap = await query.get(); + const snap = await query.get(); return ( snap.length === 2 && (snap[0].payload.walletReference?.confirmed || false) && @@ -116,7 +114,7 @@ describe('Swap control test', () => { ); }); - const memberDocRef = build5Db().doc(`${COL.MEMBER}/${h.member}`); + const memberDocRef = build5Db().doc(COL.MEMBER, h.member); const member = await memberDocRef.get(); const response = await h.wallet.client.nftOutputIds([ { address: getAddress(member, h.network) }, @@ -126,14 +124,14 @@ describe('Swap control test', () => { query = build5Db() .collection(COL.TRANSACTION) .where('member', '==', h.guardian) - .where('type', '==', TransactionType.BILL_PAYMENT) - .where('payload.swap', '==', swap.uid); + .where('type', '==', PgTransactionType.BILL_PAYMENT) + .where('payload_swap', '==', swap.uid); await wait(async () => { - const snap = await query.get(); + const snap = await query.get(); return snap.length === 1 && (snap[0].payload.walletReference?.confirmed || false); }); - mockWalletReturnValue(h.spy, h.member, { uid: swap.uid }); - await expectThrow(testEnv.wrap(rejectSwap)({}), WenError.swap_already_fulfilled.key); + mockWalletReturnValue(h.member, { uid: swap.uid }); + await expectThrow(testEnv.wrap(WEN_FUNC.rejectSwap), WenError.swap_already_fulfilled.key); }); }); diff --git a/packages/functions/test-tangle/swap/swap_4.spec.ts b/packages/functions/test-tangle/swap/swap_4.spec.ts index 4fc0888a61..ce1cdc0e0e 100644 --- a/packages/functions/test-tangle/swap/swap_4.spec.ts +++ b/packages/functions/test-tangle/swap/swap_4.spec.ts @@ -1,13 +1,5 @@ -import { build5Db } from '@build-5/database'; -import { - COL, - MIN_IOTA_AMOUNT, - Swap, - SwapStatus, - TangleRequestType, - Transaction, - TransactionType, -} from '@build-5/interfaces'; +import { PgTransactionType, build5Db } from '@build-5/database'; +import { COL, MIN_IOTA_AMOUNT, SwapStatus, TangleRequestType } from '@build-5/interfaces'; import { wait } from '../../test/controls/common'; import { getTangleOrder } from '../common'; import { requestFundsFromFaucet } from '../faucet'; @@ -44,12 +36,12 @@ describe('Swap control test', () => { customMetadata: { request }, }); - let query = build5Db().collection(COL.SWAP).where('createdBy', '==', address.bech32); + const createdByQuery = build5Db().collection(COL.SWAP).where('createdBy', '==', address.bech32); await wait(async () => { - const snap = await query.get(); + const snap = await createdByQuery.get(); return snap.length === 1; }); - const swap = (await query.get())[0]; + const swap = (await createdByQuery.get())[0]; expect(swap.bidOutputs?.length).toBe(1); expect(swap.bidOutputs![0].amount).toBe(MIN_IOTA_AMOUNT); expect(swap.status).toBe(SwapStatus.FUNDED); @@ -57,11 +49,11 @@ describe('Swap control test', () => { [MINTED_TOKEN_ID_1, MINTED_TOKEN_ID_2].sort(), ); - query = build5Db() + const query = build5Db() .collection(COL.TRANSACTION) .where('member', '==', address.bech32) - .where('type', '==', TransactionType.CREDIT_TANGLE_REQUEST); - const snap = await query.get(); + .where('type', '==', PgTransactionType.CREDIT_TANGLE_REQUEST); + const snap = await query.get(); expect(snap.length).toBe(0); }); }); diff --git a/packages/functions/test-tangle/swap/swap_5.spec.ts b/packages/functions/test-tangle/swap/swap_5.spec.ts index 0900787269..847a08adea 100644 --- a/packages/functions/test-tangle/swap/swap_5.spec.ts +++ b/packages/functions/test-tangle/swap/swap_5.spec.ts @@ -1,13 +1,5 @@ -import { build5Db } from '@build-5/database'; -import { - COL, - MIN_IOTA_AMOUNT, - Swap, - SwapStatus, - TangleRequestType, - Transaction, - TransactionType, -} from '@build-5/interfaces'; +import { PgTransactionType, build5Db } from '@build-5/database'; +import { COL, MIN_IOTA_AMOUNT, SwapStatus, TangleRequestType } from '@build-5/interfaces'; import { MnemonicService } from '../../src/services/wallet/mnemonic'; import { wait } from '../../test/controls/common'; import { getTangleOrder } from '../common'; @@ -48,38 +40,38 @@ describe('Swap control test', () => { const creditQuery = build5Db() .collection(COL.TRANSACTION) .where('member', '==', address.bech32) - .where('type', '==', TransactionType.CREDIT_TANGLE_REQUEST) + .where('type', '==', PgTransactionType.CREDIT_TANGLE_REQUEST) .orderBy('createdOn'); await wait(async () => { - const snap = await creditQuery.get(); + const snap = await creditQuery.get(); return snap.length === 1 && snap[0].payload.walletReference?.confirmed; }); - let credit = (await creditQuery.get())[0]; + let credit = (await creditQuery.get())[0]; expect(credit.payload.response?.address).toBeDefined(); expect(credit.payload.response?.swap).toBeDefined(); const swapAddress = credit.payload.response?.address as string; - const swapUid = credit.payload.response?.swap!; + const swapUid = credit.payload.response?.swap! as string; await h.wallet.send(address, tangleOrder.payload.targetAddress!, MIN_IOTA_AMOUNT, { customMetadata: { request: { requestType: TangleRequestType.SET_SWAP_FUNDED, uid: swapUid } }, }); await MnemonicService.store(address.bech32, address.mnemonic, h.network); await wait(async () => { - const snap = await creditQuery.get(); + const snap = await creditQuery.get(); return ( snap.length === 2 && snap.reduce((acc, act) => (acc && act.payload.walletReference?.confirmed) || false, true) ); }); - credit = (await creditQuery.get())[1]; + credit = (await creditQuery.get())[1]; expect(credit.payload.response?.code).toBe(2152); await h.wallet.send(address, swapAddress, MIN_IOTA_AMOUNT, {}); await MnemonicService.store(address.bech32, address.mnemonic, h.network); - const swapDocRef = build5Db().doc(`${COL.SWAP}/${swapUid}`); + const swapDocRef = build5Db().doc(COL.SWAP, swapUid); await wait(async () => { - const swap = await swapDocRef.get(); + const swap = await swapDocRef.get(); return swap?.bidOutputs?.length === 1; }); @@ -89,14 +81,14 @@ describe('Swap control test', () => { await MnemonicService.store(address.bech32, address.mnemonic, h.network); await wait(async () => { - const snap = await creditQuery.get(); + const snap = await creditQuery.get(); return ( snap.length === 3 && snap.reduce((acc, act) => (acc && act.payload.walletReference?.confirmed) || false, true) ); }); - const swap = await swapDocRef.get(); + const swap = await swapDocRef.get(); expect(swap?.bidOutputs?.length).toBe(1); expect(swap?.status).toBe(SwapStatus.FUNDED); }); diff --git a/packages/functions/test-tangle/swap/swap_6.spec.ts b/packages/functions/test-tangle/swap/swap_6.spec.ts index f026495925..44e6b892fc 100644 --- a/packages/functions/test-tangle/swap/swap_6.spec.ts +++ b/packages/functions/test-tangle/swap/swap_6.spec.ts @@ -1,21 +1,19 @@ -import { build5Db } from '@build-5/database'; +import { PgTransactionType, build5Db } from '@build-5/database'; import { COL, + Collection, MIN_IOTA_AMOUNT, Member, Nft, Swap, SwapStatus, Transaction, - TransactionType, + WEN_FUNC, WenError, } from '@build-5/interfaces'; -import { createCollection } from '../../src/runtime/firebase/collection'; -import { withdrawNft } from '../../src/runtime/firebase/nft'; -import { createSwap, rejectSwap } from '../../src/runtime/firebase/swap'; import { getAddress } from '../../src/utils/address.utils'; -import { createMember, expectThrow, mockWalletReturnValue, wait } from '../../test/controls/common'; -import { testEnv } from '../../test/set-up'; +import { expectThrow, wait } from '../../test/controls/common'; +import { mockWalletReturnValue, testEnv } from '../../test/set-up'; import { requestFundsFromFaucet, requestMintedTokenFromFaucet } from '../faucet'; import { Helper, MINTED_TOKEN_ID_1, VAULT_MNEMONIC_1 } from './Helper'; @@ -30,30 +28,30 @@ describe('Swap control test', () => { beforeEach(async () => { await h.beforeEach(); - mockWalletReturnValue(h.spy, h.guardian, h.createDummyCollection(h.space.uid, h.space.uid)); - h.collection = (await testEnv.wrap(createCollection)({})).uid; + mockWalletReturnValue(h.guardian, h.createDummyCollection(h.space.uid, h.space.uid)); + h.collection = (await testEnv.wrap(WEN_FUNC.createCollection)).uid; nfts = [(await h.createAndOrderNft(true)).uid, (await h.createAndOrderNft(true)).uid]; await h.mintCollection(); - mockWalletReturnValue(h.spy, h.guardian!, { nft: nfts[0] }); - await testEnv.wrap(withdrawNft)({}); + mockWalletReturnValue(h.guardian!, { nft: nfts[0] }); + await testEnv.wrap(WEN_FUNC.withdrawNft); - mockWalletReturnValue(h.spy, h.guardian!, { nft: nfts[1] }); - await testEnv.wrap(withdrawNft)({}); + mockWalletReturnValue(h.guardian!, { nft: nfts[1] }); + await testEnv.wrap(WEN_FUNC.withdrawNft); }); it('Should create, offer base token, request nft, reject', async () => { - mockWalletReturnValue(h.spy, h.member, { + mockWalletReturnValue(h.member, { network: h.network, nativeTokens: [{ id: MINTED_TOKEN_ID_1, amount: 5 }], nfts, recipient: h.guardian, }); - const swapOrder: Transaction = await testEnv.wrap(createSwap)({}); + const swapOrder = await testEnv.wrap(WEN_FUNC.createSwap); - const swapDocRef = build5Db().doc(`${COL.SWAP}/${swapOrder.payload.swap}`); + const swapDocRef = build5Db().doc(COL.SWAP, swapOrder.payload.swap!); let swap = await swapDocRef.get(); await requestFundsFromFaucet(h.network, swapOrder.payload.targetAddress!, MIN_IOTA_AMOUNT); @@ -62,7 +60,7 @@ describe('Swap control test', () => { return swap.bidOutputs?.length === 1; }); - const guardianDocRef = build5Db().doc(`${COL.MEMBER}/${h.guardian}`); + const guardianDocRef = build5Db().doc(COL.MEMBER, h.guardian); const guardianData = await guardianDocRef.get(); const guardianAddress = await h.wallet.getAddressDetails(getAddress(guardianData, h.network)); await wait(async () => { @@ -70,7 +68,7 @@ describe('Swap control test', () => { return result.items.length === 2; }); for (const nftUid of nfts) { - const docRef = build5Db().doc(`${COL.NFT}/${nftUid}`); + const docRef = build5Db().doc(COL.NFT, nftUid); const nft = await docRef.get(); await h.sendNftToAddress(guardianAddress, swap.address, nft.mintingData?.nftId!); } @@ -87,21 +85,21 @@ describe('Swap control test', () => { return swap.askOutputs?.length === 3 && swap.bidOutputs?.length === 1; }); - const member2 = await createMember(h.spy); - mockWalletReturnValue(h.spy, member2, { uid: swap.uid }); - await expectThrow(testEnv.wrap(rejectSwap)({}), WenError.not_swap_owner.key); + const member2 = await testEnv.createMember(); + mockWalletReturnValue(member2, { uid: swap.uid }); + await expectThrow(testEnv.wrap(WEN_FUNC.rejectSwap), WenError.not_swap_owner.key); - mockWalletReturnValue(h.spy, h.member, { uid: swap.uid }); - await testEnv.wrap(rejectSwap)({}); + mockWalletReturnValue(h.member, { uid: swap.uid }); + await testEnv.wrap(WEN_FUNC.rejectSwap); swap = await swapDocRef.get(); expect(swap.status).toBe(SwapStatus.REJECTED); let query = build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.CREDIT) - .where('payload.swap', '==', swap.uid); + .where('type', '==', PgTransactionType.CREDIT) + .where('payload_swap', '==', swap.uid); await wait(async () => { - const snap = await query.get(); + const snap = await query.get(); return ( snap.length === 2 && snap[0].payload.walletReference?.confirmed && @@ -111,17 +109,17 @@ describe('Swap control test', () => { query = build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.CREDIT_NFT) - .where('payload.swap', '==', swap.uid); + .where('type', '==', PgTransactionType.CREDIT_NFT) + .where('payload_swap', '==', swap.uid); await wait(async () => { - const snap = await query.get(); + const snap = await query.get(); return ( snap.length === 2 && snap[0].payload.walletReference?.confirmed && snap[1].payload.walletReference?.confirmed ); }); - const snap = await query.get(); + const snap = await query.get(); expect(snap[0].payload.targetAddress).toBe(guardianAddress.bech32); expect(snap[1].payload.targetAddress).toBe(guardianAddress.bech32); diff --git a/packages/functions/test-tangle/swap/swap_7.spec.ts b/packages/functions/test-tangle/swap/swap_7.spec.ts index 6288554065..e1421c6b57 100644 --- a/packages/functions/test-tangle/swap/swap_7.spec.ts +++ b/packages/functions/test-tangle/swap/swap_7.spec.ts @@ -1,6 +1,7 @@ -import { build5Db } from '@build-5/database'; +import { PgTransactionType, build5Db } from '@build-5/database'; import { COL, + Collection, MIN_IOTA_AMOUNT, Member, Nft, @@ -8,14 +9,11 @@ import { SwapStatus, TangleRequestType, Transaction, - TransactionType, + WEN_FUNC, } from '@build-5/interfaces'; -import { createCollection } from '../../src/runtime/firebase/collection'; -import { withdrawNft } from '../../src/runtime/firebase/nft'; -import { createSwap } from '../../src/runtime/firebase/swap'; import { getAddress } from '../../src/utils/address.utils'; -import { mockWalletReturnValue, wait } from '../../test/controls/common'; -import { testEnv } from '../../test/set-up'; +import { wait } from '../../test/controls/common'; +import { mockWalletReturnValue, testEnv } from '../../test/set-up'; import { getTangleOrder } from '../common'; import { requestFundsFromFaucet, requestMintedTokenFromFaucet } from '../faucet'; import { Helper, MINTED_TOKEN_ID_1, VAULT_MNEMONIC_1 } from './Helper'; @@ -31,30 +29,30 @@ describe('Swap control test', () => { beforeEach(async () => { await h.beforeEach(); - mockWalletReturnValue(h.spy, h.guardian, h.createDummyCollection(h.space.uid, h.space.uid)); - h.collection = (await testEnv.wrap(createCollection)({})).uid; + mockWalletReturnValue(h.guardian, h.createDummyCollection(h.space.uid, h.space.uid)); + h.collection = (await testEnv.wrap(WEN_FUNC.createCollection)).uid; nfts = [(await h.createAndOrderNft(true)).uid, (await h.createAndOrderNft(true)).uid]; await h.mintCollection(); - mockWalletReturnValue(h.spy, h.guardian!, { nft: nfts[0] }); - await testEnv.wrap(withdrawNft)({}); + mockWalletReturnValue(h.guardian!, { nft: nfts[0] }); + await testEnv.wrap(WEN_FUNC.withdrawNft); - mockWalletReturnValue(h.spy, h.guardian!, { nft: nfts[1] }); - await testEnv.wrap(withdrawNft)({}); + mockWalletReturnValue(h.guardian!, { nft: nfts[1] }); + await testEnv.wrap(WEN_FUNC.withdrawNft); }); it('Should create, offer base token, request nft, reject with OTR', async () => { - mockWalletReturnValue(h.spy, h.member, { + mockWalletReturnValue(h.member, { network: h.network, nativeTokens: [{ id: MINTED_TOKEN_ID_1, amount: 5 }], nfts, recipient: h.guardian, }); - const swapOrder: Transaction = await testEnv.wrap(createSwap)({}); + const swapOrder = await testEnv.wrap(WEN_FUNC.createSwap); - const swapDocRef = build5Db().doc(`${COL.SWAP}/${swapOrder.payload.swap}`); + const swapDocRef = build5Db().doc(COL.SWAP, swapOrder.payload.swap!); let swap = await swapDocRef.get(); await requestFundsFromFaucet(h.network, swapOrder.payload.targetAddress!, MIN_IOTA_AMOUNT); @@ -63,7 +61,7 @@ describe('Swap control test', () => { return swap.bidOutputs?.length === 1; }); - const guardianDocRef = build5Db().doc(`${COL.MEMBER}/${h.guardian}`); + const guardianDocRef = build5Db().doc(COL.MEMBER, h.guardian); const guardianData = await guardianDocRef.get(); const guardianAddress = await h.wallet.getAddressDetails(getAddress(guardianData, h.network)); await wait(async () => { @@ -72,7 +70,7 @@ describe('Swap control test', () => { }); for (const nftUid of nfts) { - const docRef = build5Db().doc(`${COL.NFT}/${nftUid}`); + const docRef = build5Db().doc(COL.NFT, nftUid); const nft = await docRef.get(); await h.sendNftToAddress(guardianAddress, swap.address, nft.mintingData?.nftId!); } @@ -89,7 +87,7 @@ describe('Swap control test', () => { return swap.askOutputs?.length === 3 && swap.bidOutputs?.length === 1; }); - const memberDocRef = build5Db().doc(`${COL.MEMBER}/${h.member}`); + const memberDocRef = build5Db().doc(COL.MEMBER, h.member); const memberData = await memberDocRef.get(); const memberAddress = await h.wallet.getAddressDetails(getAddress(memberData, h.network)); await requestFundsFromFaucet(h.network, memberAddress.bech32, MIN_IOTA_AMOUNT); @@ -106,10 +104,10 @@ describe('Swap control test', () => { let query = build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.CREDIT) - .where('payload.swap', '==', swap.uid); + .where('type', '==', PgTransactionType.CREDIT) + .where('payload_swap', '==', swap.uid); await wait(async () => { - const snap = await query.get(); + const snap = await query.get(); return ( snap.length === 2 && snap[0].payload.walletReference?.confirmed && @@ -119,17 +117,17 @@ describe('Swap control test', () => { query = build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.CREDIT_NFT) - .where('payload.swap', '==', swap.uid); + .where('type', '==', PgTransactionType.CREDIT_NFT) + .where('payload_swap', '==', swap.uid); await wait(async () => { - const snap = await query.get(); + const snap = await query.get(); return ( snap.length === 2 && snap[0].payload.walletReference?.confirmed && snap[1].payload.walletReference?.confirmed ); }); - const snap = await query.get(); + const snap = await query.get(); expect(snap[0].payload.targetAddress).toBe(guardianAddress.bech32); expect(snap[1].payload.targetAddress).toBe(guardianAddress.bech32); diff --git a/packages/functions/test-tangle/swap/swap_8.spec.ts b/packages/functions/test-tangle/swap/swap_8.spec.ts index da2ec59762..b05814a818 100644 --- a/packages/functions/test-tangle/swap/swap_8.spec.ts +++ b/packages/functions/test-tangle/swap/swap_8.spec.ts @@ -1,21 +1,19 @@ -import { build5Db } from '@build-5/database'; +import { PgTransactionType, build5Db } from '@build-5/database'; import { COL, + Collection, MIN_IOTA_AMOUNT, Member, NftTransferRequest, Swap, SwapStatus, Transaction, - TransactionType, + WEN_FUNC, WenError, } from '@build-5/interfaces'; -import { createCollection } from '../../src/runtime/firebase/collection'; -import { nftTransfer } from '../../src/runtime/firebase/nft'; -import { createSwap, rejectSwap, setSwapFunded } from '../../src/runtime/firebase/swap'; import { getAddress } from '../../src/utils/address.utils'; -import { expectThrow, mockWalletReturnValue, wait } from '../../test/controls/common'; -import { testEnv } from '../../test/set-up'; +import { expectThrow, wait } from '../../test/controls/common'; +import { mockWalletReturnValue, testEnv } from '../../test/set-up'; import { requestFundsFromFaucet, requestMintedTokenFromFaucet } from '../faucet'; import { Helper, MINTED_TOKEN_ID_1, VAULT_MNEMONIC_1 } from './Helper'; @@ -30,8 +28,8 @@ describe('Swap control test', () => { beforeEach(async () => { await h.beforeEach(); - mockWalletReturnValue(h.spy, h.guardian, h.createDummyCollection(h.space.uid, h.space.uid)); - h.collection = (await testEnv.wrap(createCollection)({})).uid; + mockWalletReturnValue(h.guardian, h.createDummyCollection(h.space.uid, h.space.uid)); + h.collection = (await testEnv.wrap(WEN_FUNC.createCollection)).uid; nfts = [(await h.createAndOrderNft(true)).uid, (await h.createAndOrderNft(true)).uid]; @@ -39,15 +37,15 @@ describe('Swap control test', () => { }); it('Should create, offer base token, request nft, do nft transfer', async () => { - mockWalletReturnValue(h.spy, h.member, { + mockWalletReturnValue(h.member, { network: h.network, nativeTokens: [{ id: MINTED_TOKEN_ID_1, amount: 5 }], nfts, recipient: h.guardian, }); - const swapOrder: Transaction = await testEnv.wrap(createSwap)({}); + const swapOrder = await testEnv.wrap(WEN_FUNC.createSwap); - const swapDocRef = build5Db().doc(`${COL.SWAP}/${swapOrder.payload.swap}`); + const swapDocRef = build5Db().doc(COL.SWAP, swapOrder.payload.swap!); let swap = await swapDocRef.get(); await requestFundsFromFaucet(h.network, swapOrder.payload.targetAddress!, MIN_IOTA_AMOUNT); @@ -62,8 +60,8 @@ describe('Swap control test', () => { { nft: nfts[1], target: swapOrder.payload.targetAddress! }, ], }; - mockWalletReturnValue(h.spy, h.guardian, request); - await testEnv.wrap(nftTransfer)({}); + mockWalletReturnValue(h.guardian, request); + await testEnv.wrap(WEN_FUNC.nftTransfer); const source = await h.wallet.getNewIotaAddressDetails(); await requestFundsFromFaucet(h.network, source.bech32, 10 * MIN_IOTA_AMOUNT); @@ -77,28 +75,28 @@ describe('Swap control test', () => { return swap.askOutputs?.length === 3 && swap.bidOutputs?.length === 1; }); - mockWalletReturnValue(h.spy, h.member, { uid: swap.uid }); - await testEnv.wrap(setSwapFunded)({}); + mockWalletReturnValue(h.member, { uid: swap.uid }); + await testEnv.wrap(WEN_FUNC.setSwapFunded); swap = await swapDocRef.get(); expect(swap.status).toBe(SwapStatus.FULFILLED); let query = build5Db() .collection(COL.TRANSACTION) .where('member', '==', h.member) - .where('type', '==', TransactionType.BILL_PAYMENT) - .where('payload.swap', '==', swap.uid); + .where('type', '==', PgTransactionType.BILL_PAYMENT) + .where('payload_swap', '==', swap.uid); await wait(async () => { - const snap = await query.get(); + const snap = await query.get(); return snap.length === 1 && (snap[0].payload.walletReference?.confirmed || false); }); query = build5Db() .collection(COL.TRANSACTION) .where('member', '==', h.member) - .where('type', '==', TransactionType.WITHDRAW_NFT) - .where('payload.swap', '==', swap.uid); + .where('type', '==', PgTransactionType.WITHDRAW_NFT) + .where('payload_swap', '==', swap.uid); await wait(async () => { - const snap = await query.get(); + const snap = await query.get(); return ( snap.length === 2 && (snap[0].payload.walletReference?.confirmed || false) && @@ -106,7 +104,7 @@ describe('Swap control test', () => { ); }); - const memberDocRef = build5Db().doc(`${COL.MEMBER}/${h.member}`); + const memberDocRef = build5Db().doc(COL.MEMBER, h.member); const member = await memberDocRef.get(); const response = await h.wallet.client.nftOutputIds([ { address: getAddress(member, h.network) }, @@ -116,14 +114,14 @@ describe('Swap control test', () => { query = build5Db() .collection(COL.TRANSACTION) .where('member', '==', h.guardian) - .where('type', '==', TransactionType.BILL_PAYMENT) - .where('payload.swap', '==', swap.uid); + .where('type', '==', PgTransactionType.BILL_PAYMENT) + .where('payload_swap', '==', swap.uid); await wait(async () => { - const snap = await query.get(); + const snap = await query.get(); return snap.length === 1 && (snap[0].payload.walletReference?.confirmed || false); }); - mockWalletReturnValue(h.spy, h.member, { uid: swap.uid }); - await expectThrow(testEnv.wrap(rejectSwap)({}), WenError.swap_already_fulfilled.key); + mockWalletReturnValue(h.member, { uid: swap.uid }); + await expectThrow(testEnv.wrap(WEN_FUNC.rejectSwap), WenError.swap_already_fulfilled.key); }); }); diff --git a/packages/functions/test-tangle/tangleRequest/simple.token.trade.spec.ts b/packages/functions/test-tangle/tangleRequest/simple.token.trade.spec.ts index f9f48d44a8..845e830b37 100644 --- a/packages/functions/test-tangle/tangleRequest/simple.token.trade.spec.ts +++ b/packages/functions/test-tangle/tangleRequest/simple.token.trade.spec.ts @@ -1,7 +1,6 @@ -import { build5Db } from '@build-5/database'; +import { build5Db, PgIgnoreWalletReason, PgTransactionType } from '@build-5/database'; import { COL, - IgnoreWalletReason, Member, MIN_IOTA_AMOUNT, Network, @@ -11,19 +10,16 @@ import { Token, TokenStatus, Transaction, - TransactionType, WenError, } from '@build-5/interfaces'; import { Wallet } from '../../src/services/wallet/wallet'; import { getAddress } from '../../src/utils/address.utils'; import * as wallet from '../../src/utils/wallet.utils'; -import { createMember, getRandomSymbol, wait } from '../../test/controls/common'; -import { getWallet } from '../../test/set-up'; +import { getRandomSymbol, wait } from '../../test/controls/common'; +import { getWallet, testEnv } from '../../test/set-up'; import { getTangleOrder } from '../common'; import { requestFundsFromFaucet } from '../faucet'; -let walletSpy: any; - describe('Simple token trading', () => { let member: string; let token: Token; @@ -35,8 +31,7 @@ describe('Simple token trading', () => { }); beforeEach(async () => { - walletSpy = jest.spyOn(wallet, 'decodeAuth'); - member = await createMember(walletSpy); + member = await testEnv.createMember(); token = { project: SOON_PROJECT_ID, @@ -47,8 +42,8 @@ describe('Simple token trading', () => { status: TokenStatus.AVAILABLE, approved: true, }; - await build5Db().doc(`${COL.TOKEN}/${token.uid}`).set(token); - await build5Db().doc(`${COL.TOKEN}/${token.uid}/${SUB_COL.DISTRIBUTION}/${member}`).create({ + await build5Db().doc(COL.TOKEN, token.uid).create(token); + await build5Db().doc(COL.TOKEN, token.uid, SUB_COL.DISTRIBUTION, member).create({ parentId: token.uid, parentCol: COL.TOKEN, tokenOwned: 100, @@ -58,7 +53,7 @@ describe('Simple token trading', () => { }); it('Should credit on simple token buy', async () => { - const memberData = await build5Db().doc(`${COL.MEMBER}/${member}`).get(); + const memberData = await build5Db().doc(COL.MEMBER, member).get(); const rmsAddress = await rmsWallet.getAddressDetails(getAddress(memberData, Network.RMS)!); await requestFundsFromFaucet(Network.RMS, rmsAddress.bech32, 5 * MIN_IOTA_AMOUNT); @@ -76,12 +71,12 @@ describe('Simple token trading', () => { const query = build5Db() .collection(COL.TRANSACTION) .where('member', '==', member) - .where('type', '==', TransactionType.CREDIT_TANGLE_REQUEST); + .where('type', '==', PgTransactionType.CREDIT_TANGLE_REQUEST); await wait(async () => { - const snap = await query.get(); + const snap = await query.get(); return snap.length > 0 && snap[0]?.payload?.walletReference?.confirmed; }); - const snap = await query.get(); + const snap = await query.get(); expect(snap.length).toBe(1); expect(snap[0]?.payload?.response).toEqual({ code: WenError.token_in_invalid_status.code, @@ -91,7 +86,7 @@ describe('Simple token trading', () => { }); it('Should credit on simple token sell', async () => { - const memberData = await build5Db().doc(`${COL.MEMBER}/${member}`).get(); + const memberData = await build5Db().doc(COL.MEMBER, member).get(); const rmsAddress = await rmsWallet.getAddressDetails(getAddress(memberData, Network.RMS)!); await requestFundsFromFaucet(Network.RMS, rmsAddress.bech32, 5 * MIN_IOTA_AMOUNT); @@ -109,12 +104,12 @@ describe('Simple token trading', () => { const query = build5Db() .collection(COL.TRANSACTION) .where('member', '==', member) - .where('type', '==', TransactionType.CREDIT_TANGLE_REQUEST); + .where('type', '==', PgTransactionType.CREDIT_TANGLE_REQUEST); await wait(async () => { - const snap = await query.get(); + const snap = await query.get(); return snap.length > 0 && snap[0]?.payload?.walletReference?.confirmed; }); - const snap = await query.get(); + const snap = await query.get(); expect(snap.length).toBe(1); expect(snap[0]?.payload?.response).toEqual({ code: WenError.token_in_invalid_status.code, @@ -124,7 +119,7 @@ describe('Simple token trading', () => { }); it('Should set member in case of invalid OTR payment', async () => { - const memberData = await build5Db().doc(`${COL.MEMBER}/${member}`).get(); + const memberData = await build5Db().doc(COL.MEMBER, member).get(); const rmsAddress = await rmsWallet.getAddressDetails(getAddress(memberData, Network.RMS)!); await requestFundsFromFaucet(Network.RMS, rmsAddress.bech32, 5 * MIN_IOTA_AMOUNT); @@ -144,7 +139,7 @@ describe('Simple token trading', () => { .where( 'ignoreWalletReason', '==', - IgnoreWalletReason.UNREFUNDABLE_DUE_STORAGE_DEPOSIT_CONDITION, + PgIgnoreWalletReason.UNREFUNDABLE_DUE_STORAGE_DEPOSIT_CONDITION, ); await wait(async () => { const snap = await query.get(); diff --git a/packages/functions/test-tangle/tangleRequest/tangle-request.spec.ts b/packages/functions/test-tangle/tangleRequest/tangle-request.spec.ts index b8469f38cb..80928c2135 100644 --- a/packages/functions/test-tangle/tangleRequest/tangle-request.spec.ts +++ b/packages/functions/test-tangle/tangleRequest/tangle-request.spec.ts @@ -1,4 +1,4 @@ -import { build5Db } from '@build-5/database'; +import { build5Db, PgTokenTradeOrderType, PgTransactionType } from '@build-5/database'; import { COL, Member, @@ -8,9 +8,7 @@ import { TangleRequestType, Token, TokenStatus, - TokenTradeOrderType, Transaction, - TransactionType, WenError, } from '@build-5/interfaces'; import { MnemonicService } from '../../src/services/wallet/mnemonic'; @@ -19,13 +17,11 @@ import { AddressDetails } from '../../src/services/wallet/wallet.service'; import { getAddress } from '../../src/utils/address.utils'; import { serverTime } from '../../src/utils/dateTime.utils'; import * as wallet from '../../src/utils/wallet.utils'; -import { createMember, createSpace, getRandomSymbol, wait } from '../../test/controls/common'; -import { getWallet, MEDIA } from '../../test/set-up'; +import { getRandomSymbol, wait } from '../../test/controls/common'; +import { getWallet, MEDIA, testEnv } from '../../test/set-up'; import { getTangleOrder } from '../common'; import { requestFundsFromFaucet } from '../faucet'; -let walletSpy: any; - describe('Tangle request spec', () => { let member: string; let rmsWallet: Wallet; @@ -38,22 +34,19 @@ describe('Tangle request spec', () => { }); beforeEach(async () => { - walletSpy = jest.spyOn(wallet, 'decodeAuth'); - member = await createMember(walletSpy); + member = await testEnv.createMember(); rmsWallet = await getWallet(Network.RMS); - const space = await createSpace(walletSpy, member); + const space = await testEnv.createSpace(member); token = await saveToken(space.uid, member); - const memberData = await build5Db().doc(`${COL.MEMBER}/${member}`).get(); + const memberData = await build5Db().doc(COL.MEMBER, member).get(); rmsAddress = await rmsWallet.getAddressDetails(getAddress(memberData, Network.RMS)!); await requestFundsFromFaucet(Network.RMS, rmsAddress.bech32, 10 * MIN_IOTA_AMOUNT); }); it('Should return amount, multiple users with same address', async () => { - const member2 = await createMember(walletSpy); - await build5Db() - .doc(`${COL.MEMBER}/${member2}`) - .set({ validatedAddress: { [Network.RMS]: rmsAddress.bech32 } }, true); + const member2 = await testEnv.createMember(); + await build5Db().doc(COL.MEMBER, member2).upsert({ rmsAddress: rmsAddress.bech32 }); await rmsWallet.send(rmsAddress, tangleOrder.payload.targetAddress!, 5 * MIN_IOTA_AMOUNT, { customMetadata: { @@ -69,12 +62,12 @@ describe('Tangle request spec', () => { const query = build5Db() .collection(COL.TRANSACTION) .where('member', '==', rmsAddress.bech32) - .where('type', '==', TransactionType.CREDIT_TANGLE_REQUEST); + .where('type', '==', PgTransactionType.CREDIT_TANGLE_REQUEST); await wait(async () => { - const snap = await query.get(); + const snap = await query.get(); return snap.length > 0 && snap[0]?.payload?.walletReference?.confirmed; }); - const snap = await query.get(); + const snap = await query.get(); expect(snap.length).toBe(1); expect(snap[0]?.payload?.response).toEqual({ code: WenError.multiple_members_with_same_address.code, @@ -103,20 +96,16 @@ describe('Tangle request spec', () => { const query = build5Db() .collection(COL.TOKEN_MARKET) .where('owner', '==', address.bech32) - .where('type', '==', TokenTradeOrderType.BUY); + .where('type', '==', PgTokenTradeOrderType.BUY); await wait(async () => { - const snap = await query.get(); + const snap = await query.get(); return snap.length === 1; }); - const member2 = await createMember(walletSpy); - await build5Db() - .doc(`${COL.MEMBER}/${member2}`) - .set({ validatedAddress: { [Network.RMS]: rmsAddress.bech32 } }, true); - const member3 = await createMember(walletSpy); - await build5Db() - .doc(`${COL.MEMBER}/${member3}`) - .set({ validatedAddress: { [Network.RMS]: rmsAddress.bech32 } }, true); + const member2 = await testEnv.createMember(); + await build5Db().doc(COL.MEMBER, member2).upsert({ rmsAddress: rmsAddress.bech32 }); + const member3 = await testEnv.createMember(); + await build5Db().doc(COL.MEMBER, member3).upsert({ rmsAddress: rmsAddress.bech32 }); await rmsWallet.send(address, tangleOrder.payload.targetAddress!, 0.2 * MIN_IOTA_AMOUNT, { customMetadata: { @@ -130,7 +119,7 @@ describe('Tangle request spec', () => { }); await wait(async () => { - const snap = await query.get(); + const snap = await query.get(); return snap.length === 2; }); }); @@ -164,12 +153,12 @@ describe('Tangle request spec', () => { const query = build5Db() .collection(COL.TRANSACTION) .where('member', '==', member) - .where('type', '==', TransactionType.CREDIT_TANGLE_REQUEST); + .where('type', '==', PgTransactionType.CREDIT_TANGLE_REQUEST); await wait(async () => { - const snap = await query.get(); + const snap = await query.get(); return snap.length > 0 && snap[0]?.payload?.walletReference?.confirmed; }); - const snap = await query.get(); + const snap = await query.get(); expect(snap.length).toBe(1); expect(snap[0]?.payload?.response).toEqual({ code: WenError.invalid_tangle_request_type.code, @@ -196,7 +185,7 @@ const saveToken = async (space: string, guardian: string) => { mintingData: { network: Network.RMS, }, - }; - await build5Db().doc(`${COL.TOKEN}/${token.uid}`).set(token); + } as Token; + await build5Db().doc(COL.TOKEN, token.uid).create(token); return token as Token; }; diff --git a/packages/functions/test-tangle/token-import/Helper.ts b/packages/functions/test-tangle/token-import/Helper.ts index 1aed1961d4..80cc77afc9 100644 --- a/packages/functions/test-tangle/token-import/Helper.ts +++ b/packages/functions/test-tangle/token-import/Helper.ts @@ -1,20 +1,22 @@ import { build5Db } from '@build-5/database'; -import { COL, Member, Network, Space, SUB_COL, Token, TokenStatus } from '@build-5/interfaces'; -import { mintTokenOrder } from '../../src/runtime/firebase/token/minting'; +import { + COL, + Member, + Network, + SUB_COL, + Space, + Token, + TokenStatus, + Transaction, + WEN_FUNC, +} from '@build-5/interfaces'; import { Wallet } from '../../src/services/wallet/wallet'; import { AddressDetails } from '../../src/services/wallet/wallet.service'; import { getAddress } from '../../src/utils/address.utils'; import { serverTime } from '../../src/utils/dateTime.utils'; -import * as wallet from '../../src/utils/wallet.utils'; import { getRandomEthAddress } from '../../src/utils/wallet.utils'; -import { - createMember, - createSpace, - getRandomSymbol, - mockWalletReturnValue, - wait, -} from '../../test/controls/common'; -import { getWallet, MEDIA, testEnv } from '../../test/set-up'; +import { getRandomSymbol, wait } from '../../test/controls/common'; +import { MEDIA, getWallet, mockWalletReturnValue, testEnv } from '../../test/set-up'; import { requestFundsFromFaucet } from '../faucet'; export class Helper { @@ -25,32 +27,29 @@ export class Helper { public token: Token = {} as any; public walletService: Wallet = {} as any; public member: string = ''; - public walletSpy: any = {} as any; public network = Network.RMS; public totalSupply = 1500; public beforeEach = async () => { - this.walletSpy = jest.spyOn(wallet, 'decodeAuth'); - - const guardianId = await createMember(this.walletSpy); - this.member = await createMember(this.walletSpy); - this.guardian = await build5Db().doc(`${COL.MEMBER}/${guardianId}`).get(); - this.space = await createSpace(this.walletSpy, this.guardian.uid); - this.importSpace = await createSpace(this.walletSpy, this.guardian.uid); + const guardianId = await testEnv.createMember(); + this.member = await testEnv.createMember(); + this.guardian = await build5Db().doc(COL.MEMBER, guardianId).get(); + this.space = await testEnv.createSpace(this.guardian.uid); + this.importSpace = await testEnv.createSpace(this.guardian.uid); this.token = await this.saveToken(this.space.uid, this.guardian.uid, this.member); this.walletService = await getWallet(this.network); this.address = await this.walletService.getAddressDetails( getAddress(this.guardian, this.network), ); - mockWalletReturnValue(this.walletSpy, this.guardian.uid, { + mockWalletReturnValue(this.guardian.uid, { token: this.token.uid, network: this.network, }); - const order = await testEnv.wrap(mintTokenOrder)({}); + const order = await testEnv.wrap(WEN_FUNC.mintTokenOrder); await requestFundsFromFaucet(this.network, order.payload.targetAddress, order.payload.amount); - const tokenDocRef = build5Db().doc(`${COL.TOKEN}/${this.token.uid}`); + const tokenDocRef = build5Db().doc(COL.TOKEN, this.token.uid); await wait(async () => { this.token = await tokenDocRef.get(); return this.token.status === TokenStatus.MINTED; @@ -76,11 +75,11 @@ export class Helper { description: 'myrandomtoken', icon: MEDIA, decimals: 4, - }; - await build5Db().doc(`${COL.TOKEN}/${token.uid}`).set(token); + } as Token; + await build5Db().doc(COL.TOKEN, token.uid).create(token); await build5Db() - .doc(`${COL.TOKEN}/${token.uid}/${SUB_COL.DISTRIBUTION}/${member}`) - .set({ tokenOwned: 1000 }); + .doc(COL.TOKEN, token.uid, SUB_COL.DISTRIBUTION, member) + .upsert({ tokenOwned: 1000 }); return token; }; } diff --git a/packages/functions/test-tangle/token-import/token.import_1.spec.ts b/packages/functions/test-tangle/token-import/token.import_1.spec.ts index e8c814fb63..fc5bf0c7b8 100644 --- a/packages/functions/test-tangle/token-import/token.import_1.spec.ts +++ b/packages/functions/test-tangle/token-import/token.import_1.spec.ts @@ -1,19 +1,17 @@ -import { build5Db } from '@build-5/database'; +import { PgTransactionPayloadType, PgTransactionType, build5Db } from '@build-5/database'; import { Access, COL, - MediaStatus, MIN_IOTA_AMOUNT, + MediaStatus, Token, TokenStatus, Transaction, - TransactionPayloadType, - TransactionType, + WEN_FUNC, } from '@build-5/interfaces'; -import { importMintedToken } from '../../src/runtime/firebase/token/minting'; import { getAddress } from '../../src/utils/address.utils'; -import { mockWalletReturnValue, wait } from '../../test/controls/common'; -import { testEnv } from '../../test/set-up'; +import { wait } from '../../test/controls/common'; +import { mockWalletReturnValue, testEnv } from '../../test/set-up'; import { requestFundsFromFaucet } from '../faucet'; import { Helper } from './Helper'; @@ -25,24 +23,24 @@ describe('Token import', () => { }); it('Should migrate token', async () => { - mockWalletReturnValue(helper.walletSpy, helper.guardian.uid, { + mockWalletReturnValue(helper.guardian.uid, { space: helper.importSpace.uid, tokenId: helper.token.mintingData?.tokenId, network: helper.network, }); - const order = await testEnv.wrap(importMintedToken)({}); + const order = await testEnv.wrap(WEN_FUNC.importMintedToken); const guardianBech32 = getAddress(helper.guardian, helper.network); const guardianAddress = await helper.walletService.getAddressDetails(guardianBech32); await requestFundsFromFaucet(helper.network, guardianBech32, 2 * MIN_IOTA_AMOUNT); await helper.walletService.send( guardianAddress, - order.payload.targetAddress, + order.payload.targetAddress!, 2 * MIN_IOTA_AMOUNT, {}, ); - const migratedTokenDocRef = build5Db().doc(`${COL.TOKEN}/${helper.token.mintingData?.tokenId}`); + const migratedTokenDocRef = build5Db().doc(COL.TOKEN, helper.token.mintingData?.tokenId!); await wait(async () => (await migratedTokenDocRef.get()) !== undefined); const migratedToken = await migratedTokenDocRef.get(); @@ -82,18 +80,18 @@ describe('Token import', () => { const creditQuery = build5Db() .collection(COL.TRANSACTION) .where('member', '==', helper.guardian.uid) - .where('type', '==', TransactionType.CREDIT) - .where('payload.type', '==', TransactionPayloadType.IMPORT_TOKEN); + .where('type', '==', PgTransactionType.CREDIT) + .where('payload_type', '==', PgTransactionPayloadType.IMPORT_TOKEN); await wait(async () => { - const snap = await creditQuery.get(); + const snap = await creditQuery.get(); return snap.length === 1 && snap[0]?.payload?.walletReference?.confirmed; }); - const snap = await creditQuery.get(); + const snap = await creditQuery.get(); expect(snap[0]?.payload.amount).toBe(2 * MIN_IOTA_AMOUNT); const payment = await build5Db() - .doc(`${COL.TRANSACTION}/${snap[0].payload.sourceTransaction![0]}`) - .get(); + .doc(COL.TRANSACTION, snap[0].payload.sourceTransaction![0]) + .get(); expect(payment?.payload.invalidPayment).toBe(false); }); }); diff --git a/packages/functions/test-tangle/token-import/token.import_2.spec.ts b/packages/functions/test-tangle/token-import/token.import_2.spec.ts index 86f57531f7..21a058c5e9 100644 --- a/packages/functions/test-tangle/token-import/token.import_2.spec.ts +++ b/packages/functions/test-tangle/token-import/token.import_2.spec.ts @@ -1,8 +1,7 @@ import { build5Db } from '@build-5/database'; -import { COL, MIN_IOTA_AMOUNT, Transaction } from '@build-5/interfaces'; -import { importMintedToken } from '../../src/runtime/firebase/token/minting'; -import { mockWalletReturnValue, wait } from '../../test/controls/common'; -import { testEnv } from '../../test/set-up'; +import { COL, MIN_IOTA_AMOUNT, Transaction, WEN_FUNC } from '@build-5/interfaces'; +import { wait } from '../../test/controls/common'; +import { mockWalletReturnValue, testEnv } from '../../test/set-up'; import { requestFundsFromFaucet } from '../faucet'; import { Helper } from './Helper'; @@ -14,23 +13,22 @@ describe('Token import', () => { }); it('Should throw, not guardian ', async () => { - mockWalletReturnValue(helper.walletSpy, helper.guardian.uid, { + mockWalletReturnValue(helper.guardian.uid, { space: helper.importSpace.uid, tokenId: helper.token.mintingData?.tokenId, network: helper.network, }); - const order = await testEnv.wrap(importMintedToken)({}); + const order = await testEnv.wrap(WEN_FUNC.importMintedToken); await requestFundsFromFaucet(helper.network, order.payload.targetAddress, 2 * MIN_IOTA_AMOUNT); const creditQuery = build5Db() .collection(COL.TRANSACTION) - .where('member', '==', helper.guardian.uid) - .where('payload.response.code', '==', 2122); + .where('member', '==', helper.guardian.uid); await wait(async () => { - const snap = await creditQuery.get(); + const snap = (await creditQuery.get()).filter((s) => s.payload.response?.code === 2122); return snap.length === 1 && snap[0]?.payload?.walletReference?.confirmed; }); - const migratedTokenDocRef = build5Db().doc(`${COL.TOKEN}/${helper.token.mintingData?.tokenId}`); + const migratedTokenDocRef = build5Db().doc(COL.TOKEN, helper.token.mintingData?.tokenId!); expect((await migratedTokenDocRef.get()) !== undefined).toBe(false); }); }); diff --git a/packages/functions/test-tangle/token.based.voting/Helper.ts b/packages/functions/test-tangle/token.based.voting/Helper.ts index f5d916fd19..a63d93c82c 100644 --- a/packages/functions/test-tangle/token.based.voting/Helper.ts +++ b/packages/functions/test-tangle/token.based.voting/Helper.ts @@ -1,7 +1,6 @@ -import { build5Db } from '@build-5/database'; +import { build5Db, PgTransactionType } from '@build-5/database'; import { COL, - Member, MIN_IOTA_AMOUNT, Network, NetworkAddress, @@ -10,31 +9,26 @@ import { ProposalType, SOON_PROJECT_ID, Space, + Stake, SUB_COL, + Token, TokenStatus, Transaction, - TransactionType, + WEN_FUNC, } from '@build-5/interfaces'; import dayjs from 'dayjs'; import { set } from 'lodash'; -import { - approveProposal, - createProposal, - voteOnProposal, -} from '../../src/runtime/firebase/proposal'; -import { joinSpace } from '../../src/runtime/firebase/space'; import { MnemonicService } from '../../src/services/wallet/mnemonic'; import { Wallet } from '../../src/services/wallet/wallet'; import { AddressDetails } from '../../src/services/wallet/wallet.service'; import { getAddress } from '../../src/utils/address.utils'; import { dateToTimestamp } from '../../src/utils/dateTime.utils'; import * as wallet from '../../src/utils/wallet.utils'; -import { createMember, createSpace, mockWalletReturnValue, wait } from '../../test/controls/common'; -import { getWallet, testEnv } from '../../test/set-up'; +import { wait } from '../../test/controls/common'; +import { getWallet, mockWalletReturnValue, testEnv } from '../../test/set-up'; import { requestFundsFromFaucet, requestMintedTokenFromFaucet } from '../faucet'; export class Helper { - public walletSpy: any; public guardian: string = ''; public member: string = ''; public space: Space | undefined; @@ -49,25 +43,24 @@ export class Helper { }; public beforeEach = async () => { - this.walletSpy = jest.spyOn(wallet, 'decodeAuth'); - this.guardian = await createMember(this.walletSpy); - this.member = await createMember(this.walletSpy); - this.space = await createSpace(this.walletSpy, this.guardian); + this.guardian = await testEnv.createMember(); + this.member = await testEnv.createMember(); + this.space = await testEnv.createSpace(this.guardian); - mockWalletReturnValue(this.walletSpy, this.member, { uid: this.space.uid }); - await testEnv.wrap(joinSpace)({}); + mockWalletReturnValue(this.member, { uid: this.space.uid }); + await testEnv.wrap(WEN_FUNC.joinSpace); this.proposal = dummyProposal(this.space.uid); delete (this.proposal as any).completed; - const guardianDocRef = build5Db().doc(`${COL.MEMBER}/${this.guardian}`); - const guardianData = await guardianDocRef.get(); + const guardianDocRef = build5Db().doc(COL.MEMBER, this.guardian); + const guardianData = await guardianDocRef.get(); const guardianAddressBech = getAddress(guardianData, this.network); this.guardianAddress = await this.walletService!.getAddressDetails(guardianAddressBech); this.tokenId = wallet.getRandomEthAddress(); await build5Db() - .doc(`${COL.TOKEN}/${this.tokenId}`) + .doc(COL.TOKEN, this.tokenId) .create({ project: SOON_PROJECT_ID, uid: this.tokenId, @@ -75,15 +68,15 @@ export class Helper { mintingData: { tokenId: MINTED_TOKEN_ID }, status: TokenStatus.MINTED, approved: true, - }); + } as Token); const { uid, ...requestData } = this.proposal; set(requestData, 'settings.startDate', this.proposal.settings.startDate.toDate()); set(requestData, 'settings.endDate', this.proposal.settings.endDate.toDate()); - mockWalletReturnValue(this.walletSpy, this.guardian, requestData); - this.proposal = await testEnv.wrap(createProposal)({}); - mockWalletReturnValue(this.walletSpy, this.guardian, { uid: this.proposal?.uid }); - await testEnv.wrap(approveProposal)({}); + mockWalletReturnValue(this.guardian, requestData); + this.proposal = await testEnv.wrap(WEN_FUNC.createProposal); + mockWalletReturnValue(this.guardian, { uid: this.proposal?.uid }); + await testEnv.wrap(WEN_FUNC.approveProposal); }; public requestFunds = async () => { @@ -114,10 +107,10 @@ export class Helper { ) => { const query = build5Db() .collection(COL.TRANSACTION) - .where('payload.sourceAddress', '==', voteTransactionOrderTargetAddress) - .where('type', '==', TransactionType.CREDIT); + .where('payload_sourceAddress', '==', voteTransactionOrderTargetAddress) + .where('type', '==', PgTransactionType.CREDIT); await wait(async () => { - const creditSnap = await query.get(); + const creditSnap = await query.get(); return creditSnap.length === 1 && creditSnap[0]?.payload?.walletReference?.confirmed; }); const creditSnap = await query.get(); @@ -127,36 +120,27 @@ export class Helper { public getVoteTransactionForCredit = async (creditId: string) => { const query = build5Db() .collection(COL.TRANSACTION) - .where('payload.creditId', '==', creditId) - .where('type', '==', TransactionType.VOTE); + .where('payload_creditId', '==', creditId) + .where('type', '==', PgTransactionType.VOTE); const voteTranSnap = await query.get(); return voteTranSnap[0] as Transaction; }; public updatePropoasalDates = (startDate: dayjs.Dayjs, endDate: dayjs.Dayjs) => - build5Db() - .doc(`${COL.PROPOSAL}/${this.proposal!.uid}`) - .set( - { - settings: { - startDate: dateToTimestamp(startDate), - endDate: dateToTimestamp(endDate), - }, - }, - true, - ); + build5Db().doc(COL.PROPOSAL, this.proposal!.uid).upsert({ + settings_startDate: startDate.toDate(), + settings_endDate: endDate.toDate(), + }); public updateVoteTranCreatedOn = (voteTransactionId: string, createdOn: dayjs.Dayjs) => - build5Db() - .doc(`${COL.TRANSACTION}/${voteTransactionId}`) - .update({ createdOn: dateToTimestamp(createdOn) }); + build5Db().doc(COL.TRANSACTION, voteTransactionId).update({ createdOn: createdOn.toDate() }); public assertProposalWeights = async ( total: number, voted: number, proposalId = this.proposal!.uid, ) => { - const proposalDocRef = build5Db().doc(`${COL.PROPOSAL}/${proposalId}`); + const proposalDocRef = build5Db().doc(COL.PROPOSAL, proposalId); const proposal = await proposalDocRef.get(); expect(+proposal.results?.total.toFixed(0)).toBe(total); expect(+proposal.results?.voted.toFixed(0)).toBe(voted); @@ -168,8 +152,7 @@ export class Helper { answer: number, proposalId = this.proposal!.uid, ) => { - const proposalDocRef = build5Db().doc(`${COL.PROPOSAL}/${proposalId}`); - const proposalMemberDocRef = proposalDocRef.collection(SUB_COL.MEMBERS).doc(member); + const proposalMemberDocRef = build5Db().doc(COL.PROPOSAL, proposalId, SUB_COL.MEMBERS, member); const proposalMember = await proposalMemberDocRef.get(); expect(+proposalMember.weightPerAnswer![answer].toFixed(0)).toBe(weight); }; @@ -180,12 +163,12 @@ export class Helper { member = this.guardian, proposalId = this.proposal!.uid, ) => { - mockWalletReturnValue(this.walletSpy, member, { + mockWalletReturnValue(member, { uid: proposalId, value, voteWithStakedTokes, }); - return await testEnv.wrap(voteOnProposal)({}); + return await testEnv.wrap(WEN_FUNC.voteOnProposal); }; public createStake = async (createdOn: dayjs.Dayjs, expiresAt: dayjs.Dayjs, amount = 100) => { @@ -198,13 +181,13 @@ export class Helper { member: this.guardian, uid: wallet.getRandomEthAddress(), token: this.tokenId, - }; - const docRef = build5Db().doc(`${COL.STAKE}/${stake.uid}`); + } as Stake; + const docRef = build5Db().doc(COL.STAKE, stake.uid); await docRef.create(stake); }; public getTransaction = async (uid: string) => { - const docRef = build5Db().doc(`${COL.TRANSACTION}/${uid}`); + const docRef = build5Db().doc(COL.TRANSACTION, uid); return await docRef.get(); }; } diff --git a/packages/functions/test-tangle/token.based.voting/stake.voting.spec.ts b/packages/functions/test-tangle/token.based.voting/stake.voting.spec.ts index af414c812e..4bf3ae15be 100644 --- a/packages/functions/test-tangle/token.based.voting/stake.voting.spec.ts +++ b/packages/functions/test-tangle/token.based.voting/stake.voting.spec.ts @@ -1,10 +1,8 @@ import { build5Db } from '@build-5/database'; -import { COL, SUB_COL } from '@build-5/interfaces'; +import { COL, Proposal, ProposalMember, SUB_COL, WEN_FUNC } from '@build-5/interfaces'; import dayjs from 'dayjs'; import { set } from 'lodash'; -import { approveProposal, createProposal } from '../../src/runtime/firebase/proposal'; -import { mockWalletReturnValue } from '../../test/controls/common'; -import { testEnv } from '../../test/set-up'; +import { mockWalletReturnValue, testEnv } from '../../test/set-up'; import { Helper, dummyProposal } from './Helper'; describe('Staked oken based voting', () => { @@ -17,28 +15,44 @@ describe('Staked oken based voting', () => { beforeEach(async () => { await helper.beforeEach(); - const distributionDocRef = build5Db() - .collection(COL.TOKEN) - .doc(helper.tokenId) - .collection(SUB_COL.DISTRIBUTION) - .doc(helper.guardian); - await distributionDocRef.create({}); + const distributionDocRef = build5Db().doc( + COL.TOKEN, + helper.tokenId, + SUB_COL.DISTRIBUTION, + helper.guardian, + ); + await distributionDocRef.create({ parentId: helper.tokenId, parentCol: COL.TOKEN }); }); it('Should vote with staked tokens', async () => { await helper.createStake(dayjs().subtract(2, 'd'), dayjs().add(1, 'y')); await helper.createStake(dayjs().subtract(2, 'd'), dayjs().add(3, 'd')); const voteTransaction = await helper.voteOnProposal(1, true); - expect(+voteTransaction.payload.weight.toFixed(0)).toBe(150); - - await helper.assertProposalWeights(150, 150); - await helper.assertProposalMemberWeightsPerAnser(helper.guardian, 150, 1); + expect(Math.floor(voteTransaction.payload.weight!)).toBeGreaterThanOrEqual(149); + expect(Math.floor(voteTransaction.payload.weight!)).toBeLessThanOrEqual(150); + + const proposalDocRef = build5Db().doc(COL.PROPOSAL, helper.proposal!.uid); + const proposal = await proposalDocRef.get(); + expect(Math.floor(proposal.results?.total)).toBeGreaterThanOrEqual(149); + expect(Math.floor(proposal.results?.total)).toBeLessThanOrEqual(150); + expect(Math.floor(proposal.results?.voted)).toBeGreaterThanOrEqual(149); + expect(Math.floor(proposal.results?.voted)).toBeLessThanOrEqual(150); + + const proposalMemberDocRef = build5Db().doc( + COL.PROPOSAL, + helper.proposal!.uid, + SUB_COL.MEMBERS, + helper.guardian, + ); + const proposalMember = await proposalMemberDocRef.get(); + expect(Math.floor(proposalMember.weightPerAnswer![1])).toBeGreaterThanOrEqual(149); + expect(Math.floor(proposalMember.weightPerAnswer![1])).toBeLessThanOrEqual(150); }); it('Should vote in the beginning and mid way ', async () => { await helper.createStake(dayjs().subtract(2, 'd'), dayjs().add(1, 'y')); let voteTransaction1 = await helper.voteOnProposal(1, true); - expect(+voteTransaction1.payload.weight.toFixed(2)).toBe(100); + expect(+voteTransaction1.payload.weight!.toFixed(2)).toBe(100); await helper.assertProposalWeights(100, 100); await helper.assertProposalMemberWeightsPerAnser(helper.guardian, 100, 1); @@ -47,10 +61,10 @@ describe('Staked oken based voting', () => { await helper.updateVoteTranCreatedOn(voteTransaction1.uid, dayjs().subtract(3, 'd')); const voteTransaction2 = await helper.voteOnProposal(1, true); - expect(+voteTransaction2.payload.weight.toFixed(2)).toBe(50); + expect(+voteTransaction2.payload.weight!.toFixed(2)).toBe(50); voteTransaction1 = await helper.getTransaction(voteTransaction1.uid); - expect(+voteTransaction1.payload.weight.toFixed(2)).toBe(50); + expect(+voteTransaction1.payload.weight!.toFixed(2)).toBe(50); await helper.assertProposalWeights(100, 100); await helper.assertProposalMemberWeightsPerAnser(helper.guardian, 100, 1); @@ -62,25 +76,25 @@ describe('Staked oken based voting', () => { const { uid, completed, ...requestData } = dummyProposal(helper.space!.uid); set(requestData, 'settings.startDate', requestData.settings.startDate.toDate()); set(requestData, 'settings.endDate', requestData.settings.endDate.toDate()); - mockWalletReturnValue(helper.walletSpy, helper.guardian, requestData); + mockWalletReturnValue(helper.guardian, requestData); - const proposal = await testEnv.wrap(createProposal)({}); - mockWalletReturnValue(helper.walletSpy, helper.guardian, { uid: proposal!.uid }); - await testEnv.wrap(approveProposal)({}); + const proposal = await testEnv.wrap(WEN_FUNC.createProposal); + mockWalletReturnValue(helper.guardian, { uid: proposal!.uid }); + await testEnv.wrap(WEN_FUNC.approveProposal); let voteTransaction1 = await helper.voteOnProposal(1, true); - expect(+voteTransaction1.payload.weight.toFixed(2)).toBe(100); + expect(+voteTransaction1.payload.weight!.toFixed(2)).toBe(100); await helper.updatePropoasalDates(dayjs().subtract(2, 'd'), dayjs().add(2, 'd')); await helper.updateVoteTranCreatedOn(voteTransaction1.uid, dayjs().subtract(3, 'd')); const voteTransaction2 = await helper.voteOnProposal(1, true, undefined, proposal.uid); - expect(+voteTransaction2.payload.weight.toFixed(2)).toBe(100); + expect(+voteTransaction2.payload.weight!.toFixed(2)).toBe(100); await helper.assertProposalWeights(100, 100, proposal.uid); await helper.assertProposalMemberWeightsPerAnser(helper.guardian, 100, 1, proposal.uid); voteTransaction1 = await helper.getTransaction(voteTransaction1.uid); - expect(+voteTransaction1.payload.weight.toFixed(2)).toBe(50); + expect(+voteTransaction1.payload.weight!.toFixed(2)).toBe(50); await helper.assertProposalWeights(50, 50); await helper.assertProposalMemberWeightsPerAnser(helper.guardian, 50, 1); }); diff --git a/packages/functions/test-tangle/token.based.voting/token.based.voting_1.spec.ts b/packages/functions/test-tangle/token.based.voting/token.based.voting_1.spec.ts index f2f07bea69..98ca027dd3 100644 --- a/packages/functions/test-tangle/token.based.voting/token.based.voting_1.spec.ts +++ b/packages/functions/test-tangle/token.based.voting/token.based.voting_1.spec.ts @@ -17,9 +17,9 @@ describe('Token based voting', () => { it('Should vote full, then 50%', async () => { const voteTransactionOrder = await helper.voteOnProposal(1); - await helper.sendTokensToVote(voteTransactionOrder.payload.targetAddress); + await helper.sendTokensToVote(voteTransactionOrder.payload.targetAddress!); const credit = await helper.awaitVoteTransactionCreditIsConfirmed( - voteTransactionOrder.payload.targetAddress, + voteTransactionOrder.payload.targetAddress!, ); const voteTransaction = await helper.getVoteTransactionForCredit(credit.uid); @@ -44,13 +44,13 @@ describe('Token based voting', () => { const voteTransactionOrder = await helper.voteOnProposal(1); await helper.sendTokensToVote( - voteTransactionOrder.payload.targetAddress, + voteTransactionOrder.payload.targetAddress!, 10, undefined, voteTransactionOrder.payload.amount, ); const credit = await helper.awaitVoteTransactionCreditIsConfirmed( - voteTransactionOrder.payload.targetAddress, + voteTransactionOrder.payload.targetAddress!, ); const voteTransaction = await helper.getVoteTransactionForCredit(credit.uid); diff --git a/packages/functions/test-tangle/token.based.voting/token.based.voting_2.spec.ts b/packages/functions/test-tangle/token.based.voting/token.based.voting_2.spec.ts index f4302fdb73..701dbb63c2 100644 --- a/packages/functions/test-tangle/token.based.voting/token.based.voting_2.spec.ts +++ b/packages/functions/test-tangle/token.based.voting/token.based.voting_2.spec.ts @@ -18,9 +18,9 @@ describe('Token based voting', () => { it('Should vote, spend and vote again', async () => { let voteTransactionOrder = await helper.voteOnProposal(1); - await helper.sendTokensToVote(voteTransactionOrder.payload.targetAddress); + await helper.sendTokensToVote(voteTransactionOrder.payload.targetAddress!); let credit = await helper.awaitVoteTransactionCreditIsConfirmed( - voteTransactionOrder.payload.targetAddress, + voteTransactionOrder.payload.targetAddress!, ); let voteTransaction = await helper.getVoteTransactionForCredit(credit.uid); @@ -40,9 +40,9 @@ describe('Token based voting', () => { await helper.assertProposalMemberWeightsPerAnser(helper.guardian, 5, 1); voteTransactionOrder = await helper.voteOnProposal(1); - await helper.sendTokensToVote(voteTransactionOrder.payload.targetAddress); + await helper.sendTokensToVote(voteTransactionOrder.payload.targetAddress!); credit = await helper.awaitVoteTransactionCreditIsConfirmed( - voteTransactionOrder.payload.targetAddress, + voteTransactionOrder.payload.targetAddress!, ); voteTransaction = await helper.getVoteTransactionForCredit(credit.uid); expect(+voteTransaction.payload.weight!.toFixed(2)).toBe(5); @@ -52,9 +52,9 @@ describe('Token based voting', () => { it('Should vote twice without spending', async () => { let voteTransactionOrder = await helper.voteOnProposal(1); - await helper.sendTokensToVote(voteTransactionOrder.payload.targetAddress); + await helper.sendTokensToVote(voteTransactionOrder.payload.targetAddress!); let credit = await helper.awaitVoteTransactionCreditIsConfirmed( - voteTransactionOrder.payload.targetAddress, + voteTransactionOrder.payload.targetAddress!, ); let voteTransaction = await helper.getVoteTransactionForCredit(credit.uid); @@ -76,9 +76,9 @@ describe('Token based voting', () => { ); voteTransactionOrder = await helper.voteOnProposal(1); - await helper.sendTokensToVote(voteTransactionOrder.payload.targetAddress, 10, tmp); + await helper.sendTokensToVote(voteTransactionOrder.payload.targetAddress!, 10, tmp); credit = await helper.awaitVoteTransactionCreditIsConfirmed( - voteTransactionOrder.payload.targetAddress, + voteTransactionOrder.payload.targetAddress!, ); voteTransaction = await helper.getVoteTransactionForCredit(credit.uid); expect(+voteTransaction.payload.weight!.toFixed(2)).toBe(5); diff --git a/packages/functions/test-tangle/token.based.voting/token.based.voting_3.spec.ts b/packages/functions/test-tangle/token.based.voting/token.based.voting_3.spec.ts index af84b57286..25d38ca123 100644 --- a/packages/functions/test-tangle/token.based.voting/token.based.voting_3.spec.ts +++ b/packages/functions/test-tangle/token.based.voting/token.based.voting_3.spec.ts @@ -1,8 +1,7 @@ -import { MIN_IOTA_AMOUNT, WenError } from '@build-5/interfaces'; +import { MIN_IOTA_AMOUNT, WEN_FUNC, WenError } from '@build-5/interfaces'; import dayjs from 'dayjs'; -import { voteOnProposal } from '../../src/runtime/firebase/proposal'; -import { expectThrow, mockWalletReturnValue, wait } from '../../test/controls/common'; -import { testEnv } from '../../test/set-up'; +import { expectThrow, wait } from '../../test/controls/common'; +import { mockWalletReturnValue, testEnv } from '../../test/set-up'; import { requestFundsFromFaucet, requestMintedTokenFromFaucet } from '../faucet'; import { Helper, MINTED_TOKEN_ID, VAULT_MNEMONIC } from './Helper'; @@ -20,9 +19,9 @@ describe('Token based voting', () => { it('Should vote on both answers and spend both', async () => { let voteTransactionOrder = await helper.voteOnProposal(1); - await helper.sendTokensToVote(voteTransactionOrder.payload.targetAddress); + await helper.sendTokensToVote(voteTransactionOrder.payload.targetAddress!); const credit = await helper.awaitVoteTransactionCreditIsConfirmed( - voteTransactionOrder.payload.targetAddress, + voteTransactionOrder.payload.targetAddress!, ); const voteTransaction = await helper.getVoteTransactionForCredit(credit.uid); @@ -44,9 +43,9 @@ describe('Token based voting', () => { ); voteTransactionOrder = await helper.voteOnProposal(2); - await helper.sendTokensToVote(voteTransactionOrder.payload.targetAddress, 10, tmp); + await helper.sendTokensToVote(voteTransactionOrder.payload.targetAddress!, 10, tmp); const credit2 = await helper.awaitVoteTransactionCreditIsConfirmed( - voteTransactionOrder.payload.targetAddress, + voteTransactionOrder.payload.targetAddress!, ); const voteTransaction2 = await helper.getVoteTransactionForCredit(credit2.uid); expect(+voteTransaction2.payload.weight!.toFixed(2)).toBe(5); @@ -72,10 +71,10 @@ describe('Token based voting', () => { it('Should throw, can not vote after end date', async () => { await helper.updatePropoasalDates(dayjs().subtract(2, 'd'), dayjs().subtract(1, 'd')); - mockWalletReturnValue(helper.walletSpy, helper.guardian, { + mockWalletReturnValue(helper.guardian, { uid: helper.proposal!.uid, value: 1, }); - await expectThrow(testEnv.wrap(voteOnProposal)({}), WenError.vote_is_no_longer_active.key); + await expectThrow(testEnv.wrap(WEN_FUNC.voteOnProposal), WenError.vote_is_no_longer_active.key); }); }); diff --git a/packages/functions/test-tangle/token.based.voting/token.based.voting_4.spec.ts b/packages/functions/test-tangle/token.based.voting/token.based.voting_4.spec.ts index 590933542c..5530a52e80 100644 --- a/packages/functions/test-tangle/token.based.voting/token.based.voting_4.spec.ts +++ b/packages/functions/test-tangle/token.based.voting/token.based.voting_4.spec.ts @@ -1,10 +1,9 @@ import { build5Db } from '@build-5/database'; -import { COL, Member, WenError } from '@build-5/interfaces'; +import { COL, Member, WEN_FUNC, WenError } from '@build-5/interfaces'; import dayjs from 'dayjs'; -import { voteOnProposal } from '../../src/runtime/firebase/proposal'; import { getAddress } from '../../src/utils/address.utils'; -import { expectThrow, mockWalletReturnValue, wait } from '../../test/controls/common'; -import { testEnv } from '../../test/set-up'; +import { expectThrow, wait } from '../../test/controls/common'; +import { mockWalletReturnValue, testEnv } from '../../test/set-up'; import { Helper } from './Helper'; describe('Token based voting', () => { @@ -21,18 +20,18 @@ describe('Token based voting', () => { it('Should throw, can only vote 24 hours before', async () => { await helper.updatePropoasalDates(dayjs().add(3, 'd'), dayjs().add(5, 'd')); - mockWalletReturnValue(helper.walletSpy, helper.guardian, { + mockWalletReturnValue(helper.guardian, { uid: helper.proposal!.uid, value: 1, }); - await expectThrow(testEnv.wrap(voteOnProposal)({}), WenError.vote_is_no_longer_active.key); + await expectThrow(testEnv.wrap(WEN_FUNC.voteOnProposal), WenError.vote_is_no_longer_active.key); }); it('Should vote, spend, other person votes with it', async () => { let voteTransactionOrder = await helper.voteOnProposal(1); - await helper.sendTokensToVote(voteTransactionOrder.payload.targetAddress); + await helper.sendTokensToVote(voteTransactionOrder.payload.targetAddress!); let credit = await helper.awaitVoteTransactionCreditIsConfirmed( - voteTransactionOrder.payload.targetAddress, + voteTransactionOrder.payload.targetAddress!, ); let voteTransaction = await helper.getVoteTransactionForCredit(credit.uid); @@ -43,7 +42,7 @@ describe('Token based voting', () => { await helper.updatePropoasalDates(dayjs().subtract(2, 'd'), dayjs().add(2, 'd')); await helper.updateVoteTranCreatedOn(voteTransaction.uid, dayjs().subtract(3, 'd')); - const memberDocRef = build5Db().doc(`${COL.MEMBER}/${helper.member}`); + const memberDocRef = build5Db().doc(COL.MEMBER, helper.member); const member = await memberDocRef.get(); const memberAddress = await helper.walletService!.getAddressDetails( getAddress(member, helper.network), @@ -57,9 +56,9 @@ describe('Token based voting', () => { await helper.assertProposalMemberWeightsPerAnser(helper.guardian, 5, 1); voteTransactionOrder = await helper.voteOnProposal(1, false, helper.member); - await helper.sendTokensToVote(voteTransactionOrder.payload.targetAddress, 10, memberAddress); + await helper.sendTokensToVote(voteTransactionOrder.payload.targetAddress!, 10, memberAddress); credit = await helper.awaitVoteTransactionCreditIsConfirmed( - voteTransactionOrder.payload.targetAddress, + voteTransactionOrder.payload.targetAddress!, ); voteTransaction = await helper.getVoteTransactionForCredit(credit.uid); @@ -70,9 +69,9 @@ describe('Token based voting', () => { it('Should not reduce weight when voting after end date', async () => { const voteTransactionOrder = await helper.voteOnProposal(1); - await helper.sendTokensToVote(voteTransactionOrder.payload.targetAddress); + await helper.sendTokensToVote(voteTransactionOrder.payload.targetAddress!); const credit = await helper.awaitVoteTransactionCreditIsConfirmed( - voteTransactionOrder.payload.targetAddress, + voteTransactionOrder.payload.targetAddress!, ); let voteTransaction = await helper.getVoteTransactionForCredit(credit.uid); diff --git a/packages/functions/test-tangle/token.based.voting/token.based.voting_5.spec.ts b/packages/functions/test-tangle/token.based.voting/token.based.voting_5.spec.ts index 339ed38a06..463795aac5 100644 --- a/packages/functions/test-tangle/token.based.voting/token.based.voting_5.spec.ts +++ b/packages/functions/test-tangle/token.based.voting/token.based.voting_5.spec.ts @@ -1,5 +1,5 @@ import { build5Db } from '@build-5/database'; -import { COL, SOON_PROJECT_ID, TokenStatus } from '@build-5/interfaces'; +import { COL, SOON_PROJECT_ID, Token, TokenStatus } from '@build-5/interfaces'; import { getRandomEthAddress } from '../../src/utils/wallet.utils'; import { Helper } from './Helper'; @@ -22,14 +22,14 @@ describe('Token based voting', () => { space: helper.space!.uid, status: TokenStatus.PRE_MINTED, approved: false, - }; - await build5Db().doc(`${COL.TOKEN}/${falseToken.uid}`).create(falseToken); + } as Token; + await build5Db().doc(COL.TOKEN, falseToken.uid).create(falseToken); const voteTransactionOrder = await helper.voteOnProposal(1); - await helper.sendTokensToVote(voteTransactionOrder.payload.targetAddress); + await helper.sendTokensToVote(voteTransactionOrder.payload.targetAddress!); const credit = await helper.awaitVoteTransactionCreditIsConfirmed( - voteTransactionOrder.payload.targetAddress, + voteTransactionOrder.payload.targetAddress!, ); const voteTransaction = await helper.getVoteTransactionForCredit(credit.uid); diff --git a/packages/functions/test-tangle/token.mint/Helper.ts b/packages/functions/test-tangle/token.mint/Helper.ts index 00ec543c97..926dab266f 100644 --- a/packages/functions/test-tangle/token.mint/Helper.ts +++ b/packages/functions/test-tangle/token.mint/Helper.ts @@ -33,9 +33,8 @@ import { packBasicOutput } from '../../src/utils/basic-output.utils'; import { createUnlock, packEssence, submitBlock } from '../../src/utils/block.utils'; import { serverTime } from '../../src/utils/dateTime.utils'; import * as wallet from '../../src/utils/wallet.utils'; -import { getRandomEthAddress } from '../../src/utils/wallet.utils'; -import { createMember, createSpace, getRandomSymbol } from '../../test/controls/common'; -import { MEDIA, getWallet } from '../../test/set-up'; +import { getRandomSymbol } from '../../test/controls/common'; +import { MEDIA, getWallet, testEnv } from '../../test/set-up'; export class Helper { public guardian: Member = {} as any; @@ -44,19 +43,14 @@ export class Helper { public token: Token = {} as any; public walletService: Wallet = {} as any; public member: string = ''; - public walletSpy: any = {} as any; public network = Network.RMS; public totalSupply = 1500; - public beforeEach = async () => { - this.walletSpy = jest.spyOn(wallet, 'decodeAuth'); - }; - public setup = async (approved = true, isPublicToken?: boolean) => { - const guardianId = await createMember(this.walletSpy); - this.member = await createMember(this.walletSpy); - this.guardian = await build5Db().doc(`${COL.MEMBER}/${guardianId}`).get(); - this.space = await createSpace(this.walletSpy, this.guardian.uid); + const guardianId = await testEnv.createMember(); + this.member = await testEnv.createMember(); + this.guardian = await build5Db().doc(COL.MEMBER, guardianId).get(); + this.space = await testEnv.createSpace(this.guardian.uid); this.token = await this.saveToken( this.space.uid, this.guardian.uid, @@ -77,7 +71,7 @@ export class Helper { approved = true, isPublicToken = true, ) => { - const tokenId = getRandomEthAddress(); + const tokenId = wallet.getRandomEthAddress(); const token = { project: SOON_PROJECT_ID, symbol: getRandomSymbol(), @@ -94,11 +88,11 @@ export class Helper { public: isPublicToken, approved, decimals: 5, - }; - await build5Db().doc(`${COL.TOKEN}/${token.uid}`).set(token); + } as Token; + await build5Db().doc(COL.TOKEN, token.uid).create(token); await build5Db() - .doc(`${COL.TOKEN}/${token.uid}/${SUB_COL.DISTRIBUTION}/${member}`) - .set({ tokenOwned: 1000 }); + .doc(COL.TOKEN, token.uid, SUB_COL.DISTRIBUTION, member) + .upsert({ tokenOwned: 1000 }); return token; }; @@ -161,7 +155,7 @@ export class Helper { ]; const blockId = await submitBlock(wallet, essence, unlocks); - await build5Db().doc(`blocks/${blockId}`).create({ blockId }); + await testEnv.createBlock(blockId); return blockId; }; } diff --git a/packages/functions/test-tangle/token.mint/token.mint_1.spec.ts b/packages/functions/test-tangle/token.mint/token.mint_1.spec.ts index 214567ea98..396c0ec14e 100644 --- a/packages/functions/test-tangle/token.mint/token.mint_1.spec.ts +++ b/packages/functions/test-tangle/token.mint/token.mint_1.spec.ts @@ -1,6 +1,6 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ -import { build5Db } from '@build-5/database'; +import { PgTransactionType, build5Db } from '@build-5/database'; import { COL, KEY_NAME_TANGLE, @@ -9,35 +9,30 @@ import { TokenStatus, Transaction, TransactionPayloadType, - TransactionType, + WEN_FUNC, } from '@build-5/interfaces'; import { FoundryOutput } from '@iota/sdk'; import dayjs from 'dayjs'; import { isEqual } from 'lodash'; -import { mintTokenOrder } from '../../src/runtime/firebase/token/minting'; import { getAddress } from '../../src/utils/address.utils'; import { dateToTimestamp } from '../../src/utils/dateTime.utils'; -import { mockWalletReturnValue, wait } from '../../test/controls/common'; -import { testEnv } from '../../test/set-up'; +import { wait } from '../../test/controls/common'; +import { mockWalletReturnValue, testEnv } from '../../test/set-up'; import { requestFundsFromFaucet } from '../faucet'; import { Helper, getAliasOutput, getFoundryMetadata, getStateAndGovernorAddress } from './Helper'; describe('Token minting', () => { const helper = new Helper(); - beforeEach(async () => { - await helper.beforeEach(); - }); - it.each([false, true])('Should mint token', async (hasExpiration: boolean) => { const expiresAt = hasExpiration ? dateToTimestamp(dayjs().add(2, 'h').toDate()) : undefined; await helper.setup(false, hasExpiration); - mockWalletReturnValue(helper.walletSpy, helper.guardian.uid, { + mockWalletReturnValue(helper.guardian.uid, { token: helper.token.uid, network: helper.network, }); - const order = await testEnv.wrap(mintTokenOrder)({}); + const order = await testEnv.wrap(WEN_FUNC.mintTokenOrder); await requestFundsFromFaucet( helper.network, order.payload.targetAddress, @@ -45,9 +40,9 @@ describe('Token minting', () => { expiresAt, ); - const tokenDocRef = build5Db().doc(`${COL.TOKEN}/${helper.token.uid}`); + const tokenDocRef = build5Db().doc(COL.TOKEN, helper.token.uid); await wait(async () => { - const snap = await tokenDocRef.get(); + const snap = await tokenDocRef.get(); return snap?.status === TokenStatus.MINTED; }); @@ -75,7 +70,7 @@ describe('Token minting', () => { ); return Number(Object.values(nativeTokens)[0]) === 1000; }); - const guardianData = await build5Db().doc(`${COL.MEMBER}/${helper.guardian.uid}`).get(); + const guardianData = await build5Db().doc(COL.MEMBER, helper.guardian.uid).get(); await wait(async () => { const { nativeTokens } = await helper.walletService.getBalance( getAddress(guardianData, helper.network), @@ -95,8 +90,8 @@ describe('Token minting', () => { const mintTransactions = ( await build5Db() .collection(COL.TRANSACTION) - .where('payload.token', '==', helper.token.uid) - .where('type', '==', TransactionType.MINT_TOKEN) + .where('payload_token', '==', helper.token.uid) + .where('type', '==', PgTransactionType.MINT_TOKEN) .get() ).map((d) => d); const aliasTran = mintTransactions.find( diff --git a/packages/functions/test-tangle/token.mint/token.mint_2.spec.ts b/packages/functions/test-tangle/token.mint/token.mint_2.spec.ts index accc67abe3..d9dc7069d0 100644 --- a/packages/functions/test-tangle/token.mint/token.mint_2.spec.ts +++ b/packages/functions/test-tangle/token.mint/token.mint_2.spec.ts @@ -1,12 +1,18 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ -import { build5Db } from '@build-5/database'; -import { COL, Member, Token, TokenStatus, TransactionType, WenError } from '@build-5/interfaces'; -import { mintTokenOrder } from '../../src/runtime/firebase/token/minting'; +import { PgTokenStatus, PgTransactionType, build5Db } from '@build-5/database'; +import { + COL, + Member, + Token, + TokenStatus, + Transaction, + WEN_FUNC, + WenError, +} from '@build-5/interfaces'; import { getAddress } from '../../src/utils/address.utils'; -import * as wallet from '../../src/utils/wallet.utils'; -import { expectThrow, mockWalletReturnValue, wait } from '../../test/controls/common'; -import { testEnv } from '../../test/set-up'; +import { expectThrow, wait } from '../../test/controls/common'; +import { mockWalletReturnValue, testEnv } from '../../test/set-up'; import { awaitTransactionConfirmationsForToken } from '../common'; import { requestFundsFromFaucet } from '../faucet'; import { Helper } from './Helper'; @@ -14,26 +20,22 @@ import { Helper } from './Helper'; describe('Token minting', () => { const helper = new Helper(); - beforeEach(async () => { - await helper.beforeEach(); - }); - it('Should mint token and melt some', async () => { await helper.setup(); - mockWalletReturnValue(helper.walletSpy, helper.guardian.uid, { + mockWalletReturnValue(helper.guardian.uid, { token: helper.token.uid, network: helper.network, }); - const order = await testEnv.wrap(mintTokenOrder)({}); + const order = await testEnv.wrap(WEN_FUNC.mintTokenOrder); await requestFundsFromFaucet(helper.network, order.payload.targetAddress, order.payload.amount); - const tokenDocRef = build5Db().doc(`${COL.TOKEN}/${helper.token.uid}`); + const tokenDocRef = build5Db().doc(COL.TOKEN, helper.token.uid); await wait(async () => { helper.token = await tokenDocRef.get(); return helper.token.status === TokenStatus.MINTED; }); - const guardianData = await build5Db().doc(`${COL.MEMBER}/${helper.guardian.uid}`).get(); + const guardianData = await build5Db().doc(COL.MEMBER, helper.guardian.uid).get(); const guardianAddress = getAddress(guardianData, helper.network); await wait(async () => { const { nativeTokens } = await helper.walletService.getBalance(guardianAddress); @@ -53,57 +55,61 @@ describe('Token minting', () => { it('Should create order, not approved but public', async () => { await helper.setup(); - await build5Db() - .doc(`${COL.TOKEN}/${helper.token.uid}`) - .update({ approved: false, public: true }); - mockWalletReturnValue(helper.walletSpy, helper.guardian.uid, { + await build5Db().doc(COL.TOKEN, helper.token.uid).update({ approved: false, public: true }); + mockWalletReturnValue(helper.guardian.uid, { token: helper.token.uid, network: helper.network, }); - const order = await testEnv.wrap(mintTokenOrder)({}); + const order = await testEnv.wrap(WEN_FUNC.mintTokenOrder); expect(order).toBeDefined(); }); it('Should throw, member has no valid address', async () => { await helper.setup(); - await build5Db().doc(`${COL.MEMBER}/${helper.guardian.uid}`).update({ validatedAddress: {} }); - mockWalletReturnValue(helper.walletSpy, helper.guardian.uid, { + await build5Db() + .doc(COL.MEMBER, helper.guardian.uid) + .update({ smrAddress: '', rmsAddress: '', iotaAddress: '', atoiAddress: '' }); + mockWalletReturnValue(helper.guardian.uid, { token: helper.token.uid, network: helper.network, }); await expectThrow( - testEnv.wrap(mintTokenOrder)({}), + testEnv.wrap(WEN_FUNC.mintTokenOrder), WenError.member_must_have_validated_address.key, ); }); it('Should throw, not guardian', async () => { await helper.setup(); - mockWalletReturnValue(helper.walletSpy, wallet.getRandomEthAddress(), { - token: helper.token.uid, - network: helper.network, - }); - await expectThrow(testEnv.wrap(mintTokenOrder)({}), WenError.you_are_not_guardian_of_space.key); + + mockWalletReturnValue(helper.member, { token: helper.token.uid, network: helper.network }); + await expectThrow( + testEnv.wrap(WEN_FUNC.mintTokenOrder), + WenError.you_are_not_guardian_of_space.key, + ); }); it('Should throw, already minted', async () => { await helper.setup(); - await build5Db().doc(`${COL.TOKEN}/${helper.token.uid}`).update({ status: TokenStatus.MINTED }); - mockWalletReturnValue(helper.walletSpy, helper.guardian.uid, { + await build5Db().doc(COL.TOKEN, helper.token.uid).update({ status: PgTokenStatus.MINTED }); + mockWalletReturnValue(helper.guardian.uid, { token: helper.token.uid, network: helper.network, }); - await expectThrow(testEnv.wrap(mintTokenOrder)({}), WenError.token_in_invalid_status.key); + await expectThrow( + testEnv.wrap(WEN_FUNC.mintTokenOrder), + WenError.token_in_invalid_status.key, + ); }); it('Should credit, already minted', async () => { await helper.setup(); - mockWalletReturnValue(helper.walletSpy, helper.guardian.uid, { + mockWalletReturnValue(helper.guardian.uid, { token: helper.token.uid, network: helper.network, }); - const order = await testEnv.wrap(mintTokenOrder)({}); - const order2 = await testEnv.wrap(mintTokenOrder)({}); + const order = await testEnv.wrap(WEN_FUNC.mintTokenOrder); + const order2 = await testEnv.wrap(WEN_FUNC.mintTokenOrder); await requestFundsFromFaucet(helper.network, order.payload.targetAddress, order.payload.amount); await requestFundsFromFaucet( @@ -112,15 +118,15 @@ describe('Token minting', () => { order2.payload.amount, ); - const tokenDocRef = build5Db().doc(`${COL.TOKEN}/${helper.token.uid}`); + const tokenDocRef = build5Db().doc(COL.TOKEN, helper.token.uid); await wait(async () => { - const snap = await tokenDocRef.get(); + const snap = await tokenDocRef.get(); return snap?.status === TokenStatus.MINTED; }); await wait(async () => { const snap = await build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.CREDIT) + .where('type', '==', PgTransactionType.CREDIT) .where('member', '==', helper.guardian.uid) .get(); return snap.length > 0; diff --git a/packages/functions/test-tangle/token.mint/token.mint_3.spec.ts b/packages/functions/test-tangle/token.mint/token.mint_3.spec.ts index acb79dec10..158e571fb7 100644 --- a/packages/functions/test-tangle/token.mint/token.mint_3.spec.ts +++ b/packages/functions/test-tangle/token.mint/token.mint_3.spec.ts @@ -1,6 +1,11 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ -import { build5Db } from '@build-5/database'; +import { + PgTokenTradeOrderStatus, + PgTokenTradeOrderType, + PgTransactionType, + build5Db, +} from '@build-5/database'; import { COL, MIN_IOTA_AMOUNT, @@ -8,33 +13,21 @@ import { Token, TokenDistribution, TokenStatus, - TokenTradeOrderStatus, TokenTradeOrderType, - TransactionType, + Transaction, + WEN_FUNC, WenError, } from '@build-5/interfaces'; import dayjs from 'dayjs'; -import { setTokenAvailableForSale } from '../../src/runtime/firebase/token/base'; -import { mintTokenOrder } from '../../src/runtime/firebase/token/minting'; -import { tradeToken } from '../../src/runtime/firebase/token/trading'; import { dateToTimestamp } from '../../src/utils/dateTime.utils'; -import { - expectThrow, - mockWalletReturnValue, - submitMilestoneFunc, - wait, -} from '../../test/controls/common'; -import { testEnv } from '../../test/set-up'; +import { expectThrow, submitMilestoneFunc, wait } from '../../test/controls/common'; +import { mockWalletReturnValue, testEnv } from '../../test/set-up'; import { requestFundsFromFaucet } from '../faucet'; import { Helper } from './Helper'; describe('Token minting', () => { const helper = new Helper(); - beforeEach(async () => { - await helper.beforeEach(); - }); - it('Should cancel all active buys', async () => { await helper.setup(); const request = { @@ -43,45 +36,45 @@ describe('Token minting', () => { count: 5, type: TokenTradeOrderType.BUY, }; - mockWalletReturnValue(helper.walletSpy, helper.guardian.uid, request); + mockWalletReturnValue(helper.guardian.uid, request); - const order = await testEnv.wrap(tradeToken)({}); + const order = await testEnv.wrap(WEN_FUNC.tradeToken); await submitMilestoneFunc(order); - const order2 = await testEnv.wrap(tradeToken)({}); + const order2 = await testEnv.wrap(WEN_FUNC.tradeToken); await submitMilestoneFunc(order2); await wait(async () => { const buySnap = await build5Db() .collection(COL.TOKEN_MARKET) - .where('type', '==', TokenTradeOrderType.BUY) + .where('type', '==', PgTokenTradeOrderType.BUY) .where('owner', '==', helper.guardian.uid) .get(); return buySnap.length === 2; }); - mockWalletReturnValue(helper.walletSpy, helper.guardian.uid, { + mockWalletReturnValue(helper.guardian.uid, { token: helper.token.uid, network: helper.network, }); - const mintOrder = await testEnv.wrap(mintTokenOrder)({}); + const mintOrder = await testEnv.wrap(WEN_FUNC.mintTokenOrder); await requestFundsFromFaucet( helper.network, mintOrder.payload.targetAddress, mintOrder.payload.amount, ); - const tokenDocRef = build5Db().doc(`${COL.TOKEN}/${helper.token.uid}`); + const tokenDocRef = build5Db().doc(COL.TOKEN, helper.token.uid); await wait(async () => { - const snap = await tokenDocRef.get(); + const snap = await tokenDocRef.get(); return snap?.status === TokenStatus.MINTING; }); await wait(async () => { const buySnap = await build5Db() .collection(COL.TOKEN_MARKET) - .where('type', '==', TokenTradeOrderType.BUY) - .where('status', '==', TokenTradeOrderStatus.CANCELLED_MINTING_TOKEN) + .where('type', '==', PgTokenTradeOrderType.BUY) + .where('status', '==', PgTokenTradeOrderStatus.CANCELLED_MINTING_TOKEN) .where('owner', '==', helper.guardian.uid) .get(); return buySnap.length === 2; @@ -90,7 +83,7 @@ describe('Token minting', () => { await wait(async () => { const creditSnap = await build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.CREDIT) + .where('type', '==', PgTransactionType.CREDIT) .where('member', '==', helper.guardian.uid) .get(); return creditSnap.length === 2; @@ -106,15 +99,15 @@ describe('Token minting', () => { count: 500, type: TokenTradeOrderType.SELL, }; - mockWalletReturnValue(helper.walletSpy, helper.member, request); - await testEnv.wrap(tradeToken)({}); - await testEnv.wrap(tradeToken)({}); + mockWalletReturnValue(helper.member, request); + await testEnv.wrap(WEN_FUNC.tradeToken); + await testEnv.wrap(WEN_FUNC.tradeToken); - mockWalletReturnValue(helper.walletSpy, helper.guardian.uid, { + mockWalletReturnValue(helper.guardian.uid, { token: helper.token.uid, network: helper.network, }); - const mintOrder = await testEnv.wrap(mintTokenOrder)({}); + const mintOrder = await testEnv.wrap(WEN_FUNC.mintTokenOrder); await requestFundsFromFaucet( helper.network, mintOrder.payload.targetAddress, @@ -122,24 +115,22 @@ describe('Token minting', () => { ); await wait(async () => { - const snap = await build5Db().doc(`${COL.TOKEN}/${helper.token.uid}`).get(); + const snap = await build5Db().doc(COL.TOKEN, helper.token.uid).get(); return snap?.status === TokenStatus.MINTING; }); await wait(async () => { const sellSnap = await build5Db() .collection(COL.TOKEN_MARKET) - .where('type', '==', TokenTradeOrderType.SELL) - .where('status', '==', TokenTradeOrderStatus.CANCELLED_MINTING_TOKEN) + .where('type', '==', PgTokenTradeOrderType.SELL) + .where('status', '==', PgTokenTradeOrderStatus.CANCELLED_MINTING_TOKEN) .where('owner', '==', helper.member) .get(); return sellSnap.length === 2; }); const distribution = ( - await build5Db() - .doc(`${COL.TOKEN}/${helper.token.uid}/${SUB_COL.DISTRIBUTION}/${helper.member}`) - .get() + await build5Db().doc(COL.TOKEN, helper.token.uid, SUB_COL.DISTRIBUTION, helper.member).get() ); expect(distribution.lockedForSale).toBe(0); expect(distribution.tokenOwned).toBe(1000); @@ -153,19 +144,25 @@ describe('Token minting', () => { coolDownLength: 86400000, }; await build5Db() - .doc(`${COL.TOKEN}/${helper.token.uid}`) - .update({ allocations: [{ title: 'public', percentage: 100, isPublicSale: true }] }); + .doc(COL.TOKEN, helper.token.uid) + .update({ + allocations: JSON.stringify([{ title: 'public', percentage: 100, isPublicSale: true }]), + }); const updateData = { token: helper.token.uid, ...publicTime, pricePerToken: MIN_IOTA_AMOUNT }; - mockWalletReturnValue(helper.walletSpy, helper.guardian.uid, updateData); - const result = await testEnv.wrap(setTokenAvailableForSale)({}); - expect(result?.saleStartDate.toDate()).toEqual( + mockWalletReturnValue(helper.guardian.uid, updateData); + let token = await testEnv.wrap(WEN_FUNC.setTokenAvailableForSale); + token = (await build5Db().doc(COL.TOKEN, token.uid).get())!; + expect(token.saleStartDate?.toDate()).toEqual( dateToTimestamp(dayjs(publicTime.saleStartDate), true).toDate(), ); - mockWalletReturnValue(helper.walletSpy, helper.guardian.uid, { + mockWalletReturnValue(helper.guardian.uid, { token: helper.token.uid, network: helper.network, }); - await expectThrow(testEnv.wrap(mintTokenOrder)({}), WenError.can_not_mint_in_pub_sale.key); + await expectThrow( + testEnv.wrap(WEN_FUNC.mintTokenOrder), + WenError.can_not_mint_in_pub_sale.key, + ); }); }); diff --git a/packages/functions/test-tangle/token.mint/token.mint_4.spec.ts b/packages/functions/test-tangle/token.mint/token.mint_4.spec.ts index 27de8d92fd..68ed360ed6 100644 --- a/packages/functions/test-tangle/token.mint/token.mint_4.spec.ts +++ b/packages/functions/test-tangle/token.mint/token.mint_4.spec.ts @@ -1,37 +1,31 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ -import { build5Db } from '@build-5/database'; +import { PgTransactionType, build5Db } from '@build-5/database'; import { COL, MIN_IOTA_AMOUNT, Token, TokenStatus, Transaction, - TransactionType, + WEN_FUNC, } from '@build-5/interfaces'; import dayjs from 'dayjs'; -import { cancelPublicSale, setTokenAvailableForSale } from '../../src/runtime/firebase/token/base'; -import { mintTokenOrder } from '../../src/runtime/firebase/token/minting'; -import { mockWalletReturnValue, wait } from '../../test/controls/common'; -import { testEnv } from '../../test/set-up'; +import { wait } from '../../test/controls/common'; +import { mockWalletReturnValue, testEnv } from '../../test/set-up'; import { requestFundsFromFaucet } from '../faucet'; import { Helper } from './Helper'; describe('Token minting', () => { const helper = new Helper(); - beforeEach(async () => { - await helper.beforeEach(); - }); - it('Should credit, token in public sale', async () => { await helper.setup(); - mockWalletReturnValue(helper.walletSpy, helper.guardian.uid, { + mockWalletReturnValue(helper.guardian.uid, { token: helper.token.uid, network: helper.network, }); - const order = await testEnv.wrap(mintTokenOrder)({}); + const order = await testEnv.wrap(WEN_FUNC.mintTokenOrder); const publicTime = { saleStartDate: dayjs().add(2, 'd').toDate(), @@ -39,17 +33,19 @@ describe('Token minting', () => { coolDownLength: 86400000, }; await build5Db() - .doc(`${COL.TOKEN}/${helper.token.uid}`) - .update({ allocations: [{ title: 'public', percentage: 100, isPublicSale: true }] }); + .doc(COL.TOKEN, helper.token.uid) + .update({ + allocations: JSON.stringify([{ title: 'public', percentage: 100, isPublicSale: true }]), + }); const updateData = { token: helper.token.uid, ...publicTime, pricePerToken: MIN_IOTA_AMOUNT }; - mockWalletReturnValue(helper.walletSpy, helper.guardian.uid, updateData); - await testEnv.wrap(setTokenAvailableForSale)({}); + mockWalletReturnValue(helper.guardian.uid, updateData); + await testEnv.wrap(WEN_FUNC.setTokenAvailableForSale); await requestFundsFromFaucet(helper.network, order.payload.targetAddress, order.payload.amount); const creditQuery = build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.CREDIT) + .where('type', '==', PgTransactionType.CREDIT) .where('member', '==', helper.guardian.uid); await wait(async () => { const credit = (await creditQuery.get()).map((d) => d)[0]; @@ -62,11 +58,11 @@ describe('Token minting', () => { it('Should credit, token in public sale, cancel public sale then mint', async () => { await helper.setup(); - mockWalletReturnValue(helper.walletSpy, helper.guardian.uid, { + mockWalletReturnValue(helper.guardian.uid, { token: helper.token.uid, network: helper.network, }); - const order = await testEnv.wrap(mintTokenOrder)({}); + const order = await testEnv.wrap(WEN_FUNC.mintTokenOrder); const publicTime = { saleStartDate: dayjs().add(2, 'd').toDate(), @@ -74,17 +70,19 @@ describe('Token minting', () => { coolDownLength: 86400000, }; await build5Db() - .doc(`${COL.TOKEN}/${helper.token.uid}`) - .update({ allocations: [{ title: 'public', percentage: 100, isPublicSale: true }] }); + .doc(COL.TOKEN, helper.token.uid) + .update({ + allocations: JSON.stringify([{ title: 'public', percentage: 100, isPublicSale: true }]), + }); const updateData = { token: helper.token.uid, ...publicTime, pricePerToken: MIN_IOTA_AMOUNT }; - mockWalletReturnValue(helper.walletSpy, helper.guardian.uid, updateData); - await testEnv.wrap(setTokenAvailableForSale)({}); + mockWalletReturnValue(helper.guardian.uid, updateData); + await testEnv.wrap(WEN_FUNC.setTokenAvailableForSale); await requestFundsFromFaucet(helper.network, order.payload.targetAddress, order.payload.amount); const creditQuery = build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.CREDIT) + .where('type', '==', PgTransactionType.CREDIT) .where('member', '==', helper.guardian.uid); await wait(async () => { const credit = (await creditQuery.get()).map((d) => d)[0]; @@ -93,12 +91,12 @@ describe('Token minting', () => { const credit = (await creditQuery.get()).map((d) => d)[0]; expect(credit?.payload?.amount).toBe(order.payload.amount); - mockWalletReturnValue(helper.walletSpy, helper.guardian.uid, { token: helper.token.uid }); - await testEnv.wrap(cancelPublicSale)({}); + mockWalletReturnValue(helper.guardian.uid, { token: helper.token.uid }); + await testEnv.wrap(WEN_FUNC.cancelPublicSale); await requestFundsFromFaucet(helper.network, order.payload.targetAddress, order.payload.amount); await wait(async () => { - const tokenData = await build5Db().doc(`${COL.TOKEN}/${helper.token.uid}`).get(); + const tokenData = await build5Db().doc(COL.TOKEN, helper.token.uid).get(); return tokenData.status === TokenStatus.MINTED; }); }); diff --git a/packages/functions/test-tangle/trade-base-token-order.spec.ts b/packages/functions/test-tangle/trade-base-token-order.spec.ts index 23aa588b66..cae71140c0 100644 --- a/packages/functions/test-tangle/trade-base-token-order.spec.ts +++ b/packages/functions/test-tangle/trade-base-token-order.spec.ts @@ -1,5 +1,5 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ -import { build5Db } from '@build-5/database'; +import { build5Db, PgTransactionType } from '@build-5/database'; import { COL, Member, @@ -12,48 +12,29 @@ import { TokenTradeOrderStatus, TokenTradeOrderType, Transaction, - TransactionType, + WEN_FUNC, WenError, } from '@build-5/interfaces'; -import { createMember } from '../src/runtime/firebase/member'; -import { cancelTradeOrder, tradeToken } from '../src/runtime/firebase/token/trading'; -import { AddressDetails } from '../src/services/wallet/wallet.service'; import { getAddress } from '../src/utils/address.utils'; import { serverTime } from '../src/utils/dateTime.utils'; import * as wallet from '../src/utils/wallet.utils'; -import { - createMember as createMemberTest, - createRoyaltySpaces, - createSpace, - expectThrow, - getRandomSymbol, - mockWalletReturnValue, - wait, -} from '../test/controls/common'; -import { MEDIA, testEnv } from '../test/set-up'; -import { addValidatedAddress, awaitTransactionConfirmationsForToken } from './common'; +import { createRoyaltySpaces, expectThrow, getRandomSymbol, wait } from '../test/controls/common'; +import { MEDIA, mockWalletReturnValue, testEnv } from '../test/set-up'; +import { awaitTransactionConfirmationsForToken } from './common'; import { requestFundsFromFaucet } from './faucet'; -let walletSpy: any; - describe('Trade base token controller', () => { let seller: Member; - const validateAddress = {} as { [key: string]: AddressDetails }; let token: Token; beforeEach(async () => { await createRoyaltySpaces(); - walletSpy = jest.spyOn(wallet, 'decodeAuth'); - const sellerId = wallet.getRandomEthAddress(); - mockWalletReturnValue(walletSpy, sellerId, {}); - await testEnv.wrap(createMember)({ address: sellerId }); - validateAddress[Network.ATOI] = await addValidatedAddress(Network.ATOI, sellerId); - validateAddress[Network.RMS] = await addValidatedAddress(Network.RMS, sellerId); - seller = await build5Db().doc(`${COL.MEMBER}/${sellerId}`).get(); + const sellerId = await testEnv.createMember(); + seller = await build5Db().doc(COL.MEMBER, sellerId).get(); - const guardian = await createMemberTest(walletSpy); - const space = await createSpace(walletSpy, guardian); + const guardian = await testEnv.createMember(); + const space = await testEnv.createSpace(guardian); token = await saveToken(space.uid, guardian); }); @@ -62,13 +43,13 @@ describe('Trade base token controller', () => { { sourceNetwork: Network.ATOI, targetNetwork: Network.RMS }, { sourceNetwork: Network.RMS, targetNetwork: Network.ATOI }, ])('Should create trade order', async ({ sourceNetwork, targetNetwork }) => { - mockWalletReturnValue(walletSpy, seller.uid, { + mockWalletReturnValue(seller.uid, { symbol: token.symbol, count: MIN_IOTA_AMOUNT, price: 1, type: sourceNetwork === Network.ATOI ? TokenTradeOrderType.SELL : TokenTradeOrderType.BUY, }); - const tradeOrder = await testEnv.wrap(tradeToken)({}); + const tradeOrder = await testEnv.wrap(WEN_FUNC.tradeToken); await requestFundsFromFaucet(sourceNetwork, tradeOrder.payload.targetAddress, MIN_IOTA_AMOUNT); const query = build5Db().collection(COL.TOKEN_MARKET).where('owner', '==', seller.uid); @@ -85,13 +66,13 @@ describe('Trade base token controller', () => { sourceNetwork === Network.ATOI ? TokenTradeOrderType.SELL : TokenTradeOrderType.BUY, ); - mockWalletReturnValue(walletSpy, seller.uid, { uid: trade.uid }); - const cancelled = await testEnv.wrap(cancelTradeOrder)({}); + mockWalletReturnValue(seller.uid, { uid: trade.uid }); + const cancelled = await testEnv.wrap(WEN_FUNC.cancelTradeOrder); expect(cancelled.status).toBe(TokenTradeOrderStatus.CANCELLED); const creditSnap = await build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.CREDIT) + .where('type', '==', PgTransactionType.CREDIT) .where('member', '==', seller.uid) .get(); expect(creditSnap.length).toBe(1); @@ -106,16 +87,16 @@ describe('Trade base token controller', () => { 'Should throw, source address not verified', async (network: Network) => { await build5Db() - .doc(`${COL.MEMBER}/${seller.uid}`) - .update({ [`validatedAddress.${network}`]: build5Db().deleteField() }); - mockWalletReturnValue(walletSpy, seller.uid, { + .doc(COL.MEMBER, seller.uid) + .update({ [`${network}Address`]: undefined }); + mockWalletReturnValue(seller.uid, { symbol: token.symbol, count: 10, price: MIN_IOTA_AMOUNT, type: network === Network.ATOI ? TokenTradeOrderType.SELL : TokenTradeOrderType.BUY, }); await expectThrow( - testEnv.wrap(tradeToken)({}), + testEnv.wrap(WEN_FUNC.tradeToken), WenError.member_must_have_validated_address.key, ); }, @@ -126,16 +107,16 @@ describe('Trade base token controller', () => { { sourceNetwork: Network.RMS, targetNetwork: Network.ATOI }, ])('Should throw, target address not verified', async ({ sourceNetwork, targetNetwork }) => { await build5Db() - .doc(`${COL.MEMBER}/${seller.uid}`) - .update({ [`validatedAddress.${targetNetwork}`]: build5Db().deleteField() }); - mockWalletReturnValue(walletSpy, seller.uid, { + .doc(COL.MEMBER, seller.uid) + .update({ [`${targetNetwork}Address`]: undefined }); + mockWalletReturnValue(seller.uid, { symbol: token.symbol, count: 10, price: MIN_IOTA_AMOUNT, type: sourceNetwork === Network.ATOI ? TokenTradeOrderType.SELL : TokenTradeOrderType.BUY, }); await expectThrow( - testEnv.wrap(tradeToken)({}), + testEnv.wrap(WEN_FUNC.tradeToken), WenError.member_must_have_validated_address.key, ); }); @@ -156,7 +137,7 @@ const saveToken = async (space: string, guardian: string) => { access: 0, icon: MEDIA, mintingData: { network: Network.ATOI }, - }; - await build5Db().doc(`${COL.TOKEN}/${token.uid}`).set(token); - return token as Token; + } as Token; + await build5Db().doc(COL.TOKEN, token.uid).create(token); + return token; }; diff --git a/packages/functions/test-tangle/tran.match.spec.ts b/packages/functions/test-tangle/tran.match.spec.ts index 19d2dbc426..255eb86d30 100644 --- a/packages/functions/test-tangle/tran.match.spec.ts +++ b/packages/functions/test-tangle/tran.match.spec.ts @@ -1,4 +1,4 @@ -import { build5Db } from '@build-5/database'; +import { PgTransactionType, build5Db } from '@build-5/database'; import { COL, IgnoreWalletReason, @@ -40,7 +40,7 @@ describe('Transaction match', () => { const creditSnapQuery = build5Db() .collection(COL.TRANSACTION) .where('member', '==', order.member) - .where('type', '==', TransactionType.CREDIT); + .where('type', '==', PgTransactionType.CREDIT); await wait(async () => { const snap = await creditSnapQuery.get(); return snap.length === 1; @@ -57,7 +57,7 @@ describe('Transaction match', () => { const creditSnapQuery = build5Db() .collection(COL.TRANSACTION) .where('member', '==', order.member) - .where('type', '==', TransactionType.CREDIT); + .where('type', '==', PgTransactionType.CREDIT); await wait(async () => { const snap = await creditSnapQuery.get(); return snap.length === 1; @@ -87,6 +87,6 @@ const saveOrder = async (wallet: Wallet) => { validationType: TransactionValidationType.ADDRESS, }, }; - await build5Db().doc(`${COL.TRANSACTION}/${data.uid}`).create(data); + await build5Db().doc(COL.TRANSACTION, data.uid).create(data); return data; }; diff --git a/packages/functions/test-tangle/transaction-trigger/transaction-trigger_1.spec.ts b/packages/functions/test-tangle/transaction-trigger/transaction-trigger_1.spec.ts index d92c02aead..9d53c59c2a 100644 --- a/packages/functions/test-tangle/transaction-trigger/transaction-trigger_1.spec.ts +++ b/packages/functions/test-tangle/transaction-trigger/transaction-trigger_1.spec.ts @@ -49,16 +49,14 @@ describe('Transaction trigger spec', () => { void: false, }, }; - await build5Db().doc(`${COL.TRANSACTION}/${billPayment.uid}`).create(billPayment); + await build5Db().doc(COL.TRANSACTION, billPayment.uid).create(billPayment); await wait(async () => { const { amount } = await wallet.getBalance(targetAddress.bech32); return amount === MIN_IOTA_AMOUNT; }); await wait(async () => { - billPayment = ( - await build5Db().doc(`${COL.TRANSACTION}/${billPayment.uid}`).get() - ); + billPayment = await build5Db().doc(COL.TRANSACTION, billPayment.uid).get(); return billPayment.payload?.walletReference?.confirmed; }); }, diff --git a/packages/functions/test-tangle/transaction-trigger/transaction-trigger_10.spec.ts b/packages/functions/test-tangle/transaction-trigger/transaction-trigger_10.spec.ts index 3d9ff01ef9..a95b5b2503 100644 --- a/packages/functions/test-tangle/transaction-trigger/transaction-trigger_10.spec.ts +++ b/packages/functions/test-tangle/transaction-trigger/transaction-trigger_10.spec.ts @@ -49,15 +49,13 @@ describe('Transaction trigger spec', () => { targetAddress.bech32, ); const batch = build5Db().batch(); - batch.create(build5Db().doc(`${COL.TRANSACTION}/${credit.uid}`), credit); - batch.create(build5Db().doc(`${COL.TRANSACTION}/${billPayment.uid}`), billPayment); + batch.create(build5Db().doc(COL.TRANSACTION, credit.uid), credit); + batch.create(build5Db().doc(COL.TRANSACTION, billPayment.uid), billPayment); await batch.commit(); await wait(async () => { - billPayment = ( - await build5Db().doc(`${COL.TRANSACTION}/${billPayment.uid}`).get() - ); - credit = await build5Db().doc(`${COL.TRANSACTION}/${credit.uid}`).get(); + billPayment = await build5Db().doc(COL.TRANSACTION, billPayment.uid).get(); + credit = await build5Db().doc(COL.TRANSACTION, credit.uid).get(); return ( billPayment?.payload?.walletReference?.confirmed && credit?.payload?.walletReference?.confirmed diff --git a/packages/functions/test-tangle/transaction-trigger/transaction-trigger_11.spec.ts b/packages/functions/test-tangle/transaction-trigger/transaction-trigger_11.spec.ts index 7970ba70f1..d14f437b0e 100644 --- a/packages/functions/test-tangle/transaction-trigger/transaction-trigger_11.spec.ts +++ b/packages/functions/test-tangle/transaction-trigger/transaction-trigger_11.spec.ts @@ -45,7 +45,7 @@ describe('Transaction trigger spec', () => { sourceAddress.bech32, targetAddress.bech32, ); - await build5Db().doc(`${COL.TRANSACTION}/${billPayment.uid}`).create(billPayment); + await build5Db().doc(COL.TRANSACTION, billPayment.uid).create(billPayment); await wait(async () => { const mnemonic = await MnemonicService.getData(sourceAddress.bech32); @@ -54,9 +54,7 @@ describe('Transaction trigger spec', () => { await wait(async () => { const mnemonic = await MnemonicService.getData(sourceAddress.bech32); - const payment = ( - await build5Db().doc(`${COL.TRANSACTION}/${billPayment.uid}`).get() - ); + const payment = await build5Db().doc(COL.TRANSACTION, billPayment.uid).get(); return ( isEmpty(mnemonic.consumedOutputIds) && payment?.payload?.walletReference?.confirmed && diff --git a/packages/functions/test-tangle/transaction-trigger/transaction-trigger_12.spec.ts b/packages/functions/test-tangle/transaction-trigger/transaction-trigger_12.spec.ts index d796c6b603..c6dbbf8a4b 100644 --- a/packages/functions/test-tangle/transaction-trigger/transaction-trigger_12.spec.ts +++ b/packages/functions/test-tangle/transaction-trigger/transaction-trigger_12.spec.ts @@ -15,7 +15,7 @@ import { isEmpty } from 'lodash'; import { retryWallet } from '../../src/cron/wallet.cron'; import { MnemonicService } from '../../src/services/wallet/mnemonic'; import { AddressDetails } from '../../src/services/wallet/wallet.service'; -import { dateToTimestamp, serverTime } from '../../src/utils/dateTime.utils'; +import { serverTime } from '../../src/utils/dateTime.utils'; import { getRandomEthAddress } from '../../src/utils/wallet.utils'; import { wait } from '../../test/controls/common'; import { getWallet } from '../../test/set-up'; @@ -52,7 +52,7 @@ describe('Transaction trigger spec', () => { 2 * MIN_IOTA_AMOUNT, ), }; - const billPaymentDocRef = build5Db().doc(`${COL.TRANSACTION}/${billPayment.uid}`); + const billPaymentDocRef = build5Db().doc(COL.TRANSACTION, billPayment.uid); await billPaymentDocRef.create(billPayment); await wait(async () => { @@ -65,10 +65,8 @@ describe('Transaction trigger spec', () => { expect(consumedOutputIds.sort()).toEqual(outputIds.sort()); await billPaymentDocRef.update({ - 'payload.amount': MIN_IOTA_AMOUNT, - 'payload.walletReference.processedOn': dateToTimestamp( - dayjs().subtract(4, 'minute').toDate(), - ), + payload_amount: MIN_IOTA_AMOUNT, + payload_walletReference_processedOn: dayjs().subtract(4, 'minute').toDate(), }); const result = await retryWallet(); expect(result.find((r) => r === billPayment.uid)).toBeDefined(); diff --git a/packages/functions/test-tangle/transaction-trigger/transaction-trigger_13.spec.ts b/packages/functions/test-tangle/transaction-trigger/transaction-trigger_13.spec.ts index aba50ef86c..f3968fe645 100644 --- a/packages/functions/test-tangle/transaction-trigger/transaction-trigger_13.spec.ts +++ b/packages/functions/test-tangle/transaction-trigger/transaction-trigger_13.spec.ts @@ -15,7 +15,7 @@ import dayjs from 'dayjs'; import { isEmpty } from 'lodash'; import { retryWallet } from '../../src/cron/wallet.cron'; import { AddressDetails } from '../../src/services/wallet/wallet.service'; -import { dateToTimestamp, serverTime } from '../../src/utils/dateTime.utils'; +import { serverTime } from '../../src/utils/dateTime.utils'; import { getRandomEthAddress } from '../../src/utils/wallet.utils'; import { wait } from '../../test/controls/common'; import { getWallet } from '../../test/set-up'; @@ -51,20 +51,20 @@ describe('Transaction trigger spec', () => { ), ignoreWallet: true, }; - await build5Db().doc(`${COL.TRANSACTION}/${billPayment.uid}`).create(billPayment); + await build5Db().doc(COL.TRANSACTION, billPayment.uid).create(billPayment); await new Promise((r) => setTimeout(r, 1000)); await build5Db() - .doc(`${COL.MNEMONIC}/${sourceAddress.bech32}`) + .doc(COL.MNEMONIC, sourceAddress.bech32) .update({ lockedBy: billPayment.uid, consumedOutputIds: outputIds }); await build5Db() - .doc(`${COL.TRANSACTION}/${billPayment.uid}`) + .doc(COL.TRANSACTION, billPayment.uid) .update({ ignoreWallet: false, - 'payload.walletReference.confirmed': false, - 'payload.walletReference.inProgress': true, - 'payload.walletReference.count': MAX_WALLET_RETRY, - 'payload.walletReference.processedOn': dateToTimestamp(dayjs().subtract(4, 'd').toDate()), + payload_walletReference_confirmed: false, + payload_walletReference_inProgress: true, + payload_walletReference_count: MAX_WALLET_RETRY, + payload_walletReference_processedOn: dayjs().subtract(4, 'd').toDate(), }); let billPayment2 = dummyPayment( @@ -73,17 +73,13 @@ describe('Transaction trigger spec', () => { sourceAddress.bech32, targetAddress.bech32, ); - await build5Db().doc(`${COL.TRANSACTION}/${billPayment2.uid}`).create(billPayment2); + await build5Db().doc(COL.TRANSACTION, billPayment2.uid).create(billPayment2); await retryWallet(); await wait(async () => { - const mnemonic = ( - await build5Db().doc(`${COL.MNEMONIC}/${sourceAddress.bech32}`).get() - ); - billPayment = ( - await build5Db().doc(`${COL.TRANSACTION}/${billPayment.uid}`).get() - ); + const mnemonic = await build5Db().doc(COL.MNEMONIC, sourceAddress.bech32).get(); + billPayment = await build5Db().doc(COL.TRANSACTION, billPayment.uid).get(); return ( !billPayment.payload?.walletReference?.inProgress && !billPayment.payload?.walletReference?.confirmed && @@ -93,9 +89,7 @@ describe('Transaction trigger spec', () => { }); await wait(async () => { - billPayment2 = ( - await build5Db().doc(`${COL.TRANSACTION}/${billPayment2.uid}`).get() - ); + billPayment2 = await build5Db().doc(COL.TRANSACTION, billPayment2.uid).get(); return billPayment2.payload?.walletReference?.confirmed; }); }, diff --git a/packages/functions/test-tangle/transaction-trigger/transaction-trigger_14.spec.ts b/packages/functions/test-tangle/transaction-trigger/transaction-trigger_14.spec.ts index ebddd11ad9..cfae38face 100644 --- a/packages/functions/test-tangle/transaction-trigger/transaction-trigger_14.spec.ts +++ b/packages/functions/test-tangle/transaction-trigger/transaction-trigger_14.spec.ts @@ -12,7 +12,7 @@ import dayjs from 'dayjs'; import { isEmpty } from 'lodash'; import { retryWallet } from '../../src/cron/wallet.cron'; import { AddressDetails } from '../../src/services/wallet/wallet.service'; -import { dateToTimestamp, serverTime } from '../../src/utils/dateTime.utils'; +import { serverTime } from '../../src/utils/dateTime.utils'; import { getRandomEthAddress } from '../../src/utils/wallet.utils'; import { wait } from '../../test/controls/common'; import { getWallet } from '../../test/set-up'; @@ -50,7 +50,7 @@ describe('Transaction trigger spec', () => { void: false, }, }; - const docRef = build5Db().doc(`${COL.TRANSACTION}/${billPayment.uid}`); + const docRef = build5Db().doc(COL.TRANSACTION, billPayment.uid); await docRef.create(billPayment); await wait(async () => { @@ -65,21 +65,19 @@ describe('Transaction trigger spec', () => { let retryWalletResult = await retryWallet(); expect(retryWalletResult.find((r) => r == billPayment.uid)).toBeUndefined(); docRef.update({ - 'payload.walletReference.processedOn': dateToTimestamp( - dayjs().subtract(4, 'minute').toDate(), - ), - 'payload.amount': MIN_IOTA_AMOUNT, + payload_walletReference_processedOn: dayjs().subtract(4, 'minute').toDate(), + payload_amount: MIN_IOTA_AMOUNT, }); retryWalletResult = await retryWallet(); expect(retryWalletResult.find((r) => r == billPayment.uid)).toBeDefined(); await wait(async () => { - const data = await docRef.get(); + const data = await docRef.get(); return data?.payload?.walletReference?.confirmed; }); - const billPaymentDocRef = build5Db().doc(`${COL.TRANSACTION}/${billPayment.uid}`); + const billPaymentDocRef = build5Db().doc(COL.TRANSACTION, billPayment.uid); await wait(async () => { billPayment = await billPaymentDocRef.get(); return billPayment.payload?.walletReference?.confirmed; diff --git a/packages/functions/test-tangle/transaction-trigger/transaction-trigger_15.spec.ts b/packages/functions/test-tangle/transaction-trigger/transaction-trigger_15.spec.ts index 6b9ad048e1..3da66e74cb 100644 --- a/packages/functions/test-tangle/transaction-trigger/transaction-trigger_15.spec.ts +++ b/packages/functions/test-tangle/transaction-trigger/transaction-trigger_15.spec.ts @@ -1,7 +1,7 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ import { build5Db } from '@build-5/database'; -import { COL, MIN_IOTA_AMOUNT, Network, TangleRequestType, Transaction } from '@build-5/interfaces'; +import { COL, MIN_IOTA_AMOUNT, Network, TangleRequestType } from '@build-5/interfaces'; import dayjs from 'dayjs'; import { dateToTimestamp } from '../../src/utils/dateTime.utils'; import { wait } from '../../test/controls/common'; @@ -37,7 +37,7 @@ describe('Transaction trigger spec', () => { const snap = await build5Db() .collection(COL.TRANSACTION) .where('member', '==', address.bech32) - .get(); + .get(); return snap.length === 1 && snap[0].payload.invalidPayment; }); diff --git a/packages/functions/test-tangle/transaction-trigger/transaction-trigger_2.spec.ts b/packages/functions/test-tangle/transaction-trigger/transaction-trigger_2.spec.ts index 3f90b0bb17..5d36ca98e4 100644 --- a/packages/functions/test-tangle/transaction-trigger/transaction-trigger_2.spec.ts +++ b/packages/functions/test-tangle/transaction-trigger/transaction-trigger_2.spec.ts @@ -53,10 +53,10 @@ describe('Transaction trigger spec', () => { void: false, }, }; - const docRef = build5Db().doc(`${COL.TRANSACTION}/${billPayment.uid}`); + const docRef = build5Db().doc(COL.TRANSACTION, billPayment.uid); await docRef.create(billPayment); await wait(async () => { - const doc = await docRef.get(); + const doc = await docRef.get(); return doc?.payload?.walletReference?.confirmed; }); const outputs = await wallet.getOutputs(targetAddress.bech32, [], undefined); diff --git a/packages/functions/test-tangle/transaction-trigger/transaction-trigger_3.spec.ts b/packages/functions/test-tangle/transaction-trigger/transaction-trigger_3.spec.ts index 373567c76f..9d625733ec 100644 --- a/packages/functions/test-tangle/transaction-trigger/transaction-trigger_3.spec.ts +++ b/packages/functions/test-tangle/transaction-trigger/transaction-trigger_3.spec.ts @@ -60,7 +60,7 @@ describe('Transaction trigger spec', () => { void: false, }, }; - await build5Db().doc(`${COL.TRANSACTION}/${billPayment.uid}`).create(billPayment); + await build5Db().doc(COL.TRANSACTION, billPayment.uid).create(billPayment); await wait(async () => { const { nativeTokens } = await wallet.getBalance(targetAddress.bech32); @@ -72,9 +72,7 @@ describe('Transaction trigger spec', () => { }); await wait(async () => { - billPayment = ( - await build5Db().doc(`${COL.TRANSACTION}/${billPayment.uid}`).get() - ); + billPayment = await build5Db().doc(COL.TRANSACTION, billPayment.uid).get(); return billPayment.payload?.walletReference?.confirmed; }); }); diff --git a/packages/functions/test-tangle/transaction-trigger/transaction-trigger_4.spec.ts b/packages/functions/test-tangle/transaction-trigger/transaction-trigger_4.spec.ts index 6d767901f3..2371f6e09e 100644 --- a/packages/functions/test-tangle/transaction-trigger/transaction-trigger_4.spec.ts +++ b/packages/functions/test-tangle/transaction-trigger/transaction-trigger_4.spec.ts @@ -60,7 +60,7 @@ describe('Transaction trigger spec', () => { void: false, }, }; - await build5Db().doc(`${COL.TRANSACTION}/${billPayment.uid}`).create(billPayment); + await build5Db().doc(COL.TRANSACTION, billPayment.uid).create(billPayment); await wait(async () => { const { nativeTokens } = await wallet.getBalance(targetAddress.bech32); return Number(Object.values(nativeTokens)[0]) === 1; @@ -80,17 +80,15 @@ describe('Transaction trigger spec', () => { void: false, }, }; - await build5Db().doc(`${COL.TRANSACTION}/${credit.uid}`).create(credit); + await build5Db().doc(COL.TRANSACTION, credit.uid).create(credit); await wait(async () => { const { nativeTokens } = await wallet.getBalance(sourceAddress.bech32); return Number(Object.values(nativeTokens)[0]) === 1; }); await wait(async () => { - billPayment = ( - await build5Db().doc(`${COL.TRANSACTION}/${billPayment.uid}`).get() - ); - credit = await build5Db().doc(`${COL.TRANSACTION}/${credit.uid}`).get(); + billPayment = await build5Db().doc(COL.TRANSACTION, billPayment.uid).get(); + credit = await build5Db().doc(COL.TRANSACTION, credit.uid).get(); return ( billPayment.payload?.walletReference?.confirmed && credit.payload?.walletReference?.confirmed diff --git a/packages/functions/test-tangle/transaction-trigger/transaction-trigger_5.spec.ts b/packages/functions/test-tangle/transaction-trigger/transaction-trigger_5.spec.ts index 2fbff204c0..53430c4cce 100644 --- a/packages/functions/test-tangle/transaction-trigger/transaction-trigger_5.spec.ts +++ b/packages/functions/test-tangle/transaction-trigger/transaction-trigger_5.spec.ts @@ -12,7 +12,7 @@ import dayjs from 'dayjs'; import { isEmpty } from 'lodash'; import { retryWallet } from '../../src/cron/wallet.cron'; import { AddressDetails } from '../../src/services/wallet/wallet.service'; -import { dateToTimestamp, serverTime } from '../../src/utils/dateTime.utils'; +import { serverTime } from '../../src/utils/dateTime.utils'; import { getRandomEthAddress } from '../../src/utils/wallet.utils'; import { wait } from '../../test/controls/common'; import { getWallet } from '../../test/set-up'; @@ -50,7 +50,7 @@ describe('Transaction trigger spec', () => { void: false, }, }; - const docRef = build5Db().doc(`${COL.TRANSACTION}/${billPayment.uid}`); + const docRef = build5Db().doc(COL.TRANSACTION, billPayment.uid); await docRef.create(billPayment); await wait(async () => { @@ -61,24 +61,20 @@ describe('Transaction trigger spec', () => { let retryWalletResult = await retryWallet(); expect(retryWalletResult.find((r) => r == billPayment.uid)).toBeUndefined(); docRef.update({ - 'payload.walletReference.processedOn': dateToTimestamp( - dayjs().subtract(4, 'minute').toDate(), - ), - 'payload.amount': MIN_IOTA_AMOUNT, + payload_walletReference_processedOn: dayjs().subtract(4, 'minute').toDate(), + payload_amount: MIN_IOTA_AMOUNT, }); retryWalletResult = await retryWallet(); expect(retryWalletResult.find((r) => r == billPayment.uid)).toBeDefined(); await wait(async () => { - const data = await docRef.get(); + const data = await docRef.get(); return data?.payload?.walletReference?.confirmed; }); await wait(async () => { - billPayment = ( - await build5Db().doc(`${COL.TRANSACTION}/${billPayment.uid}`).get() - ); + billPayment = await build5Db().doc(COL.TRANSACTION, billPayment.uid).get(); return billPayment.payload?.walletReference?.confirmed; }); }); diff --git a/packages/functions/test-tangle/transaction-trigger/transaction-trigger_6.spec.ts b/packages/functions/test-tangle/transaction-trigger/transaction-trigger_6.spec.ts index f9cc74ca6d..5fa02fd3ea 100644 --- a/packages/functions/test-tangle/transaction-trigger/transaction-trigger_6.spec.ts +++ b/packages/functions/test-tangle/transaction-trigger/transaction-trigger_6.spec.ts @@ -48,10 +48,10 @@ describe('Transaction trigger spec', () => { void: false, }, }; - const docRef = build5Db().doc(`${COL.TRANSACTION}/${billPayment.uid}`); + const docRef = build5Db().doc(COL.TRANSACTION, billPayment.uid); await docRef.create(billPayment); await wait(async () => { - const doc = await docRef.get(); + const doc = await docRef.get(); return ( doc?.payload?.walletReference?.confirmed === true && !doc?.payload?.walletReference?.inProgress @@ -59,9 +59,7 @@ describe('Transaction trigger spec', () => { }); await wait(async () => { - billPayment = ( - await build5Db().doc(`${COL.TRANSACTION}/${billPayment.uid}`).get() - ); + billPayment = await build5Db().doc(COL.TRANSACTION, billPayment.uid).get(); return billPayment.payload?.walletReference?.confirmed; }); }, diff --git a/packages/functions/test-tangle/transaction-trigger/transaction-trigger_7.spec.ts b/packages/functions/test-tangle/transaction-trigger/transaction-trigger_7.spec.ts index ab674ed548..cac299f52c 100644 --- a/packages/functions/test-tangle/transaction-trigger/transaction-trigger_7.spec.ts +++ b/packages/functions/test-tangle/transaction-trigger/transaction-trigger_7.spec.ts @@ -53,23 +53,23 @@ describe('Transaction trigger spec', () => { void: false, }, }; - const docRef = build5Db().doc(`${COL.TRANSACTION}/${billPayment.uid}`); + const docRef = build5Db().doc(COL.TRANSACTION, billPayment.uid); return docRef.create(billPayment); }); await Promise.all(promises); const query = build5Db() .collection(COL.TRANSACTION) - .where('payload.sourceAddress', '==', sourceAddress.bech32); + .where('payload_sourceAddress', '==', sourceAddress.bech32); await wait(async () => { - const snap = await query.get(); + const snap = await query.get(); const allConfirmed = snap.reduce( (acc, act) => acc && (act?.payload?.walletReference?.confirmed || false), true, ); return snap.length === count && allConfirmed; }); - const snap = await query.get(); + const snap = await query.get(); for (const doc of snap) { expect(doc?.payload?.walletReference?.count).toBe(1); } diff --git a/packages/functions/test-tangle/transaction-trigger/transaction-trigger_8.spec.ts b/packages/functions/test-tangle/transaction-trigger/transaction-trigger_8.spec.ts index b788252c21..6b1f453507 100644 --- a/packages/functions/test-tangle/transaction-trigger/transaction-trigger_8.spec.ts +++ b/packages/functions/test-tangle/transaction-trigger/transaction-trigger_8.spec.ts @@ -51,7 +51,7 @@ describe('Transaction trigger spec', () => { void: false, }, }; - const docRef = build5Db().doc(`${COL.TRANSACTION}/${billPayment.uid}`); + const docRef = build5Db().doc(COL.TRANSACTION, billPayment.uid); return docRef.create(billPayment); }); await Promise.all(promises); @@ -59,9 +59,9 @@ describe('Transaction trigger spec', () => { await wait(async () => { const snap = await build5Db() .collection(COL.TRANSACTION) - .where('payload.sourceAddress', '==', sourceAddress.bech32) - .where('payload.walletReference.confirmed', '==', true) - .get(); + .where('payload_sourceAddress', '==', sourceAddress.bech32) + .where('payload_walletReference_confirmed', '==', true) + .get(); const countSum = snap.reduce( (acc, act) => acc + (act?.payload?.walletReference?.count || 0), 0, diff --git a/packages/functions/test-tangle/transaction-trigger/transaction-trigger_9.spec.ts b/packages/functions/test-tangle/transaction-trigger/transaction-trigger_9.spec.ts index e779ebdaf8..5015fbadc1 100644 --- a/packages/functions/test-tangle/transaction-trigger/transaction-trigger_9.spec.ts +++ b/packages/functions/test-tangle/transaction-trigger/transaction-trigger_9.spec.ts @@ -53,31 +53,23 @@ describe('Transaction trigger spec', () => { targetAddress.bech32, ); const batch = build5Db().batch(); - batch.create(build5Db().doc(`${COL.TRANSACTION}/${billPayment1.uid}`), billPayment1); - batch.create(build5Db().doc(`${COL.TRANSACTION}/${credit.uid}`), credit); - batch.create(build5Db().doc(`${COL.TRANSACTION}/${billPayment2.uid}`), billPayment2); + batch.create(build5Db().doc(COL.TRANSACTION, billPayment1.uid), billPayment1); + batch.create(build5Db().doc(COL.TRANSACTION, credit.uid), credit); + batch.create(build5Db().doc(COL.TRANSACTION, billPayment2.uid), billPayment2); await batch.commit(); await wait(async () => { - billPayment1 = ( - await build5Db().doc(`${COL.TRANSACTION}/${billPayment1.uid}`).get() - ); - billPayment2 = ( - await build5Db().doc(`${COL.TRANSACTION}/${billPayment2.uid}`).get() - ); - credit = await build5Db().doc(`${COL.TRANSACTION}/${credit.uid}`).get(); + billPayment1 = await build5Db().doc(COL.TRANSACTION, billPayment1.uid).get(); + billPayment2 = await build5Db().doc(COL.TRANSACTION, billPayment2.uid).get(); + credit = await build5Db().doc(COL.TRANSACTION, credit.uid).get(); return ( billPayment1?.payload?.walletReference?.confirmed && billPayment2?.payload?.walletReference?.confirmed && credit?.payload?.walletReference?.confirmed ); }); - billPayment1 = ( - await build5Db().doc(`${COL.TRANSACTION}/${billPayment1.uid}`).get() - ); - billPayment2 = ( - await build5Db().doc(`${COL.TRANSACTION}/${billPayment2.uid}`).get() - ); - credit = await build5Db().doc(`${COL.TRANSACTION}/${credit.uid}`).get(); + billPayment1 = await build5Db().doc(COL.TRANSACTION, billPayment1.uid).get(); + billPayment2 = await build5Db().doc(COL.TRANSACTION, billPayment2.uid).get(); + credit = await build5Db().doc(COL.TRANSACTION, credit.uid).get(); expect( dayjs(billPayment1?.payload?.walletReference?.processedOn?.toDate()).isBefore( diff --git a/packages/functions/test-tangle/web3/web3_1.spec.ts b/packages/functions/test-tangle/web3/web3_1.spec.ts index fbb71abd65..3a0d4fd05f 100644 --- a/packages/functions/test-tangle/web3/web3_1.spec.ts +++ b/packages/functions/test-tangle/web3/web3_1.spec.ts @@ -1,4 +1,4 @@ -import { build5Db } from '@build-5/database'; +import { PgMediaStatus, build5Db } from '@build-5/database'; import { COL, Collection, @@ -9,23 +9,17 @@ import { SUB_COL, Token, TokenStatus, + Transaction, + WEN_FUNC, } from '@build-5/interfaces'; import { uploadMediaToWeb3 } from '../../src/cron/media.cron'; -import { mintTokenOrder } from '../../src/runtime/firebase/token/minting'; -import { serverTime } from '../../src/utils/dateTime.utils'; +import { dateToTimestamp, serverTime } from '../../src/utils/dateTime.utils'; import * as wallet from '../../src/utils/wallet.utils'; -import { - createMember, - createSpace, - getRandomSymbol, - mockWalletReturnValue, - wait, -} from '../../test/controls/common'; -import { MEDIA, testEnv } from '../../test/set-up'; +import { getRandomSymbol, wait } from '../../test/controls/common'; +import { MEDIA, mockWalletReturnValue, testEnv } from '../../test/set-up'; import { CollectionMintHelper } from '../collection-minting/Helper'; import { requestFundsFromFaucet } from '../faucet'; -let walletSpy: any; const network = Network.RMS; const totalSupply = 1500; @@ -45,62 +39,61 @@ const saveToken = async (space: string, guardian: string, member: string) => { status: TokenStatus.AVAILABLE, access: 0, icon: MEDIA, - }; - await build5Db().doc(`${COL.TOKEN}/${token.uid}`).set(token); + } as Token; + await build5Db().doc(COL.TOKEN, token.uid).create(token); await build5Db() - .doc(`${COL.TOKEN}/${token.uid}/${SUB_COL.DISTRIBUTION}/${member}`) - .set({ tokenOwned: 1000 }); + .doc(COL.TOKEN, token.uid, SUB_COL.DISTRIBUTION, member) + .upsert({ tokenOwned: 1000 }); return token; }; describe('Web3 cron test', () => { - const collectionHelper = new CollectionMintHelper(); + const h = new CollectionMintHelper(); beforeEach(async () => { - walletSpy = jest.spyOn(wallet, 'decodeAuth'); await cleanupPendingUploads(); }); it('Should upload collection&nft media on mint', async () => { - await collectionHelper.beforeAll(); - await collectionHelper.beforeEach(); + await h.beforeAll(); + await h.beforeEach(); const count = 5; - await build5Db() - .doc(`${COL.COLLECTION}/${collectionHelper.collection}`) - .update({ total: count }); + await build5Db().doc(COL.COLLECTION, h.collection).update({ total: count }); const promises = Array.from(Array(count)).map(() => { - const nft = collectionHelper.createDummyNft( - collectionHelper.collection!, - collectionHelper.getRandomDescrptiron(), - ); + const nft = h.createDummyNft(h.collection!, h.getRandomDescrptiron()); return build5Db() - .doc(`${COL.NFT}/${nft.uid}`) - .create({ ...nft, project: SOON_PROJECT_ID }); + .doc(COL.NFT, nft.uid) + .create({ + ...nft, + availableFrom: dateToTimestamp(nft.availableFrom), + project: SOON_PROJECT_ID, + } as any); }); await Promise.all(promises); - await collectionHelper.mintCollection(); + await h.mintCollection(); await uploadMediaToWeb3(); - const collectionDocRef = build5Db().doc(`${COL.COLLECTION}/${collectionHelper.collection}`); + const collectionDocRef = build5Db().doc(COL.COLLECTION, h.collection); const collection = await collectionDocRef.get(); expect(collection.mintingData?.nftMediaToUpload).toBe(0); + expect(collection.mediaStatus).toBe(MediaStatus.UPLOADED); }); it('Should upload token media on mint', async () => { - const guardianId = await createMember(walletSpy); - const member = await createMember(walletSpy); - const guardian = await build5Db().doc(`${COL.MEMBER}/${guardianId}`).get(); - const space = await createSpace(walletSpy, guardian.uid); + const guardianId = await testEnv.createMember(); + const member = await testEnv.createMember(); + const guardian = await build5Db().doc(COL.MEMBER, guardianId).get(); + const space = await testEnv.createSpace(guardian.uid); let token = await saveToken(space.uid, guardian.uid, member); - mockWalletReturnValue(walletSpy, guardian.uid, { token: token.uid, network }); - const order = await testEnv.wrap(mintTokenOrder)({}); + mockWalletReturnValue(guardian.uid, { token: token.uid, network }); + const order = await testEnv.wrap(WEN_FUNC.mintTokenOrder); await requestFundsFromFaucet(network, order.payload.targetAddress, order.payload.amount); - const tokenDocRef = build5Db().doc(`${COL.TOKEN}/${token.uid}`); + const tokenDocRef = build5Db().doc(COL.TOKEN, token.uid); await wait(async () => { - const snap = await tokenDocRef.get(); + const snap = await tokenDocRef.get(); return snap?.status === TokenStatus.MINTED; }); @@ -121,14 +114,16 @@ describe('Web3 cron test', () => { const cleanupPendingUploads = async () => { for (const col of [COL.TOKEN, COL.NFT, COL.COLLECTION]) { - const snap = await pendingUploadsQuery(col).get>(); + const snap = await pendingUploadsQuery(col as COL.TOKEN).get(); const promises = snap.map((d) => { - const docRef = build5Db().doc(`${col}/${d.uid}`); - return docRef.update({ mediaStatus: build5Db().deleteField() }); + const docRef = build5Db().doc(col as COL.TOKEN, d.uid); + return docRef.update({ mediaStatus: undefined }); }); await Promise.all(promises); } }; -const pendingUploadsQuery = (col: COL) => - build5Db().collection(col).where('mediaStatus', '==', MediaStatus.PENDING_UPLOAD); +const pendingUploadsQuery = (col: COL.TOKEN | COL.NFT | COL.COLLECTION) => + build5Db() + .collection(col as COL.TOKEN) + .where('mediaStatus', '==', PgMediaStatus.PENDING_UPLOAD); diff --git a/packages/functions/test-tangle/web3/web3_2.spec.ts b/packages/functions/test-tangle/web3/web3_2.spec.ts index 2c276d91b5..8276867486 100644 --- a/packages/functions/test-tangle/web3/web3_2.spec.ts +++ b/packages/functions/test-tangle/web3/web3_2.spec.ts @@ -1,18 +1,15 @@ -import { build5Db } from '@build-5/database'; +import { PgMediaStatus, build5Db } from '@build-5/database'; import { COL, Collection, MediaStatus, Space } from '@build-5/interfaces'; import { uploadMediaToWeb3 } from '../../src/cron/media.cron'; import { collectionToIpfsMetadata, nftToIpfsMetadata } from '../../src/utils/car.utils'; -import * as wallet from '../../src/utils/wallet.utils'; -import { createMember, createSpace, wait } from '../../test/controls/common'; +import { wait } from '../../test/controls/common'; +import { testEnv } from '../../test/set-up'; import { CollectionMintHelper } from '../collection-minting/Helper'; -let walletSpy: any; - describe('Web3 cron test', () => { const collectionHelper = new CollectionMintHelper(); beforeEach(async () => { - walletSpy = jest.spyOn(wallet, 'decodeAuth'); await cleanupPendingUploads(); }); @@ -20,7 +17,7 @@ describe('Web3 cron test', () => { await collectionHelper.beforeAll(); await collectionHelper.beforeEach(); - const collectionDocRef = build5Db().doc(`${COL.COLLECTION}/${collectionHelper.collection}`); + const collectionDocRef = build5Db().doc(COL.COLLECTION, collectionHelper.collection); const collection = await collectionDocRef.get(); const nft = collectionHelper.createDummyNft(collection.uid, collectionHelper.space!.uid) as any; @@ -47,12 +44,12 @@ describe('Web3 cron test', () => { }); it('Should upload space media', async () => { - const guardian = await createMember(walletSpy); - let space = await createSpace(walletSpy, guardian); + const guardian = await testEnv.createMember(); + let space = await testEnv.createSpace(guardian); await uploadMediaToWeb3(); - const spaceDocRef = build5Db().doc(`${COL.SPACE}/${space.uid}`); + const spaceDocRef = build5Db().doc(COL.SPACE, space.uid); await wait(async () => { space = await spaceDocRef.get(); return space.mediaStatus === MediaStatus.UPLOADED; @@ -66,14 +63,16 @@ describe('Web3 cron test', () => { const cleanupPendingUploads = async () => { for (const col of [COL.TOKEN, COL.NFT, COL.COLLECTION]) { - const snap = await pendingUploadsQuery(col).get>(); + const snap = await pendingUploadsQuery(col).get(); const promises = snap.map((d) => { - const docRef = build5Db().doc(`${col}/${d.uid}`); - return docRef.update({ mediaStatus: build5Db().deleteField() }); + const docRef = build5Db().doc(col as COL.TOKEN, d.uid); + return docRef.update({ mediaStatus: undefined }); }); await Promise.all(promises); } }; const pendingUploadsQuery = (col: COL) => - build5Db().collection(col).where('mediaStatus', '==', MediaStatus.PENDING_UPLOAD); + build5Db() + .collection(col as COL.TOKEN) + .where('mediaStatus', '==', PgMediaStatus.PENDING_UPLOAD); diff --git a/packages/functions/test-tangle/web3/web3_3.spec.ts b/packages/functions/test-tangle/web3/web3_3.spec.ts index 9648a2c315..95a16865bc 100644 --- a/packages/functions/test-tangle/web3/web3_3.spec.ts +++ b/packages/functions/test-tangle/web3/web3_3.spec.ts @@ -1,28 +1,23 @@ -import { build5Db } from '@build-5/database'; -import { COL, MediaStatus, Space } from '@build-5/interfaces'; +import { PgMediaStatus, build5Db } from '@build-5/database'; +import { COL, MediaStatus, Space, WEN_FUNC } from '@build-5/interfaces'; import { uploadMediaToWeb3 } from '../../src/cron/media.cron'; -import { updateSpace } from '../../src/runtime/firebase/space'; -import * as wallet from '../../src/utils/wallet.utils'; -import { createMember, createSpace, mockWalletReturnValue, wait } from '../../test/controls/common'; -import { MEDIA, testEnv } from '../../test/set-up'; - -let walletSpy: any; +import { wait } from '../../test/controls/common'; +import { MEDIA, mockWalletReturnValue, testEnv } from '../../test/set-up'; describe('Web3 cron test', () => { beforeEach(async () => { - walletSpy = jest.spyOn(wallet, 'decodeAuth'); await cleanupPendingUploads(); }); it('Should upload space media after edit vote', async () => { - const guardian = await createMember(walletSpy); - let space = await createSpace(walletSpy, guardian); + const guardian = await testEnv.createMember(); + let space = await testEnv.createSpace(guardian); - const spaceDocRef = build5Db().doc(`${COL.SPACE}/${space.uid}`); + const spaceDocRef = build5Db().doc(COL.SPACE, space.uid); await spaceDocRef.update({ bannerUrl: '' }); - mockWalletReturnValue(walletSpy, guardian, { uid: space?.uid, bannerUrl: MEDIA }); - await testEnv.wrap(updateSpace)({}); + mockWalletReturnValue(guardian, { uid: space?.uid, bannerUrl: MEDIA }); + await testEnv.wrap(WEN_FUNC.updateSpace); await wait(async () => { space = await spaceDocRef.get(); @@ -38,11 +33,11 @@ describe('Web3 cron test', () => { }); it('Should fail first then retry', async () => { - const guardian = await createMember(walletSpy); - let space = await createSpace(walletSpy, guardian); + const guardian = await testEnv.createMember(); + let space = await testEnv.createSpace(guardian); - const spaceDocRef = build5Db().doc(`${COL.SPACE}/${space.uid}`); - await spaceDocRef.update({ bannerUrl: 'asd' }); + const spaceDocRef = build5Db().doc(COL.SPACE, space.uid); + await spaceDocRef.update({ bannerUrl: 'wrong-banner-url' }); await uploadMediaToWeb3(); @@ -58,11 +53,11 @@ describe('Web3 cron test', () => { }); it('Should fail 5 times, then set to error', async () => { - const guardian = await createMember(walletSpy); - let space = await createSpace(walletSpy, guardian); + const guardian = await testEnv.createMember(); + let space = await testEnv.createSpace(guardian); - const spaceDocRef = build5Db().doc(`${COL.SPACE}/${space.uid}`); - await spaceDocRef.update({ bannerUrl: 'asd' }); + const spaceDocRef = build5Db().doc(COL.SPACE, space.uid); + await spaceDocRef.update({ bannerUrl: 'wrong-banner-url' }); for (let i = 0; i < 6; ++i) { await uploadMediaToWeb3(); @@ -79,14 +74,16 @@ describe('Web3 cron test', () => { const cleanupPendingUploads = async () => { for (const col of [COL.TOKEN, COL.NFT, COL.COLLECTION]) { - const snap = await pendingUploadsQuery(col).get>(); + const snap = await pendingUploadsQuery(col).get(); const promises = snap.map((d) => { - const docRef = build5Db().doc(`${col}/${d.uid}`); - return docRef.update({ mediaStatus: build5Db().deleteField() }); + const docRef = build5Db().doc(col as COL.TOKEN, d.uid); + return docRef.update({ mediaStatus: undefined }); }); await Promise.all(promises); } }; const pendingUploadsQuery = (col: COL) => - build5Db().collection(col).where('mediaStatus', '==', MediaStatus.PENDING_UPLOAD); + build5Db() + .collection(col as COL.TOKEN) + .where('mediaStatus', '==', PgMediaStatus.PENDING_UPLOAD); diff --git a/packages/functions/test-tangle/withdraw-deposit-nft/Helper.ts b/packages/functions/test-tangle/withdraw-deposit-nft/Helper.ts index 84c5cd0b93..3c1efe199a 100644 --- a/packages/functions/test-tangle/withdraw-deposit-nft/Helper.ts +++ b/packages/functions/test-tangle/withdraw-deposit-nft/Helper.ts @@ -1,5 +1,5 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ -import { build5Db } from '@build-5/database'; +import { PgTransactionPayloadType, PgTransactionType, build5Db } from '@build-5/database'; import { Access, COL, @@ -19,9 +19,9 @@ import { Space, Timestamp, Transaction, - TransactionPayloadType, TransactionType, UnsoldMintingOptions, + WEN_FUNC, } from '@build-5/interfaces'; import { AddressUnlockCondition, @@ -34,14 +34,6 @@ import { } from '@iota/sdk'; import dayjs from 'dayjs'; import { cloneDeep } from 'lodash'; -import { createCollection, mintCollection } from '../../src/runtime/firebase/collection/index'; -import { - createNft, - orderNft, - setForSaleNft, - withdrawNft, -} from '../../src/runtime/firebase/nft/index'; -import { claimSpace } from '../../src/runtime/firebase/space'; import { NftWallet } from '../../src/services/wallet/NftWallet'; import { MnemonicService } from '../../src/services/wallet/mnemonic'; import { Wallet } from '../../src/services/wallet/wallet'; @@ -49,49 +41,39 @@ import { AddressDetails } from '../../src/services/wallet/wallet.service'; import { getAddress } from '../../src/utils/address.utils'; import { createUnlock, packEssence, submitBlock } from '../../src/utils/block.utils'; import { serverTime } from '../../src/utils/dateTime.utils'; -import * as wallet from '../../src/utils/wallet.utils'; import { getRandomEthAddress } from '../../src/utils/wallet.utils'; -import { - createMember as createMemberTest, - createSpace, - mockWalletReturnValue, - submitMilestoneFunc, - wait, -} from '../../test/controls/common'; -import { MEDIA, getWallet, testEnv } from '../../test/set-up'; +import { submitMilestoneFunc, wait } from '../../test/controls/common'; +import { MEDIA, getWallet, mockWalletReturnValue, testEnv } from '../../test/set-up'; import { requestFundsFromFaucet } from '../faucet'; export class Helper { public network = Network.RMS; - public collection: string | undefined; - public guardian: string | undefined; - public space: Space | undefined; - public walletService: Wallet | undefined; - public walletSpy: any; - public nft: Nft | undefined; - public guardianAddress: AddressDetails | undefined; - public royaltySpace: Space | undefined; + public collection = ''; + public guardian = ''; + public space: Space = {} as any; + public walletService: Wallet = {} as any; + public nft: Nft = {} as any; + public guardianAddress: AddressDetails = {} as any; + public royaltySpace: Space = {} as any; public beforeAll = async () => { - this.walletSpy = jest.spyOn(wallet, 'decodeAuth'); this.walletService = await getWallet(this.network); }; public beforeEach = async () => { - this.guardian = await createMemberTest(this.walletSpy); - this.space = await createSpace(this.walletSpy, this.guardian!); - this.royaltySpace = await createSpace(this.walletSpy, this.guardian!); + this.guardian = await testEnv.createMember(); + this.space = await testEnv.createSpace(this.guardian); + this.royaltySpace = await testEnv.createSpace(this.guardian); mockWalletReturnValue( - this.walletSpy, this.guardian!, this.createDummyCollection(this.space!.uid, this.royaltySpace!.uid), ); - this.collection = (await testEnv.wrap(createCollection)({})).uid; + this.collection = (await testEnv.wrap(WEN_FUNC.createCollection)).uid; - await build5Db().doc(`${COL.COLLECTION}/${this.collection}`).update({ approved: true }); + await build5Db().doc(COL.COLLECTION, this.collection).update({ approved: true }); - const guardianDocRef = build5Db().doc(`${COL.MEMBER}/${this.guardian}`); + const guardianDocRef = build5Db().doc(COL.MEMBER, this.guardian); const guardianData = await guardianDocRef.get(); const guardianBech32 = getAddress(guardianData, this.network!); this.guardianAddress = await this.walletService?.getAddressDetails(guardianBech32)!; @@ -100,31 +82,31 @@ export class Helper { public createAndOrderNft = async () => { let nft: any = this.createDummyNft(this.collection!); delete nft.uid; - mockWalletReturnValue(this.walletSpy, this.guardian!, nft); - nft = await testEnv.wrap(createNft)({}); + mockWalletReturnValue(this.guardian!, nft); + nft = await testEnv.wrap(WEN_FUNC.createNft); await build5Db() - .doc(`${COL.NFT}/${nft.uid}`) + .doc(COL.NFT, nft.uid) .update({ availableFrom: dayjs().subtract(1, 'h').toDate() }); - mockWalletReturnValue(this.walletSpy, this.guardian!, { + mockWalletReturnValue(this.guardian!, { collection: this.collection, nft: nft.uid, }); - const order = await testEnv.wrap(orderNft)({}); + const order = await testEnv.wrap(WEN_FUNC.orderNft); await submitMilestoneFunc(order); - this.nft = await build5Db().doc(`${COL.NFT}/${nft.uid}`).get(); + this.nft = await build5Db().doc(COL.NFT, nft.uid).get(); return this.nft; }; public mintCollection = async (expiresAt?: Timestamp) => { - mockWalletReturnValue(this.walletSpy, this.guardian!, { + mockWalletReturnValue(this.guardian!, { collection: this.collection!, network: this.network, unsoldMintingOptions: UnsoldMintingOptions.KEEP_PRICE, }); - const collectionMintOrder = await testEnv.wrap(mintCollection)({}); + const collectionMintOrder = await testEnv.wrap(WEN_FUNC.mintCollection); await requestFundsFromFaucet( this.network, this.guardianAddress!.bech32, @@ -133,13 +115,13 @@ export class Helper { ); await this.walletService!.send( this.guardianAddress!, - collectionMintOrder.payload.targetAddress, - collectionMintOrder.payload.amount, + collectionMintOrder.payload.targetAddress!, + collectionMintOrder.payload.amount!, {}, ); await MnemonicService.store(this.guardianAddress!.bech32, this.guardianAddress!.mnemonic); - const collectionDocRef = build5Db().doc(`${COL.COLLECTION}/${this.collection}`); + const collectionDocRef = build5Db().doc(COL.COLLECTION, this.collection!); await wait(async () => { const data = await collectionDocRef.get(); return data.status === CollectionStatus.MINTED; @@ -155,8 +137,8 @@ export class Helper { const ownerChangeTran = ( await build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.MINT_COLLECTION) - .where('payload.type', '==', TransactionPayloadType.SEND_ALIAS_TO_GUARDIAN) + .where('type', '==', PgTransactionType.MINT_COLLECTION) + .where('payload_type', '==', PgTransactionPayloadType.SEND_ALIAS_TO_GUARDIAN) .where('member', '==', this.guardian) .get() ).map((d) => d); @@ -167,8 +149,8 @@ export class Helper { public updateGuardianAddress = (address: NetworkAddress) => build5Db() - .doc(`${COL.MEMBER}/${this.guardian}`) - .update({ [`validatedAddress.${this.network}`]: address }); + .doc(COL.MEMBER, this.guardian) + .update({ [`${this.network}Address`]: address }); public sendNftToAddress = async ( sourceAddress: AddressDetails, @@ -188,11 +170,11 @@ export class Helper { payload: { sourceAddress: sourceAddress.bech32, targetAddress: targetAddressBech32, - expiresOn: expiresOn || null, + expiresOn: expiresOn || undefined, nftId: nftId || '', }, }; - await build5Db().doc(`${COL.TRANSACTION}/${order.uid}`).create(order); + await build5Db().doc(COL.TRANSACTION, order.uid).create(order); return order.uid; } @@ -245,37 +227,33 @@ export class Helper { const unlocks = [await createUnlock(essence, sourceAddress), new ReferenceUnlock(0)]; const blockId = await submitBlock(this.walletService!, essence, unlocks); - await build5Db().doc(`blocks/${blockId}`).create({ blockId }); + await testEnv.createBlock(blockId); return blockId; }; public withdrawNftAndAwait = async (nft: string) => { - mockWalletReturnValue(this.walletSpy, this.guardian!, { nft }); - await testEnv.wrap(withdrawNft)({}); + mockWalletReturnValue(this.guardian!, { nft }); + await testEnv.wrap(WEN_FUNC.withdrawNft); await wait(async () => { const snap = await build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.WITHDRAW_NFT) - .where('payload.nft', '==', nft) - .get(); + .where('type', '==', PgTransactionType.WITHDRAW_NFT) + .where('payload_nft', '==', nft) + .get(); return snap[0]?.payload?.walletReference?.confirmed; }); }; public setAvailableForAuction = async () => { - mockWalletReturnValue(this.walletSpy, this.guardian!, this.dummyAuctionData(this.nft!.uid)); - await testEnv.wrap(setForSaleNft)({}); - await wait( - async () => (await build5Db().doc(`${COL.NFT}/${this.nft!.uid}`).get())?.available === 3, - ); + mockWalletReturnValue(this.guardian!, this.dummyAuctionData(this.nft!.uid)); + await testEnv.wrap(WEN_FUNC.setForSaleNft); + await wait(async () => (await build5Db().doc(COL.NFT, this.nft!.uid).get())?.available === 3); }; public setAvailableForSale = async () => { - mockWalletReturnValue(this.walletSpy, this.guardian!, this.dummySaleData(this.nft!.uid)); - await testEnv.wrap(setForSaleNft)({}); - await wait( - async () => (await build5Db().doc(`${COL.NFT}/${this.nft!.uid}`).get())?.available === 1, - ); + mockWalletReturnValue(this.guardian!, this.dummySaleData(this.nft!.uid)); + await testEnv.wrap(WEN_FUNC.setForSaleNft); + await wait(async () => (await build5Db().doc(COL.NFT, this.nft!.uid).get())?.available === 1); }; public createDummyCollection = (space: string, royaltiesSpace: string) => ({ @@ -333,17 +311,17 @@ export class Helper { }); public claimSpaceFunc = async (spaceId: string) => { - mockWalletReturnValue(this.walletSpy, this.guardian!, { uid: spaceId }); - const order = await testEnv.wrap(claimSpace)({}); + mockWalletReturnValue(this.guardian!, { uid: spaceId }); + const order = await testEnv.wrap(WEN_FUNC.claimSpace); await this.walletService!.send( this.guardianAddress!, - order.payload.targetAddress, - order.payload.amount, + order.payload.targetAddress!, + order.payload.amount!, {}, ); await MnemonicService.store(this.guardianAddress!.bech32, this.guardianAddress!.mnemonic); - const spaceDocRef = build5Db().doc(`${COL.SPACE}/${spaceId}`); + const spaceDocRef = build5Db().doc(COL.SPACE, spaceId); await wait(async () => { const space = await spaceDocRef.get(); return space.claimed || false; @@ -354,77 +332,87 @@ export class Helper { expect(space.totalMembers).toBe(1); expect(space.totalGuardians).toBe(1); - const spaceMemberDocRef = spaceDocRef.collection(SUB_COL.MEMBERS).doc(this.guardian!); + const spaceMemberDocRef = build5Db().doc(COL.SPACE, spaceId, SUB_COL.MEMBERS, this.guardian!); const spaceMember = await spaceMemberDocRef.get(); expect(spaceMember !== undefined).toBe(true); - const spaceGuardianDocRef = spaceDocRef.collection(SUB_COL.GUARDIANS).doc(this.guardian!); + const spaceGuardianDocRef = build5Db().doc( + COL.SPACE, + spaceId, + SUB_COL.GUARDIANS, + this.guardian!, + ); const spaceGuardian = await spaceGuardianDocRef.get(); expect(spaceGuardian !== undefined).toBe(true); - const guardianDocRef = build5Db().doc(`${COL.MEMBER}/${this.guardian}`); + const guardianDocRef = build5Db().doc(COL.MEMBER, this.guardian); const guardianData = await guardianDocRef.get(); expect(guardianData.spaces![space.uid].isMember).toBe(true); }; public isInvalidPayment = async (paymentId: string) => { - const paymentDocRef = build5Db().doc(`${COL.TRANSACTION}/${paymentId}`); - const payment = (await paymentDocRef.get())!; + const paymentDocRef = build5Db().doc(COL.TRANSACTION, paymentId); + const payment = (await paymentDocRef.get())!; expect(payment.payload.invalidPayment).toBe(true); }; public mintWithCustomNftCID = async (func: (ipfsMedia: string) => string) => { let nft = await this.createAndOrderNft(); - const nftDocRef = build5Db().doc(`${COL.NFT}/${nft.uid}`); + const nftDocRef = build5Db().doc(COL.NFT, nft.uid); - mockWalletReturnValue(this.walletSpy, this.guardian!, { + mockWalletReturnValue(this.guardian!, { collection: this.collection!, network: this.network, unsoldMintingOptions: UnsoldMintingOptions.KEEP_PRICE, }); - const collectionMintOrder = await testEnv.wrap(mintCollection)({}); + const collectionMintOrder = await testEnv.wrap(WEN_FUNC.mintCollection); await requestFundsFromFaucet(this.network, this.guardianAddress!.bech32, 10 * MIN_IOTA_AMOUNT); await this.walletService!.send( this.guardianAddress!, - collectionMintOrder.payload.targetAddress, - collectionMintOrder.payload.amount, + collectionMintOrder.payload.targetAddress!, + collectionMintOrder.payload.amount!, {}, ); await MnemonicService.store(this.guardianAddress!.bech32, this.guardianAddress!.mnemonic); - const unsubscribe = nftDocRef.onSnapshot(async (doc) => { - const nft = doc as Nft; - const ipfsMedia = func(nft.ipfsMedia || ''); - if (nft.mediaStatus === MediaStatus.PENDING_UPLOAD && nft.ipfsMedia !== ipfsMedia) { - await nftDocRef.update({ ipfsMedia }); - } - }); + await wait( + async () => { + const nft = await nftDocRef.get(); + const ipfsMedia = func(nft.ipfsMedia || ''); + if (nft.mediaStatus === MediaStatus.PENDING_UPLOAD && nft.ipfsMedia !== ipfsMedia) { + await nftDocRef.update({ ipfsMedia }); + } + return nft.mediaStatus === MediaStatus.PENDING_UPLOAD && nft.ipfsMedia !== ipfsMedia; + }, + undefined, + 100, + ); + await wait(async () => { const nft = await nftDocRef.get(); return nft.mediaStatus === MediaStatus.PENDING_UPLOAD; }); - unsubscribe(); - const collectionDocRef = build5Db().doc(`${COL.COLLECTION}/${this.collection}`); + const collectionDocRef = build5Db().doc(COL.COLLECTION, this.collection); await wait(async () => { const collection = await collectionDocRef.get(); return collection.status === CollectionStatus.MINTED; }); - mockWalletReturnValue(this.walletSpy, this.guardian!, { nft: nft.uid }); - await testEnv.wrap(withdrawNft)({}); + mockWalletReturnValue(this.guardian!, { nft: nft.uid }); + await testEnv.wrap(WEN_FUNC.withdrawNft); let query = build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.WITHDRAW_NFT) - .where('payload.nft', '==', nft.uid); + .where('type', '==', PgTransactionType.WITHDRAW_NFT) + .where('payload_nft', '==', nft.uid); await wait(async () => { - const snap = await query.get(); + const snap = await query.get(); return snap.length === 1 && snap[0]?.payload?.walletReference?.confirmed; }); nft = await nftDocRef.get(); await nftDocRef.delete(); - await build5Db().doc(`${COL.COLLECTION}/${nft.collection}`).delete(); + await build5Db().doc(COL.COLLECTION, nft.collection).delete(); }; } diff --git a/packages/functions/test-tangle/withdraw-deposit-nft/deposit-withraw-nft_10_1.spec.ts b/packages/functions/test-tangle/withdraw-deposit-nft/deposit-withraw-nft_10_1.spec.ts index bae5e75b56..1925a6a999 100644 --- a/packages/functions/test-tangle/withdraw-deposit-nft/deposit-withraw-nft_10_1.spec.ts +++ b/packages/functions/test-tangle/withdraw-deposit-nft/deposit-withraw-nft_10_1.spec.ts @@ -1,9 +1,8 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ -import { build5Db } from '@build-5/database'; -import { COL, Transaction, TransactionType } from '@build-5/interfaces'; -import { depositNft } from '../../src/runtime/firebase/nft'; -import { mockWalletReturnValue, wait } from '../../test/controls/common'; -import { testEnv } from '../../test/set-up'; +import { PgTransactionType, build5Db } from '@build-5/database'; +import { COL, Transaction, WEN_FUNC } from '@build-5/interfaces'; +import { wait } from '../../test/controls/common'; +import { mockWalletReturnValue, testEnv } from '../../test/set-up'; import { Helper } from './Helper'; describe('Collection minting', () => { @@ -24,14 +23,14 @@ describe('Collection minting', () => { .join(''), ); - mockWalletReturnValue(helper.walletSpy, helper.guardian!, { network: helper.network }); - const depositOrder = await testEnv.wrap(depositNft)({}); - await helper.sendNftToAddress(helper.guardianAddress!, depositOrder.payload.targetAddress); + mockWalletReturnValue(helper.guardian!, { network: helper.network }); + const depositOrder = await testEnv.wrap(WEN_FUNC.depositNft); + await helper.sendNftToAddress(helper.guardianAddress!, depositOrder.payload.targetAddress!); const query = build5Db() .collection(COL.TRANSACTION) .where('member', '==', helper.guardian) - .where('type', '==', TransactionType.CREDIT_NFT); + .where('type', '==', PgTransactionType.CREDIT_NFT); await wait(async () => { const snap = await query.get(); return snap.length === 1; diff --git a/packages/functions/test-tangle/withdraw-deposit-nft/deposit-withraw-nft_10_2.spec.ts b/packages/functions/test-tangle/withdraw-deposit-nft/deposit-withraw-nft_10_2.spec.ts index 8602fc71bd..10034bc059 100644 --- a/packages/functions/test-tangle/withdraw-deposit-nft/deposit-withraw-nft_10_2.spec.ts +++ b/packages/functions/test-tangle/withdraw-deposit-nft/deposit-withraw-nft_10_2.spec.ts @@ -1,9 +1,8 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ -import { build5Db } from '@build-5/database'; -import { COL, Transaction, TransactionType } from '@build-5/interfaces'; -import { depositNft } from '../../src/runtime/firebase/nft'; -import { mockWalletReturnValue, wait } from '../../test/controls/common'; -import { testEnv } from '../../test/set-up'; +import { PgTransactionType, build5Db } from '@build-5/database'; +import { COL, Transaction, WEN_FUNC } from '@build-5/interfaces'; +import { wait } from '../../test/controls/common'; +import { mockWalletReturnValue, testEnv } from '../../test/set-up'; import { Helper } from './Helper'; const HUGE_CID = 'bafybeidxlcm7vs3uh3afk6tzye3rdzjjgaqrmj6fzaz3jf23e66f35dkce'; @@ -23,14 +22,14 @@ describe('Collection minting', () => { it.skip('Should credit, ipfs max size', async () => { await helper.mintWithCustomNftCID(() => HUGE_CID); - mockWalletReturnValue(helper.walletSpy, helper.guardian!, { network: helper.network }); - const depositOrder = await testEnv.wrap(depositNft)({}); - await helper.sendNftToAddress(helper.guardianAddress!, depositOrder.payload.targetAddress); + mockWalletReturnValue(helper.guardian!, { network: helper.network }); + const depositOrder = await testEnv.wrap(WEN_FUNC.depositNft); + await helper.sendNftToAddress(helper.guardianAddress!, depositOrder.payload.targetAddress!); const query = build5Db() .collection(COL.TRANSACTION) .where('member', '==', helper.guardian) - .where('type', '==', TransactionType.CREDIT_NFT); + .where('type', '==', PgTransactionType.CREDIT_NFT); await wait(async () => { const snap = await query.get(); return snap.length === 1; diff --git a/packages/functions/test-tangle/withdraw-deposit-nft/deposit-withraw-nft_10_3.spec.ts b/packages/functions/test-tangle/withdraw-deposit-nft/deposit-withraw-nft_10_3.spec.ts index 3ccbfa210a..56c6426c22 100644 --- a/packages/functions/test-tangle/withdraw-deposit-nft/deposit-withraw-nft_10_3.spec.ts +++ b/packages/functions/test-tangle/withdraw-deposit-nft/deposit-withraw-nft_10_3.spec.ts @@ -1,9 +1,8 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ -import { build5Db } from '@build-5/database'; -import { COL, Transaction, TransactionType } from '@build-5/interfaces'; -import { depositNft } from '../../src/runtime/firebase/nft'; -import { mockWalletReturnValue, wait } from '../../test/controls/common'; -import { testEnv } from '../../test/set-up'; +import { PgTransactionType, build5Db } from '@build-5/database'; +import { COL, Transaction, WEN_FUNC } from '@build-5/interfaces'; +import { wait } from '../../test/controls/common'; +import { mockWalletReturnValue, testEnv } from '../../test/set-up'; import { Helper } from './Helper'; describe('Collection minting', () => { @@ -22,14 +21,14 @@ describe('Collection minting', () => { () => 'bafybeidzgwp4grz4a3bze26xaouzts4jkkovz6idpu456n3dy36gpe6qem', ); - mockWalletReturnValue(helper.walletSpy, helper.guardian!, { network: helper.network }); - const depositOrder = await testEnv.wrap(depositNft)({}); - await helper.sendNftToAddress(helper.guardianAddress!, depositOrder.payload.targetAddress); + mockWalletReturnValue(helper.guardian!, { network: helper.network }); + const depositOrder = await testEnv.wrap(WEN_FUNC.depositNft); + await helper.sendNftToAddress(helper.guardianAddress!, depositOrder.payload.targetAddress!); const query = build5Db() .collection(COL.TRANSACTION) .where('member', '==', helper.guardian) - .where('type', '==', TransactionType.CREDIT_NFT); + .where('type', '==', PgTransactionType.CREDIT_NFT); await wait(async () => { const snap = await query.get(); return snap.length === 1; diff --git a/packages/functions/test-tangle/withdraw-deposit-nft/deposit-withraw-nft_11.spec.ts b/packages/functions/test-tangle/withdraw-deposit-nft/deposit-withraw-nft_11.spec.ts index 268cec4af3..9dba0dd81d 100644 --- a/packages/functions/test-tangle/withdraw-deposit-nft/deposit-withraw-nft_11.spec.ts +++ b/packages/functions/test-tangle/withdraw-deposit-nft/deposit-withraw-nft_11.spec.ts @@ -1,10 +1,8 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ -import { build5Db } from '@build-5/database'; -import { COL, Collection, Nft, Space, Transaction, TransactionType } from '@build-5/interfaces'; -import { depositNft, withdrawNft } from '../../src/runtime/firebase/nft/index'; -import { claimSpace } from '../../src/runtime/firebase/space'; -import { mockWalletReturnValue, wait } from '../../test/controls/common'; -import { testEnv } from '../../test/set-up'; +import { PgTransactionType, build5Db } from '@build-5/database'; +import { COL, Collection, Nft, Space, Transaction, WEN_FUNC } from '@build-5/interfaces'; +import { wait } from '../../test/controls/common'; +import { mockWalletReturnValue, testEnv } from '../../test/set-up'; import { Helper } from './Helper'; describe('Nft depositing', () => { @@ -18,16 +16,16 @@ describe('Nft depositing', () => { }); const withdrawNftFunc = async (nftId: string) => { - const nftDocRef = build5Db().doc(`${COL.NFT}/${nftId}`); - mockWalletReturnValue(helper.walletSpy, helper.guardian!, { nft: nftId }); - await testEnv.wrap(withdrawNft)({}); + const nftDocRef = build5Db().doc(COL.NFT, nftId); + mockWalletReturnValue(helper.guardian!, { nft: nftId }); + await testEnv.wrap(WEN_FUNC.withdrawNft); const query = build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.WITHDRAW_NFT) - .where('payload.nft', '==', nftId); + .where('type', '==', PgTransactionType.WITHDRAW_NFT) + .where('payload_nft', '==', nftId); await wait(async () => { - const snap = await query.get(); + const snap = await query.get(); return snap.length === 1 && snap[0]?.payload?.walletReference?.confirmed; }); return await nftDocRef.get(); @@ -42,20 +40,20 @@ describe('Nft depositing', () => { nft1 = await withdrawNftFunc(nft1.uid); nft2 = await withdrawNftFunc(nft2.uid); - const collectionDocRef = build5Db().doc(`${COL.COLLECTION}/${nft1.collection}`); + const collectionDocRef = build5Db().doc(COL.COLLECTION, nft1.collection); collection = await collectionDocRef.get(); }); it('Should deposit 2 nfts minted outside build-5', async () => { - await build5Db().doc(`${COL.NFT}/${nft1.uid}`).delete(); - await build5Db().doc(`${COL.NFT}/${nft2.uid}`).delete(); - await build5Db().doc(`${COL.COLLECTION}/${collection.uid}`).delete(); + await build5Db().doc(COL.NFT, nft1.uid).delete(); + await build5Db().doc(COL.NFT, nft2.uid).delete(); + await build5Db().doc(COL.COLLECTION, collection.uid).delete(); - mockWalletReturnValue(helper.walletSpy, helper.guardian!, { network: helper.network }); - let depositOrder = await testEnv.wrap(depositNft)({}); + mockWalletReturnValue(helper.guardian!, { network: helper.network }); + let depositOrder = await testEnv.wrap(WEN_FUNC.depositNft); await helper.sendNftToAddress( helper.guardianAddress!, - depositOrder.payload.targetAddress, + depositOrder.payload.targetAddress!, undefined, nft1.mintingData!.nftId, ); @@ -66,29 +64,29 @@ describe('Nft depositing', () => { return snap.length === 1; }); - const nft1DocRef = build5Db().doc(`${COL.NFT}/${nft1.mintingData!.nftId}`); + const nft1DocRef = build5Db().doc(COL.NFT, nft1.mintingData!.nftId!); nft1 = await nft1DocRef.get(); - mockWalletReturnValue(helper.walletSpy, helper.guardian!, { uid: nft1.space }); - const order = await testEnv.wrap(claimSpace)({}); + mockWalletReturnValue(helper.guardian!, { uid: nft1.space }); + const order = await testEnv.wrap(WEN_FUNC.claimSpace); await helper.walletService!.send( helper.guardianAddress!, - order.payload.targetAddress, - order.payload.amount, + order.payload.targetAddress!, + order.payload.amount!, {}, ); - const spaceDocRef = build5Db().doc(`${COL.SPACE}/${nft1.space}`); + const spaceDocRef = build5Db().doc(COL.SPACE, nft1.space); await wait(async () => { const space = await spaceDocRef.get(); return space.claimed || false; }); - mockWalletReturnValue(helper.walletSpy, helper.guardian!, { network: helper.network }); - depositOrder = await testEnv.wrap(depositNft)({}); + mockWalletReturnValue(helper.guardian!, { network: helper.network }); + depositOrder = await testEnv.wrap(WEN_FUNC.depositNft); await helper.sendNftToAddress( helper.guardianAddress!, - depositOrder.payload.targetAddress, + depositOrder.payload.targetAddress!, undefined, nft2.mintingData!.nftId, ); @@ -98,7 +96,7 @@ describe('Nft depositing', () => { return snap.length === 2; }); - const nft2DocRef = build5Db().doc(`${COL.NFT}/${nft2.mintingData!.nftId}`); + const nft2DocRef = build5Db().doc(COL.NFT, nft2.mintingData!.nftId!); nft2 = await nft2DocRef.get(); expect(nft1.collection).toBe(nft2.collection); diff --git a/packages/functions/test-tangle/withdraw-deposit-nft/deposit-withraw-nft_12_a.spec.ts b/packages/functions/test-tangle/withdraw-deposit-nft/deposit-withraw-nft_12_a.spec.ts index df6d756bd4..02c7c402e1 100644 --- a/packages/functions/test-tangle/withdraw-deposit-nft/deposit-withraw-nft_12_a.spec.ts +++ b/packages/functions/test-tangle/withdraw-deposit-nft/deposit-withraw-nft_12_a.spec.ts @@ -1,11 +1,11 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ -import { build5Db } from '@build-5/database'; +import { PgTransactionType, build5Db } from '@build-5/database'; import { COL, MIN_IOTA_AMOUNT, Network, Transaction, - TransactionType, + WEN_FUNC, WenError, } from '@build-5/interfaces'; import { @@ -20,14 +20,13 @@ import { Utils, } from '@iota/sdk'; import { cloneDeep } from 'lodash'; -import { depositNft } from '../../src/runtime/firebase/nft'; import { NftWallet } from '../../src/services/wallet/NftWallet'; import { AddressDetails } from '../../src/services/wallet/wallet.service'; import { packBasicOutput } from '../../src/utils/basic-output.utils'; import { createUnlock, indexToString, packEssence, submitBlock } from '../../src/utils/block.utils'; import { EMPTY_NFT_ID, createNftOutput } from '../../src/utils/collection-minting-utils/nft.utils'; -import { mockWalletReturnValue, wait } from '../../test/controls/common'; -import { getWallet, testEnv } from '../../test/set-up'; +import { wait } from '../../test/controls/common'; +import { getWallet, mockWalletReturnValue, testEnv } from '../../test/set-up'; import { awaitLedgerInclusionState, requestFundsFromFaucet } from '../faucet'; import { Helper } from './Helper'; @@ -47,9 +46,9 @@ describe('Collection minting', () => { const query = build5Db() .collection(COL.TRANSACTION) .where('member', '==', helper.guardian) - .where('type', '==', TransactionType.CREDIT_NFT); + .where('type', '==', PgTransactionType.CREDIT_NFT); await wait(async () => { - const snap = await query.get(); + const snap = await query.get(); return snap.length === 1 && snap[0]?.payload?.walletReference?.confirmed; }); const snap = await query.get(); @@ -83,11 +82,11 @@ describe('Collection minting', () => { fail(); } - mockWalletReturnValue(helper.walletSpy, helper.guardian!, { network: helper.network }); - const depositOrder = await testEnv.wrap(depositNft)({}); + mockWalletReturnValue(helper.guardian!, { network: helper.network }); + const depositOrder = await testEnv.wrap(WEN_FUNC.depositNft); await helper.sendNftToAddress( helper.guardianAddress!, - depositOrder.payload.targetAddress, + depositOrder.payload.targetAddress!, undefined, nftId, ); @@ -121,7 +120,7 @@ const mintCustomCollection = async (address: AddressDetails, metadata: any) => { const unlocks = [await createUnlock(essence, address)]; const blockId = await submitBlock(wallet, essence, unlocks); - await build5Db().doc(`blocks/${blockId}`).create({ blockId }); + await testEnv.createBlock(blockId); const payload = new TransactionPayload(essence, unlocks); const collectionOutputId = Utils.computeOutputId(Utils.transactionId(payload), 0); @@ -179,7 +178,7 @@ const mintNft = async (address: AddressDetails, metadata: any) => { const payload = new TransactionPayload(essence, unlocks); const blockId = await submitBlock(wallet, essence, unlocks); - await build5Db().doc(`blocks/${blockId}`).create({ blockId }); + await testEnv.createBlock(blockId); const nftId = Utils.computeNftId(Utils.transactionId(payload) + indexToString(1)); return [blockId, nftId]; diff --git a/packages/functions/test-tangle/withdraw-deposit-nft/deposit-withraw-nft_12_b.spec.ts b/packages/functions/test-tangle/withdraw-deposit-nft/deposit-withraw-nft_12_b.spec.ts index c2bb123b89..decd3b987b 100644 --- a/packages/functions/test-tangle/withdraw-deposit-nft/deposit-withraw-nft_12_b.spec.ts +++ b/packages/functions/test-tangle/withdraw-deposit-nft/deposit-withraw-nft_12_b.spec.ts @@ -1,6 +1,6 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ import { build5Db } from '@build-5/database'; -import { COL, MIN_IOTA_AMOUNT, Network } from '@build-5/interfaces'; +import { COL, MIN_IOTA_AMOUNT, Network, Transaction, WEN_FUNC } from '@build-5/interfaces'; import { Ed25519Address, NftAddress, @@ -13,14 +13,13 @@ import { Utils, } from '@iota/sdk'; import { cloneDeep } from 'lodash'; -import { depositNft } from '../../src/runtime/firebase/nft'; import { NftWallet } from '../../src/services/wallet/NftWallet'; import { AddressDetails } from '../../src/services/wallet/wallet.service'; import { packBasicOutput } from '../../src/utils/basic-output.utils'; import { createUnlock, packEssence, submitBlock } from '../../src/utils/block.utils'; import { EMPTY_NFT_ID, createNftOutput } from '../../src/utils/collection-minting-utils/nft.utils'; -import { mockWalletReturnValue, wait } from '../../test/controls/common'; -import { getWallet, testEnv } from '../../test/set-up'; +import { wait } from '../../test/controls/common'; +import { getWallet, mockWalletReturnValue, testEnv } from '../../test/set-up'; import { awaitLedgerInclusionState, requestFundsFromFaucet } from '../faucet'; import { Helper } from './Helper'; @@ -80,11 +79,11 @@ describe('Collection minting', () => { fail(); } - mockWalletReturnValue(helper.walletSpy, helper.guardian!, { network: helper.network }); - const depositOrder = await testEnv.wrap(depositNft)({}); + mockWalletReturnValue(helper.guardian!, { network: helper.network }); + const depositOrder = await testEnv.wrap(WEN_FUNC.depositNft); await helper.sendNftToAddress( helper.guardianAddress!, - depositOrder.payload.targetAddress, + depositOrder.payload.targetAddress!, undefined, nftId, ); @@ -119,7 +118,7 @@ const mintCustomCollection = async (address: AddressDetails, metadata: any) => { const payload = new TransactionPayload(essence, unlocks); const blockId = await submitBlock(wallet, essence, unlocks); - await build5Db().doc(`blocks/${blockId}`).create({ blockId }); + await testEnv.createBlock(blockId); const collectionOutputId = Utils.computeOutputId(Utils.transactionId(payload), 0); const collectionId = Utils.computeNftId(collectionOutputId); @@ -176,7 +175,7 @@ const mintNft = async (address: AddressDetails, metadata: any) => { const payload = new TransactionPayload(essence, unlocks); const blockId = await submitBlock(wallet, essence, unlocks); - await build5Db().doc(`blocks/${blockId}`).create({ blockId }); + await testEnv.createBlock(blockId); const nftOutputId = Utils.computeOutputId(Utils.transactionId(payload), 1); const nftId = Utils.computeNftId(nftOutputId); diff --git a/packages/functions/test-tangle/withdraw-deposit-nft/deposit-withraw-nft_13.spec.ts b/packages/functions/test-tangle/withdraw-deposit-nft/deposit-withraw-nft_13.spec.ts index 9e6c7798a7..0ed8702ab0 100644 --- a/packages/functions/test-tangle/withdraw-deposit-nft/deposit-withraw-nft_13.spec.ts +++ b/packages/functions/test-tangle/withdraw-deposit-nft/deposit-withraw-nft_13.spec.ts @@ -1,6 +1,6 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ import { build5Db } from '@build-5/database'; -import { COL, MIN_IOTA_AMOUNT, Network, Nft } from '@build-5/interfaces'; +import { COL, MIN_IOTA_AMOUNT, Network, Nft, Transaction, WEN_FUNC } from '@build-5/interfaces'; import { Ed25519Address, NftAddress, @@ -13,14 +13,13 @@ import { Utils, } from '@iota/sdk'; import { cloneDeep } from 'lodash'; -import { depositNft } from '../../src/runtime/firebase/nft'; import { NftWallet } from '../../src/services/wallet/NftWallet'; import { AddressDetails } from '../../src/services/wallet/wallet.service'; import { packBasicOutput } from '../../src/utils/basic-output.utils'; import { createUnlock, packEssence, submitBlock } from '../../src/utils/block.utils'; import { EMPTY_NFT_ID, createNftOutput } from '../../src/utils/collection-minting-utils/nft.utils'; -import { mockWalletReturnValue, wait } from '../../test/controls/common'; -import { getWallet, testEnv } from '../../test/set-up'; +import { wait } from '../../test/controls/common'; +import { getWallet, mockWalletReturnValue, testEnv } from '../../test/set-up'; import { awaitLedgerInclusionState, requestFundsFromFaucet } from '../faucet'; import { Helper } from './Helper'; @@ -105,11 +104,11 @@ describe('Collection minting', () => { fail(); } - mockWalletReturnValue(helper.walletSpy, helper.guardian!, { network: helper.network }); - const depositOrder = await testEnv.wrap(depositNft)({}); + mockWalletReturnValue(helper.guardian!, { network: helper.network }); + const depositOrder = await testEnv.wrap(WEN_FUNC.depositNft); await helper.sendNftToAddress( helper.guardianAddress!, - depositOrder.payload.targetAddress, + depositOrder.payload.targetAddress!, undefined, nftId, ); @@ -144,7 +143,7 @@ const mintCustomCollection = async (address: AddressDetails, metadata: any) => { const payload = new TransactionPayload(essence, unlocks); const blockId = await submitBlock(wallet, essence, unlocks); - await build5Db().doc(`blocks/${blockId}`).create({ blockId }); + await testEnv.createBlock(blockId); const collectionOutputId = Utils.computeOutputId(Utils.transactionId(payload), 0); const collectionId = Utils.computeNftId(collectionOutputId); @@ -200,7 +199,7 @@ const mintNft = async (address: AddressDetails, metadata: any) => { const payload = new TransactionPayload(essence, unlocks); const blockId = await submitBlock(wallet, essence, unlocks); - await build5Db().doc(`blocks/${blockId}`).create({ blockId }); + await testEnv.createBlock(blockId); const nftOutputId = Utils.computeOutputId(Utils.transactionId(payload), 1); const nftId = Utils.computeNftId(nftOutputId); diff --git a/packages/functions/test-tangle/withdraw-deposit-nft/deposit-withraw-nft_14.spec.ts b/packages/functions/test-tangle/withdraw-deposit-nft/deposit-withraw-nft_14.spec.ts index 1fe09fb440..9496242904 100644 --- a/packages/functions/test-tangle/withdraw-deposit-nft/deposit-withraw-nft_14.spec.ts +++ b/packages/functions/test-tangle/withdraw-deposit-nft/deposit-withraw-nft_14.spec.ts @@ -1,5 +1,5 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ -import { build5Db } from '@build-5/database'; +import { PgTransactionType, build5Db } from '@build-5/database'; import { COL, IgnoreWalletReason, @@ -7,16 +7,14 @@ import { Network, Nft, Transaction, - TransactionType, + WEN_FUNC, } from '@build-5/interfaces'; import dayjs from 'dayjs'; -import { creditUnrefundable } from '../../src/runtime/firebase/credit/index'; -import { depositNft, withdrawNft } from '../../src/runtime/firebase/nft/index'; import { NftWallet } from '../../src/services/wallet/NftWallet'; import { getAddress } from '../../src/utils/address.utils'; import { dateToTimestamp } from '../../src/utils/dateTime.utils'; -import { mockWalletReturnValue, wait } from '../../test/controls/common'; -import { getWallet, testEnv } from '../../test/set-up'; +import { wait } from '../../test/controls/common'; +import { getWallet, mockWalletReturnValue, testEnv } from '../../test/set-up'; import { requestFundsFromFaucet } from '../faucet'; import { Helper } from './Helper'; describe('Collection minting', () => { @@ -36,36 +34,36 @@ describe('Collection minting', () => { const tmpAddress = await helper.walletService!.getNewIotaAddressDetails(); await helper.updateGuardianAddress(tmpAddress.bech32); - const nftDocRef = build5Db().doc(`${COL.NFT}/${nft.uid}`); - mockWalletReturnValue(helper.walletSpy, helper.guardian!, { nft: nft.uid }); - await testEnv.wrap(withdrawNft)({}); + const nftDocRef = build5Db().doc(COL.NFT, nft.uid); + mockWalletReturnValue(helper.guardian!, { nft: nft.uid }); + await testEnv.wrap(WEN_FUNC.withdrawNft); const query = build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.WITHDRAW_NFT) - .where('payload.nft', '==', nft.uid); + .where('type', '==', PgTransactionType.WITHDRAW_NFT) + .where('payload_nft', '==', nft.uid); await wait(async () => { - const snap = await query.get(); + const snap = await query.get(); return snap.length === 1 && snap[0]?.payload?.walletReference?.confirmed; }); nft = await nftDocRef.get(); - let snap = await query.get(); + let snap = await query.get(); expect(snap[0].payload.nftId).toBe(nft.mintingData?.nftId); const wallet = await getWallet(helper.network); - const guardianDocRef = build5Db().doc(`${COL.MEMBER}/${helper.guardian}`); + const guardianDocRef = build5Db().doc(COL.MEMBER, helper.guardian!); const guardianData = await guardianDocRef.get(); const guardianAddress = getAddress(guardianData, helper.network!); const nftWallet = new NftWallet(wallet); const outputs = await nftWallet.getNftOutputs(undefined, guardianAddress); expect(Object.keys(outputs).length).toBe(1); - mockWalletReturnValue(helper.walletSpy, helper.guardian!, { network: helper.network }); - let depositOrder = await testEnv.wrap(depositNft)({}); + mockWalletReturnValue(helper.guardian!, { network: helper.network }); + let depositOrder = await testEnv.wrap(WEN_FUNC.depositNft); const sourceAddress = await helper.walletService!.getAddressDetails(guardianAddress); await helper.sendNftToAddress( sourceAddress!, - depositOrder.payload.targetAddress, + depositOrder.payload.targetAddress!, dateToTimestamp(dayjs().add(1, 'd')), undefined, guardianAddress, @@ -74,7 +72,7 @@ describe('Collection minting', () => { const creditQuery = build5Db() .collection(COL.TRANSACTION) .where('member', '==', helper.guardian) - .where('type', '==', TransactionType.CREDIT_NFT); + .where('type', '==', PgTransactionType.CREDIT_NFT); await wait(async () => { const snap = await creditQuery.get(); return snap.length === 1; @@ -87,12 +85,12 @@ describe('Collection minting', () => { IgnoreWalletReason.UNREFUNDABLE_DUE_STORAGE_DEPOSIT_CONDITION, ); - mockWalletReturnValue(helper.walletSpy, helper.guardian!, { transaction: credit.uid }); - const order = await testEnv.wrap(creditUnrefundable)({}); + mockWalletReturnValue(helper.guardian!, { transaction: credit.uid }); + const order = await testEnv.wrap(WEN_FUNC.creditUnrefundable); await requestFundsFromFaucet(Network.RMS, order.payload.targetAddress, order.payload.amount); await wait(async () => { - const snap = await creditQuery.get(); + const snap = await creditQuery.get(); return snap[0]?.payload?.walletReference?.confirmed; }); }); diff --git a/packages/functions/test-tangle/withdraw-deposit-nft/deposit-withraw-nft_15.spec.ts b/packages/functions/test-tangle/withdraw-deposit-nft/deposit-withraw-nft_15.spec.ts index 57f09a31c2..bb86ae3ee2 100644 --- a/packages/functions/test-tangle/withdraw-deposit-nft/deposit-withraw-nft_15.spec.ts +++ b/packages/functions/test-tangle/withdraw-deposit-nft/deposit-withraw-nft_15.spec.ts @@ -1,6 +1,6 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ import { build5Db } from '@build-5/database'; -import { COL, MIN_IOTA_AMOUNT, Network } from '@build-5/interfaces'; +import { COL, MIN_IOTA_AMOUNT, Network, Transaction, WEN_FUNC } from '@build-5/interfaces'; import { Ed25519Address, NftAddress, @@ -13,14 +13,13 @@ import { Utils, } from '@iota/sdk'; import { cloneDeep } from 'lodash'; -import { depositNft } from '../../src/runtime/firebase/nft'; import { NftWallet } from '../../src/services/wallet/NftWallet'; import { AddressDetails } from '../../src/services/wallet/wallet.service'; import { packBasicOutput } from '../../src/utils/basic-output.utils'; import { createUnlock, packEssence, submitBlock } from '../../src/utils/block.utils'; import { EMPTY_NFT_ID, createNftOutput } from '../../src/utils/collection-minting-utils/nft.utils'; -import { mockWalletReturnValue, wait } from '../../test/controls/common'; -import { MEDIA, getWallet, testEnv } from '../../test/set-up'; +import { wait } from '../../test/controls/common'; +import { MEDIA, getWallet, mockWalletReturnValue, testEnv } from '../../test/set-up'; import { awaitLedgerInclusionState, requestFundsFromFaucet } from '../faucet'; import { Helper } from './Helper'; @@ -78,11 +77,11 @@ describe('Collection minting', () => { fail(); } - mockWalletReturnValue(helper.walletSpy, helper.guardian!, { network: helper.network }); - const depositOrder = await testEnv.wrap(depositNft)({}); + mockWalletReturnValue(helper.guardian!, { network: helper.network }); + const depositOrder = await testEnv.wrap(WEN_FUNC.depositNft); await helper.sendNftToAddress( helper.guardianAddress!, - depositOrder.payload.targetAddress, + depositOrder.payload.targetAddress!, undefined, nftId, ); @@ -117,7 +116,7 @@ const mintCustomCollection = async (address: AddressDetails, metadata: any) => { const payload = new TransactionPayload(essence, unlocks); const blockId = await submitBlock(wallet, essence, unlocks); - await build5Db().doc(`blocks/${blockId}`).create({ blockId }); + await testEnv.createBlock(blockId); const collectionOutputId = Utils.computeOutputId(Utils.transactionId(payload), 0); const collectionId = Utils.computeNftId(collectionOutputId); @@ -173,7 +172,7 @@ const mintNft = async (address: AddressDetails, metadata: any) => { const payload = new TransactionPayload(essence, unlocks); const blockId = await submitBlock(wallet, essence, unlocks); - await build5Db().doc(`blocks/${blockId}`).create({ blockId }); + await testEnv.createBlock(blockId); const nftOutputId = Utils.computeOutputId(Utils.transactionId(payload), 1); const nftId = Utils.computeNftId(nftOutputId); diff --git a/packages/functions/test-tangle/withdraw-deposit-nft/deposit-withraw-nft_16.spec.ts b/packages/functions/test-tangle/withdraw-deposit-nft/deposit-withraw-nft_16.spec.ts index ea6fef011a..af06f3d6f9 100644 --- a/packages/functions/test-tangle/withdraw-deposit-nft/deposit-withraw-nft_16.spec.ts +++ b/packages/functions/test-tangle/withdraw-deposit-nft/deposit-withraw-nft_16.spec.ts @@ -1,9 +1,8 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ -import { build5Db } from '@build-5/database'; -import { COL, MIN_IOTA_AMOUNT, Network, Transaction, TransactionType } from '@build-5/interfaces'; -import { depositNft } from '../../src/runtime/firebase/nft/index'; -import { mockWalletReturnValue, wait } from '../../test/controls/common'; -import { testEnv } from '../../test/set-up'; +import { PgTransactionType, build5Db } from '@build-5/database'; +import { COL, MIN_IOTA_AMOUNT, Network, Transaction, WEN_FUNC } from '@build-5/interfaces'; +import { wait } from '../../test/controls/common'; +import { mockWalletReturnValue, testEnv } from '../../test/set-up'; import { requestFundsFromFaucet } from '../faucet'; import { Helper } from './Helper'; @@ -19,16 +18,16 @@ describe('Collection minting', () => { }); it('Should return credits when nft deposit order does not receive nft', async () => { - mockWalletReturnValue(helper.walletSpy, helper.guardian!, { network: helper.network }); - const order = await testEnv.wrap(depositNft)({}); + mockWalletReturnValue(helper.guardian!, { network: helper.network }); + const order = await testEnv.wrap(WEN_FUNC.depositNft); await requestFundsFromFaucet(Network.RMS, order.payload.targetAddress, MIN_IOTA_AMOUNT); const query = build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.CREDIT) + .where('type', '==', PgTransactionType.CREDIT) .where('member', '==', helper.guardian!); await wait(async () => { - const snap = await query.get(); + const snap = await query.get(); return ( snap.length === 1 && snap[0].payload.walletReference?.confirmed && diff --git a/packages/functions/test-tangle/withdraw-deposit-nft/deposit-withraw-nft_1_a.spec.ts b/packages/functions/test-tangle/withdraw-deposit-nft/deposit-withraw-nft_1_a.spec.ts index 775216cc9b..2d7b17f61b 100644 --- a/packages/functions/test-tangle/withdraw-deposit-nft/deposit-withraw-nft_1_a.spec.ts +++ b/packages/functions/test-tangle/withdraw-deposit-nft/deposit-withraw-nft_1_a.spec.ts @@ -1,12 +1,11 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ -import { build5Db } from '@build-5/database'; -import { COL, Member, Nft, NftStatus, Transaction, TransactionType } from '@build-5/interfaces'; +import { PgTransactionType, build5Db } from '@build-5/database'; +import { COL, Member, Nft, NftStatus, Transaction, WEN_FUNC } from '@build-5/interfaces'; import { isEqual } from 'lodash'; -import { depositNft, withdrawNft } from '../../src/runtime/firebase/nft/index'; import { NftWallet } from '../../src/services/wallet/NftWallet'; import { getAddress } from '../../src/utils/address.utils'; -import { mockWalletReturnValue, wait } from '../../test/controls/common'; -import { getWallet, testEnv } from '../../test/set-up'; +import { wait } from '../../test/controls/common'; +import { getWallet, mockWalletReturnValue, testEnv } from '../../test/set-up'; import { Helper } from './Helper'; describe('Collection minting', () => { @@ -26,27 +25,29 @@ describe('Collection minting', () => { const tmpAddress = await helper.walletService!.getNewIotaAddressDetails(); await helper.updateGuardianAddress(tmpAddress.bech32); - const nftDocRef = build5Db().doc(`${COL.NFT}/${nft.uid}`); + const nftDocRef = build5Db().doc(COL.NFT, nft.uid); const mintingData = (await nftDocRef.get()).mintingData; - mockWalletReturnValue(helper.walletSpy, helper.guardian!, { nft: nft.uid }); - await testEnv.wrap(withdrawNft)({}); + mockWalletReturnValue(helper.guardian!, { nft: nft.uid }); + await testEnv.wrap(WEN_FUNC.withdrawNft); const query = build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.WITHDRAW_NFT) - .where('payload.nft', '==', nft.uid); + .where('type', '==', PgTransactionType.WITHDRAW_NFT) + .where('payload_nft', '==', nft.uid); await wait(async () => { - const snap = await query.get(); + const snap = await query.get(); return snap.length === 1 && snap[0]?.payload?.walletReference?.confirmed; }); nft = await nftDocRef.get(); expect(nft.status).toBe(NftStatus.WITHDRAWN); expect(nft.hidden).toBe(true); expect(nft.isOwned).toBe(false); - expect(nft.owner).toBeNull(); + expect(nft.owner).toBeUndefined(); + delete (nft.mintingData as any).mintedOn; + delete (mintingData as any).mintedOn; expect(isEqual(nft.mintingData, mintingData)).toBe(true); const wallet = await getWallet(helper.network); - const guardianData = await build5Db().doc(`${COL.MEMBER}/${helper.guardian}`).get(); + const guardianData = await build5Db().doc(COL.MEMBER, helper.guardian!).get(); const nftWallet = new NftWallet(wallet); let outputs = await nftWallet.getNftOutputs( undefined, @@ -54,21 +55,19 @@ describe('Collection minting', () => { ); expect(Object.keys(outputs).length).toBe(1); - mockWalletReturnValue(helper.walletSpy, helper.guardian!, { network: helper.network }); - let depositOrder = await testEnv.wrap(depositNft)({}); + mockWalletReturnValue(helper.guardian!, { network: helper.network }); + let depositOrder = await testEnv.wrap(WEN_FUNC.depositNft); const sourceAddress = await helper.walletService?.getAddressDetails( getAddress(guardianData, helper.network!), ); - await helper.sendNftToAddress(sourceAddress!, depositOrder.payload.targetAddress); + await helper.sendNftToAddress(sourceAddress!, depositOrder.payload.targetAddress!); await wait(async () => { nft = await nftDocRef.get(); return nft.status === NftStatus.MINTED; }); - depositOrder = ( - await build5Db().doc(`${COL.TRANSACTION}/${depositOrder.uid}`).get() - ); + depositOrder = await build5Db().doc(COL.TRANSACTION, depositOrder.uid).get(); expect(depositOrder.payload.nft).toBe(nft.uid); expect(nft.depositData?.storageDeposit).toBe(Number(Object.values(outputs)[0].amount)); expect(nft.depositData?.address).toBe(depositOrder.payload.targetAddress); diff --git a/packages/functions/test-tangle/withdraw-deposit-nft/deposit-withraw-nft_1_b.spec.ts b/packages/functions/test-tangle/withdraw-deposit-nft/deposit-withraw-nft_1_b.spec.ts index efa94de6dc..ab49c7a490 100644 --- a/packages/functions/test-tangle/withdraw-deposit-nft/deposit-withraw-nft_1_b.spec.ts +++ b/packages/functions/test-tangle/withdraw-deposit-nft/deposit-withraw-nft_1_b.spec.ts @@ -1,22 +1,21 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ -import { build5Db } from '@build-5/database'; +import { PgTransactionType, build5Db } from '@build-5/database'; import { COL, - Member, MIN_IOTA_AMOUNT, + Member, Nft, NftStatus, Transaction, - TransactionType, + WEN_FUNC, } from '@build-5/interfaces'; import dayjs from 'dayjs'; import { isEqual } from 'lodash'; -import { depositNft, withdrawNft } from '../../src/runtime/firebase/nft/index'; import { NftWallet } from '../../src/services/wallet/NftWallet'; import { getAddress } from '../../src/utils/address.utils'; import { dateToTimestamp } from '../../src/utils/dateTime.utils'; -import { mockWalletReturnValue, wait } from '../../test/controls/common'; -import { getWallet, testEnv } from '../../test/set-up'; +import { wait } from '../../test/controls/common'; +import { getWallet, mockWalletReturnValue, testEnv } from '../../test/set-up'; import { Helper } from './Helper'; describe('Collection minting', () => { @@ -38,27 +37,29 @@ describe('Collection minting', () => { const tmpAddress = await helper.walletService!.getNewIotaAddressDetails(); await helper.updateGuardianAddress(tmpAddress.bech32); - const nftDocRef = build5Db().doc(`${COL.NFT}/${nft.uid}`); + const nftDocRef = build5Db().doc(COL.NFT, nft.uid); const mintingData = (await nftDocRef.get()).mintingData; - mockWalletReturnValue(helper.walletSpy, helper.guardian!, { nft: nft.uid }); - await testEnv.wrap(withdrawNft)({}); + mockWalletReturnValue(helper.guardian!, { nft: nft.uid }); + await testEnv.wrap(WEN_FUNC.withdrawNft); const query = build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.WITHDRAW_NFT) - .where('payload.nft', '==', nft.uid); + .where('type', '==', PgTransactionType.WITHDRAW_NFT) + .where('payload_nft', '==', nft.uid); await wait(async () => { - const snap = await query.get(); + const snap = await query.get(); return snap.length === 1 && snap[0]?.payload?.walletReference?.confirmed; }); nft = await nftDocRef.get(); expect(nft.status).toBe(NftStatus.WITHDRAWN); expect(nft.hidden).toBe(true); expect(nft.isOwned).toBe(false); - expect(nft.owner).toBeNull(); + expect(nft.owner).toBeUndefined(); + delete (nft.mintingData as any).mintedOn; + delete (mintingData as any).mintedOn; expect(isEqual(nft.mintingData, mintingData)).toBe(true); const wallet = await getWallet(helper.network); - const guardianData = await build5Db().doc(`${COL.MEMBER}/${helper.guardian}`).get(); + const guardianData = await build5Db().doc(COL.MEMBER, helper.guardian!).get(); const nftWallet = new NftWallet(wallet); let outputs = await nftWallet.getNftOutputs( undefined, @@ -66,21 +67,19 @@ describe('Collection minting', () => { ); expect(Object.keys(outputs).length).toBe(1); - mockWalletReturnValue(helper.walletSpy, helper.guardian!, { network: helper.network }); - let depositOrder = await testEnv.wrap(depositNft)({}); + mockWalletReturnValue(helper.guardian!, { network: helper.network }); + let depositOrder = await testEnv.wrap(WEN_FUNC.depositNft); const sourceAddress = await helper.walletService?.getAddressDetails( getAddress(guardianData, helper.network!), ); - await helper.sendNftToAddress(sourceAddress!, depositOrder.payload.targetAddress, expiresAt); + await helper.sendNftToAddress(sourceAddress!, depositOrder.payload.targetAddress!, expiresAt); await wait(async () => { nft = await nftDocRef.get(); return nft.status === NftStatus.MINTED; }); - depositOrder = ( - await build5Db().doc(`${COL.TRANSACTION}/${depositOrder.uid}`).get() - ); + depositOrder = await build5Db().doc(COL.TRANSACTION, depositOrder.uid).get(); expect(depositOrder.payload.nft).toBe(nft.uid); expect(nft.depositData?.storageDeposit).toBe( Number(Object.values(outputs)[0].amount) + MIN_IOTA_AMOUNT, diff --git a/packages/functions/test-tangle/withdraw-deposit-nft/deposit-withraw-nft_1_c.spec.ts b/packages/functions/test-tangle/withdraw-deposit-nft/deposit-withraw-nft_1_c.spec.ts index 1a21aa5272..f158c893d0 100644 --- a/packages/functions/test-tangle/withdraw-deposit-nft/deposit-withraw-nft_1_c.spec.ts +++ b/packages/functions/test-tangle/withdraw-deposit-nft/deposit-withraw-nft_1_c.spec.ts @@ -1,14 +1,13 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ -import { build5Db } from '@build-5/database'; -import { COL, Member, Nft, NftStatus, Transaction, TransactionType } from '@build-5/interfaces'; +import { PgTransactionType, build5Db } from '@build-5/database'; +import { COL, Member, Nft, NftStatus, Transaction, WEN_FUNC } from '@build-5/interfaces'; import dayjs from 'dayjs'; import { isEqual } from 'lodash'; -import { depositNft, withdrawNft } from '../../src/runtime/firebase/nft/index'; import { NftWallet } from '../../src/services/wallet/NftWallet'; import { getAddress } from '../../src/utils/address.utils'; import { dateToTimestamp } from '../../src/utils/dateTime.utils'; -import { mockWalletReturnValue, wait } from '../../test/controls/common'; -import { getWallet, testEnv } from '../../test/set-up'; +import { wait } from '../../test/controls/common'; +import { getWallet, mockWalletReturnValue, testEnv } from '../../test/set-up'; import { Helper } from './Helper'; describe('Collection minting', () => { @@ -29,25 +28,27 @@ describe('Collection minting', () => { const tmpAddress = await helper.walletService!.getNewIotaAddressDetails(); await helper.updateGuardianAddress(tmpAddress.bech32); - const nftDocRef = build5Db().doc(`${COL.NFT}/${nft.uid}`); + const nftDocRef = build5Db().doc(COL.NFT, nft.uid); const mintingData = (await nftDocRef.get()).mintingData; - mockWalletReturnValue(helper.walletSpy, helper.guardian!, { nft: nft.uid }); - await testEnv.wrap(withdrawNft)({}); + mockWalletReturnValue(helper.guardian!, { nft: nft.uid }); + await testEnv.wrap(WEN_FUNC.withdrawNft); const query = build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.WITHDRAW_NFT) - .where('payload.nft', '==', nft.uid); + .where('type', '==', PgTransactionType.WITHDRAW_NFT) + .where('payload_nft', '==', nft.uid); await wait(async () => { - const snap = await query.get(); + const snap = await query.get(); return snap.length === 1 && snap[0]?.payload?.walletReference?.confirmed; }); nft = await nftDocRef.get(); expect(nft.status).toBe(NftStatus.WITHDRAWN); expect(nft.hidden).toBe(true); + delete (nft.mintingData as any).mintedOn; + delete (mintingData as any).mintedOn; expect(isEqual(nft.mintingData, mintingData)).toBe(true); const wallet = await getWallet(helper.network); - const guardianData = await build5Db().doc(`${COL.MEMBER}/${helper.guardian}`).get(); + const guardianData = await build5Db().doc(COL.MEMBER, helper.guardian!).get(); const nftWallet = new NftWallet(wallet); let outputs = await nftWallet.getNftOutputs( undefined, @@ -55,23 +56,23 @@ describe('Collection minting', () => { ); expect(Object.keys(outputs).length).toBe(1); - mockWalletReturnValue(helper.walletSpy, helper.guardian!, { network: helper.network }); - const depositOrder = await testEnv.wrap(depositNft)({}); + mockWalletReturnValue(helper.guardian!, { network: helper.network }); + const depositOrder = await testEnv.wrap(WEN_FUNC.depositNft); await build5Db() - .doc(`${COL.TRANSACTION}/${depositOrder.uid}`) - .update({ 'payload.expiresOn': dateToTimestamp(dayjs().subtract(2, 'h').toDate()) }); + .doc(COL.TRANSACTION, depositOrder.uid) + .update({ payload_expiresOn: dayjs().subtract(2, 'h').toDate() }); const sourceAddress = await helper.walletService?.getAddressDetails( getAddress(guardianData, helper.network!), ); - await helper.sendNftToAddress(sourceAddress!, depositOrder.payload.targetAddress, expiresAt); + await helper.sendNftToAddress(sourceAddress!, depositOrder.payload.targetAddress!, expiresAt); await wait(async () => { const snap = await build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.CREDIT_NFT) + .where('type', '==', PgTransactionType.CREDIT_NFT) .where('member', '==', helper.guardian!) - .get(); + .get(); return ( snap.length === 1 && snap[0]!.payload.walletReference?.confirmed && diff --git a/packages/functions/test-tangle/withdraw-deposit-nft/deposit-withraw-nft_2.spec.ts b/packages/functions/test-tangle/withdraw-deposit-nft/deposit-withraw-nft_2.spec.ts index 48f3ec9440..4b053751d5 100644 --- a/packages/functions/test-tangle/withdraw-deposit-nft/deposit-withraw-nft_2.spec.ts +++ b/packages/functions/test-tangle/withdraw-deposit-nft/deposit-withraw-nft_2.spec.ts @@ -1,9 +1,8 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ -import { build5Db } from '@build-5/database'; -import { COL, Transaction, TransactionType } from '@build-5/interfaces'; -import { depositNft } from '../../src/runtime/firebase/nft/index'; -import { mockWalletReturnValue, wait } from '../../test/controls/common'; -import { testEnv } from '../../test/set-up'; +import { PgTransactionType, build5Db } from '@build-5/database'; +import { COL, Transaction, WEN_FUNC } from '@build-5/interfaces'; +import { wait } from '../../test/controls/common'; +import { mockWalletReturnValue, testEnv } from '../../test/set-up'; import { Helper } from './Helper'; describe('Collection minting', () => { @@ -30,21 +29,21 @@ describe('Collection minting', () => { await helper.updateGuardianAddress(tmpAddress2.bech32); await helper.withdrawNftAndAwait(nft2.uid); - mockWalletReturnValue(helper.walletSpy, helper.guardian!, { network: helper.network }); - const depositOrder = await testEnv.wrap(depositNft)({}); + mockWalletReturnValue(helper.guardian!, { network: helper.network }); + const depositOrder = await testEnv.wrap(WEN_FUNC.depositNft); const promises = [ - helper.sendNftToAddress(tmpAddress1, depositOrder.payload.targetAddress), - helper.sendNftToAddress(tmpAddress2, depositOrder.payload.targetAddress), + helper.sendNftToAddress(tmpAddress1, depositOrder.payload.targetAddress!), + helper.sendNftToAddress(tmpAddress2, depositOrder.payload.targetAddress!), ]; await Promise.all(promises); await wait(async () => { const snap = await build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.CREDIT_NFT) + .where('type', '==', PgTransactionType.CREDIT_NFT) .where('member', '==', helper.guardian) - .get(); + .get(); return snap.length === 1 && snap[0]?.payload?.walletReference?.confirmed; }); }); diff --git a/packages/functions/test-tangle/withdraw-deposit-nft/deposit-withraw-nft_4.spec.ts b/packages/functions/test-tangle/withdraw-deposit-nft/deposit-withraw-nft_4.spec.ts index fd4b512e50..b264f5d41a 100644 --- a/packages/functions/test-tangle/withdraw-deposit-nft/deposit-withraw-nft_4.spec.ts +++ b/packages/functions/test-tangle/withdraw-deposit-nft/deposit-withraw-nft_4.spec.ts @@ -1,9 +1,8 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ import { build5Db } from '@build-5/database'; -import { COL, WenError } from '@build-5/interfaces'; -import { withdrawNft } from '../../src/runtime/firebase/nft/index'; -import { expectThrow, mockWalletReturnValue } from '../../test/controls/common'; -import { testEnv } from '../../test/set-up'; +import { COL, WEN_FUNC, WenError } from '@build-5/interfaces'; +import { expectThrow } from '../../test/controls/common'; +import { mockWalletReturnValue, testEnv } from '../../test/set-up'; import { Helper } from './Helper'; describe('Collection minting', () => { @@ -22,20 +21,20 @@ describe('Collection minting', () => { await helper.mintCollection(); await helper.setAvailableForSale(); - mockWalletReturnValue(helper.walletSpy, helper.guardian!, { nft: helper.nft!.uid }); - await expectThrow(testEnv.wrap(withdrawNft)({}), WenError.nft_on_sale.key); + mockWalletReturnValue(helper.guardian!, { nft: helper.nft!.uid }); + await expectThrow(testEnv.wrap(WEN_FUNC.withdrawNft), WenError.nft_on_sale.key); - await build5Db().doc(`${COL.NFT}/${helper.nft!.uid}`).update({ - auctionFrom: null, - auctionTo: null, - auctionFloorPrice: null, - auctionLength: null, - auctionHighestBid: null, - auctionHighestBidder: null, + await build5Db().doc(COL.NFT, helper.nft!.uid).update({ + auctionFrom: undefined, + auctionTo: undefined, + auctionFloorPrice: undefined, + auctionLength: undefined, + auctionHighestBid: undefined, + auctionHighestBidder: undefined, }); await helper.setAvailableForAuction(); - mockWalletReturnValue(helper.walletSpy, helper.guardian!, { nft: helper.nft!.uid }); - await expectThrow(testEnv.wrap(withdrawNft)({}), WenError.nft_on_sale.key); + mockWalletReturnValue(helper.guardian!, { nft: helper.nft!.uid }); + await expectThrow(testEnv.wrap(WEN_FUNC.withdrawNft), WenError.nft_on_sale.key); }); }); diff --git a/packages/functions/test-tangle/withdraw-deposit-nft/deposit-withraw-nft_4_b.spec.ts b/packages/functions/test-tangle/withdraw-deposit-nft/deposit-withraw-nft_4_b.spec.ts index 7cc185c190..b1351ab41f 100644 --- a/packages/functions/test-tangle/withdraw-deposit-nft/deposit-withraw-nft_4_b.spec.ts +++ b/packages/functions/test-tangle/withdraw-deposit-nft/deposit-withraw-nft_4_b.spec.ts @@ -1,10 +1,8 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ import { build5Db } from '@build-5/database'; -import { COL, Nft, NftStatus, WenError } from '@build-5/interfaces'; -import { updateMember } from '../../src/runtime/firebase/member'; -import { withdrawNft } from '../../src/runtime/firebase/nft/index'; -import { expectThrow, mockWalletReturnValue } from '../../test/controls/common'; -import { testEnv } from '../../test/set-up'; +import { COL, Nft, NftStatus, WEN_FUNC, WenError } from '@build-5/interfaces'; +import { expectThrow } from '../../test/controls/common'; +import { mockWalletReturnValue, testEnv } from '../../test/set-up'; import { Helper } from './Helper'; describe('Collection minting', () => { @@ -22,19 +20,19 @@ describe('Collection minting', () => { await helper.createAndOrderNft(); await helper.mintCollection(); - mockWalletReturnValue(helper.walletSpy, helper.guardian!, { avatarNft: helper.nft?.uid }); - await testEnv.wrap(updateMember)({}); + mockWalletReturnValue(helper.guardian!, { avatarNft: helper.nft?.uid }); + await testEnv.wrap(WEN_FUNC.updateMember); - mockWalletReturnValue(helper.walletSpy, helper.guardian!, { nft: helper.nft!.uid }); - await expectThrow(testEnv.wrap(withdrawNft)({}), WenError.nft_set_as_avatar.key); + mockWalletReturnValue(helper.guardian!, { nft: helper.nft!.uid }); + await expectThrow(testEnv.wrap(WEN_FUNC.withdrawNft), WenError.nft_set_as_avatar.key); - mockWalletReturnValue(helper.walletSpy, helper.guardian!, { avatarNft: undefined }); - await testEnv.wrap(updateMember)({}); + mockWalletReturnValue(helper.guardian!, { avatarNft: undefined }); + await testEnv.wrap(WEN_FUNC.updateMember); - mockWalletReturnValue(helper.walletSpy, helper.guardian!, { nft: helper.nft!.uid }); - await testEnv.wrap(withdrawNft)({}); + mockWalletReturnValue(helper.guardian!, { nft: helper.nft!.uid }); + await testEnv.wrap(WEN_FUNC.withdrawNft); - const nftDocRef = build5Db().doc(`${COL.NFT}/${helper.nft?.uid}`); + const nftDocRef = build5Db().doc(COL.NFT, helper.nft?.uid!); const nft = await nftDocRef.get(); expect(nft.status).toBe(NftStatus.WITHDRAWN); }); diff --git a/packages/functions/test-tangle/withdraw-deposit-nft/deposit-withraw-nft_5.spec.ts b/packages/functions/test-tangle/withdraw-deposit-nft/deposit-withraw-nft_5.spec.ts index f19db509f7..909944d175 100644 --- a/packages/functions/test-tangle/withdraw-deposit-nft/deposit-withraw-nft_5.spec.ts +++ b/packages/functions/test-tangle/withdraw-deposit-nft/deposit-withraw-nft_5.spec.ts @@ -1,10 +1,9 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ -import { build5Db } from '@build-5/database'; -import { COL, Member, Nft, Transaction, TransactionType } from '@build-5/interfaces'; -import { depositNft, withdrawNft } from '../../src/runtime/firebase/nft/index'; +import { PgTransactionType, build5Db } from '@build-5/database'; +import { COL, Member, Nft, Transaction, WEN_FUNC } from '@build-5/interfaces'; import { getAddress } from '../../src/utils/address.utils'; -import { mockWalletReturnValue, wait } from '../../test/controls/common'; -import { testEnv } from '../../test/set-up'; +import { wait } from '../../test/controls/common'; +import { mockWalletReturnValue, testEnv } from '../../test/set-up'; import { Helper } from './Helper'; describe('Collection minting', () => { @@ -22,37 +21,37 @@ describe('Collection minting', () => { await helper.createAndOrderNft(); await helper.mintCollection(); - mockWalletReturnValue(helper.walletSpy, helper.guardian!, { nft: helper.nft!.uid }); - await testEnv.wrap(withdrawNft)({}); + mockWalletReturnValue(helper.guardian!, { nft: helper.nft!.uid }); + await testEnv.wrap(WEN_FUNC.withdrawNft); const query = build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.WITHDRAW_NFT) - .where('payload.nft', '==', helper.nft!.uid); + .where('type', '==', PgTransactionType.WITHDRAW_NFT) + .where('payload_nft', '==', helper.nft!.uid); await wait(async () => { - const snap = await query.get(); + const snap = await query.get(); return snap.length === 1 && snap[0]?.payload?.walletReference?.confirmed; }); - await build5Db().doc(`${COL.COLLECTION}/${helper.collection}`).update({ approved: false }); + await build5Db().doc(COL.COLLECTION, helper.collection!).update({ approved: false }); - const guardianData = await build5Db().doc(`${COL.MEMBER}/${helper.guardian}`).get(); - mockWalletReturnValue(helper.walletSpy, helper.guardian!, { network: helper.network }); - const depositOrder = await testEnv.wrap(depositNft)({}); + const guardianData = await build5Db().doc(COL.MEMBER, helper.guardian!).get(); + mockWalletReturnValue(helper.guardian!, { network: helper.network }); + const depositOrder = await testEnv.wrap(WEN_FUNC.depositNft); const sourceAddress = await helper.walletService?.getAddressDetails( getAddress(guardianData, helper.network!), ); - await helper.sendNftToAddress(sourceAddress!, depositOrder.payload.targetAddress); + await helper.sendNftToAddress(sourceAddress!, depositOrder.payload.targetAddress!); const creditNftQuery = build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.CREDIT_NFT) + .where('type', '==', PgTransactionType.CREDIT_NFT) .where('member', '==', helper.guardian); await wait(async () => { - const snap = await creditNftQuery.get(); + const snap = await creditNftQuery.get(); return snap.length === 1 && snap[0]?.payload?.walletReference?.confirmed; }); - const nft = await build5Db().doc(`${COL.NFT}/${helper.nft!.uid}`).get(); + const nft = await build5Db().doc(COL.NFT, helper.nft!.uid).get(); const creditNftTransaction = (await creditNftQuery.get())[0] as Transaction; expect(creditNftTransaction.payload.nftId).toBe(nft.mintingData?.nftId); }); diff --git a/packages/functions/test-tangle/withdraw-deposit-nft/deposit-withraw-nft_6.spec.ts b/packages/functions/test-tangle/withdraw-deposit-nft/deposit-withraw-nft_6.spec.ts index bfd91dc7a1..af6e053772 100644 --- a/packages/functions/test-tangle/withdraw-deposit-nft/deposit-withraw-nft_6.spec.ts +++ b/packages/functions/test-tangle/withdraw-deposit-nft/deposit-withraw-nft_6.spec.ts @@ -1,5 +1,5 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ -import { build5Db } from '@build-5/database'; +import { PgTransactionType, build5Db } from '@build-5/database'; import { COL, Collection, @@ -10,12 +10,11 @@ import { NftStatus, Space, Transaction, - TransactionType, + WEN_FUNC, } from '@build-5/interfaces'; -import { depositNft, withdrawNft } from '../../src/runtime/firebase/nft/index'; import { getAddress } from '../../src/utils/address.utils'; -import { mockWalletReturnValue, wait } from '../../test/controls/common'; -import { testEnv } from '../../test/set-up'; +import { wait } from '../../test/controls/common'; +import { mockWalletReturnValue, testEnv } from '../../test/set-up'; import { Helper } from './Helper'; describe('Nft depositing', () => { @@ -32,33 +31,33 @@ describe('Nft depositing', () => { nft = await helper.createAndOrderNft(); await helper.mintCollection(); - const nftDocRef = build5Db().doc(`${COL.NFT}/${nft.uid}`); - mockWalletReturnValue(helper.walletSpy, helper.guardian!, { nft: nft.uid }); - await testEnv.wrap(withdrawNft)({}); + const nftDocRef = build5Db().doc(COL.NFT, nft.uid); + mockWalletReturnValue(helper.guardian!, { nft: nft.uid }); + await testEnv.wrap(WEN_FUNC.withdrawNft); const query = build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.WITHDRAW_NFT) - .where('payload.nft', '==', nft.uid); + .where('type', '==', PgTransactionType.WITHDRAW_NFT) + .where('payload_nft', '==', nft.uid); await wait(async () => { - const snap = await query.get(); + const snap = await query.get(); return snap.length === 1 && snap[0]?.payload?.walletReference?.confirmed; }); nft = await nftDocRef.get(); - const collectionDocRef = build5Db().doc(`${COL.COLLECTION}/${nft.collection}`); + const collectionDocRef = build5Db().doc(COL.COLLECTION, nft.collection); collection = await collectionDocRef.get(); }); it('Should deposit nft minted outside build-5 and withdraw it', async () => { - const nftDocRef = build5Db().doc(`${COL.NFT}/${nft.uid}`); + const nftDocRef = build5Db().doc(COL.NFT, nft.uid); await nftDocRef.delete(); - await build5Db().doc(`${COL.COLLECTION}/${nft.collection}`).delete(); + await build5Db().doc(COL.COLLECTION, nft.collection).delete(); - mockWalletReturnValue(helper.walletSpy, helper.guardian!, { network: helper.network }); - let depositOrder = await testEnv.wrap(depositNft)({}); - await helper.sendNftToAddress(helper.guardianAddress!, depositOrder.payload.targetAddress); + mockWalletReturnValue(helper.guardian!, { network: helper.network }); + let depositOrder = await testEnv.wrap(WEN_FUNC.depositNft); + await helper.sendNftToAddress(helper.guardianAddress!, depositOrder.payload.targetAddress!); const nftQuery = build5Db().collection(COL.NFT).where('owner', '==', helper.guardian); await wait(async () => { @@ -76,7 +75,8 @@ describe('Nft depositing', () => { expect(migratedNft.space).toBeDefined(); expect(migratedNft.owner).toBe(helper.guardian); expect(migratedNft.isOwned).toBe(true); - expect(migratedNft.depositData?.network).toBe(nft.mintingData?.network); + expect(migratedNft.depositData?.network).toBe(helper.network); + expect(migratedNft.mintingData?.network).toBe(helper.network); expect(migratedNft.depositData?.nftId).toBe(nft.mintingData?.nftId); expect(migratedNft.depositData?.address).toBe(depositOrder.payload.targetAddress); expect(migratedNft.status).toBe(NftStatus.MINTED); @@ -85,7 +85,7 @@ describe('Nft depositing', () => { expect(migratedNft.properties.custom.value).toBe(1); expect(migratedNft.properties.customStat.value).toBe('customStat'); - const migratedCollectionDocRef = build5Db().doc(`${COL.COLLECTION}/${migratedNft.collection}`); + const migratedCollectionDocRef = build5Db().doc(COL.COLLECTION, migratedNft.collection); const migratedCollection = await migratedCollectionDocRef.get(); expect(migratedCollection.space).toBe(migratedNft.space); expect(migratedCollection.uid).toBe(collection.mintingData?.nftId!); @@ -100,7 +100,7 @@ describe('Nft depositing', () => { expect(migratedCollection.royaltiesFee).toBe(0.45); expect(migratedCollection.royaltiesSpace).toBe(getAddress(helper.royaltySpace!, Network.RMS)); - const spaceDocRef = build5Db().doc(`${COL.SPACE}/${migratedNft.space}`); + const spaceDocRef = build5Db().doc(COL.SPACE, migratedNft.space); const space = await spaceDocRef.get(); expect(space.uid).toBeDefined(); expect(space.name).toBe(migratedCollection.name); @@ -109,18 +109,18 @@ describe('Nft depositing', () => { expect(space.avatarUrl).toBe(migratedCollection.bannerUrl); const nftId = nft.mintingData?.nftId; - mockWalletReturnValue(helper.walletSpy, helper.guardian!, { nft: nftId }); - await testEnv.wrap(withdrawNft)({}); + mockWalletReturnValue(helper.guardian!, { nft: nftId }); + await testEnv.wrap(WEN_FUNC.withdrawNft); const query = build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.WITHDRAW_NFT) - .where('payload.nft', '==', nftId); + .where('type', '==', PgTransactionType.WITHDRAW_NFT) + .where('payload_nft', '==', nftId); await wait(async () => { - const snap = await query.get(); + const snap = await query.get(); return snap.length === 1 && snap[0]?.payload?.walletReference?.confirmed; }); - const depositOrderDocRef = build5Db().doc(`${COL.TRANSACTION}/${depositOrder.uid}`); + const depositOrderDocRef = build5Db().doc(COL.TRANSACTION, depositOrder.uid); depositOrder = await depositOrderDocRef.get(); expect(depositOrder.payload.nft).toBe(nftId); }); diff --git a/packages/functions/test-tangle/withdraw-deposit-nft/deposit-withraw-nft_7.spec.ts b/packages/functions/test-tangle/withdraw-deposit-nft/deposit-withraw-nft_7.spec.ts index 2780132e62..5addcc00ad 100644 --- a/packages/functions/test-tangle/withdraw-deposit-nft/deposit-withraw-nft_7.spec.ts +++ b/packages/functions/test-tangle/withdraw-deposit-nft/deposit-withraw-nft_7.spec.ts @@ -1,9 +1,8 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ -import { build5Db } from '@build-5/database'; -import { COL, Network, Nft, Transaction, TransactionType } from '@build-5/interfaces'; -import { depositNft, withdrawNft } from '../../src/runtime/firebase/nft/index'; -import { mockWalletReturnValue, wait } from '../../test/controls/common'; -import { testEnv } from '../../test/set-up'; +import { PgTransactionType, build5Db } from '@build-5/database'; +import { COL, Network, Nft, Transaction, WEN_FUNC } from '@build-5/interfaces'; +import { wait } from '../../test/controls/common'; +import { mockWalletReturnValue, testEnv } from '../../test/set-up'; import { Helper } from './Helper'; describe('Collection minting', () => { @@ -19,30 +18,30 @@ describe('Collection minting', () => { nft = await helper.createAndOrderNft(); await helper.mintCollection(); - const nftDocRef = build5Db().doc(`${COL.NFT}/${nft.uid}`); - mockWalletReturnValue(helper.walletSpy, helper.guardian!, { nft: nft.uid }); - await testEnv.wrap(withdrawNft)({}); + const nftDocRef = build5Db().doc(COL.NFT, nft.uid); + mockWalletReturnValue(helper.guardian!, { nft: nft.uid }); + await testEnv.wrap(WEN_FUNC.withdrawNft); const query = build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.WITHDRAW_NFT) - .where('payload.nft', '==', nft.uid); + .where('type', '==', PgTransactionType.WITHDRAW_NFT) + .where('payload_nft', '==', nft.uid); await wait(async () => { - const snap = await query.get(); + const snap = await query.get(); return snap.length === 1 && snap[0]?.payload?.walletReference?.confirmed; }); nft = await nftDocRef.get(); }); it('Should deposit and claim space', async () => { - const nftDocRef = build5Db().doc(`${COL.NFT}/${nft.uid}`); + const nftDocRef = build5Db().doc(COL.NFT, nft.uid); await nftDocRef.delete(); - await build5Db().doc(`${COL.COLLECTION}/${nft.collection}`).delete(); + await build5Db().doc(COL.COLLECTION, nft.collection).delete(); - mockWalletReturnValue(helper.walletSpy, helper.guardian!, { network: helper.network }); - const depositOrder = await testEnv.wrap(depositNft)({}); - await helper.sendNftToAddress(helper.guardianAddress!, depositOrder.payload.targetAddress); + mockWalletReturnValue(helper.guardian!, { network: helper.network }); + const depositOrder = await testEnv.wrap(WEN_FUNC.depositNft); + await helper.sendNftToAddress(helper.guardianAddress!, depositOrder.payload.targetAddress!); const nftQuery = build5Db().collection(COL.NFT).where('owner', '==', helper.guardian); await wait(async () => { diff --git a/packages/functions/test-tangle/withdraw-deposit-nft/deposit-withraw-nft_8.spec.ts b/packages/functions/test-tangle/withdraw-deposit-nft/deposit-withraw-nft_8.spec.ts index c1f097ba50..e3388eff3f 100644 --- a/packages/functions/test-tangle/withdraw-deposit-nft/deposit-withraw-nft_8.spec.ts +++ b/packages/functions/test-tangle/withdraw-deposit-nft/deposit-withraw-nft_8.spec.ts @@ -1,9 +1,8 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ -import { build5Db } from '@build-5/database'; -import { COL, Collection, Nft, Transaction, TransactionType } from '@build-5/interfaces'; -import { depositNft, withdrawNft } from '../../src/runtime/firebase/nft/index'; -import { mockWalletReturnValue, wait } from '../../test/controls/common'; -import { testEnv } from '../../test/set-up'; +import { PgTransactionType, build5Db } from '@build-5/database'; +import { COL, Collection, Nft, Transaction, WEN_FUNC } from '@build-5/interfaces'; +import { wait } from '../../test/controls/common'; +import { mockWalletReturnValue, testEnv } from '../../test/set-up'; import { Helper } from './Helper'; describe('Collection minting', () => { @@ -20,32 +19,32 @@ describe('Collection minting', () => { nft = await helper.createAndOrderNft(); await helper.mintCollection(); - const nftDocRef = build5Db().doc(`${COL.NFT}/${nft.uid}`); - mockWalletReturnValue(helper.walletSpy, helper.guardian!, { nft: nft.uid }); - await testEnv.wrap(withdrawNft)({}); + const nftDocRef = build5Db().doc(COL.NFT, nft.uid); + mockWalletReturnValue(helper.guardian!, { nft: nft.uid }); + await testEnv.wrap(WEN_FUNC.withdrawNft); const query = build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.WITHDRAW_NFT) - .where('payload.nft', '==', nft.uid); + .where('type', '==', PgTransactionType.WITHDRAW_NFT) + .where('payload_nft', '==', nft.uid); await wait(async () => { - const snap = await query.get(); + const snap = await query.get(); return snap.length === 1 && snap[0]?.payload?.walletReference?.confirmed; }); nft = await nftDocRef.get(); - const collectionDocRef = build5Db().doc(`${COL.COLLECTION}/${nft.collection}`); + const collectionDocRef = build5Db().doc(COL.COLLECTION, nft.collection); collection = await collectionDocRef.get(); }); it('Should migrate nft to existing collection', async () => { - const nftDocRef = build5Db().doc(`${COL.NFT}/${nft.uid}`); + const nftDocRef = build5Db().doc(COL.NFT, nft.uid); await nftDocRef.delete(); - mockWalletReturnValue(helper.walletSpy, helper.guardian!, { network: helper.network }); - const depositOrder = await testEnv.wrap(depositNft)({}); - await helper.sendNftToAddress(helper.guardianAddress!, depositOrder.payload.targetAddress); + mockWalletReturnValue(helper.guardian!, { network: helper.network }); + const depositOrder = await testEnv.wrap(WEN_FUNC.depositNft); + await helper.sendNftToAddress(helper.guardianAddress!, depositOrder.payload.targetAddress!); const nftQuery = build5Db().collection(COL.NFT).where('owner', '==', helper.guardian); await wait(async () => { diff --git a/packages/functions/test-tangle/withdraw-deposit-nft/deposit-withraw-nft_9.spec.ts b/packages/functions/test-tangle/withdraw-deposit-nft/deposit-withraw-nft_9.spec.ts index 5622f31f1a..33c83f3e39 100644 --- a/packages/functions/test-tangle/withdraw-deposit-nft/deposit-withraw-nft_9.spec.ts +++ b/packages/functions/test-tangle/withdraw-deposit-nft/deposit-withraw-nft_9.spec.ts @@ -1,9 +1,8 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ -import { build5Db, build5Storage } from '@build-5/database'; -import { Bucket, COL, Collection, Nft, Transaction, TransactionType } from '@build-5/interfaces'; -import { depositNft, withdrawNft } from '../../src/runtime/firebase/nft/index'; -import { mockWalletReturnValue, wait } from '../../test/controls/common'; -import { testEnv } from '../../test/set-up'; +import { PgTransactionType, build5Db, build5Storage } from '@build-5/database'; +import { Bucket, COL, Collection, Nft, Transaction, WEN_FUNC } from '@build-5/interfaces'; +import { wait } from '../../test/controls/common'; +import { mockWalletReturnValue, testEnv } from '../../test/set-up'; import { Helper } from './Helper'; describe('Collection minting', () => { @@ -19,16 +18,16 @@ describe('Collection minting', () => { nft = await helper.createAndOrderNft(); await helper.mintCollection(); - const nftDocRef = build5Db().doc(`${COL.NFT}/${nft.uid}`); - mockWalletReturnValue(helper.walletSpy, helper.guardian!, { nft: nft.uid }); - await testEnv.wrap(withdrawNft)({}); + const nftDocRef = build5Db().doc(COL.NFT, nft.uid); + mockWalletReturnValue(helper.guardian!, { nft: nft.uid }); + await testEnv.wrap(WEN_FUNC.withdrawNft); const query = build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.WITHDRAW_NFT) - .where('payload.nft', '==', nft.uid); + .where('type', '==', PgTransactionType.WITHDRAW_NFT) + .where('payload_nft', '==', nft.uid); await wait(async () => { - const snap = await query.get(); + const snap = await query.get(); return snap.length === 1 && snap[0]?.payload?.walletReference?.confirmed; }); nft = await nftDocRef.get(); @@ -41,14 +40,14 @@ describe('Collection minting', () => { }); it('Should migrate media', async () => { - const nftDocRef = build5Db().doc(`${COL.NFT}/${nft.uid}`); + const nftDocRef = build5Db().doc(COL.NFT, nft.uid); await nftDocRef.delete(); - await build5Db().doc(`${COL.COLLECTION}/${nft.collection}`).delete(); + await build5Db().doc(COL.COLLECTION, nft.collection).delete(); - mockWalletReturnValue(helper.walletSpy, helper.guardian!, { network: helper.network }); - const depositOrder = await testEnv.wrap(depositNft)({}); - await helper.sendNftToAddress(helper.guardianAddress!, depositOrder.payload.targetAddress); + mockWalletReturnValue(helper.guardian!, { network: helper.network }); + const depositOrder = await testEnv.wrap(WEN_FUNC.depositNft); + await helper.sendNftToAddress(helper.guardianAddress!, depositOrder.payload.targetAddress!); const nftQuery = build5Db().collection(COL.NFT).where('owner', '==', helper.guardian); await wait(async () => { @@ -60,7 +59,7 @@ describe('Collection minting', () => { const migratedNft = snap[0]; await validateStorageFileCount(helper.guardian!, migratedNft.uid); - const migratedCollectionDocRef = build5Db().doc(`${COL.COLLECTION}/${migratedNft.collection}`); + const migratedCollectionDocRef = build5Db().doc(COL.COLLECTION, migratedNft.collection); const migratedCollection = await migratedCollectionDocRef.get(); await validateStorageFileCount(migratedCollection.space!, migratedCollection.uid); }); diff --git a/packages/functions/test-tangle/workflow-online.spec.ts b/packages/functions/test-tangle/workflow-online.spec.ts deleted file mode 100644 index efc6c19726..0000000000 --- a/packages/functions/test-tangle/workflow-online.spec.ts +++ /dev/null @@ -1,25 +0,0 @@ -import fs from 'fs'; - -describe('Workflow test', () => { - it('Test if workflow contains all files', async () => { - const buffer = fs.readFileSync( - '../../.github/workflows/functions_tangle-online-unit-tests_emulator.yml', - ); - const workflowTxt = buffer.toString(); - - const glob = require('glob'); - const testFileNames = glob - .sync(`./test-tangle/**/*.spec.ts`) - .filter((f: any) => !f.includes('exclude')) - .filter((f: any) => !f.includes('only.spec.ts')) - .filter((f: any) => !f.includes('web3.spec')) - .filter((f: any) => !f.includes('dbRoll')); - for (const testFileName of testFileNames) { - if (!workflowTxt.includes(testFileName)) { - throw Error( - `Action misses the following file: ${testFileName}. Pls run node workflow-online.build.js`, - ); - } - } - }); -}); diff --git a/packages/functions/test/auth.spec.ts b/packages/functions/test/auth.spec.ts index 84fcca88fd..cf31c2aa3c 100644 --- a/packages/functions/test/auth.spec.ts +++ b/packages/functions/test/auth.spec.ts @@ -3,30 +3,24 @@ import { COL, Member, Network, WEN_FUNC, WenError } from '@build-5/interfaces'; import { CoinType, utf8ToHex } from '@iota/sdk'; import jwt from 'jsonwebtoken'; import { get } from 'lodash'; -import { generateCustomToken } from '../src/runtime/firebase/auth'; import * as config from '../src/utils/config.utils'; import { getJwtSecretKey } from '../src/utils/config.utils'; import { getSecretManager } from '../src/utils/secret.manager.utils'; -import * as wallet from '../src/utils/wallet.utils'; import { decodeAuth, getRandomNonce } from '../src/utils/wallet.utils'; -import { createMember, expectThrow, mockWalletReturnValue } from './controls/common'; -import { PROJECT_API_KEY, getWallet, testEnv } from './set-up'; +import { expectThrow } from './controls/common'; +import { PROJECT_API_KEY, getWallet, mockWalletReturnValue, testEnv } from './set-up'; describe('Auth control test', () => { - let walletSpy: jest.SpyInstance; let configSpy: jest.SpyInstance; let member: string; beforeEach(async () => { - walletSpy = jest.spyOn(wallet, 'decodeAuth'); - member = await createMember(walletSpy); + member = await testEnv.createMember(); }); it('Should create and reuse custom token', async () => { - mockWalletReturnValue(walletSpy, member, {}); - const token = await testEnv.wrap(generateCustomToken)({}); - walletSpy.mockRestore(); - const tokenGeneratedWithToken = await testEnv.wrap(generateCustomToken)({}, member, token); + mockWalletReturnValue(member, {}); + const tokenGeneratedWithToken = await testEnv.wrap(WEN_FUNC.generateCustomToken); expect(tokenGeneratedWithToken).toBeDefined(); const decoded = jwt.verify(tokenGeneratedWithToken, getJwtSecretKey()); expect(get(decoded, 'uid')).toBe(member); @@ -35,19 +29,23 @@ describe('Auth control test', () => { }); it('Should throw, custom token for func expired', async () => { - mockWalletReturnValue(walletSpy, member, {}); - const token = await testEnv.wrap(generateCustomToken)({}); - walletSpy.mockRestore(); - + mockWalletReturnValue(member, undefined); + const token = await testEnv.wrap(WEN_FUNC.generateCustomToken); configSpy = jest.spyOn(config, 'getCustomTokenLifetime'); configSpy.mockReturnValue(1); - await new Promise((resolve) => setTimeout(resolve, 2000)); - await expectThrow( - testEnv.wrap(generateCustomToken)({}, member, token), - WenError.invalid_custom_token.key, + const call = decodeAuth( + { + address: member, + projectApiKey: PROJECT_API_KEY, + signature: '', + publicKey: {} as any, + customToken: token, + body: {}, + }, + WEN_FUNC.generateCustomToken, ); - + await expectThrow(call, WenError.invalid_custom_token.key); configSpy.mockRestore(); }); }); @@ -56,11 +54,9 @@ describe('Pub key test', () => { it.each([Network.RMS, Network.SMR])('Should validate SMR pub key', async (network: Network) => { const wallet = await getWallet(network); const address = await wallet.getNewIotaAddressDetails(); - const nonce = getRandomNonce(); - const userDocRef = build5Db().doc(`${COL.MEMBER}/${address.bech32}`); + const userDocRef = build5Db().doc(COL.MEMBER, address.bech32); await userDocRef.create({ uid: address.bech32, nonce }); - const secretManager = getSecretManager(address.mnemonic); const signature = await secretManager.signEd25519(utf8ToHex(nonce), { coinType: CoinType.IOTA, @@ -69,17 +65,11 @@ describe('Pub key test', () => { address: 'address', projectApiKey: PROJECT_API_KEY, signature: signature.signature, - publicKey: { - hex: signature.publicKey, - network, - }, + publicKey: { hex: signature.publicKey, network }, body: {}, }; - const result = await decodeAuth(request, WEN_FUNC.approveProposal); - expect(result.address).toBe(address.bech32); - const user = await userDocRef.get(); expect(user.validatedAddress![network]).toBe(address.bech32); }); @@ -89,11 +79,9 @@ describe('Pub key test', () => { async (network: Network) => { const wallet = await getWallet(network); const address = await wallet.getNewIotaAddressDetails(); - const nonce = getRandomNonce(); - const userDocRef = build5Db().doc(`${COL.MEMBER}/${address.bech32}`); + const userDocRef = build5Db().doc(COL.MEMBER, address.bech32); await userDocRef.create({ uid: address.bech32, nonce }); - const secretManager = getSecretManager(address.mnemonic); const signature = await secretManager.signEd25519(utf8ToHex(nonce), { coinType: CoinType.IOTA, @@ -102,17 +90,11 @@ describe('Pub key test', () => { address: address.bech32, signature: signature.signature, projectApiKey: PROJECT_API_KEY, - publicKey: { - hex: signature.publicKey, - network, - }, + publicKey: { hex: signature.publicKey, network }, body: {}, }; - const result = await decodeAuth(request, WEN_FUNC.approveProposal); - expect(result.address).toBe(address.bech32); - const user = await userDocRef.get(); expect(user.validatedAddress![network]).toBe(address.bech32); }, @@ -121,16 +103,13 @@ describe('Pub key test', () => { it.each([Network.RMS, Network.SMR])('Should throw wrong pub key', async (network: Network) => { const wallet = await getWallet(network); const address = await wallet.getNewIotaAddressDetails(); - const nonce = getRandomNonce(); - const userDocRef = build5Db().doc(`${COL.MEMBER}/${address.bech32}`); + const userDocRef = build5Db().doc(COL.MEMBER, address.bech32); await userDocRef.create({ uid: address.bech32, nonce }); - const secretManager = getSecretManager(address.mnemonic); const signature = await secretManager.signEd25519(utf8ToHex(nonce), { coinType: CoinType.IOTA, }); - const wallet2 = await getWallet(network === Network.SMR ? Network.RMS : Network.SMR); const secondAddress = await wallet2.getNewIotaAddressDetails(); const secretManagerSecond = getSecretManager(secondAddress.mnemonic); @@ -141,28 +120,21 @@ describe('Pub key test', () => { address: 'address', projectApiKey: PROJECT_API_KEY, signature: signature.signature, - publicKey: { - hex: signatureSecond.publicKey, - network, - }, + publicKey: { hex: signatureSecond.publicKey, network }, body: {}, }; - try { - await decodeAuth(request, WEN_FUNC.approveProposal); - fail(); - } catch (error: any) { - expect(error.details.key).toBe(WenError.failed_to_decode_token.key); - } + await expectThrow( + decodeAuth(request, WEN_FUNC.approveProposal), + WenError.failed_to_decode_token.key, + ); }); it('Should update nonce when public key sign in', async () => { const wallet = await getWallet(Network.RMS); const address = await wallet.getNewIotaAddressDetails(); - const nonce = getRandomNonce(); - const userDocRef = build5Db().doc(`${COL.MEMBER}/${address.bech32}`); + const userDocRef = build5Db().doc(COL.MEMBER, address.bech32); await userDocRef.create({ uid: address.bech32, nonce }); - const secretManager = getSecretManager(address.mnemonic); const signature = await secretManager.signEd25519(utf8ToHex(nonce), { coinType: CoinType.IOTA, @@ -171,17 +143,11 @@ describe('Pub key test', () => { address: 'address', signature: signature.signature, projectApiKey: PROJECT_API_KEY, - publicKey: { - hex: signature.publicKey, - network: Network.RMS, - }, + publicKey: { hex: signature.publicKey, network: Network.RMS }, body: {}, }; - const result = await decodeAuth(request, WEN_FUNC.approveProposal); - expect(result.address).toBe(address.bech32); - const user = await userDocRef.get(); expect(user.validatedAddress![Network.RMS]).toBe(address.bech32); expect(user.nonce).not.toBe(nonce); diff --git a/packages/functions/test/auth/legacy.auth.spec.ts b/packages/functions/test/auth/legacy.auth.spec.ts index 6358f0e6aa..61094db9d3 100644 --- a/packages/functions/test/auth/legacy.auth.spec.ts +++ b/packages/functions/test/auth/legacy.auth.spec.ts @@ -13,16 +13,15 @@ import { Converter } from '@iota/util.js'; import { Converter as ConverterNext } from '@iota/util.js-next'; import { generateMnemonic } from 'bip39'; import { decodeAuth, getRandomNonce } from '../../src/utils/wallet.utils'; +import { expectThrow } from '../controls/common'; import { PROJECT_API_KEY } from '../set-up'; describe('Legacy Pub key test', () => { - it.each([Network.RMS])('Should validate SMR pub key', async (network: Network) => { + it.each([Network.RMS, Network.SMR])('Should validate SMR pub key', async (network: Network) => { const address = getSmrAddress(network); - const nonce = getRandomNonce(); - const userDocRef = build5Db().doc(`${COL.MEMBER}/${address.bech32}`); + const userDocRef = build5Db().doc(COL.MEMBER, address.bech32); await userDocRef.create({ uid: address.bech32, nonce }); - const signature = Ed25519Next.sign( address.keyPair.privateKey, Converter.utf8ToBytes(`0x${toHex(nonce)}`), @@ -31,33 +30,24 @@ describe('Legacy Pub key test', () => { address: 'address', signature: ConverterNext.bytesToHex(signature), projectApiKey: PROJECT_API_KEY, - legacyPublicKey: { - hex: ConverterNext.bytesToHex(address.keyPair.publicKey), - network, - }, + legacyPublicKey: { hex: ConverterNext.bytesToHex(address.keyPair.publicKey), network }, body: {}, }; - const result = await decodeAuth(request, WEN_FUNC.approveProposal); - expect(result.address).toBe(address.bech32); - const user = await userDocRef.get(); expect(user.validatedAddress![network]).toBe(address.bech32); }); it('Should validate IOTA pub key', async () => { const address = await getIotaAddress(Network.IOTA); - const nonce = getRandomNonce(); - const userDocRef = build5Db().doc(`${COL.MEMBER}/${address.bech32}`); + const userDocRef = build5Db().doc(COL.MEMBER, address.bech32); await userDocRef.create({ uid: address.bech32, nonce }); - const signature = Ed25519.sign( address.keyPair.privateKey, Converter.utf8ToBytes(`0x${toHex(nonce)}`), ); - const request = { address: 'address', signature: Converter.bytesToHex(signature), @@ -68,53 +58,40 @@ describe('Legacy Pub key test', () => { }, body: {}, }; - const result = await decodeAuth(request, WEN_FUNC.approveProposal); - expect(result.address).toBe(address.bech32); - const user = await userDocRef.get(); expect(user.validatedAddress![Network.IOTA]).toBe(address.bech32); }); it.each([Network.RMS, Network.SMR])('Should throw wrong pub key', async (network: Network) => { const address = getSmrAddress(network); - const nonce = getRandomNonce(); - const userDocRef = build5Db().doc(`${COL.MEMBER}/${address.bech32}`); + const userDocRef = build5Db().doc(COL.MEMBER, address.bech32); await userDocRef.create({ uid: address.bech32, nonce }); - const signature = Ed25519Next.sign( address.keyPair.privateKey, Converter.utf8ToBytes(`0x${toHex(nonce)}`), ); - const secondAddress = getSmrAddress(network); const request = { address: 'address', signature: ConverterNext.bytesToHex(signature), projectApiKey: PROJECT_API_KEY, - legacyPublicKey: { - hex: ConverterNext.bytesToHex(secondAddress.keyPair.publicKey), - network, - }, + legacyPublicKey: { hex: ConverterNext.bytesToHex(secondAddress.keyPair.publicKey), network }, body: {}, }; - try { - await decodeAuth(request, WEN_FUNC.approveProposal); - fail(); - } catch (error: any) { - expect(error.details.key).toBe(WenError.failed_to_decode_token.key); - } + await expectThrow( + decodeAuth(request, WEN_FUNC.approveProposal), + WenError.failed_to_decode_token.key, + ); }); it('Should update nonce when public key sign in', async () => { const address = getSmrAddress(Network.RMS); - const nonce = getRandomNonce(); - const userDocRef = build5Db().doc(`${COL.MEMBER}/${address.bech32}`); + const userDocRef = build5Db().doc(COL.MEMBER, address.bech32); await userDocRef.create({ uid: address.bech32, nonce }); - const signature = Ed25519Next.sign( address.keyPair.privateKey, Converter.utf8ToBytes(`0x${toHex(nonce)}`), @@ -129,11 +106,8 @@ describe('Legacy Pub key test', () => { }, body: {}, }; - const result = await decodeAuth(request, WEN_FUNC.approveProposal); - expect(result.address).toBe(address.bech32); - const user = await userDocRef.get(); expect(user.validatedAddress![Network.RMS]).toBe(address.bech32); expect(user.nonce).not.toBe(nonce); @@ -148,7 +122,6 @@ const toHex = (stringToConvert: string) => const getSmrAddress = (network: Network) => { const mnemonic = generateMnemonic() + ' ' + generateMnemonic(); - const walletSeed = Ed25519SeedNext.fromMnemonic(mnemonic); const walletPath = new Bip32PathNext("m/44'/4218'/0'/0'/0'"); const walletAddressSeed = walletSeed.generateSeedFromPath(walletPath); @@ -157,7 +130,6 @@ const getSmrAddress = (network: Network) => { const walletAddress = walletEd25519Address.toAddress(); const hex = ConverterNext.bytesToHex(walletAddress, true); const bech32 = Bech32HelperNext.toBech32(ED25519_ADDRESS_TYPE_NEXT, walletAddress, network); - return { mnemonic, keyPair, hex, bech32 }; }; @@ -171,6 +143,5 @@ const getIotaAddress = async (network: Network) => { const genesisWalletAddress = genesisEd25519Address.toAddress(); const hex = Converter.bytesToHex(genesisWalletAddress); const bech32 = Bech32Helper.toBech32(ED25519_ADDRESS_TYPE, genesisWalletAddress, network); - return { mnemonic, bech32, keyPair, hex }; }; diff --git a/packages/functions/test/controls/address.spec.ts b/packages/functions/test/controls/address.spec.ts index 7857623922..5220dfcef3 100644 --- a/packages/functions/test/controls/address.spec.ts +++ b/packages/functions/test/controls/address.spec.ts @@ -1,72 +1,58 @@ import { build5Db } from '@build-5/database'; -import { COL, Member, Network, Proposal, Space, WenError } from '@build-5/interfaces'; +import { COL, Member, Network, Space, Transaction, WEN_FUNC, WenError } from '@build-5/interfaces'; import { isEmpty } from 'lodash'; -import { validateAddress } from '../../src/runtime/firebase/address'; import { getAddress } from '../../src/utils/address.utils'; -import * as wallet from '../../src/utils/wallet.utils'; -import { getWallet, testEnv } from '../set-up'; -import { - createMember, - createSpace, - expectThrow, - mockWalletReturnValue, - submitMilestoneFunc, - validateMemberAddressFunc, - validateSpaceAddressFunc, - wait, -} from './common'; - -const waitForAddressValidation = async (id: string, col: COL) => { +import { getRandomEthAddress } from '../../src/utils/wallet.utils'; +import { getWallet, mockWalletReturnValue, testEnv } from '../set-up'; +import { expectThrow, submitMilestoneFunc, validateMemberAddressFunc, wait } from './common'; + +const waitForAddressValidation = async ( + id: string, + col: COL.SPACE | COL.MEMBER, + network = Network.RMS, +) => { await wait(async () => { - const doc = await build5Db().doc(`${col}/${id}`).get>(); - return !isEmpty(getAddress(doc, Network.IOTA)); + const data = await build5Db().doc(col, id).get(); + return !isEmpty(getAddress(data, network)); }); }; describe('Address validation test', () => { let member: string; - let space: string; - let walletSpy: any; + let space: Space; beforeEach(async () => { - walletSpy = jest.spyOn(wallet, 'decodeAuth'); - member = await createMember(walletSpy); - await build5Db().doc(`${COL.MEMBER}/${member}`).update({ validatedAddress: {} }); - space = (await createSpace(walletSpy, member)).uid; - await build5Db().doc(`${COL.SPACE}/${space}`).update({ validatedAddress: {} }); + member = await testEnv.createMember(); + await build5Db().doc(COL.MEMBER, member).update({ rmsAddress: '' }); + space = await testEnv.createSpace(member); + await build5Db().doc(COL.SPACE, space.uid).update({ rmsAddress: '', iotaAddress: '' }); }); it('Should validate member address', async () => { - const order = await validateMemberAddressFunc(walletSpy, member); + const order = await validateMemberAddressFunc(member, Network.RMS); await submitMilestoneFunc(order); - await waitForAddressValidation(member, COL.MEMBER); + await waitForAddressValidation(member, COL.MEMBER, Network.RMS); }); - it.each([Network.RMS, Network.SMR])( - 'Should throw, member id is address', - async (network: Network) => { - const wallet = await getWallet(network); - const address = await wallet.getNewIotaAddressDetails(); - const memberDocRef = build5Db().doc(`${COL.MEMBER}/${address.bech32}`); - await memberDocRef.create({ uid: address.bech32 }); - await expectThrow( - validateMemberAddressFunc(walletSpy, address.bech32, network), - WenError.can_not_change_validated_addess.key, - ); - }, - ); + it('Should throw, member id is address', async () => { + const wallet = await getWallet(Network.RMS); + const address = await wallet.getNewIotaAddressDetails(); + mockWalletReturnValue(member, { address: address.bech32 }); + const member2 = await testEnv.wrap(WEN_FUNC.createMember); + const call = validateMemberAddressFunc(member2.uid, Network.RMS); + await expectThrow(call, WenError.can_not_change_validated_addess.key); + }); it('Should validate space address', async () => { - let order = await validateSpaceAddressFunc(walletSpy, member, space); + mockWalletReturnValue(member, { space: space.uid }); + let order = await testEnv.wrap(WEN_FUNC.validateAddress); const milestone = await submitMilestoneFunc(order); - - const proposalQuery = build5Db().collection(COL.PROPOSAL).where('space', '==', space); + const proposalQuery = build5Db().collection(COL.PROPOSAL).where('space', '==', space.uid); await wait(async () => { const snap = await proposalQuery.get(); return snap.length > 0; }); - - const snap = await proposalQuery.get(); + const snap = await proposalQuery.get(); const proposal = snap[0]!; expect(proposal.questions[0].text).toBe("Do you want to update the space's validate address?"); expect(proposal.questions[0].additionalInfo).toBe( @@ -75,11 +61,11 @@ describe('Address validation test', () => { expect((proposal.settings.spaceUpdateData!.validatedAddress as any)![Network.IOTA]).toBe( milestone.fromAdd, ); - expect(proposal.settings.spaceUpdateData!.uid).toBe(space); - - await waitForAddressValidation(space, COL.SPACE); + expect(proposal.settings.spaceUpdateData!.uid).toBe(space.uid); - order = await validateSpaceAddressFunc(walletSpy, member, space); + await waitForAddressValidation(space.uid, COL.SPACE, Network.IOTA); + mockWalletReturnValue(member, { space: space.uid }); + order = await testEnv.wrap(WEN_FUNC.validateAddress); const milestone2 = await submitMilestoneFunc(order); await wait(async () => { @@ -88,50 +74,56 @@ describe('Address validation test', () => { }); await wait(async () => { - const spaceData = await build5Db().doc(`${COL.SPACE}/${space}`).get(); + const spaceData = await build5Db().doc(COL.SPACE, space.uid).get(); return getAddress(spaceData, order.network!) === milestone2.fromAdd; }); - const spaceData = await build5Db().doc(`${COL.SPACE}/${space}`).get(); + const spaceData = await build5Db().doc(COL.SPACE, space.uid).get(); expect(spaceData?.prevValidatedAddresses).toEqual([milestone.fromAdd]); }); it('Should throw, not guardian', async () => { - const randomMember = await createMember(walletSpy); - mockWalletReturnValue(walletSpy, randomMember, { space }); - await expectThrow( - testEnv.wrap(validateAddress)({}), - WenError.you_are_not_guardian_of_space.key, - ); + const randomMember = await testEnv.createMember(); + mockWalletReturnValue(randomMember, { space: space.uid }); + const call = testEnv.wrap(WEN_FUNC.validateAddress); + await expectThrow(call, WenError.you_are_not_guardian_of_space.key); }); it('Should throw, member does not exist', async () => { - mockWalletReturnValue(walletSpy, wallet.getRandomEthAddress(), { space }); - await expectThrow(testEnv.wrap(validateAddress)({}), WenError.member_does_not_exists.key); + await build5Db().doc(COL.MEMBER, member).delete(); + mockWalletReturnValue(member, { space: space.uid }); + const call = testEnv.wrap(WEN_FUNC.validateAddress); + await expectThrow(call, WenError.member_does_not_exists.key); }); it('Should throw, space does not exist', async () => { - mockWalletReturnValue(walletSpy, member, { space: wallet.getRandomEthAddress() }); - await expectThrow(testEnv.wrap(validateAddress)({}), WenError.space_does_not_exists.key); + mockWalletReturnValue(member, { + network: Network.RMS, + space: getRandomEthAddress(), + }); + const call = testEnv.wrap(WEN_FUNC.validateAddress); + await expectThrow(call, WenError.space_does_not_exists.key); }); it('Should replace member address', async () => { + const network = Network.RMS; const validate = async () => { - const order = await validateMemberAddressFunc(walletSpy, member); + const order = await validateMemberAddressFunc(member, network); await submitMilestoneFunc(order); }; await validate(); - await waitForAddressValidation(member, COL.MEMBER); - const docRef = build5Db().doc(`${COL.MEMBER}/${member}`); + await waitForAddressValidation(member, COL.MEMBER, network); + + const docRef = build5Db().doc(COL.MEMBER, member); const memberData = await docRef.get(); await validate(); await wait(async () => { const data = await docRef.get(); - return getAddress(data, Network.IOTA) !== getAddress(memberData, Network.IOTA); + return getAddress(data, network) !== getAddress(memberData, network); }); const updatedMemberData = await docRef.get(); expect(updatedMemberData.prevValidatedAddresses?.length).toBe(1); - expect(updatedMemberData.prevValidatedAddresses![0]).toBe(getAddress(memberData, Network.IOTA)); + expect(updatedMemberData.prevValidatedAddresses![0]).toBe(getAddress(memberData, network)); }); }); diff --git a/packages/functions/test/controls/auction/Helper.ts b/packages/functions/test/controls/auction/Helper.ts index 04762b2c69..9be2e307e5 100644 --- a/packages/functions/test/controls/auction/Helper.ts +++ b/packages/functions/test/controls/auction/Helper.ts @@ -1,44 +1,44 @@ -import { IDocument, build5Db } from '@build-5/database'; -import { Auction, COL, MIN_IOTA_AMOUNT, Network, Space } from '@build-5/interfaces'; +import { IDocument, PgAuction, PgAuctionUpdate, build5Db } from '@build-5/database'; +import { + Auction, + COL, + MIN_IOTA_AMOUNT, + Network, + Space, + Transaction, + WEN_FUNC, +} from '@build-5/interfaces'; import dayjs from 'dayjs'; -import { auctionCreate, bidAuction } from '../../../src/runtime/firebase/auction/index'; -import * as wallet from '../../../src/utils/wallet.utils'; -import { testEnv } from '../../set-up'; -import { createMember, createSpace, mockWalletReturnValue, submitMilestoneFunc } from '../common'; - +import { mockWalletReturnValue, testEnv } from '../../set-up'; +import { submitMilestoneFunc } from '../common'; export class Helper { - public spy: any = {} as any; public space: Space = {} as any; public member: string = {} as any; public members: string[] = []; public auction: Auction = {} as any; - public auctionDocRef: IDocument = {} as any; - - public beforeAll = async () => { - this.spy = jest.spyOn(wallet, 'decodeAuth'); - }; + public auctionDocRef: IDocument = {} as any; public beforeEach = async (now: dayjs.Dayjs) => { - this.member = await createMember(this.spy); - this.space = await createSpace(this.spy, this.member); - const memberPromises = Array.from(Array(3)).map(() => createMember(this.spy)); + this.member = await testEnv.createMember(); + this.space = await testEnv.createSpace(this.member); + const memberPromises = Array.from(Array(3)).map(() => testEnv.createMember()); this.members = await Promise.all(memberPromises); - await this.createAuction(now); }; public createAuction = async (now: dayjs.Dayjs, customAuctionParams?: { [key: string]: any }) => { - mockWalletReturnValue(this.spy, this.member, { + mockWalletReturnValue(this.member, { ...auctionRequest(this.space.uid, now), ...customAuctionParams, }); - this.auction = await testEnv.wrap(auctionCreate)({}); - this.auctionDocRef = build5Db().doc(`${COL.AUCTION}/${this.auction.uid}`); + const auc = await testEnv.wrap(WEN_FUNC.createauction); + this.auction = (await build5Db().doc(COL.AUCTION, auc.uid).get())!; + this.auctionDocRef = build5Db().doc(COL.AUCTION, this.auction.uid); }; public bidOnAuction = async (memberId: string, amount: number) => { - mockWalletReturnValue(this.spy, memberId, { auction: this.auction.uid }); - const bidOrder = await testEnv.wrap(bidAuction)({}); + mockWalletReturnValue(memberId, { auction: this.auction.uid }); + const bidOrder = await testEnv.wrap(WEN_FUNC.bidAuction); await submitMilestoneFunc(bidOrder, amount); return bidOrder; }; diff --git a/packages/functions/test/controls/auction/auction.bid.spec.ts b/packages/functions/test/controls/auction/auction.bid.spec.ts index 5f25802050..04427fe738 100644 --- a/packages/functions/test/controls/auction/auction.bid.spec.ts +++ b/packages/functions/test/controls/auction/auction.bid.spec.ts @@ -1,18 +1,8 @@ -import { IQuery, build5Db } from '@build-5/database'; -import { - Auction, - AuctionType, - COL, - MIN_IOTA_AMOUNT, - Member, - Network, - Transaction, - TransactionType, -} from '@build-5/interfaces'; +import { IQuery, PgTransactionType, build5Db } from '@build-5/database'; +import { Auction, AuctionType, COL, MIN_IOTA_AMOUNT, Network } from '@build-5/interfaces'; import dayjs from 'dayjs'; import { finalizeAuctions } from '../../../src/cron/auction.cron'; import { getAddress } from '../../../src/utils/address.utils'; -import { dateToTimestamp } from '../../../src/utils/dateTime.utils'; import { getWallet } from '../../set-up'; import { wait } from '../common'; import { Helper } from './Helper'; @@ -21,10 +11,6 @@ describe('Open auction bid', () => { const h = new Helper(); const now = dayjs(); - beforeAll(async () => { - await h.beforeAll(); - }); - beforeEach(async () => { await h.beforeEach(now); }); @@ -77,9 +63,9 @@ describe('Open auction bid', () => { const credits = await build5Db() .collection(COL.TRANSACTION) - .where('member', 'in', h.members) - .where('type', '==', TransactionType.CREDIT) - .get(); + .where('type', '==', PgTransactionType.CREDIT) + .whereIn('member', h.members) + .get(); expect(credits.length).toBe(1); expect(credits[0].member).toBe(h.members[1]); }); @@ -88,20 +74,20 @@ describe('Open auction bid', () => { await h.bidOnAuction(h.members[0], 2 * MIN_IOTA_AMOUNT); await h.bidOnAuction(h.members[0], 3 * MIN_IOTA_AMOUNT); - const auctionDocRef = build5Db().doc(`${COL.AUCTION}/${h.auction.uid}`); - await auctionDocRef.update({ auctionTo: dateToTimestamp(dayjs().subtract(1, 'minute')) }); + const auctionDocRef = build5Db().doc(COL.AUCTION, h.auction.uid); + await auctionDocRef.update({ auctionTo: dayjs().subtract(1, 'minute').toDate() }); await finalizeAuctions(); - const memberDocRef = build5Db().doc(`${COL.MEMBER}/${h.member}`); - const member = await memberDocRef.get(); + const memberDocRef = build5Db().doc(COL.MEMBER, h.member); + const member = await memberDocRef.get(); const address = getAddress(member, h.auction.network); const billPayments = await build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.BILL_PAYMENT) + .where('type', '==', PgTransactionType.BILL_PAYMENT) .where('member', '==', h.members[0]) - .get(); + .get(); billPayments.sort((a, b) => a.payload.amount! - b.payload.amount!); expect(billPayments.length).toBe(2); expect(billPayments[0].payload.amount!).toBe(2 * MIN_IOTA_AMOUNT); @@ -119,16 +105,16 @@ describe('Open auction bid', () => { await h.bidOnAuction(h.members[0], 2 * MIN_IOTA_AMOUNT); await h.bidOnAuction(h.members[0], 3 * MIN_IOTA_AMOUNT); - const auctionDocRef = build5Db().doc(`${COL.AUCTION}/${h.auction.uid}`); - await auctionDocRef.update({ auctionTo: dateToTimestamp(dayjs().subtract(1, 'minute')) }); + const auctionDocRef = build5Db().doc(COL.AUCTION, h.auction.uid); + await auctionDocRef.update({ auctionTo: dayjs().subtract(1, 'minute').toDate() }); await finalizeAuctions(); const billPayments = await build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.BILL_PAYMENT) + .where('type', '==', PgTransactionType.BILL_PAYMENT) .where('member', '==', h.members[0]) - .get(); + .get(); billPayments.sort((a, b) => a.payload.amount! - b.payload.amount!); expect(billPayments.length).toBe(2); expect(billPayments[0].payload.amount!).toBe(2 * MIN_IOTA_AMOUNT); @@ -138,12 +124,12 @@ describe('Open auction bid', () => { }); it('Should finalize open auction, no bids', async () => { - const auctionDocRef = build5Db().doc(`${COL.AUCTION}/${h.auction.uid}`); - await auctionDocRef.update({ auctionTo: dateToTimestamp(dayjs().subtract(1, 'minute')) }); + const auctionDocRef = build5Db().doc(COL.AUCTION, h.auction.uid); + await auctionDocRef.update({ auctionTo: dayjs().subtract(1, 'minute').toDate() }); await finalizeAuctions(); }); - const awaitPayments = (query: IQuery, count: number) => + const awaitPayments = (query: IQuery, count: number) => wait(async () => { const snap = await query.get(); return snap.length === count; @@ -154,14 +140,14 @@ describe('Open auction bid', () => { const validPaymentsQuery = build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.PAYMENT) + .where('type', '==', PgTransactionType.PAYMENT) .where('member', '==', h.members[0]) - .where('payload.invalidPayment', '==', false); + .where('payload_invalidPayment', '==', false); const invalidPaymentsQuery = build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.PAYMENT) + .where('type', '==', PgTransactionType.PAYMENT) .where('member', '==', h.members[0]) - .where('payload.invalidPayment', '==', true); + .where('payload_invalidPayment', '==', true); // Below floor, credit await h.bidOnAuction(h.members[0], 1.5 * MIN_IOTA_AMOUNT); @@ -192,14 +178,14 @@ describe('Open auction bid', () => { const validPaymentsQuery = build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.PAYMENT) + .where('type', '==', PgTransactionType.PAYMENT) .where('member', '==', h.members[0]) - .where('payload.invalidPayment', '==', false); + .where('payload_invalidPayment', '==', false); const invalidPaymentsQuery = build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.PAYMENT) + .where('type', '==', PgTransactionType.PAYMENT) .where('member', '==', h.members[0]) - .where('payload.invalidPayment', '==', true); + .where('payload_invalidPayment', '==', true); // Below floor, credit await h.bidOnAuction(h.members[0], 1.5 * MIN_IOTA_AMOUNT); diff --git a/packages/functions/test/controls/collection.spec.ts b/packages/functions/test/controls/collection.spec.ts index 1ff165575c..28ce257c60 100644 --- a/packages/functions/test/controls/collection.spec.ts +++ b/packages/functions/test/controls/collection.spec.ts @@ -1,55 +1,41 @@ -import { build5Db } from '@build-5/database'; +import { PgCollectionStatus, build5Db } from '@build-5/database'; import { Access, Bucket, COL, Categories, Collection, - CollectionStats, - CollectionStatus, CollectionType, MIN_IOTA_AMOUNT, - Member, NetworkAddress, Nft, RANKING_TEST, + Rank, SOON_PROJECT_ID, SUB_COL, Space, StakeType, Token, + Vote, WEN_FUNC, WenError, } from '@build-5/interfaces'; import dayjs from 'dayjs'; -import { chunk, set } from 'lodash'; -import { createNft } from '../../src/runtime/firebase/nft'; -import { rankController } from '../../src/runtime/firebase/rank'; -import { voteController } from '../../src/runtime/firebase/vote'; -import * as wallet from '../../src/utils/wallet.utils'; -import { soonTokenId, testEnv } from '../set-up'; -import { - createCollection, - rejectCollection, - updateCollection, -} from './../../src/runtime/firebase/collection/index'; -import { createMember } from './../../src/runtime/firebase/member'; +import { chunk, isEmpty, set } from 'lodash'; +import { dateToTimestamp } from '../../src/utils/dateTime.utils'; +import { getRandomEthAddress } from '../../src/utils/wallet.utils'; +import { mockWalletReturnValue, soonTokenId, testEnv } from '../set-up'; import { addGuardianToSpace, - createMember as createMemberFunc, createRoyaltySpaces, - createSpace as createSpaceFunc, expectThrow, getRandomSymbol, - mockWalletReturnValue, setProdTiers, setTestTiers, wait, } from './common'; -let walletSpy: any; - -const dummyCollection: any = (spaceId: string, royaltiesFee: number, noSpace = false) => { +const dummyCollection = (space: Space, royaltiesFee: number, noSpace = false) => { const data = { name: 'Collection A', description: 'babba', @@ -57,33 +43,28 @@ const dummyCollection: any = (spaceId: string, royaltiesFee: number, noSpace = f category: Categories.ART, access: Access.OPEN, royaltiesFee, - royaltiesSpace: spaceId, + royaltiesSpace: space.uid, onePerMemberOnly: false, availableFrom: dayjs().add(1, 'hour').toDate(), price: 10 * 1000 * 1000, }; if (!noSpace) { - set(data, 'space', spaceId); + set(data, 'space', space.uid); } return data; }; describe('CollectionController: ' + WEN_FUNC.createCollection, () => { - let dummyAddress: NetworkAddress; - let space: any; - let member: Member; - + let space: Space; + let member: string; beforeEach(async () => { - walletSpy = jest.spyOn(wallet, 'decodeAuth'); - dummyAddress = await createMemberFunc(walletSpy); - member = await testEnv.wrap(createMember)({ address: dummyAddress }); - expect(member?.uid).toEqual(dummyAddress.toLowerCase()); - space = await createSpaceFunc(walletSpy, dummyAddress); + member = await testEnv.createMember(); + space = await testEnv.createSpace(member); }); it('successfully create collection', async () => { - mockWalletReturnValue(walletSpy, dummyAddress, dummyCollection(space.uid, 0.6)); - const collection = await testEnv.wrap(createCollection)({}); + mockWalletReturnValue(member, dummyCollection(space, 0.6)); + const collection = await testEnv.wrap(WEN_FUNC.createCollection); expect(collection?.uid).toBeDefined(); expect(collection?.createdOn).toBeDefined(); expect(collection?.approved).toBe(false); @@ -91,12 +72,11 @@ describe('CollectionController: ' + WEN_FUNC.createCollection, () => { expect(collection?.updatedOn).toBeDefined(); expect(collection?.total).toBe(0); expect(collection?.sold).toBe(0); - walletSpy.mockRestore(); }); it('successfully create collection, no space', async () => { - mockWalletReturnValue(walletSpy, dummyAddress, dummyCollection(space.uid, 0.6, true)); - const collection = await testEnv.wrap(createCollection)({}); + mockWalletReturnValue(member, dummyCollection(space, 0.6, true)); + const collection = await testEnv.wrap(WEN_FUNC.createCollection); expect(collection?.uid).toBeDefined(); expect(collection?.createdOn).toBeDefined(); expect(collection?.approved).toBe(false); @@ -105,100 +85,95 @@ describe('CollectionController: ' + WEN_FUNC.createCollection, () => { expect(collection?.total).toBe(0); expect(collection?.sold).toBe(0); expect(collection.space).toBe(''); - walletSpy.mockRestore(); }); it('Should throw, invalid icon url', async () => { - mockWalletReturnValue(walletSpy, dummyAddress, { - media: 'asd', - ...dummyCollection(space.uid, 0.6), + mockWalletReturnValue(member, { + media: 'name', + ...dummyCollection(space, 0.6), }); - await expectThrow(testEnv.wrap(createCollection)({}), WenError.invalid_params.key); - - mockWalletReturnValue(walletSpy, dummyAddress, { - media: `https://firebasestorage.googleapis.com/v0/b/${Bucket.DEV}/o/`, - ...dummyCollection(space.uid, 0.6), + let call = testEnv.wrap(WEN_FUNC.createCollection); + await expectThrow(call, WenError.invalid_params.key); + mockWalletReturnValue(member, { + media: `https://storage.googleapis.com/download/storage/v1/b/${Bucket.DEV}/o`, + ...dummyCollection(space, 0.6), }); - await expectThrow(testEnv.wrap(createCollection)({}), WenError.invalid_params.key); + call = testEnv.wrap(WEN_FUNC.createCollection); + await expectThrow(call, WenError.invalid_params.key); }); it('Should throw, no soon staked', async () => { - mockWalletReturnValue(walletSpy, dummyAddress, dummyCollection(space.uid, 0.6)); await setProdTiers(); - await expectThrow(testEnv.wrap(createCollection)({}), WenError.no_staked_soon.key); + mockWalletReturnValue(member, dummyCollection(space, 0.6)); + const call = testEnv.wrap(WEN_FUNC.createCollection); + await expectThrow(call, WenError.no_staked_soon.key); await setTestTiers(); }); it('Should create collection, soon check', async () => { await build5Db() - .doc(`${COL.TOKEN}/${soonTokenId}/${SUB_COL.DISTRIBUTION}/${dummyAddress}`) + .doc(COL.TOKEN, soonTokenId, SUB_COL.DISTRIBUTION, member) .create({ - stakes: { - [StakeType.DYNAMIC]: { - value: 10 * MIN_IOTA_AMOUNT, - }, - }, + parentId: soonTokenId, + parentCol: COL.TOKEN, + stakes: { [StakeType.DYNAMIC]: { value: 10 * MIN_IOTA_AMOUNT } }, }); - - mockWalletReturnValue(walletSpy, dummyAddress, dummyCollection(space.uid, 0.6)); await setProdTiers(); - const collection = await testEnv.wrap(createCollection)({}); + mockWalletReturnValue(member, dummyCollection(space, 0.6)); + const collection = await testEnv.wrap(WEN_FUNC.createCollection); expect(collection?.uid).toBeDefined(); await setTestTiers(); }); it('fail to create collection - wrong royalties', async () => { - mockWalletReturnValue(walletSpy, dummyAddress, dummyCollection(space.uid, 4)); - await expectThrow(testEnv.wrap(createCollection)({}), WenError.invalid_params.key); - walletSpy.mockRestore(); + mockWalletReturnValue(member, dummyCollection(space, 4)); + const call = testEnv.wrap(WEN_FUNC.createCollection); + await expectThrow(call, WenError.invalid_params.key); }); it('fail to create collection - missing royalties space', async () => { - const collection = dummyCollection(space.uid, 0.1); - delete collection.royaltiesSpace; - mockWalletReturnValue(walletSpy, dummyAddress, collection); - await expectThrow(testEnv.wrap(createCollection)({}), WenError.invalid_params.key); - walletSpy.mockRestore(); + const collection = dummyCollection(space, 0.1); + delete (collection as any).royaltiesSpace; + mockWalletReturnValue(member, dummyCollection(space, 4)); + const call = testEnv.wrap(WEN_FUNC.createCollection); + await expectThrow(call, WenError.invalid_params.key); }); it('collection does not exists for update', async () => { - mockWalletReturnValue(walletSpy, dummyAddress, { - uid: wallet.getRandomEthAddress(), + const collection = { + uid: getRandomEthAddress(), name: 'Collection A', description: 'babba', royaltiesFee: 0.6, royaltiesSpace: space.uid, - }); - await expectThrow(testEnv.wrap(updateCollection)({}), WenError.collection_does_not_exists.key); - walletSpy.mockRestore(); + }; + mockWalletReturnValue(member, collection); + const call = testEnv.wrap(WEN_FUNC.updateCollection); + await expectThrow(call, WenError.collection_does_not_exists.key); }); it('successfully create collection & update', async () => { - const collection = dummyCollection(space.uid, 0.6); - mockWalletReturnValue(walletSpy, dummyAddress, collection); - - const cCollection = await testEnv.wrap(createCollection)({}); + const collection = dummyCollection(space, 0.6); + mockWalletReturnValue(member, collection); + const cCollection = await testEnv.wrap(WEN_FUNC.createCollection); expect(cCollection?.uid).toBeDefined(); expect(cCollection?.description).toBe('babba'); - - mockWalletReturnValue(walletSpy, dummyAddress, { + const uData = { uid: cCollection?.uid, name: 'Collection A', description: '123', royaltiesFee: 0.6, royaltiesSpace: space.uid, - }); - const uCollection = await testEnv.wrap(updateCollection)({}); + }; + mockWalletReturnValue(member, uData); + const uCollection = await testEnv.wrap(WEN_FUNC.updateCollection); expect(uCollection?.uid).toBeDefined(); expect(uCollection?.description).toBe('123'); - walletSpy.mockRestore(); }); it('successfully create collection & update, no space', async () => { - mockWalletReturnValue(walletSpy, dummyAddress, dummyCollection(space.uid, 0.6, true)); - - const cCollection = await testEnv.wrap(createCollection)({}); - + mockWalletReturnValue(member, dummyCollection(space, 0.6, true)); + const cCollection = await testEnv.wrap(WEN_FUNC.createCollection); const updateData = { uid: cCollection?.uid, name: 'Collection A', @@ -206,28 +181,21 @@ describe('CollectionController: ' + WEN_FUNC.createCollection, () => { royaltiesFee: 0.6, royaltiesSpace: space.uid, }; - - const randomMember = await createMemberFunc(walletSpy); - mockWalletReturnValue(walletSpy, randomMember, updateData); - await expectThrow( - testEnv.wrap(updateCollection)({}), - WenError.you_must_be_the_creator_of_this_collection.key, - ); - - mockWalletReturnValue(walletSpy, dummyAddress, updateData); - const uCollection = await testEnv.wrap(updateCollection)({}); + const randomMember = await testEnv.createMember(); + mockWalletReturnValue(randomMember, updateData); + const call = testEnv.wrap(WEN_FUNC.updateCollection); + await expectThrow(call, WenError.you_must_be_the_creator_of_this_collection.key); + mockWalletReturnValue(member, updateData); + const uCollection = await testEnv.wrap(WEN_FUNC.updateCollection); expect(uCollection?.name).toBe(updateData.name); expect(uCollection?.description).toBe(updateData.description); - walletSpy.mockRestore(); }); it('successfully create collection & update price', async () => { - let collection = dummyCollection(space.uid, 0.6); - mockWalletReturnValue(walletSpy, dummyAddress, collection); - collection = await testEnv.wrap(createCollection)({}); - - await build5Db().doc(`${COL.COLLECTION}/${collection.uid}`).update({ approved: true }); - + let collection = dummyCollection(space, 0.6) as unknown as Collection; + mockWalletReturnValue(member, collection); + collection = await testEnv.wrap(WEN_FUNC.createCollection); + await build5Db().doc(COL.COLLECTION, collection.uid).update({ approved: true }); const dummyNft = () => ({ name: 'Collection A', description: 'babba', @@ -237,94 +205,90 @@ describe('CollectionController: ' + WEN_FUNC.createCollection, () => { }); const nfts: Nft[] = []; for (let i = 0; i < 4; ++i) { - mockWalletReturnValue(walletSpy, dummyAddress, dummyNft()); - const nft = await testEnv.wrap(createNft)({}); + mockWalletReturnValue(member, dummyNft()); + const nft = await testEnv.wrap(WEN_FUNC.createNft); nfts.push(nft); } - const availableFrom = dayjs().add(1, 'd'); - mockWalletReturnValue(walletSpy, dummyAddress, { + const updateCollection = { uid: collection?.uid, price: 15 * MIN_IOTA_AMOUNT, - name: 'asd', + name: 'name', description: '123', royaltiesFee: 0.6, royaltiesSpace: space.uid, availableFrom: availableFrom.toDate(), - }); - const uCollection = await testEnv.wrap(updateCollection)({}); + }; + mockWalletReturnValue(member, updateCollection); + const uCollection = await testEnv.wrap(WEN_FUNC.updateCollection); expect(uCollection?.uid).toBe(collection.uid); expect(uCollection?.price).toBe(15 * MIN_IOTA_AMOUNT); expect(uCollection?.availablePrice).toBe(15 * MIN_IOTA_AMOUNT); - for (let i = 0; i < 4; ++i) { - const nftDocRef = build5Db().doc(`${COL.NFT}/${nfts[i].uid}`); + const nftDocRef = build5Db().doc(COL.NFT, nfts[i].uid); const nft = await nftDocRef.get(); expect(nft.price).toBe(15 * MIN_IOTA_AMOUNT); expect(nft.availablePrice).toBe(15 * MIN_IOTA_AMOUNT); } - - walletSpy.mockRestore(); }); it('Only allow discounts, access, accessAwards, accessCollections update on minted collection', async () => { const token = await saveToken(space.uid); - const collection = dummyCollection(space.uid, 0.6); - mockWalletReturnValue(walletSpy, dummyAddress, collection); - const cCollection = await testEnv.wrap(createCollection)({}); + const collection = dummyCollection(space, 0.6); + mockWalletReturnValue(member, collection); + const cCollection = await testEnv.wrap(WEN_FUNC.createCollection); await build5Db() - .doc(`${COL.COLLECTION}/${cCollection.uid}`) - .update({ status: CollectionStatus.MINTED }); - - mockWalletReturnValue(walletSpy, dummyAddress, { uid: cCollection?.uid, name: 'Collection A' }); - await expectThrow(testEnv.wrap(updateCollection)({}), WenError.invalid_params.key); - - mockWalletReturnValue(walletSpy, dummyAddress, { + .doc(COL.COLLECTION, cCollection.uid) + .update({ status: PgCollectionStatus.MINTED }); + expect(cCollection?.access).toBe(Access.OPEN); + mockWalletReturnValue(member, { + uid: cCollection?.uid, + name: 'Collection A', + }); + await expectThrow(testEnv.wrap(WEN_FUNC.updateCollection), WenError.invalid_params.key); + mockWalletReturnValue(member, { uid: cCollection?.uid, discounts: [{ tokenSymbol: token.symbol, tokenReward: 10, amount: 0.5 }], }); - let uCollection = await testEnv.wrap(updateCollection)({}); + let uCollection = await testEnv.wrap(WEN_FUNC.updateCollection); expect(uCollection?.discounts).toEqual([ { tokenSymbol: token.symbol, tokenUid: token.uid, tokenReward: 10, amount: 0.5 }, ]); expect(uCollection?.access).toBe(Access.OPEN); - const updateAwards = { uid: cCollection?.uid, access: Access.MEMBERS_WITH_BADGE, - accessAwards: [wallet.getRandomEthAddress()], + accessAwards: [getRandomEthAddress()], }; - mockWalletReturnValue(walletSpy, dummyAddress, updateAwards); - uCollection = await testEnv.wrap(updateCollection)({}); + mockWalletReturnValue(member, updateAwards); + uCollection = await testEnv.wrap(WEN_FUNC.updateCollection); expect(uCollection?.access).toBe(Access.MEMBERS_WITH_BADGE); expect(uCollection?.accessAwards).toEqual(updateAwards.accessAwards); - const updateCollections = { uid: cCollection?.uid, access: Access.MEMBERS_WITH_NFT_FROM_COLLECTION, - accessCollections: [wallet.getRandomEthAddress()], + accessCollections: [getRandomEthAddress()], }; - mockWalletReturnValue(walletSpy, dummyAddress, updateCollections); - uCollection = await testEnv.wrap(updateCollection)({}); + mockWalletReturnValue(member, updateCollections); + uCollection = await testEnv.wrap(WEN_FUNC.updateCollection); expect(uCollection?.access).toBe(Access.MEMBERS_WITH_NFT_FROM_COLLECTION); expect(uCollection?.accessCollections).toEqual(updateCollections.accessCollections); }); it('Should not update placeholder nft when collection is minted', async () => { const token = await saveToken(space.uid); - const collection = { ...dummyCollection(space.uid, 0.6), type: CollectionType.SFT }; - mockWalletReturnValue(walletSpy, dummyAddress, collection); - const cCollection = await testEnv.wrap(createCollection)({}); + const collection = { ...dummyCollection(space, 0.6), type: CollectionType.SFT }; + mockWalletReturnValue(member, collection); + const cCollection = await testEnv.wrap(WEN_FUNC.createCollection); await build5Db() - .doc(`${COL.COLLECTION}/${cCollection.uid}`) - .update({ status: CollectionStatus.MINTED }); - - mockWalletReturnValue(walletSpy, dummyAddress, { + .doc(COL.COLLECTION, cCollection.uid) + .update({ status: PgCollectionStatus.MINTED }); + mockWalletReturnValue(member, { uid: cCollection?.uid, discounts: [{ tokenSymbol: token.symbol, tokenReward: 10, amount: 0.5 }], access: Access.GUARDIANS_ONLY, }); - let uCollection = await testEnv.wrap(updateCollection)({}); + let uCollection = await testEnv.wrap(WEN_FUNC.updateCollection); expect(uCollection?.discounts).toEqual([ { tokenSymbol: token.symbol, tokenUid: token.uid, tokenReward: 10, amount: 0.5 }, ]); @@ -333,173 +297,162 @@ describe('CollectionController: ' + WEN_FUNC.createCollection, () => { it('Should throw, discount has same tokenReward', async () => { const token = await saveToken(space.uid); - const collection = dummyCollection(space.uid, 0.6); - mockWalletReturnValue(walletSpy, dummyAddress, collection); - const cCollection = await testEnv.wrap(createCollection)({}); - - mockWalletReturnValue(walletSpy, dummyAddress, { + const collection = dummyCollection(space, 0.6); + mockWalletReturnValue(member, collection); + const cCollection = await testEnv.wrap(WEN_FUNC.createCollection); + mockWalletReturnValue(member, { uid: cCollection?.uid, discounts: [ { tokenSymbol: token.symbol, tokenReward: 10, amount: 0.5 }, { tokenSymbol: token.symbol, tokenReward: 10, amount: 0.6 }, ], }); - await expectThrow(testEnv.wrap(updateCollection)({}), WenError.invalid_params.key); + await expectThrow( + testEnv.wrap(WEN_FUNC.updateCollection), + WenError.invalid_params.key, + ); }); it('Should throw, token does not exist', async () => { - const collection = dummyCollection(space.uid, 0.6); - mockWalletReturnValue(walletSpy, dummyAddress, collection); - const cCollection = await testEnv.wrap(createCollection)({}); + const collection = dummyCollection(space, 0.6); + mockWalletReturnValue(member, collection); + const cCollection = await testEnv.wrap(WEN_FUNC.createCollection); await build5Db() - .doc(`${COL.COLLECTION}/${cCollection.uid}`) - .update({ status: CollectionStatus.MINTED }); - - mockWalletReturnValue(walletSpy, dummyAddress, { + .doc(COL.COLLECTION, cCollection.uid) + .update({ status: PgCollectionStatus.MINTED }); + mockWalletReturnValue(member, { uid: cCollection?.uid, discounts: [{ tokenSymbol: 'ASD', tokenReward: 10, amount: 0.5 }], }); - await expectThrow(testEnv.wrap(updateCollection)({}), WenError.token_does_not_exist.key); + await expectThrow( + testEnv.wrap(WEN_FUNC.updateCollection), + WenError.token_does_not_exist.key, + ); }); it('successfully create collection & approve', async () => { - mockWalletReturnValue(walletSpy, dummyAddress, dummyCollection(space.uid, 0.6)); - const cCollection = await testEnv.wrap(createCollection)({}); + mockWalletReturnValue(member, dummyCollection(space, 0.6)); + const cCollection = await testEnv.wrap(WEN_FUNC.createCollection); expect(cCollection?.uid).toBeDefined(); expect(cCollection?.description).toBe('babba'); }); it('successfully create collection & reject', async () => { - mockWalletReturnValue(walletSpy, dummyAddress, dummyCollection(space.uid, 0.6)); - const returns = await testEnv.wrap(createCollection)({}); + mockWalletReturnValue(member, dummyCollection(space, 0.6)); + const returns = await testEnv.wrap(WEN_FUNC.createCollection); expect(returns?.uid).toBeDefined(); expect(returns?.description).toBe('babba'); - - mockWalletReturnValue(walletSpy, dummyAddress, { uid: returns?.uid }); - const returns2 = await testEnv.wrap(rejectCollection)({}); + mockWalletReturnValue(member, { uid: returns?.uid }); + const returns2 = await testEnv.wrap(WEN_FUNC.rejectCollection); expect(returns2?.uid).toBeDefined(); expect(returns2?.approved).toBe(false); expect(returns2?.rejected).toBe(true); - walletSpy.mockRestore(); }); it('successfully create collection & reject, no space', async () => { - mockWalletReturnValue(walletSpy, dummyAddress, dummyCollection(space.uid, 0.6, true)); - const returns = await testEnv.wrap(createCollection)({}); - - mockWalletReturnValue(walletSpy, wallet.getRandomEthAddress(), { uid: returns?.uid }); + mockWalletReturnValue(member, dummyCollection(space, 0.6, true)); + let collection = await testEnv.wrap(WEN_FUNC.createCollection); + const randomMember = await testEnv.createMember(); + mockWalletReturnValue(randomMember, { uid: collection.uid }); await expectThrow( - testEnv.wrap(rejectCollection)({}), + testEnv.wrap(WEN_FUNC.rejectCollection), WenError.you_must_be_the_creator_of_this_collection.key, ); - - mockWalletReturnValue(walletSpy, dummyAddress, { uid: returns?.uid }); - const returns2 = await testEnv.wrap(rejectCollection)({}); - expect(returns2?.uid).toBeDefined(); - expect(returns2?.approved).toBe(false); - expect(returns2?.rejected).toBe(true); - walletSpy.mockRestore(); + mockWalletReturnValue(member, { uid: collection.uid }); + collection = await testEnv.wrap(WEN_FUNC.rejectCollection); + expect(collection.uid).toBeDefined(); + expect(collection.approved).toBe(false); + expect(collection.rejected).toBe(true); }); it('Any guardian can update collection after approved', async () => { - const secondGuardian = await createMemberFunc(walletSpy); + const secondGuardian = await testEnv.createMember(); await addGuardianToSpace(space.uid, secondGuardian); - - mockWalletReturnValue(walletSpy, dummyAddress, dummyCollection(space.uid, 0.6)); - const cCollection = await testEnv.wrap(createCollection)({}); - + mockWalletReturnValue(member, dummyCollection(space, 0.6)); + const cCollection = await testEnv.wrap(WEN_FUNC.createCollection); const updateData = { uid: cCollection?.uid, - name: 'asd', + name: 'name', description: '123', royaltiesFee: 0.6, royaltiesSpace: space.uid, }; - mockWalletReturnValue(walletSpy, secondGuardian, updateData); + mockWalletReturnValue(secondGuardian, updateData); await expectThrow( - testEnv.wrap(updateCollection)({}), + testEnv.wrap(WEN_FUNC.updateCollection), WenError.you_must_be_the_creator_of_this_collection.key, ); - - await build5Db().doc(`${COL.COLLECTION}/${cCollection?.uid}`).update({ approved: true }); - - mockWalletReturnValue(walletSpy, secondGuardian, updateData); - const uCollection = await testEnv.wrap(updateCollection)({}); + await build5Db().doc(COL.COLLECTION, cCollection?.uid).update({ approved: true }); + mockWalletReturnValue(secondGuardian, updateData); + const uCollection = await testEnv.wrap(WEN_FUNC.updateCollection); expect(uCollection?.uid).toBeDefined(); - expect(uCollection?.name).toBe('asd'); - - walletSpy.mockRestore(); + expect(uCollection?.name).toBe('name'); }); }); describe('Collection trigger test', () => { it('Should set approved&reject properly on nfts', async () => { + const member = await testEnv.createMember(); + const space = await testEnv.createSpace(member); const collection = { - ...dummyCollection('', 0.1), + ...dummyCollection(space, 0.1), project: SOON_PROJECT_ID, - uid: wallet.getRandomEthAddress(), + uid: getRandomEthAddress(), }; - await build5Db().doc(`${COL.COLLECTION}/${collection.uid}`).create(collection); - + await build5Db() + .doc(COL.COLLECTION, collection.uid) + .create({ + ...collection, + availableFrom: dateToTimestamp(collection.availableFrom), + } as Collection); const nftIds = Array.from(Array(1000)); const chunks = chunk(nftIds, 500); for (let chunkIndex = 0; chunkIndex < chunks.length; ++chunkIndex) { 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), + const promises = chunks[chunkIndex].map(async (_, index) => { + const id = getRandomEthAddress(); + const nft = dummyNft(chunkIndex * 500 + index, id, collection.uid); + batch.create(build5Db().doc(COL.NFT, id), { + ...nft, + availableFrom: dateToTimestamp(nft.availableFrom), project: SOON_PROJECT_ID, - }); + } as unknown as Nft); }); + await Promise.all(promises); await batch.commit(); } - - await build5Db().doc(`${COL.COLLECTION}/${collection.uid}`).update({ - approved: true, - }); - + await build5Db().doc(COL.COLLECTION, collection.uid).update({ approved: true }); await wait(async () => { const snap = await build5Db() .collection(COL.NFT) .where('collection', '==', collection.uid) - .get(); + .get(); const allHaveUpdated = snap.reduce((acc, act) => acc && act.approved, true); return allHaveUpdated; }); - - await build5Db().doc(`${COL.COLLECTION}/${collection.uid}`).update({ - approved: false, - }); - await build5Db().doc(`${COL.COLLECTION}/${collection.uid}`).update({ - approved: true, - }); - + await build5Db().doc(COL.COLLECTION, collection.uid).update({ approved: false }); + await build5Db().doc(COL.COLLECTION, collection.uid).update({ approved: true }); await wait(async () => { const snap = await build5Db() .collection(COL.NFT) .where('collection', '==', collection.uid) - .get(); + .get(); const allHaveUpdated = snap.reduce((acc, act) => acc && act.approved, true); return allHaveUpdated; }); - - await build5Db().doc(`${COL.COLLECTION}/${collection.uid}`).update({ - approved: false, - rejected: true, - }); - + await build5Db() + .doc(COL.COLLECTION, collection.uid) + .update({ approved: false, rejected: true }); await wait(async () => { const snap = await build5Db() .collection(COL.NFT) .where('collection', '==', collection.uid) - .get(); + .get(); const allHaveUpdated = snap.reduce((acc, act) => acc && !act.approved && act.rejected, true); return allHaveUpdated; }); }); }); - const dummyNft = (index: number, uid: string, collection: string, description = 'babba') => ({ uid, name: 'Nft ' + index, @@ -510,54 +463,56 @@ const dummyNft = (index: number, uid: string, collection: string, description = }); describe('Collection vote test', () => { - let memberAddress: NetworkAddress; + let member: NetworkAddress; let space: Space; let collection: any; - beforeEach(async () => { - walletSpy = jest.spyOn(wallet, 'decodeAuth'); - memberAddress = await createMemberFunc(walletSpy); - space = await createSpaceFunc(walletSpy, memberAddress); - - mockWalletReturnValue(walletSpy, memberAddress, dummyCollection(space.uid, 0.6)); - collection = await testEnv.wrap(createCollection)({}); + member = await testEnv.createMember(); + space = await testEnv.createSpace(member); + mockWalletReturnValue(member, dummyCollection(space, 0.6)); + collection = await testEnv.wrap(WEN_FUNC.createCollection); }); it('Should throw, no collection', async () => { - mockWalletReturnValue(walletSpy, memberAddress, { + mockWalletReturnValue(member, { collection: COL.COLLECTION, - uid: wallet.getRandomEthAddress(), + uid: getRandomEthAddress(), direction: 1, }); - await expectThrow(testEnv.wrap(voteController)({}), WenError.collection_does_not_exists.key); + await expectThrow( + testEnv.wrap(WEN_FUNC.voteController), + WenError.collection_does_not_exists.key, + ); }); it('Should throw, invalid direction', async () => { - mockWalletReturnValue(walletSpy, memberAddress, { + mockWalletReturnValue(member, { collection: COL.COLLECTION, uid: collection.uid, direction: 2, }); - await expectThrow(testEnv.wrap(voteController)({}), WenError.invalid_params.key); + await expectThrow(testEnv.wrap(WEN_FUNC.voteController), WenError.invalid_params.key); }); it('Should throw, no soons staked', async () => { await setProdTiers(); - mockWalletReturnValue(walletSpy, memberAddress, { + mockWalletReturnValue(member, { collection: COL.COLLECTION, uid: collection.uid, direction: 1, }); - await expectThrow(testEnv.wrap(voteController)({}), WenError.no_staked_soon.key); + await expectThrow(testEnv.wrap(WEN_FUNC.voteController), WenError.no_staked_soon.key); await setTestTiers(); }); - const validateStats = async (upvotes: number, downvotes: number, diff: number) => { await wait(async () => { const statsDocRef = build5Db().doc( - `${COL.COLLECTION}/${collection.uid}/${SUB_COL.STATS}/${collection.uid}`, + COL.COLLECTION, + collection.uid, + SUB_COL.STATS, + collection.uid, ); - const stats = await statsDocRef.get(); + const stats = await statsDocRef.get(); return ( stats?.votes?.upvotes === upvotes && stats?.votes?.downvotes === downvotes && @@ -565,34 +520,30 @@ describe('Collection vote test', () => { ); }); }; - const sendVote = async (direction: number) => { - mockWalletReturnValue(walletSpy, memberAddress, { + mockWalletReturnValue(member, { collection: COL.COLLECTION, uid: collection.uid, direction, }); - const vote = await testEnv.wrap(voteController)({}); - expect(vote.uid).toBe(memberAddress); + const vote = await testEnv.wrap(WEN_FUNC.voteController); + expect(vote.uid).toBe(member); expect(vote.parentId).toBe(collection.uid); expect(vote.parentCol).toBe(COL.COLLECTION); expect(vote.direction).toBe(direction); }; - it('Should vote', async () => { await sendVote(1); await validateStats(1, 0, 1); - await sendVote(-1); await validateStats(0, 1, -1); - - mockWalletReturnValue(walletSpy, memberAddress, { + mockWalletReturnValue(member, { collection: COL.COLLECTION, uid: collection.uid, direction: 0, }); - const vote = await testEnv.wrap(voteController)({}); - expect(vote).toBe(undefined); + const vote = await testEnv.wrap(WEN_FUNC.voteController); + expect(isEmpty(vote)).toBe(true); }); }); @@ -600,80 +551,79 @@ describe('Collection rank test', () => { let member: string; let space: Space; let collection: any; - beforeAll(async () => { await createRoyaltySpaces(); }); - beforeEach(async () => { - walletSpy = jest.spyOn(wallet, 'decodeAuth'); - member = await createMemberFunc(walletSpy); - space = await createSpaceFunc(walletSpy, member); - - mockWalletReturnValue(walletSpy, member, dummyCollection(space.uid, 0.6)); - collection = await testEnv.wrap(createCollection)({}); - + member = await testEnv.createMember(); + space = await testEnv.createSpace(member); + mockWalletReturnValue(member, dummyCollection(space, 0.6)); + collection = await testEnv.wrap(WEN_FUNC.createCollection); await build5Db() - .doc(`${COL.SPACE}/${RANKING_TEST.collectionSpace}/${SUB_COL.GUARDIANS}/${member}`) - .set({ - uid: member, - parentId: RANKING_TEST.collectionSpace, - parentCol: COL.SPACE, - }); + .doc(COL.SPACE, RANKING_TEST.collectionSpace, SUB_COL.GUARDIANS, member) + .upsert({ parentId: RANKING_TEST.collectionSpace }); }); it('Should throw, no collection', async () => { - mockWalletReturnValue(walletSpy, member, { + mockWalletReturnValue(member, { collection: COL.COLLECTION, - uid: wallet.getRandomEthAddress(), + uid: getRandomEthAddress(), rank: 1, }); - await expectThrow(testEnv.wrap(rankController)({}), WenError.collection_does_not_exists.key); + await expectThrow( + testEnv.wrap(WEN_FUNC.rankController), + WenError.collection_does_not_exists.key, + ); }); it('Should throw, invalid rank', async () => { - mockWalletReturnValue(walletSpy, member, { + mockWalletReturnValue(member, { collection: COL.COLLECTION, uid: collection.uid, rank: 200, }); - await expectThrow(testEnv.wrap(rankController)({}), WenError.invalid_params.key); + await expectThrow(testEnv.wrap(WEN_FUNC.rankController), WenError.invalid_params.key); }); it('Should throw, no soons staked', async () => { - mockWalletReturnValue(walletSpy, member, { + await setProdTiers(); + mockWalletReturnValue(member, { collection: COL.COLLECTION, uid: collection.uid, rank: 1, }); - await setProdTiers(); - await expectThrow(testEnv.wrap(rankController)({}), WenError.no_staked_soon.key); + await expectThrow(testEnv.wrap(WEN_FUNC.rankController), WenError.no_staked_soon.key); await setTestTiers(); }); it('Should throw, not space member', async () => { await build5Db() - .doc(`${COL.SPACE}/${RANKING_TEST.collectionSpace}/${SUB_COL.GUARDIANS}/${member}`) + .doc(COL.SPACE, RANKING_TEST.collectionSpace, SUB_COL.GUARDIANS, member) .delete(); - - mockWalletReturnValue(walletSpy, member, { + mockWalletReturnValue(member, { collection: COL.COLLECTION, uid: collection.uid, rank: 1, }); - await expectThrow(testEnv.wrap(rankController)({}), WenError.you_are_not_guardian_of_space.key); + await expectThrow( + testEnv.wrap(WEN_FUNC.rankController), + WenError.you_are_not_guardian_of_space.key, + ); }); - const validateStats = async (count: number, sum: number) => { await wait(async () => { - const collectionDocRef = build5Db().doc(`${COL.COLLECTION}/${collection.uid}`); - const statsDocRef = collectionDocRef.collection(SUB_COL.STATS).doc(collection.uid); - const stats = await statsDocRef.get(); + const collectionDocRef = build5Db().doc(COL.COLLECTION, collection.uid); + const statsDocRef = build5Db().doc( + COL.COLLECTION, + collection.uid, + SUB_COL.STATS, + collection.uid, + ); + const stats = await statsDocRef.get(); const statsAreCorrect = stats?.ranks?.count === count && stats?.ranks?.sum === sum && stats?.ranks?.avg === Number((stats?.ranks?.sum! / stats?.ranks?.count!).toFixed(3)); - collection = await collectionDocRef.get(); return ( statsAreCorrect && @@ -683,55 +633,45 @@ describe('Collection rank test', () => { ); }); }; - const sendRank = async (rankValue: number, memberAddress?: string) => { - mockWalletReturnValue(walletSpy, memberAddress || member, { + mockWalletReturnValue(memberAddress || member, { collection: COL.COLLECTION, uid: collection.uid, rank: rankValue, }); - const rank = await testEnv.wrap(rankController)({}); + const rank = await testEnv.wrap(WEN_FUNC.rankController); expect(rank.uid).toBe(memberAddress || member); expect(rank.parentId).toBe(collection.uid); expect(rank.parentCol).toBe(COL.COLLECTION); expect(rank.rank).toBe(rankValue); }; - it('Should rank', async () => { await sendRank(100); await validateStats(1, 100); - await sendRank(-100); await validateStats(1, -100); - - const secondMember = await createMemberFunc(walletSpy); + const secondMember = await testEnv.createMember(); await build5Db() - .doc(`${COL.SPACE}/${RANKING_TEST.collectionSpace}/${SUB_COL.GUARDIANS}/${secondMember}`) - .set({ - uid: secondMember, - parentId: RANKING_TEST.collectionSpace, - parentCol: COL.SPACE, - }); - + .doc(COL.SPACE, RANKING_TEST.collectionSpace, SUB_COL.GUARDIANS, secondMember) + .upsert({ parentId: RANKING_TEST.collectionSpace }); await sendRank(-50, secondMember); await validateStats(2, -150); - await wait(async () => { - const doc = await build5Db().doc(`${COL.COLLECTION}/${collection.uid}`).get(); - return !doc.approved && doc.rejected; + const doc = await build5Db().doc(COL.COLLECTION, collection.uid).get(); + return !doc!.approved && doc!.rejected; }); }); }); - const saveToken = async (space: string) => { const token = { project: SOON_PROJECT_ID, - uid: wallet.getRandomEthAddress(), + uid: getRandomEthAddress(), symbol: getRandomSymbol(), approved: true, space, name: 'MyToken', }; - await build5Db().doc(`${COL.TOKEN}/${token.uid}`).set(token); - return token; + const docRef = build5Db().doc(COL.TOKEN, token.uid); + await docRef.upsert(token); + return await docRef.get(); }; diff --git a/packages/functions/test/controls/common.ts b/packages/functions/test/controls/common.ts index 9e1dcfa14e..f44b0c90da 100644 --- a/packages/functions/test/controls/common.ts +++ b/packages/functions/test/controls/common.ts @@ -1,74 +1,35 @@ import { build5Db } from '@build-5/database'; import { COL, - DecodedToken, MIN_IOTA_AMOUNT, Network, - NetworkAddress, SOON_PROJECT_ID, SUB_COL, - Space, TOKEN_SALE_TEST, - Token, - TokenDistribution, TokenStatus, Transaction, TransactionPayloadType, TransactionType, + WEN_FUNC, getMilestoneCol, } from '@build-5/interfaces'; import { TransactionPayload, UTXOInput, Utils } from '@iota/sdk'; import dayjs from 'dayjs'; -import { validateAddress } from '../../src/runtime/firebase/address'; -import { createMember as createMemberFunc } from '../../src/runtime/firebase/member'; -import { createSpace as createSpaceFunc } from '../../src/runtime/firebase/space/index'; +import { createSpaceControl } from '../../src/controls/space/space.create.control'; import { packBasicOutput } from '../../src/utils/basic-output.utils'; import { createUnlock, packEssence } from '../../src/utils/block.utils'; import * as config from '../../src/utils/config.utils'; import * as ipUtils from '../../src/utils/ip.utils'; import * as wallet from '../../src/utils/wallet.utils'; -import { MEDIA, getWallet, testEnv } from '../set-up'; +import { getRandomEthAddress } from '../../src/utils/wallet.utils'; +import { MEDIA, getWallet, mockWalletReturnValue, testEnv } from '../set-up'; -export const mockWalletReturnValue = ( - walletSpy: any, - address: NetworkAddress, - body: T, - noProject = false, -) => { - const decodedToken: DecodedToken = { address, body, project: noProject ? '' : SOON_PROJECT_ID }; - return walletSpy.mockReturnValue(Promise.resolve(decodedToken)); -}; - -export const expectThrow = async (call: C | Promise, error: E, message?: string) => { - try { - await call; - fail(); - } catch (e: any) { - expect(e.key).toBe(error); - if (message) { - expect(e.message).toBe(message); - } - } -}; - -export const milestoneProcessed = async ( - nextMilestone: string, - defTranId: string, - network: Network, -) => { - for (let attempt = 0; attempt < 400; ++attempt) { - await new Promise((r) => setTimeout(r, 500)); - const milestoneTranDocRef = build5Db() - .collection(getMilestoneCol(network)) - .doc(nextMilestone) - .collection(SUB_COL.TRANSACTIONS) - .doc(defTranId); - const doc = await milestoneTranDocRef.get>(); - if (doc?.processed) { - return; - } - } - throw new Error('Milestone was not processed. Id: ' + nextMilestone); +export const validateMemberAddressFunc = async (member: string, network = Network.RMS) => { + mockWalletReturnValue(member, { network }); + const order = await testEnv.wrap(WEN_FUNC.validateAddress); + expect(order?.type).toBe(TransactionType.ORDER); + expect(order?.payload.type).toBe(TransactionPayloadType.MEMBER_ADDRESS_VALIDATION); + return order; }; export const submitMilestoneFunc = async (order: Transaction, customAmount?: number) => { @@ -76,9 +37,7 @@ export const submitMilestoneFunc = async (order: Transaction, customAmount?: num const network = order.network || Network.IOTA; const to = order.payload.targetAddress!; const walletService = await getWallet(network); - const from = await walletService.getNewIotaAddressDetails(); - const consumedOutputId = '0xbdb062b39e38c3ea0b37c32d564ee839da4e1d66ceb035a56ed1e87caa3fc5950000'; const consumedOutputs = await packBasicOutput(walletService, from.bech32, amount, {}); const inputs = [UTXOInput.fromOutputId(consumedOutputId)]; @@ -87,91 +46,40 @@ export const submitMilestoneFunc = async (order: Transaction, customAmount?: num const essence = await packEssence(walletService, inputs, inputsCommitment, outputs, {}); const unlocks = [await createUnlock(essence, from)]; const payload = new TransactionPayload(essence, unlocks); - - const milestoneColl = getMilestoneCol(network); - const nextMilestone = wallet.getRandomEthAddress(); - const defTranId = wallet.getRandomEthAddress(); - const tranDocRef = build5Db() - .doc(`${milestoneColl}/${nextMilestone}`) - .collection(SUB_COL.TRANSACTIONS) - .doc(defTranId); - await tranDocRef.set({ - uid: defTranId, + const milestoneCol = getMilestoneCol(network); + const nextMilestone = Math.floor(Math.random() * MIN_IOTA_AMOUNT).toString(); + const defTranId = getRandomEthAddress(); + const tranDocRef = build5Db().doc(milestoneCol, nextMilestone, SUB_COL.TRANSACTIONS, defTranId); + await tranDocRef.upsert({ createdOn: dayjs().toDate(), - blockId: wallet.getRandomEthAddress(), - milestone: wallet.getRandomEthAddress(), - payload: JSON.parse(JSON.stringify(payload)), + blockId: getRandomEthAddress(), + milestone: Number(nextMilestone), + payload: JSON.stringify(payload), }); - await tranDocRef.update({ complete: true }); - await milestoneProcessed(nextMilestone, defTranId, network); - return { milestone: nextMilestone, tranId: defTranId, fromAdd: from.bech32 }; }; -export const validateSpaceAddressFunc = async ( - spy: any, - adr: string, - space: string, - network?: Network, +export const milestoneProcessed = async ( + nextMilestone: string, + defTranId: string, + network: Network, ) => { - mockWalletReturnValue(spy, adr, network ? { space, network } : { space }); - const order = await testEnv.wrap(validateAddress)({}); - expect(order?.type).toBe(TransactionType.ORDER); - expect(order?.payload.type).toBe(TransactionPayloadType.SPACE_ADDRESS_VALIDATION); - return order; -}; - -export const validateMemberAddressFunc = async (spy: any, adr: string, network?: Network) => { - mockWalletReturnValue(spy, adr, network ? { network } : {}); - const order = await testEnv.wrap(validateAddress)({}); - expect(order?.type).toBe(TransactionType.ORDER); - expect(order?.payload.type).toBe(TransactionPayloadType.MEMBER_ADDRESS_VALIDATION); - return order; -}; - -export const createMember = async (spy: any): Promise => { - const memberAddress = wallet.getRandomEthAddress(); - mockWalletReturnValue(spy, memberAddress, {}); - await testEnv.wrap(createMemberFunc)({ address: memberAddress }); - for (const network of Object.values(Network)) { - const wallet = await getWallet(network); - const address = await wallet.getNewIotaAddressDetails(); - await build5Db() - .doc(`${COL.MEMBER}/${memberAddress}`) - .update({ [`validatedAddress.${network}`]: address.bech32, name: getRandomSymbol() }); - } - return memberAddress; -}; - -export const createSpace = async (spy: any, guardian: string): Promise => { - mockWalletReturnValue(spy, guardian, { name: 'Space A', bannerUrl: MEDIA }); - const space = await testEnv.wrap(createSpaceFunc)({}); - const spaceDocRef = build5Db().doc(`${COL.SPACE}/${space.uid}`); - for (const network of Object.values(Network)) { - const wallet = await getWallet(network); - const address = await wallet.getNewIotaAddressDetails(); - await spaceDocRef.update({ [`validatedAddress.${network}`]: address.bech32 }); - } - return await spaceDocRef.get(); -}; - -export const tokenProcessed = (tokenId: string, distributionLength: number, reconciled: boolean) => - wait(async () => { - const doc = await build5Db().doc(`${COL.TOKEN}/${tokenId}`).get(); - const distributionsSnap = await build5Db() - .doc(`${COL.TOKEN}/${tokenId}`) - .collection(SUB_COL.DISTRIBUTION) - .get(); - const distributionsOk = distributionsSnap.reduce( - (acc, doc) => acc && (doc?.reconciled || false) === reconciled, - distributionLength === distributionsSnap.length, + for (let attempt = 0; attempt < 400; ++attempt) { + await new Promise((r) => setTimeout(r, 500)); + const milestoneTranDocRef = build5Db().doc( + getMilestoneCol(network), + nextMilestone, + SUB_COL.TRANSACTIONS, + defTranId, ); - if (doc?.status === TokenStatus.ERROR) { - throw new Error('Token not processed: ' + tokenId); + const doc = await milestoneTranDocRef.get(); + if (doc?.processed) { + return; } - return distributionsOk && doc?.status === TokenStatus.PRE_MINTED; - }); + } + throw new Error('Milestone was not processed. Id: ' + nextMilestone); +}; export const wait = async ( func: () => Promise, @@ -187,93 +95,125 @@ export const wait = async ( throw new Error('Timeout'); }; -const isProdSpy = jest.spyOn(config, 'isProdEnv'); -const blockedCountriesSpy = jest.spyOn(ipUtils, 'getBlockedCountries'); -const ipInfoMock = jest.spyOn(ipUtils, 'getIpInfo'); - -export const mockIpCheck = ( - isProdEnv: boolean, - blockedCountries: { [key: string]: string[] }, - ipInfo: any, -) => { - isProdSpy.mockReturnValueOnce(isProdEnv); - blockedCountriesSpy.mockReturnValueOnce(blockedCountries); - ipInfoMock.mockReturnValueOnce(ipInfo); +export const setProdTiers = async () => { + const soonProjDocRef = build5Db().doc(COL.PROJECT, SOON_PROJECT_ID); + const soonProject = { + config_tiers: [0, 10, 4000, 6000, 15000].map((v) => v * MIN_IOTA_AMOUNT), + config_tokenTradingFeeDiscountPercentage: [0, 25, 50, 75, 100], + }; + await soonProjDocRef.upsert(soonProject); }; +export const setTestTiers = async () => { + const soonProjDocRef = build5Db().doc(COL.PROJECT, SOON_PROJECT_ID); + const soonProject = { + config_tiers: [0, 0, 0, 0, 0].map((v) => v * MIN_IOTA_AMOUNT), + config_tokenTradingFeeDiscountPercentage: [0, 0, 0, 0, 0], + }; + await soonProjDocRef.upsert(soonProject); +}; const alphabet = 'abcdefghijklmnopqrstuvwxyz'; + export const getRandomSymbol = () => Array.from(Array(4)) .map(() => alphabet[Math.floor(Math.random() * alphabet.length)]) .join('') .toUpperCase(); +export const expectThrow = async (call: Promise, error: string, message = '') => { + try { + await call; + fail(); + } catch (e: any) { + expect(e.key || e.eKey).toBe(error); + if (message) { + expect(e.message || e.eMessage).toBe(message); + } + } +}; + +export const addGuardianToSpace = async (space: string, member: string) => { + const guardianDocRef = build5Db().doc(COL.SPACE, space, SUB_COL.GUARDIANS, member); + const guardian = await guardianDocRef.get(); + if (guardian) { + return; + } + await guardianDocRef.upsert({ parentId: space }); + await build5Db() + .doc(COL.SPACE, space) + .update({ totalGuardians: build5Db().inc(1), totalMembers: build5Db().inc(1) }); +}; + export const createRoyaltySpaces = async () => { + const guardian = await testEnv.createMember(); const spaceOneId = TOKEN_SALE_TEST.spaceone; const spaceTwoId = TOKEN_SALE_TEST.spacetwo; - const walletSpy = jest.spyOn(wallet, 'decodeAuth'); - const guardian = await createMember(walletSpy); - const spaceIdSpy = jest.spyOn(wallet, 'getRandomEthAddress'); - const spaceOneDoc = await build5Db().doc(`${COL.SPACE}/${spaceOneId}`).get(); - if (!spaceOneDoc) { + const spaceOneDoc = build5Db().doc(COL.SPACE, spaceOneId); + if (!(await spaceOneDoc.get())) { spaceIdSpy.mockReturnValue(spaceOneId); - await createSpace(walletSpy, guardian); + mockWalletReturnValue(guardian, { name: 'Space A', bannerUrl: MEDIA }); + await testEnv.mockWrap(createSpaceControl); + const addresses = {} as any; + const promises = Object.values(Network).map(async (network) => { + const wallet = await getWallet(network); + const address = await wallet.getNewIotaAddressDetails(); + addresses[`${network}Address`] = address.bech32; + }); + await Promise.all(promises); + await spaceOneDoc.update(addresses); } - - const spaceTwoDoc = await build5Db().doc(`${COL.SPACE}/${spaceTwoId}`).get(); - if (!spaceTwoDoc) { + const spaceTwoDoc = build5Db().doc(COL.SPACE, spaceTwoId); + if (!(await spaceTwoDoc.get())) { spaceIdSpy.mockReturnValue(spaceTwoId); - await createSpace(walletSpy, guardian); + mockWalletReturnValue(guardian, { name: 'Space A', bannerUrl: MEDIA }); + await testEnv.mockWrap(createSpaceControl); + const addresses = {} as any; + const promises = Object.values(Network).map(async (network) => { + const wallet = await getWallet(network); + const address = await wallet.getNewIotaAddressDetails(); + addresses[`${network}Address`] = address.bech32; + }); + await Promise.all(promises); + await spaceTwoDoc.update(addresses); } - spaceIdSpy.mockRestore(); - walletSpy.mockRestore(); -}; - -export const addGuardianToSpace = async (space: string, member: string) => { - const spaceDocRef = build5Db().doc(`${COL.SPACE}/${space}`); - const guardianDocRef = spaceDocRef.collection(SUB_COL.GUARDIANS).doc(member); - const guardian = await guardianDocRef.get(); - if (guardian) { - return; - } - await guardianDocRef.set({ - uid: member, - parentId: space, - parentCol: COL.SPACE, - }); - await spaceDocRef.update({ totalGuardians: build5Db().inc(1), totalMembers: build5Db().inc(1) }); }; export const removeGuardianFromSpace = async (space: string, member: string) => { - const spaceDocRef = build5Db().doc(`${COL.SPACE}/${space}`); - const guardianDocRef = spaceDocRef.collection(SUB_COL.GUARDIANS).doc(member); + const spaceDocRef = build5Db().doc(COL.SPACE, space); + const guardianDocRef = build5Db().doc(COL.SPACE, space, SUB_COL.GUARDIANS, member); await guardianDocRef.delete(); await spaceDocRef.update({ totalGuardians: build5Db().inc(-1), - totalMembers: build5Db().inc(-11), + totalMembers: build5Db().inc(-1), }); }; -export const setProdTiers = async () => { - const soonProjDocRef = build5Db().doc(`${COL.PROJECT}/${SOON_PROJECT_ID}`); - const soonProject = { - config: { - tiers: [0, 10, 4000, 6000, 15000].map((v) => v * MIN_IOTA_AMOUNT), - tokenTradingFeeDiscountPercentage: [0, 25, 50, 75, 100], - }, - }; - await soonProjDocRef.set(soonProject, true); -}; - -export const setTestTiers = async () => { - const soonProjDocRef = build5Db().doc(`${COL.PROJECT}/${SOON_PROJECT_ID}`); - const soonProject = { - config: { - tiers: [0, 0, 0, 0, 0].map((v) => v * MIN_IOTA_AMOUNT), - tokenTradingFeeDiscountPercentage: [0, 0, 0, 0, 0], - }, - }; - await soonProjDocRef.set(soonProject, true); +export const tokenProcessed = (tokenId: string, distributionLength: number, reconciled: boolean) => + wait(async () => { + const doc = await build5Db().doc(COL.TOKEN, tokenId).get(); + const distributionsSnap = await build5Db() + .collection(COL.TOKEN, tokenId, SUB_COL.DISTRIBUTION) + .get(); + const distributionsOk = distributionsSnap.reduce( + (acc, doc) => acc && (doc?.reconciled || false) === reconciled, + distributionLength === distributionsSnap.length, + ); + if (doc?.status === TokenStatus.ERROR) { + throw new Error('Token not processed: ' + tokenId); + } + return distributionsOk && doc?.status === TokenStatus.PRE_MINTED; + }); +const isProdSpy = jest.spyOn(config, 'isProdEnv'); +const blockedCountriesSpy = jest.spyOn(ipUtils, 'getBlockedCountries'); +const ipInfoMock = jest.spyOn(ipUtils, 'getIpInfo'); +export const mockIpCheck = ( + isProdEnv: boolean, + blockedCountries: { [key: string]: string[] }, + ipInfo: any, +) => { + isProdSpy.mockReturnValueOnce(isProdEnv); + blockedCountriesSpy.mockReturnValueOnce(blockedCountries); + ipInfoMock.mockReturnValueOnce(ipInfo); }; diff --git a/packages/functions/test/controls/member.spec.ts b/packages/functions/test/controls/member.spec.ts index 0230cf533e..50cc78a9a2 100644 --- a/packages/functions/test/controls/member.spec.ts +++ b/packages/functions/test/controls/member.spec.ts @@ -1,6 +1,7 @@ -import { build5Db } from '@build-5/database'; +import { PgNftAvailable, PgNftStatus, build5Db } from '@build-5/database'; import { COL, + Member, Nft, NftAvailable, NftStatus, @@ -8,101 +9,86 @@ import { 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'; -import { expectThrow, mockWalletReturnValue } from './common'; +import { getRandomEthAddress } from '../../src/utils/wallet.utils'; +import { MEDIA, mockWalletReturnValue, testEnv } from '../set-up'; +import { expectThrow } from './common'; -let walletSpy: any; - -describe('MemberController: ' + WEN_FUNC.createMember, () => { +describe('Member control - create', () => { it('successfully create member', async () => { - const dummyAddress = wallet.getRandomEthAddress(); - const member = await testEnv.wrap(createMember)({ address: dummyAddress }); - expect(member?.uid).toEqual(dummyAddress.toLowerCase()); + const uid = await testEnv.createMember(); + const memberDocRef = build5Db().doc(COL.MEMBER, uid); + const member = await memberDocRef.get(); + expect(member?.uid).toEqual(uid.toLowerCase()); expect(member?.createdOn).toBeDefined(); expect(member?.updatedOn).toBeDefined(); }); }); -describe('MemberController: ' + WEN_FUNC.updateMember, () => { - let dummyAddress: any; - let doc: any; - +describe('Member control - update', () => { + let member: string; beforeEach(async () => { - dummyAddress = wallet.getRandomEthAddress(); - walletSpy = jest.spyOn(wallet, 'decodeAuth'); - mockWalletReturnValue(walletSpy, dummyAddress, {}); - doc = await testEnv.wrap(createMember)({ address: dummyAddress }); - expect(doc?.uid).toEqual(dummyAddress.toLowerCase()); + member = await testEnv.createMember(); }); it('successfully update member', async () => { const updateParams = { - name: wallet.getRandomEthAddress(), + name: getRandomEthAddress(), about: 'He rocks', discord: 'adamkun#1233', twitter: 'asdasd', github: 'asdasda', }; - mockWalletReturnValue(walletSpy, dummyAddress, updateParams); - const uMember: any = await testEnv.wrap(updateMember)({}); - expect(uMember?.name).toEqual(updateParams.name); - expect(uMember?.about).toEqual('He rocks'); - expect(uMember?.discord).toEqual(updateParams.discord); - expect(uMember?.twitter).toEqual(updateParams.twitter); - expect(uMember?.github).toEqual(updateParams.github); - walletSpy.mockRestore(); + mockWalletReturnValue(member, updateParams); + const updated = await testEnv.wrap(WEN_FUNC.updateMember); + expect(updated.name).toEqual(updateParams.name); + expect(updated.about).toEqual(updateParams.about); + expect(updated.discord).toEqual(updateParams.discord); + expect(updated.twitter).toEqual(updateParams.twitter); + expect(updated.github).toEqual(updateParams.github); }); it('fail to update member username exists already', async () => { const updateParams = { name: 'abcd' + Math.floor(Math.random() * 1000) }; - mockWalletReturnValue(walletSpy, dummyAddress, updateParams); - const uMember = await testEnv.wrap(updateMember)({}); - expect(uMember?.name).toEqual(updateParams.name); - - const dummyAddress2 = wallet.getRandomEthAddress(); - mockWalletReturnValue(walletSpy, dummyAddress2, {}); - const cMember = await testEnv.wrap(createMember)({ address: dummyAddress2 }); - expect(cMember?.uid).toEqual(dummyAddress2.toLowerCase()); - - mockWalletReturnValue(walletSpy, dummyAddress2, { name: updateParams.name }); - await expectThrow(testEnv.wrap(updateMember)({}), WenError.member_username_exists.key); + mockWalletReturnValue(member, updateParams); + const updated = await testEnv.wrap(WEN_FUNC.updateMember); + expect(updated.name).toEqual(updateParams.name); + const member2 = await testEnv.createMember(); + mockWalletReturnValue(member2, updateParams); + const call = testEnv.wrap(WEN_FUNC.updateMember); + await expectThrow(call, WenError.member_username_exists.key); }); it('unset discord', async () => { const updateParams = { discord: undefined }; - mockWalletReturnValue(walletSpy, dummyAddress, updateParams); - const uMember = await testEnv.wrap(updateMember)({}); - expect(uMember?.discord).toEqual(null); - walletSpy.mockRestore(); + mockWalletReturnValue(member, updateParams); + const updated = await testEnv.wrap(WEN_FUNC.updateMember); + expect(updated?.discord).toBe(''); }); it('Should set nft as avatar, then unset', async () => { const nft = { + name: 'mynft', + description: 'description', project: SOON_PROJECT_ID, - uid: wallet.getRandomEthAddress(), + uid: getRandomEthAddress(), media: MEDIA, - owner: dummyAddress, + owner: member, status: NftStatus.MINTED, available: NftAvailable.UNAVAILABLE, - }; - const nftDocRef = build5Db().doc(`${COL.NFT}/${nft.uid}`); + } as Nft; + const nftDocRef = build5Db().doc(COL.NFT, nft.uid); await nftDocRef.create(nft); const updateParams = { avatarNft: nft.uid }; - mockWalletReturnValue(walletSpy, dummyAddress, updateParams); - let uMember = await testEnv.wrap(updateMember)({}); - expect(uMember.avatarNft).toBe(nft.uid); - expect(uMember.avatar).toBe(MEDIA); - - let nftData = await nftDocRef.get(); + mockWalletReturnValue(member, updateParams); + let updated = await testEnv.wrap(WEN_FUNC.updateMember); + expect(updated.avatarNft).toBe(nft.uid); + expect(updated.avatar).toBe(MEDIA); + let nftData = await nftDocRef.get(); expect(nftData?.setAsAvatar).toBe(true); - - mockWalletReturnValue(walletSpy, dummyAddress, { avatarNft: undefined }); - uMember = await testEnv.wrap(updateMember)({}); - expect(uMember.avatarNft).toBeNull(); - expect(uMember.avatar).toBeNull(); - + mockWalletReturnValue(member, { avatarNft: undefined }); + updated = await testEnv.wrap(WEN_FUNC.updateMember); + expect(updated.avatarNft).toBe(''); + expect(updated.avatar).toBe(''); nftData = await nftDocRef.get(); expect(nftData?.setAsAvatar).toBe(false); }); @@ -110,41 +96,39 @@ describe('MemberController: ' + WEN_FUNC.updateMember, () => { it('Should set nft as avatar, when available field is missing', async () => { const nft = { project: SOON_PROJECT_ID, - uid: wallet.getRandomEthAddress(), + uid: getRandomEthAddress(), media: MEDIA, - owner: dummyAddress, + owner: member, status: NftStatus.MINTED, - }; - const nftDocRef = build5Db().doc(`${COL.NFT}/${nft.uid}`); + } as Nft; + const nftDocRef = build5Db().doc(COL.NFT, nft.uid); await nftDocRef.create(nft); const updateParams = { avatarNft: nft.uid }; - mockWalletReturnValue(walletSpy, dummyAddress, updateParams); - let uMember = await testEnv.wrap(updateMember)({}); - expect(uMember.avatarNft).toBe(nft.uid); - expect(uMember.avatar).toBe(MEDIA); + mockWalletReturnValue(member, updateParams); + const updated = await testEnv.wrap(WEN_FUNC.updateMember); + expect(updated.avatarNft).toBe(nft.uid); + expect(updated.avatar).toBe(MEDIA); }); it('Should throw, invalid nft not nft owner', async () => { - mockWalletReturnValue(walletSpy, dummyAddress, { avatarNft: wallet.getRandomEthAddress() }); - await expectThrow(testEnv.wrap(updateMember)({}), WenError.nft_does_not_exists.key); - - const nft = { - project: SOON_PROJECT_ID, - uid: wallet.getRandomEthAddress(), - media: MEDIA, - }; - const nftDocRef = build5Db().doc(`${COL.NFT}/${nft.uid}`); - + mockWalletReturnValue(member, { + avatarNft: getRandomEthAddress(), + }); + let call = testEnv.wrap(WEN_FUNC.updateMember); + await expectThrow(call, WenError.nft_does_not_exists.key); + const nft = { project: SOON_PROJECT_ID, uid: getRandomEthAddress(), media: MEDIA } as Nft; + const nftDocRef = build5Db().doc(COL.NFT, nft.uid); await nftDocRef.create(nft); - mockWalletReturnValue(walletSpy, dummyAddress, { avatarNft: nft.uid }); - await expectThrow(testEnv.wrap(updateMember)({}), WenError.you_must_be_the_owner_of_nft.key); - - await nftDocRef.update({ status: NftStatus.WITHDRAWN, owner: dummyAddress }); - mockWalletReturnValue(walletSpy, dummyAddress, { avatarNft: nft.uid }); - await expectThrow(testEnv.wrap(updateMember)({}), WenError.nft_not_minted.key); - - await nftDocRef.update({ status: NftStatus.MINTED, available: NftAvailable.AUCTION }); - mockWalletReturnValue(walletSpy, dummyAddress, { avatarNft: nft.uid }); - await expectThrow(testEnv.wrap(updateMember)({}), WenError.nft_on_sale.key); + mockWalletReturnValue(member, { avatarNft: nft.uid }); + call = testEnv.wrap(WEN_FUNC.updateMember); + await expectThrow(call, WenError.you_must_be_the_owner_of_nft.key); + await nftDocRef.update({ status: PgNftStatus.WITHDRAWN, owner: member }); + mockWalletReturnValue(member, { avatarNft: nft.uid }); + call = testEnv.wrap(WEN_FUNC.updateMember); + await expectThrow(call, WenError.nft_not_minted.key); + await nftDocRef.update({ status: PgNftStatus.MINTED, available: PgNftAvailable.AUCTION }); + mockWalletReturnValue(member, { avatarNft: nft.uid }); + call = testEnv.wrap(WEN_FUNC.updateMember); + await expectThrow(call, WenError.nft_on_sale.key); }); }); diff --git a/packages/functions/test/controls/nft.spec.ts b/packages/functions/test/controls/nft.spec.ts index d76d4c4651..63434a7b97 100644 --- a/packages/functions/test/controls/nft.spec.ts +++ b/packages/functions/test/controls/nft.spec.ts @@ -15,31 +15,25 @@ import { WenError, } from '@build-5/interfaces'; import dayjs from 'dayjs'; -import { createCollection } from '../../src/runtime/firebase/collection/index'; import * as wallet from '../../src/utils/wallet.utils'; -import { MEDIA, testEnv } from '../set-up'; -import { createBatchNft, createNft, updateUnsoldNft } from './../../src/runtime/firebase/nft/index'; -import { createMember, createSpace, expectThrow, mockWalletReturnValue } from './common'; - -let walletSpy: any; +import { MEDIA, mockWalletReturnValue, testEnv } from '../set-up'; +import { expectThrow } from './common'; describe('Nft controll: ' + WEN_FUNC.createCollection, () => { let space: Space; let collection: Collection; let member: string; - beforeEach(async () => { - walletSpy = jest.spyOn(wallet, 'decodeAuth'); - member = await createMember(walletSpy); - space = await createSpace(walletSpy, member); - mockWalletReturnValue(walletSpy, member, dummyCollection(space)); - collection = await testEnv.wrap(createCollection)({}); + member = await testEnv.createMember(); + space = await testEnv.createSpace(member); + mockWalletReturnValue(member, dummyCollection(space)); + collection = await testEnv.wrap(WEN_FUNC.createCollection); }); it('successfully create NFT', async () => { const nft = { media: MEDIA, ...dummyNft(collection.uid) }; - mockWalletReturnValue(walletSpy, member, nft); - const cNft = await testEnv.wrap(createNft)({}); + mockWalletReturnValue(member, nft); + const cNft = await testEnv.wrap(WEN_FUNC.createNft); expect(cNft?.createdOn).toBeDefined(); expect(cNft?.updatedOn).toBeDefined(); expect(cNft?.status).toBe(NftStatus.PRE_MINTED); @@ -47,66 +41,62 @@ describe('Nft controll: ' + WEN_FUNC.createCollection, () => { it('successfully create NFT with sale access', async () => { const nft = dummyNft(collection.uid, '', [member]); - mockWalletReturnValue(walletSpy, member, nft); - const cNft = await testEnv.wrap(createNft)({}); - + mockWalletReturnValue(member, nft); + const cNft = await testEnv.wrap(WEN_FUNC.createNft); expect(cNft?.saleAccessMembers).toEqual([member]); expect(cNft?.saleAccess).toBe(NftAccess.MEMBERS); expect(cNft?.status).toBe(NftStatus.PRE_MINTED); - const nfts = [ dummyNft(collection.uid, '', [member]), dummyNft(collection.uid, '', [member]), dummyNft(collection.uid), ]; - mockWalletReturnValue(walletSpy, member, nfts); - const cBatchNft = await testEnv.wrap(createBatchNft)({}); + mockWalletReturnValue(member, nfts); + const cBatchNft = await testEnv.wrap(WEN_FUNC.createBatchNft); expect(cBatchNft?.length).toBe(3); - for (let i = 0; i < nfts.length; ++i) { - const docRef = build5Db().doc(`${COL.NFT}/${cBatchNft[i]}`); + const docRef = build5Db().doc(COL.NFT, cBatchNft[i]); const nft = await docRef.get(); expect(nft.saleAccessMembers).toEqual(i === nfts.length - 1 ? [] : [member]); } }); it('successfully create NFT', async () => { - let nft = { media: 'asd', ...dummyNft(collection.uid) }; - mockWalletReturnValue(walletSpy, member, nft); - await expectThrow(testEnv.wrap(createNft)({}), WenError.invalid_params.key); - + let nft = { media: 'some-media-url', ...dummyNft(collection.uid) }; + mockWalletReturnValue(member, nft); + await expectThrow(testEnv.wrap(WEN_FUNC.createNft), WenError.invalid_params.key); nft = { - media: `https://firebasestorage.googleapis.com/v0/b/${Bucket.DEV}/o/`, + media: `https://storage.googleapis.com/download/storage/v1/b/${Bucket.DEV}/o`, ...dummyNft(collection.uid), }; - mockWalletReturnValue(walletSpy, member, nft); - await expectThrow(testEnv.wrap(createNft)({}), WenError.invalid_params.key); + mockWalletReturnValue(member, nft); + await expectThrow(testEnv.wrap(WEN_FUNC.createNft), WenError.invalid_params.key); }); it('successfully batch create 2 NFT', async () => { - mockWalletReturnValue(walletSpy, member, [ - dummyNft(collection.uid), - dummyNft(collection.uid, 'babbssa'), - ]); - const cBatchNft = await testEnv.wrap(createBatchNft)({}); + mockWalletReturnValue(member, [dummyNft(collection.uid), dummyNft(collection.uid, 'babbssa')]); + const cBatchNft = await testEnv.wrap(WEN_FUNC.createBatchNft); expect(cBatchNft?.length).toBe(2); }); it('successfully create NFT to high buy price', async () => { const nft = { ...dummyNft(collection.uid), price: 1000 * 1000 * 1000 * 1000 * 1000 }; - mockWalletReturnValue(walletSpy, member, nft); - await expectThrow(testEnv.wrap(createNft)({}), WenError.invalid_params.key); + mockWalletReturnValue(member, nft); + await expectThrow(testEnv.wrap(WEN_FUNC.createNft), WenError.invalid_params.key); }); it('successfully create NFT to high buy price - wrong collection', async () => { const nft = { ...dummyNft(collection.uid), collection: wallet.getRandomEthAddress() }; - mockWalletReturnValue(walletSpy, member, nft); - await expectThrow(testEnv.wrap(createNft)({}), WenError.collection_does_not_exists.key); + mockWalletReturnValue(member, nft); + await expectThrow( + testEnv.wrap(WEN_FUNC.createNft), + WenError.collection_does_not_exists.key, + ); }); it('successfully create NFT - validate space/type', async () => { - mockWalletReturnValue(walletSpy, member, dummyNft(collection.uid)); - const cNft = await testEnv.wrap(createNft)({}); + mockWalletReturnValue(member, dummyNft(collection.uid)); + const cNft = await testEnv.wrap(WEN_FUNC.createNft); expect(cNft?.createdOn).toBeDefined(); expect(cNft?.updatedOn).toBeDefined(); expect(cNft?.space).toBe(space.uid); @@ -119,49 +109,51 @@ describe('Nft controll: ' + WEN_FUNC.updateUnsoldNft, () => { let space: Space; let collection: Collection; let member: string; - beforeEach(async () => { - walletSpy = jest.spyOn(wallet, 'decodeAuth'); - member = await createMember(walletSpy); - space = await createSpace(walletSpy, member); - mockWalletReturnValue(walletSpy, member, dummyCollection(space)); - collection = await testEnv.wrap(createCollection)({}); + member = await testEnv.createMember(); + space = await testEnv.createSpace(member); + mockWalletReturnValue(member, dummyCollection(space)); + collection = await testEnv.wrap(WEN_FUNC.createCollection); }); it('Should update unsold nft price', async () => { - mockWalletReturnValue(walletSpy, member, { media: MEDIA, ...dummyNft(collection.uid) }); - let nft = await testEnv.wrap(createNft)({}); + mockWalletReturnValue(member, { media: MEDIA, ...dummyNft(collection.uid) }); + let nft = await testEnv.wrap(WEN_FUNC.createNft); expect(nft.price).toBe(10 * MIN_IOTA_AMOUNT); - mockWalletReturnValue(walletSpy, member, { uid: nft.uid, price: 50 * MIN_IOTA_AMOUNT }); - nft = await testEnv.wrap(updateUnsoldNft)({}); + mockWalletReturnValue(member, { uid: nft.uid, price: 50 * MIN_IOTA_AMOUNT }); + nft = await testEnv.wrap(WEN_FUNC.updateUnsoldNft); expect(nft.price).toBe(50 * MIN_IOTA_AMOUNT); }); it('Should throw, nft can not be updated', async () => { - mockWalletReturnValue(walletSpy, member, { media: MEDIA, ...dummyNft(collection.uid) }); - let nft = await testEnv.wrap(createNft)({}); + mockWalletReturnValue(member, { media: MEDIA, ...dummyNft(collection.uid) }); + let nft = await testEnv.wrap(WEN_FUNC.createNft); expect(nft.price).toBe(10 * MIN_IOTA_AMOUNT); - mockWalletReturnValue(walletSpy, member, { uid: nft.uid, price: 50 * MIN_IOTA_AMOUNT }); - - await build5Db().doc(`${COL.NFT}/${nft.uid}`).update({ sold: true }); - await expectThrow(testEnv.wrap(updateUnsoldNft)({}), WenError.nft_already_sold.key); + await build5Db().doc(COL.NFT, nft.uid).update({ sold: true }); + mockWalletReturnValue(member, { + uid: nft.uid, + price: 50 * MIN_IOTA_AMOUNT, + }); + await expectThrow(testEnv.wrap(WEN_FUNC.updateUnsoldNft), WenError.nft_already_sold.key); - await build5Db().doc(`${COL.NFT}/${nft.uid}`).update({ hidden: true, sold: false }); - await expectThrow(testEnv.wrap(updateUnsoldNft)({}), WenError.hidden_nft.key); + await build5Db().doc(COL.NFT, nft.uid).update({ hidden: true, sold: false }); + mockWalletReturnValue(member, { uid: nft.uid, price: 50 * MIN_IOTA_AMOUNT }); + await expectThrow(testEnv.wrap(WEN_FUNC.updateUnsoldNft), WenError.hidden_nft.key); - await build5Db().doc(`${COL.NFT}/${nft.uid}`).update({ placeholderNft: true, hidden: false }); + await build5Db().doc(COL.NFT, nft.uid).update({ placeholderNft: true, hidden: false }); + mockWalletReturnValue(member, { uid: nft.uid, price: 50 * MIN_IOTA_AMOUNT }); await expectThrow( - testEnv.wrap(updateUnsoldNft)({}), + testEnv.wrap(WEN_FUNC.updateUnsoldNft), WenError.nft_placeholder_cant_be_updated.key, ); - await build5Db().doc(`${COL.NFT}/${nft.uid}`).update({ placeholderNft: false }); + await build5Db().doc(COL.NFT, nft.uid).update({ placeholderNft: false }); - const tmpMember = await createMember(walletSpy); - mockWalletReturnValue(walletSpy, tmpMember, { uid: nft.uid, price: 50 * MIN_IOTA_AMOUNT }); + const tmpMember = await testEnv.createMember(); + mockWalletReturnValue(tmpMember, { uid: nft.uid, price: 50 * MIN_IOTA_AMOUNT }); await expectThrow( - testEnv.wrap(updateUnsoldNft)({}), + testEnv.wrap(WEN_FUNC.updateUnsoldNft), WenError.you_are_not_guardian_of_space.key, ); }); @@ -189,6 +181,4 @@ const dummyNft = (collection: string, description = 'babba', saleAccessMembers: price: 10 * 1000 * 1000, saleAccessMembers, }); - -// TODO test invalid royalty amount -// TODO add set new price once owned. +// TODO test invalid royalty amount// TODO add set new price once owned. diff --git a/packages/functions/test/controls/nft/Helper.ts b/packages/functions/test/controls/nft/Helper.ts index b6de746c2f..6799469f6e 100644 --- a/packages/functions/test/controls/nft/Helper.ts +++ b/packages/functions/test/controls/nft/Helper.ts @@ -9,39 +9,26 @@ import { Nft, NftAccess, Space, + Transaction, + WEN_FUNC, } from '@build-5/interfaces'; import dayjs from 'dayjs'; -import { createCollection } from '../../../src/runtime/firebase/collection'; -import { createNft, openBid, orderNft } from '../../../src/runtime/firebase/nft'; -import * as wallet from '../../../src/utils/wallet.utils'; -import { MEDIA, testEnv } from '../../set-up'; -import { - createMember, - createSpace, - mockWalletReturnValue, - submitMilestoneFunc, - wait, -} from '../common'; +import { MEDIA, mockWalletReturnValue, testEnv } from '../../set-up'; +import { submitMilestoneFunc, wait } from '../common'; export class Helper { - public spy: any = {} as any; public member: string = {} as any; public members: string[] = []; public space: Space = {} as any; public collection: Collection = {} as any; public nft: Nft = {} as any; - public beforeAll = async () => { - this.spy = jest.spyOn(wallet, 'decodeAuth'); - }; - public beforeEach = async () => { - this.member = await createMember(this.spy); - const memberPromises = Array.from(Array(3)).map(() => createMember(this.spy)); + this.member = await testEnv.createMember(); + const memberPromises = Array.from(Array(3)).map(() => testEnv.createMember()); this.members = await Promise.all(memberPromises); - this.space = await createSpace(this.spy, this.member); - - mockWalletReturnValue(this.spy, this.member, { + this.space = await testEnv.createSpace(this.member); + const dummyCol = { name: 'Collection A', description: 'babba', type: CollectionType.CLASSIC, @@ -53,44 +40,41 @@ export class Helper { onePerMemberOnly: false, availableFrom: dayjs().toDate(), price: 10 * 1000 * 1000, - }); - - this.collection = await testEnv.wrap(createCollection)({}); - await build5Db().doc(`${COL.COLLECTION}/${this.collection.uid}`).update({ approved: true }); + }; + mockWalletReturnValue(this.member, dummyCol); + this.collection = await testEnv.wrap(WEN_FUNC.createCollection); + await build5Db().doc(COL.COLLECTION, this.collection.uid).update({ approved: true }); this.nft = await this.createNft(); - - const collectionDocRef = build5Db().doc(`${COL.COLLECTION}/${this.collection.uid}`); + const collectionDocRef = build5Db().doc(COL.COLLECTION, this.collection.uid); await wait(async () => { this.collection = await collectionDocRef.get(); return this.collection.availableNfts === 1; }); - await this.orderNft(this.nft.uid); - await wait(async () => { this.collection = await collectionDocRef.get(); return this.collection.availableNfts === 0; }); }; - public createNft = async () => { - mockWalletReturnValue(this.spy, this.member, { + public createNft = () => { + mockWalletReturnValue(this.member, { media: MEDIA, ...dummyNft(this.collection.uid), }); - return (await testEnv.wrap(createNft)({})) as Nft; + return testEnv.wrap(WEN_FUNC.createNft); }; public orderNft = async (nft: string) => { - mockWalletReturnValue(this.spy, this.member, { collection: this.collection.uid, nft }); - const nftOrder = await testEnv.wrap(orderNft)({}); + mockWalletReturnValue(this.member, { collection: this.collection.uid, nft }); + const nftOrder = await testEnv.wrap(WEN_FUNC.orderNft); await submitMilestoneFunc(nftOrder); }; public bidNft = async (memberId: string, amount: number) => { - mockWalletReturnValue(this.spy, memberId, { nft: this.nft.uid }); - const bidOrder = await testEnv.wrap(openBid)({}); + mockWalletReturnValue(memberId, { nft: this.nft.uid }); + const bidOrder = await testEnv.wrap(WEN_FUNC.openBid); await submitMilestoneFunc(bidOrder, amount); return bidOrder; }; diff --git a/packages/functions/test/controls/nft/nft.bidding.extends.spec.ts b/packages/functions/test/controls/nft/nft.bidding.extends.spec.ts index 3d09652fcc..5f73dcc9ed 100644 --- a/packages/functions/test/controls/nft/nft.bidding.extends.spec.ts +++ b/packages/functions/test/controls/nft/nft.bidding.extends.spec.ts @@ -1,22 +1,16 @@ -import { IDocument, build5Db } from '@build-5/database'; -import { Auction, COL, MIN_IOTA_AMOUNT, Nft, WenError } from '@build-5/interfaces'; +import { IDocument, PgNft, PgNftUpdate, build5Db } from '@build-5/database'; +import { Auction, COL, MIN_IOTA_AMOUNT, Nft, WEN_FUNC, WenError } from '@build-5/interfaces'; import dayjs from 'dayjs'; import { set } from 'lodash'; -import { setForSaleNft } from '../../../src/runtime/firebase/nft'; import { dateToTimestamp } from '../../../src/utils/dateTime.utils'; -import { testEnv } from '../../set-up'; -import { expectThrow, mockWalletReturnValue, wait } from '../common'; +import { mockWalletReturnValue, testEnv } from '../../set-up'; +import { expectThrow, wait } from '../common'; import { Helper, dummyAuctionData } from './Helper'; describe('Nft bidding with extended auction', () => { const h = new Helper(); - let now: dayjs.Dayjs; - let nftDocRef: IDocument; - - beforeAll(async () => { - await h.beforeAll(); - }); + let nftDocRef: IDocument; beforeEach(async () => { await h.beforeEach(); @@ -29,10 +23,9 @@ describe('Nft bidding with extended auction', () => { extendedAuctionLength: 60000 * 10, }; extendAuctionWithin && set(auctionData, 'extendAuctionWithin', extendAuctionWithin); - mockWalletReturnValue(h.spy, h.member, auctionData); - await testEnv.wrap(setForSaleNft)({}); - - nftDocRef = build5Db().doc(`${COL.NFT}/${h.nft.uid}`); + mockWalletReturnValue(h.member, auctionData); + await testEnv.wrap(WEN_FUNC.setForSaleNft); + nftDocRef = build5Db().doc(COL.NFT, h.nft.uid); await wait(async () => { h.nft = await nftDocRef.get(); return h.nft.available === 3; @@ -41,32 +34,27 @@ describe('Nft bidding with extended auction', () => { it('Should bid and auction date to extended date', async () => { await setForSale(); - expect(h.nft.auctionLength).toBe(60000 * 4); let auctionToDate = dayjs(h.nft.auctionTo?.toDate()); const expectedAuctionToDate = dayjs(dateToTimestamp(now, true).toDate()).add( h.nft.auctionLength!, ); expect(auctionToDate.isSame(expectedAuctionToDate)).toBe(true); - let auctionExtendedDate = dayjs(h.nft.extendedAuctionTo?.toDate()); const expectedAuctionExtendedToDate = dayjs(dateToTimestamp(now, true).toDate()).add( h.nft.extendedAuctionLength!, ); expect(auctionExtendedDate.isSame(expectedAuctionExtendedToDate)).toBe(true); expect(h.nft.extendedAuctionLength).toBe(60000 * 10); - await h.bidNft(h.members[0], MIN_IOTA_AMOUNT); - h.nft = await build5Db().doc(`${COL.NFT}/${h.nft.uid}`).get(); + h.nft = await build5Db().doc(COL.NFT, h.nft.uid).get(); expect(h.nft.auctionHighestBidder).toBe(h.members[0]); - h.nft = await nftDocRef.get(); auctionToDate = dayjs(h.nft.auctionTo?.toDate()); auctionExtendedDate = dayjs(h.nft.extendedAuctionTo?.toDate()); expect(auctionToDate.isSame(expectedAuctionExtendedToDate)).toBe(true); expect(h.nft.auctionLength).toBe(h.nft.extendedAuctionLength); - - const auctionDocRef = build5Db().doc(`${COL.AUCTION}/${h.nft.auction}`); + const auctionDocRef = build5Db().doc(COL.AUCTION, h.nft.auction!); const auction = await auctionDocRef.get(); auctionToDate = dayjs(auction.auctionTo?.toDate()); auctionExtendedDate = dayjs(auction.extendedAuctionTo?.toDate()); @@ -77,29 +65,25 @@ describe('Nft bidding with extended auction', () => { it('Should bid but not set auction date to extended date', async () => { await setForSale(60000 * 6); h.nft = await nftDocRef.get(); - expect(h.nft.auctionLength).toBe(60000 * 6); let auctionToDate = dayjs(h.nft.auctionTo?.toDate()); const expectedAuctionToDate = dayjs(dateToTimestamp(now, true).toDate()).add( h.nft.auctionLength!, ); expect(auctionToDate.isSame(expectedAuctionToDate)).toBe(true); - let auctionExtendedDate = dayjs(h.nft.extendedAuctionTo?.toDate()); const expectedAuctionExtendedToDate = dayjs(dateToTimestamp(now, true).toDate()).add( h.nft.extendedAuctionLength!, ); expect(auctionExtendedDate.isSame(expectedAuctionExtendedToDate)).toBe(true); expect(h.nft.extendedAuctionLength).toBe(60000 * 10); - await h.bidNft(h.members[0], MIN_IOTA_AMOUNT); h.nft = await nftDocRef.get(); expect(h.nft.auctionHighestBidder).toBe(h.members[0]); auctionToDate = dayjs(h.nft.auctionTo?.toDate()); expect(auctionToDate.isSame(expectedAuctionToDate)).toBe(true); expect(h.nft.auctionLength).toBe(60000 * 6); - - const auctionDocRef = build5Db().doc(`${COL.AUCTION}/${h.nft.auction}`); + const auctionDocRef = build5Db().doc(COL.AUCTION, h.nft.auction!); const auction = await auctionDocRef.get(); auctionToDate = dayjs(auction.auctionTo?.toDate()); expect(auctionToDate.isSame(expectedAuctionToDate)).toBe(true); @@ -107,32 +91,26 @@ describe('Nft bidding with extended auction', () => { }); it('Should throw, extended auction lenght must be greater then auction lenght', async () => { - const auctionData = { - ...dummyAuctionData(h.nft.uid), - extendedAuctionLength: 60000 * 3, - }; - mockWalletReturnValue(h.spy, h.member, auctionData); - await expectThrow(testEnv.wrap(setForSaleNft)({}), WenError.invalid_params.key); + const auctionData = { ...dummyAuctionData(h.nft.uid), extendedAuctionLength: 60000 * 3 }; + mockWalletReturnValue(h.member, auctionData); + await expectThrow(testEnv.wrap(WEN_FUNC.setForSaleNft), WenError.invalid_params.key); }); it('Should bid but custom extend within time', async () => { await setForSale(60000 * 6, 60000 * 6); h.nft = await nftDocRef.get(); - expect(h.nft.auctionLength).toBe(60000 * 6); let auctionToDate = dayjs(h.nft.auctionTo?.toDate()); const expectedAuctionToDate = dayjs(dateToTimestamp(now, true).toDate()).add( h.nft.auctionLength!, ); expect(auctionToDate.isSame(expectedAuctionToDate)).toBe(true); - let auctionExtendedDate = dayjs(h.nft.extendedAuctionTo?.toDate()); const expectedAuctionExtendedToDate = dayjs(dateToTimestamp(now, true).toDate()).add( h.nft.extendedAuctionLength!, ); expect(auctionExtendedDate.isSame(expectedAuctionExtendedToDate)).toBe(true); expect(h.nft.extendedAuctionLength).toBe(60000 * 10); - await h.bidNft(h.members[0], MIN_IOTA_AMOUNT); h.nft = await nftDocRef.get(); expect(h.nft.auctionHighestBidder).toBe(h.members[0]); @@ -148,7 +126,7 @@ describe('Nft bidding with extended auction', () => { extendedAuctionLength: 60000 * 10, extendAuctionWithin: 0, }; - mockWalletReturnValue(h.spy, h.member, auctionData); - await expectThrow(testEnv.wrap(setForSaleNft)({}), WenError.invalid_params.key); + mockWalletReturnValue(h.member, auctionData); + await expectThrow(testEnv.wrap(WEN_FUNC.setForSaleNft), WenError.invalid_params.key); }); }); diff --git a/packages/functions/test/controls/nft/nft.bidding.finalize.spec.ts b/packages/functions/test/controls/nft/nft.bidding.finalize.spec.ts index 92110e94f5..9cc4dddd94 100644 --- a/packages/functions/test/controls/nft/nft.bidding.finalize.spec.ts +++ b/packages/functions/test/controls/nft/nft.bidding.finalize.spec.ts @@ -1,4 +1,4 @@ -import { build5Db } from '@build-5/database'; +import { PgNotificationType, PgTransactionType, build5Db } from '@build-5/database'; import { Auction, COL, @@ -6,31 +6,23 @@ import { MIN_IOTA_AMOUNT, Nft, NftAvailable, - NotificationType, - Transaction, - TransactionType, + WEN_FUNC, } from '@build-5/interfaces'; import dayjs from 'dayjs'; import { finalizeAuctions } from '../../../src/cron/auction.cron'; -import { setForSaleNft } from '../../../src/runtime/firebase/nft'; -import { dateToTimestamp } from '../../../src/utils/dateTime.utils'; -import { testEnv } from '../../set-up'; -import { mockWalletReturnValue, wait } from '../common'; +import { mockWalletReturnValue, testEnv } from '../../set-up'; +import { wait } from '../common'; import { Helper, dummyAuctionData } from './Helper'; describe('Should finalize bidding', () => { const h = new Helper(); - beforeAll(async () => { - await h.beforeAll(); - }); - beforeEach(async () => { await h.beforeEach(); - mockWalletReturnValue(h.spy, h.member, dummyAuctionData(h.nft.uid)); - await testEnv.wrap(setForSaleNft)({}); + mockWalletReturnValue(h.member, dummyAuctionData(h.nft.uid)); + await testEnv.wrap(WEN_FUNC.setForSaleNft); await wait(async () => { - const docRef = build5Db().doc(`${COL.NFT}/${h.nft.uid}`); + const docRef = build5Db().doc(COL.NFT, h.nft.uid); h.nft = await docRef.get(); return h.nft.available === 3; }); @@ -39,84 +31,73 @@ describe('Should finalize bidding', () => { it.each([true, false])('Should bid and finalize it', async (noRoyaltySpace: boolean) => { if (noRoyaltySpace) { await build5Db() - .doc(`${COL.COLLECTION}/${h.collection.uid}`) + .doc(COL.COLLECTION, h.collection.uid) .update({ royaltiesSpace: '', royaltiesFee: 0 }); } const bidOrder = await h.bidNft(h.members[0], MIN_IOTA_AMOUNT); - expect(bidOrder.payload.restrictions.collection).toEqual({ + expect(bidOrder.payload.restrictions!.collection).toEqual({ access: h.collection.access, accessAwards: h.collection.accessAwards || [], accessCollections: h.collection.accessCollections || [], }); - expect(bidOrder.payload.restrictions.nft).toEqual({ - saleAccess: h.nft.saleAccess || null, + expect(bidOrder.payload.restrictions!.nft).toEqual({ + saleAccess: h.nft.saleAccess || undefined, saleAccessMembers: h.nft.saleAccessMembers || [], }); - - const nftDocRef = build5Db().doc(`${COL.NFT}/${h.nft.uid}`); + const nftDocRef = build5Db().doc(COL.NFT, h.nft.uid); h.nft = await nftDocRef.get(); expect(h.nft.auctionHighestBidder).toBe(h.members[0]); - - const collectionDocRef = build5Db().doc(`${COL.COLLECTION}/${h.nft.collection}`); + const collectionDocRef = build5Db().doc(COL.COLLECTION, h.nft.collection); h.collection = await collectionDocRef.get(); expect(h.collection.nftsOnAuction).toBe(1); - - const auctionDocRef = build5Db().doc(`${COL.AUCTION}/${h.nft.auction}`); - await auctionDocRef.update({ auctionTo: dateToTimestamp(dayjs().subtract(1, 'minute')) }); - + const auctionDocRef = build5Db().doc(COL.AUCTION, h.nft.auction!); + await auctionDocRef.update({ auctionTo: dayjs().subtract(1, 'minute').toDate() }); await finalizeAuctions(); - await wait(async () => { h.nft = await nftDocRef.get(); return h.nft.available === NftAvailable.UNAVAILABLE; }); expect(h.nft.owner).toBe(h.members[0]); - expect(h.nft.auctionFrom).toBeNull(); - expect(h.nft.auctionTo).toBeNull(); - expect(h.nft.auction).toBeNull(); - + expect(h.nft.auctionFrom).toBeUndefined(); + expect(h.nft.auctionTo).toBeUndefined(); + expect(h.nft.auction).toBeUndefined(); const snap = await build5Db() .collection(COL.NOTIFICATION) .where('member', '==', h.members[0]) - .where('type', '==', NotificationType.WIN_BID) + .where('type', '==', PgNotificationType.WIN_BID) .get(); expect(snap.length).toBe(1); - h.collection = await collectionDocRef.get(); expect(h.collection.nftsOnAuction).toBe(0); expect(h.collection.lastTradedOn).toBeDefined(); expect(h.collection.totalTrades).toBe(2); - h.nft = await nftDocRef.get(); expect(h.nft.lastTradedOn).toBeDefined(); expect(h.nft.totalTrades).toBe(2); - const billPayments = await build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.BILL_PAYMENT) - .where('payload.nft', '==', h.nft.uid) - .get(); + .where('type', '==', PgTransactionType.BILL_PAYMENT) + .where('payload_nft', '==', h.nft.uid) + .get(); for (const billPayment of billPayments) { expect(billPayment.payload.restrictions).toEqual(bidOrder.payload.restrictions); } - const auction = await auctionDocRef.get(); expect(auction.active).toBe(false); }); it('Should finalize it, no bids', async () => { - const auctionDocRef = build5Db().doc(`${COL.AUCTION}/${h.nft.auction}`); - await auctionDocRef.update({ auctionTo: dateToTimestamp(dayjs().subtract(1, 'minute')) }); + const auctionDocRef = build5Db().doc(COL.AUCTION, h.nft.auction!); + await auctionDocRef.update({ auctionTo: dayjs().subtract(1, 'minute').toDate() }); await finalizeAuctions(); - - const nftDocRef = build5Db().doc(`${COL.NFT}/${h.nft.uid}`); + const nftDocRef = build5Db().doc(COL.NFT, h.nft.uid); await wait(async () => { h.nft = await nftDocRef.get(); return h.nft.available === NftAvailable.SALE; }); expect(h.nft.owner).toBe(h.member); - expect(h.nft.auctionFrom).toBeNull(); - expect(h.nft.auctionTo).toBeNull(); - expect(h.nft.auction).toBeNull(); + expect(h.nft.auctionFrom).toBeUndefined(); + expect(h.nft.auctionTo).toBeUndefined(); + expect(h.nft.auction).toBeUndefined(); }); }); diff --git a/packages/functions/test/controls/nft/nft.bidding.spec.ts b/packages/functions/test/controls/nft/nft.bidding.spec.ts index 6e0411cbd6..3bc9272bdd 100644 --- a/packages/functions/test/controls/nft/nft.bidding.spec.ts +++ b/packages/functions/test/controls/nft/nft.bidding.spec.ts @@ -1,4 +1,4 @@ -import { build5Db } from '@build-5/database'; +import { PgTransactionPayloadType, PgTransactionType, build5Db } from '@build-5/database'; import { Auction, COL, @@ -6,28 +6,21 @@ import { MIN_IOTA_AMOUNT, Nft, Transaction, - TransactionPayloadType, - TransactionType, TransactionValidationType, + WEN_FUNC, } from '@build-5/interfaces'; -import { orderNft, setForSaleNft } from '../../../src/runtime/firebase/nft'; -import { testEnv } from '../../set-up'; -import { mockWalletReturnValue, submitMilestoneFunc, wait } from '../common'; +import { mockWalletReturnValue, testEnv } from '../../set-up'; +import { submitMilestoneFunc, wait } from '../common'; import { Helper, dummyAuctionData } from './Helper'; describe('Nft bidding', () => { const h = new Helper(); - - beforeAll(async () => { - await h.beforeAll(); - }); - beforeEach(async () => { await h.beforeEach(); - mockWalletReturnValue(h.spy, h.member, dummyAuctionData(h.nft.uid)); - await testEnv.wrap(setForSaleNft)({}); + mockWalletReturnValue(h.member, dummyAuctionData(h.nft.uid)); + await testEnv.wrap(WEN_FUNC.setForSaleNft); await wait(async () => { - const docRef = build5Db().doc(`${COL.NFT}/${h.nft.uid}`); + const docRef = build5Db().doc(COL.NFT, h.nft.uid); h.nft = await docRef.get(); return h.nft.available === 3; }); @@ -37,8 +30,8 @@ describe('Nft bidding', () => { await h.bidNft(h.members[0], MIN_IOTA_AMOUNT); const snap = await build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.ORDER) - .where('payload.type', '==', TransactionPayloadType.NFT_BID) + .where('type', '==', PgTransactionType.ORDER) + .where('payload_type', '==', PgTransactionPayloadType.NFT_BID) .where('member', '==', h.members[0]) .get(); expect(snap.length).toBe(1); @@ -52,20 +45,17 @@ describe('Nft bidding', () => { expect(tran.payload.validationType).toBe(TransactionValidationType.ADDRESS); expect(tran.payload.nft).toBe(h.nft.uid); expect(tran.payload.collection).toBe(h.collection.uid); - - const nftDocRef = build5Db().doc(`${COL.NFT}/${h.nft.uid}`); + const nftDocRef = build5Db().doc(COL.NFT, h.nft.uid); h.nft = await nftDocRef.get(); expect(h.nft.lastTradedOn).toBeDefined(); expect(h.nft.totalTrades).toBe(1); expect(h.nft.auctionHighestBid).toBe(MIN_IOTA_AMOUNT); expect(h.nft.auctionHighestBidder).toBe(h.members[0]); - - const collectionDocRef = build5Db().doc(`${COL.COLLECTION}/${h.nft.collection}`); + const collectionDocRef = build5Db().doc(COL.COLLECTION, h.nft.collection); h.collection = await collectionDocRef.get(); expect(h.collection.lastTradedOn).toBeDefined(); expect(h.collection.totalTrades).toBe(1); - - const auctionDocRef = build5Db().doc(`${COL.AUCTION}/${h.nft.auction}`); + const auctionDocRef = build5Db().doc(COL.AUCTION, h.nft.auction!); const auction = await auctionDocRef.get(); expect(auction.bids.length).toBe(1); expect(auction.bids[0].amount).toBe(MIN_IOTA_AMOUNT); @@ -75,32 +65,29 @@ describe('Nft bidding', () => { it('Should override 2 bids for same user', async () => { await h.bidNft(h.members[0], MIN_IOTA_AMOUNT); await h.bidNft(h.members[0], 2 * MIN_IOTA_AMOUNT); - - const auctionDocRef = build5Db().doc(`${COL.AUCTION}/${h.nft.auction}`); + const auctionDocRef = build5Db().doc(COL.AUCTION, h.nft.auction!); const auction = await auctionDocRef.get(); expect(auction.bids.length).toBe(1); expect(auction.bids[0].amount).toBe(2 * MIN_IOTA_AMOUNT); expect(auction.bids[0].bidder).toBe(h.members[0]); - const orders = await build5Db() .collection(COL.TRANSACTION) .where('member', '==', h.members[0]) - .where('type', '==', TransactionType.ORDER) - .where('payload.type', '==', TransactionPayloadType.NFT_BID) - .get(); + .where('type', '==', PgTransactionType.ORDER) + .where('payload_type', '==', PgTransactionPayloadType.NFT_BID) + .get(); expect(orders.length).toBe(2); - const credits = await build5Db() .collection(COL.TRANSACTION) .where('member', '==', h.members[0]) - .where('type', '==', TransactionType.CREDIT) - .get(); + .where('type', '==', PgTransactionType.CREDIT) + .get(); expect(credits.length).toBe(1); expect(credits[0].payload.amount).toBe(MIN_IOTA_AMOUNT); }); it('Should overbid 2 bids, topup', async () => { - const auctionDocRef = build5Db().doc(`${COL.AUCTION}/${h.nft.auction}`); + const auctionDocRef = build5Db().doc(COL.AUCTION, h.nft.auction!); await auctionDocRef.update({ topUpBased: true }); await h.bidNft(h.members[0], MIN_IOTA_AMOUNT); @@ -112,12 +99,10 @@ describe('Nft bidding', () => { expect(auction.bids[0].bidder).toBe(h.members[0]); expect(auction.auctionHighestBid).toBe(2 * MIN_IOTA_AMOUNT); expect(auction.auctionHighestBidder).toBe(h.members[0]); - - const nftDocRef = build5Db().doc(`${COL.NFT}/${h.nft.uid}`); + const nftDocRef = build5Db().doc(COL.NFT, h.nft.uid); h.nft = await nftDocRef.get(); expect(h.nft.auctionHighestBid).toBe(2 * MIN_IOTA_AMOUNT); expect(h.nft.auctionHighestBidder).toBe(h.members[0]); - await h.bidNft(h.members[1], 3 * MIN_IOTA_AMOUNT); auction = await auctionDocRef.get(); expect(auction.bids.length).toBe(1); @@ -125,60 +110,53 @@ describe('Nft bidding', () => { expect(auction.bids[0].bidder).toBe(h.members[1]); expect(auction.auctionHighestBid).toBe(3 * MIN_IOTA_AMOUNT); expect(auction.auctionHighestBidder).toBe(h.members[1]); - h.nft = await nftDocRef.get(); expect(h.nft.auctionHighestBid).toBe(3 * MIN_IOTA_AMOUNT); expect(h.nft.auctionHighestBidder).toBe(h.members[1]); - const payments = await build5Db() .collection(COL.TRANSACTION) .where('member', '==', h.members[0]) - .where('type', '==', TransactionType.PAYMENT) - .get(); + .where('type', '==', PgTransactionType.PAYMENT) + .get(); for (const payment of payments) { expect(payment.payload.invalidPayment).toBe(true); const credit = await build5Db() .collection(COL.TRANSACTION) - .where('payload.sourceTransaction', 'array-contains', payment.uid) - .get(); + .where('payload_sourceTransaction', 'array-contains', payment.uid as any) + .get(); expect(credit).toBeDefined(); } }); it('Should reject smaller bid', async () => { - const nftDocRef = build5Db().doc(`${COL.NFT}/${h.nft.uid}`); + const nftDocRef = build5Db().doc(COL.NFT, h.nft.uid); await h.bidNft(h.members[0], 2 * MIN_IOTA_AMOUNT); h.nft = await nftDocRef.get(); expect(h.nft.auctionHighestBidder).toBe(h.members[0]); - await h.bidNft(h.members[1], MIN_IOTA_AMOUNT); h.nft = await nftDocRef.get(); expect(h.nft.auctionHighestBidder).toBe(h.members[0]); - const snap = await build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.CREDIT) + .where('type', '==', PgTransactionType.CREDIT) .where('member', '==', h.members[1]) - .where('payload.nft', '==', h.nft.uid) + .where('payload_nft', '==', h.nft.uid) .get(); expect(snap.length).toBe(1); }); it('Should reject bid where min inc is too small', async () => { - const nftDocRef = build5Db().doc(`${COL.NFT}/${h.nft.uid}`); + const nftDocRef = build5Db().doc(COL.NFT, h.nft.uid); await h.bidNft(h.members[0], MIN_IOTA_AMOUNT); - h.nft = await nftDocRef.get(); expect(h.nft.auctionHighestBidder).toBe(h.members[0]); - await h.bidNft(h.members[0], 1.5 * MIN_IOTA_AMOUNT); - const snap = await build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.CREDIT) + .where('type', '==', PgTransactionType.CREDIT) .where('member', '==', h.members[0]) - .where('payload.nft', '==', h.nft.uid) - .get(); + .where('payload_nft', '==', h.nft.uid) + .get(); expect(snap.length).toBe(1); expect(snap[0].payload.amount).toBe(1.5 * MIN_IOTA_AMOUNT); }); @@ -190,16 +168,14 @@ describe('Nft bidding', () => { h.bidNft(h.members[2], MIN_IOTA_AMOUNT), ]; await Promise.all(bidPromises); - - const nftDocRef = build5Db().doc(`${COL.NFT}/${h.nft.uid}`); + const nftDocRef = build5Db().doc(COL.NFT, h.nft.uid); h.nft = await nftDocRef.get(); expect(h.nft.auctionHighestBidder).toBe(h.members[1]); - const transactionSnap = await build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.CREDIT) - .where('member', 'in', [h.members[0], h.members[2]]) - .where('payload.nft', '==', h.nft.uid) + .where('type', '==', PgTransactionType.CREDIT) + .where('payload_nft', '==', h.nft.uid) + .whereIn('member', [h.members[0], h.members[2]]) .get(); expect(transactionSnap.length).toBe(2); }); @@ -207,20 +183,17 @@ describe('Nft bidding', () => { it('Should create bid, then credit on sold', async () => { await h.bidNft(h.members[0], MIN_IOTA_AMOUNT); await h.bidNft(h.members[0], MIN_IOTA_AMOUNT); - - mockWalletReturnValue(h.spy, h.members[1], { collection: h.nft.collection, nft: h.nft.uid }); - const nftOrder = await testEnv.wrap(orderNft)({}); + mockWalletReturnValue(h.members[1], { collection: h.nft.collection, nft: h.nft.uid }); + const nftOrder = await testEnv.wrap(WEN_FUNC.orderNft); await submitMilestoneFunc(nftOrder); - - const nftDocRef = build5Db().doc(`${COL.NFT}/${h.nft.uid}`); + const nftDocRef = build5Db().doc(COL.NFT, h.nft.uid); h.nft = await nftDocRef.get(); expect(h.nft.owner).toBe(h.members[1]); - const credits = await build5Db() .collection(COL.TRANSACTION) .where('member', '==', h.members[0]) - .where('type', '==', TransactionType.CREDIT) - .get(); + .where('type', '==', PgTransactionType.CREDIT) + .get(); expect(credits.length).toBe(2); }); }); diff --git a/packages/functions/test/controls/nft/nft.set.for.sale.spec.ts b/packages/functions/test/controls/nft/nft.set.for.sale.spec.ts index a8af4e8c80..202440bd30 100644 --- a/packages/functions/test/controls/nft/nft.set.for.sale.spec.ts +++ b/packages/functions/test/controls/nft/nft.set.for.sale.spec.ts @@ -1,27 +1,22 @@ import { build5Db } from '@build-5/database'; -import { COL, Collection, Nft, WenError } from '@build-5/interfaces'; -import { setForSaleNft } from '../../../src/runtime/firebase/nft'; +import { COL, Collection, Nft, WEN_FUNC, WenError } from '@build-5/interfaces'; import { getRandomEthAddress } from '../../../src/utils/wallet.utils'; -import { testEnv } from '../../set-up'; -import { expectThrow, mockWalletReturnValue, wait } from '../common'; +import { mockWalletReturnValue, testEnv } from '../../set-up'; +import { expectThrow, wait } from '../common'; import { Helper, dummyAuctionData, dummySaleData } from './Helper'; describe('Nft set for sale', () => { const h = new Helper(); - beforeAll(async () => { - await h.beforeAll(); - }); - beforeEach(async () => { await h.beforeEach(); }); it('Should set nft for sale', async () => { - mockWalletReturnValue(h.spy, h.member, dummySaleData(h.nft.uid)); - await testEnv.wrap(setForSaleNft)({}); + mockWalletReturnValue(h.member, dummySaleData(h.nft.uid)); + await testEnv.wrap(WEN_FUNC.setForSaleNft); - const nftDocRef = build5Db().doc(`${COL.NFT}/${h.nft.uid}`); + const nftDocRef = build5Db().doc(COL.NFT, h.nft.uid); await wait(async () => { const nft = await nftDocRef.get(); return nft.available === 1; @@ -31,59 +26,61 @@ describe('Nft set for sale', () => { expect(saleNft.available).toBe(1); expect(saleNft.availableFrom).toBeDefined(); - const collectionDocRef = build5Db().doc(`${COL.COLLECTION}/${saleNft.collection}`); + const collectionDocRef = build5Db().doc(COL.COLLECTION, saleNft.collection); const collection = await collectionDocRef.get(); expect(collection.nftsOnAuction).toBe(0); expect(collection.nftsOnSale).toBe(1); }); it('Should throw, nft set as avatar', async () => { - const nftDocRef = build5Db().doc(`${COL.NFT}/${h.nft.uid}`); + const nftDocRef = build5Db().doc(COL.NFT, h.nft.uid); await nftDocRef.update({ setAsAvatar: true }); - - mockWalletReturnValue(h.spy, h.member, dummySaleData(h.nft.uid)); - await expectThrow(testEnv.wrap(setForSaleNft)({}), WenError.nft_set_as_avatar.key); + mockWalletReturnValue(h.member, dummySaleData(h.nft.uid)); + await expectThrow(testEnv.wrap(WEN_FUNC.setForSaleNft), WenError.nft_set_as_avatar.key); }); it('Should set nft for auction', async () => { - mockWalletReturnValue(h.spy, h.member, dummyAuctionData(h.nft.uid)); - await testEnv.wrap(setForSaleNft)({}); + mockWalletReturnValue(h.member, dummyAuctionData(h.nft.uid)); + await testEnv.wrap(WEN_FUNC.setForSaleNft); - const nftDocRef = build5Db().doc(`${COL.NFT}/${h.nft.uid}`); + const nftDocRef = build5Db().doc(COL.NFT, h.nft.uid); await wait(async () => { const nft = await nftDocRef.get(); return nft.available === 3; }); - const auctionNft = await build5Db().doc(`${COL.NFT}/${h.nft.uid}`).get(); + const auctionNft = await build5Db().doc(COL.NFT, h.nft.uid).get(); expect(auctionNft.available).toBe(3); expect(auctionNft.auctionFrom).toBeDefined(); expect(auctionNft.auctionTo).toBeDefined(); expect(auctionNft.auctionLength).toBeDefined(); - const collectionDocRef = build5Db().doc(`${COL.COLLECTION}/${auctionNft.collection}`); + const collectionDocRef = build5Db().doc(COL.COLLECTION, auctionNft.collection); const collection = await collectionDocRef.get(); expect(collection.nftsOnAuction).toBe(1); expect(collection.nftsOnSale).toBe(1); }); it('Should throw, auction already in progress', async () => { - mockWalletReturnValue(h.spy, h.member, dummyAuctionData(h.nft.uid)); - await testEnv.wrap(setForSaleNft)({}); - mockWalletReturnValue(h.spy, h.member, dummyAuctionData(h.nft.uid)); - await expectThrow(testEnv.wrap(setForSaleNft)({}), WenError.auction_already_in_progress.key); + mockWalletReturnValue(h.member, dummyAuctionData(h.nft.uid)); + await testEnv.wrap(WEN_FUNC.setForSaleNft); + mockWalletReturnValue(h.member, dummyAuctionData(h.nft.uid)); + await expectThrow( + testEnv.wrap(WEN_FUNC.setForSaleNft), + WenError.auction_already_in_progress.key, + ); }); it('Should throw, invalid nft', async () => { - mockWalletReturnValue(h.spy, h.member, { - ...dummyAuctionData(h.nft.uid), - nft: getRandomEthAddress(), - }); - await expectThrow(testEnv.wrap(setForSaleNft)({}), WenError.nft_does_not_exists.key); + mockWalletReturnValue(h.member, { ...dummyAuctionData(h.nft.uid), nft: getRandomEthAddress() }); + await expectThrow(testEnv.wrap(WEN_FUNC.setForSaleNft), WenError.nft_does_not_exists.key); }); it('Should throw, not owner', async () => { - mockWalletReturnValue(h.spy, h.members[0], dummyAuctionData(h.nft.uid)); - await expectThrow(testEnv.wrap(setForSaleNft)({}), WenError.you_must_be_the_owner_of_nft.key); + mockWalletReturnValue(h.members[0], dummyAuctionData(h.nft.uid)); + await expectThrow( + testEnv.wrap(WEN_FUNC.setForSaleNft), + WenError.you_must_be_the_owner_of_nft.key, + ); }); }); diff --git a/packages/functions/test/controls/order.spec.ts b/packages/functions/test/controls/order.spec.ts index 1f62c25964..22cc9b93b9 100644 --- a/packages/functions/test/controls/order.spec.ts +++ b/packages/functions/test/controls/order.spec.ts @@ -1,4 +1,4 @@ -import { build5Db } from '@build-5/database'; +import { PgTransactionType, build5Db } from '@build-5/database'; import { Access, COL, @@ -6,6 +6,7 @@ import { Collection, CollectionType, MIN_IOTA_AMOUNT, + Network, NetworkAddress, Nft, NftAccess, @@ -14,31 +15,17 @@ import { Transaction, TransactionPayloadType, TransactionType, + WEN_FUNC, WenError, } from '@build-5/interfaces'; import dayjs from 'dayjs'; -import { - createNft, - orderNft, - setForSaleNft, -} from '../../../functions/src/runtime/firebase//nft/index'; -import { createCollection } from '../../../functions/src/runtime/firebase/collection/index'; +import { orderNftControl } from '../../src/controls/nft/nft.puchase.control'; import * as wallet from '../../src/utils/wallet.utils'; -import { testEnv } from '../set-up'; -import { - createMember, - createSpace, - expectThrow, - mockIpCheck, - mockWalletReturnValue, - submitMilestoneFunc, - wait, -} from './common'; +import { mockWalletReturnValue, testEnv } from '../set-up'; +import { expectThrow, mockIpCheck, submitMilestoneFunc, wait } from './common'; const db = build5Db(); -let walletSpy: any; - const dummyCollection = ( space: Space, type: CollectionType, @@ -72,24 +59,24 @@ const dummyNft = ( }); const createCollectionFunc = async (address: NetworkAddress, params: T) => { - mockWalletReturnValue(walletSpy, address, params); - const cCollection = await testEnv.wrap(createCollection)({}); + mockWalletReturnValue(address, params); + const cCollection = await testEnv.wrap(WEN_FUNC.createCollection); expect(cCollection?.uid).toBeDefined(); - await build5Db().doc(`${COL.COLLECTION}/${cCollection?.uid}`).update({ approved: true }); + await build5Db().doc(COL.COLLECTION, cCollection?.uid).update({ approved: true }); return cCollection; }; const createNftFunc = async (address: NetworkAddress, params: T) => { - mockWalletReturnValue(walletSpy, address, params); - const nft = await testEnv.wrap(createNft)({}); + mockWalletReturnValue(address, params); + const nft = await testEnv.wrap(WEN_FUNC.createNft); expect(nft?.createdOn).toBeDefined(); return nft; }; const submitOrderFunc = async (address: NetworkAddress, params: T) => { - mockWalletReturnValue(walletSpy, address, params); - const order = await testEnv.wrap(orderNft)({}); + mockWalletReturnValue(address, params); + const order = await testEnv.wrap(WEN_FUNC.orderNft); expect(order?.createdOn).toBeDefined(); return order; }; @@ -106,9 +93,8 @@ describe('Ordering flows', () => { let space: Space; beforeEach(async () => { - walletSpy = jest.spyOn(wallet, 'decodeAuth'); - member = await createMember(walletSpy); - space = await createSpace(walletSpy, member); + member = await testEnv.createMember(); + space = await testEnv.createSpace(member); }); it('One collection, one classic NFT, one purchase - not paid for', async () => { @@ -145,19 +131,18 @@ describe('Ordering flows', () => { ); if (noRoyaltySpace) { await build5Db() - .doc(`${COL.COLLECTION}/${collection.uid}`) + .doc(COL.COLLECTION, collection.uid) .update({ royaltiesSpace: '', royaltiesFee: 0 }); } let nft: Nft = await createNftFunc(member, dummyNft(collection, price)); - const order = await submitOrderFunc(member, { collection: collection.uid, nft: nft.uid }); - expect(order.payload.restrictions.collection).toEqual({ + expect(order.payload.restrictions!.collection).toEqual({ access: collection.access, accessAwards: collection.accessAwards || [], accessCollections: collection.accessCollections || [], }); - expect(order.payload.restrictions.nft).toEqual({ - saleAccess: nft.saleAccess || null, + expect(order.payload.restrictions!.nft).toEqual({ + saleAccess: nft.saleAccess || undefined, saleAccessMembers: nft.saleAccessMembers || [], }); await submitMilestoneFunc(order); @@ -175,9 +160,9 @@ describe('Ordering flows', () => { const billPayments = await build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.BILL_PAYMENT) - .where('payload.nft', '==', nft.uid) - .get(); + .where('type', '==', PgTransactionType.BILL_PAYMENT) + .where('payload_nft', '==', nft.uid) + .get(); for (const billPayment of billPayments) { expect(billPayment.payload.restrictions).toEqual(order.payload.restrictions); } @@ -199,17 +184,17 @@ describe('Ordering flows', () => { nft = await nftDocRef.get(); expect(nft.soldOn).toBeDefined(); - mockWalletReturnValue(walletSpy, member, dummySaleData(nft.uid)); - await testEnv.wrap(setForSaleNft)({}); + mockWalletReturnValue(member, dummySaleData(nft.uid)); + await testEnv.wrap(WEN_FUNC.setForSaleNft); await new Promise((resolve) => setTimeout(resolve, 1000)); - const buyer = await createMember(walletSpy); + const buyer = await testEnv.createMember(); order = await submitOrderFunc(buyer, { collection: collection.uid, nft: nft.uid }); await submitMilestoneFunc(order); const secondSoldNft = await nftDocRef.get(); - expect(secondSoldNft.soldOn).toEqual(nft.soldOn); + expect(secondSoldNft.soldOn?.seconds).toBe(nft.soldOn?.seconds); }); it('One collection, one classic NFT, one purchase & paid for and try again', async () => { @@ -245,7 +230,7 @@ describe('Ordering flows', () => { const order = await submitOrderFunc(member, { collection: collection.uid }); await submitMilestoneFunc(order); - const nftDbRec: any = await db.collection(COL.NFT).doc(order.payload.nft).get(); + const nftDbRec: any = await db.doc(COL.NFT, order.payload.nft!).get(); expect(member).toBe(nftDbRec.owner); }); @@ -262,7 +247,7 @@ describe('Ordering flows', () => { const order = await submitOrderFunc(member, { collection: collection.uid }); await submitMilestoneFunc(order); - const nftDbRec: any = await db.collection(COL.NFT).doc(order.payload.nft).get(); + const nftDbRec: any = await db.collection(COL.NFT).doc(order.payload.nft!).get(); expect(member).toBe(nftDbRec.owner); await expectThrow( @@ -270,7 +255,7 @@ describe('Ordering flows', () => { WenError.no_more_nft_available_for_sale.key, ); - const placeholderNftDocRef = build5Db().doc(`${COL.NFT}/${collection.placeholderNft}`); + const placeholderNftDocRef = build5Db().doc(COL.NFT, collection.placeholderNft); await wait(async () => { const placeholderNft = await placeholderNftDocRef.get(); return placeholderNft.hidden || false; @@ -279,7 +264,7 @@ describe('Ordering flows', () => { it('One collection, generated NFT, 15 Nfts should equal to 15 purchases', async () => { const batchSize = 15; - const memberPromises = Array.from(Array(batchSize)).map(() => createMember(walletSpy)); + const memberPromises = Array.from(Array(batchSize)).map(() => testEnv.createMember()); const members = await Promise.all(memberPromises); const price = 100; @@ -311,7 +296,7 @@ describe('Ordering flows', () => { batchSize + ' purchases + payment in multiple milestone', async () => { - const memberPromises = Array.from(Array(batchSize)).map(() => createMember(walletSpy)); + const memberPromises = Array.from(Array(batchSize)).map(() => testEnv.createMember()); const members = await Promise.all(memberPromises); const price = 100; @@ -368,13 +353,13 @@ describe('Ordering flows', () => { const order = await submitOrderFunc(member, { collection: collection.uid }); // Confirm payment. - const wrongAmount = order.payload.amount * 1.5; + const wrongAmount = order.payload.amount! * 1.5; const milestone = await submitMilestoneFunc(order, wrongAmount); - const nftDbRec = await db.collection(COL.NFT).doc(order.payload.nft).get(); + const nftDbRec = await db.collection(COL.NFT).doc(order.payload.nft!).get(); expect(nftDbRec?.sold).toBe(false); - const tran = await db.collection(COL.TRANSACTION).doc(order.uid).get(); + const tran = await db.collection(COL.TRANSACTION).doc(order.uid).get(); expect(tran?.linkedTransactions?.length).toBe(2); let c = 0; @@ -413,7 +398,7 @@ describe('Ordering flows', () => { await submitMilestoneFunc(order); - const nftDbRec: any = await db.collection(COL.NFT).doc(order.payload.nft).get(); + const nftDbRec: any = await db.collection(COL.NFT).doc(order.payload.nft!).get(); expect(nftDbRec.sold).toBe(true); const tran: any = await db.collection(COL.TRANSACTION).doc(order.uid).get(); @@ -438,10 +423,9 @@ describe('Ordering flows', () => { ); const nft = await createNftFunc(member, dummyNft(collection, price)); mockIpCheck(true, { common: ['HU'] }, { countryCode: 'HU' }); - await expectThrow( - submitOrderFunc(member, { collection: collection.uid, nft: nft.uid }), - WenError.blocked_country.key, - ); + mockWalletReturnValue(member, { collection: collection.uid, nft: nft.uid }); + const call = testEnv.mockWrap(orderNftControl); + await expectThrow(call, WenError.blocked_country.key); }); it('Order should fail, country blocked for nft', async () => { @@ -452,10 +436,10 @@ describe('Ordering flows', () => { ); const nft = await createNftFunc(member, dummyNft(collection, price)); mockIpCheck(true, { common: ['USA'], [nft.uid]: ['USA', 'HU'] }, { countryCode: 'HU' }); - await expectThrow( - submitOrderFunc(member, { collection: collection.uid, nft: nft.uid }), - WenError.blocked_country.key, - ); + + mockWalletReturnValue(member, { collection: collection.uid, nft: nft.uid }); + const call = testEnv.mockWrap(orderNftControl); + await expectThrow(call, WenError.blocked_country.key); }); it('Should validate access awards', async () => { @@ -478,8 +462,9 @@ describe('Ordering flows', () => { type: TransactionType.AWARD, uid: wallet.getRandomEthAddress(), payload: { type: TransactionPayloadType.BADGE, award: awards[0] }, + network: Network.RMS, }; - await build5Db().doc(`${COL.TRANSACTION}/${badge.uid}`).create(badge); + await build5Db().doc(COL.TRANSACTION, badge.uid).create(badge); await expectThrow( submitOrderFunc(member, { collection: collection.uid, nft: nft.uid }), WenError.you_dont_have_required_badge.key, @@ -491,17 +476,18 @@ describe('Ordering flows', () => { type: TransactionType.AWARD, uid: wallet.getRandomEthAddress(), payload: { type: TransactionPayloadType.BADGE, award: awards[1] }, + network: Network.RMS, }; - await build5Db().doc(`${COL.TRANSACTION}/${badge.uid}`).create(badge); + await build5Db().doc(COL.TRANSACTION, badge.uid).create(badge); const order = await submitOrderFunc(member, { collection: collection.uid, nft: nft.uid }); expect(order).toBeDefined(); - expect(order.payload.restrictions.collection).toEqual({ + expect(order.payload.restrictions!.collection).toEqual({ access: collection.access, accessAwards: collection.accessAwards || [], accessCollections: collection.accessCollections || [], }); - expect(order.payload.restrictions.nft).toEqual({ - saleAccess: nft.saleAccess || null, + expect(order.payload.restrictions!.nft).toEqual({ + saleAccess: nft.saleAccess || undefined, saleAccessMembers: nft.saleAccessMembers || [], }); }); diff --git a/packages/functions/test/controls/project/project.create.spec.ts b/packages/functions/test/controls/project/project.create.spec.ts index 947b419b71..8bbf0b21cb 100644 --- a/packages/functions/test/controls/project/project.create.spec.ts +++ b/packages/functions/test/controls/project/project.create.spec.ts @@ -1,49 +1,37 @@ -import { build5Db } from '@build-5/database'; +import { PgProjectBilling, PgTokenStatus, build5Db } from '@build-5/database'; import { COL, - Network, - Project, - ProjectAdmin, ProjectBilling, + ProjectCreateResponse, SOON_PROJECT_ID, SUB_COL, Token, - TokenStatus, Transaction, + WEN_FUNC, WenError, } from '@build-5/interfaces'; -import { CoinType, utf8ToHex } from '@iota/sdk'; -import axios from 'axios'; import { AVAILABLE_NETWORKS } from '../../../src/controls/common'; -import { createProject } from '../../../src/runtime/firebase/project/index'; -import { getSecretManager } from '../../../src/utils/secret.manager.utils'; import * as wallet from '../../../src/utils/wallet.utils'; -import { getRandomNonce } from '../../../src/utils/wallet.utils'; -import { getWallet, testEnv } from '../../set-up'; -import { createMember, expectThrow, getRandomSymbol, mockWalletReturnValue } from '../common'; +import { mockWalletReturnValue, testEnv } from '../../set-up'; +import { expectThrow, getRandomSymbol } from '../common'; describe('Project create', () => { - let walletSpy: any; let guardian: string; let token: Token; - - beforeAll(async () => { - walletSpy = jest.spyOn(wallet, 'decodeAuth'); - }); - beforeEach(async () => { - guardian = await createMember(walletSpy); + guardian = await testEnv.createMember(); const tokenId = wallet.getRandomEthAddress(); - token = { + const tokenUpsert = { project: SOON_PROJECT_ID, uid: tokenId, symbol: getRandomSymbol(), name: 'MyToken', space: 'myspace', - status: TokenStatus.AVAILABLE, + status: PgTokenStatus.AVAILABLE, approved: true, }; - await build5Db().doc(`${COL.TOKEN}/${tokenId}`).set(token); + await build5Db().doc(COL.TOKEN, tokenId).upsert(tokenUpsert); + token = (await build5Db().doc(COL.TOKEN, tokenId).get())!; }); it('Should create volume based project', async () => { @@ -52,27 +40,33 @@ describe('Project create', () => { contactEmail: 'myemail@gmail.com', config: { billing: ProjectBilling.VOLUME_BASED }, }; - mockWalletReturnValue(walletSpy, guardian, dummyProject); - const { project: newProject } = await testEnv.wrap(createProject)({}); - const projectDocRef = build5Db().doc(`${COL.PROJECT}/${newProject.uid}`); - const project = await projectDocRef.get(); + mockWalletReturnValue(guardian, dummyProject); + const { project: newProject } = await testEnv.wrap( + WEN_FUNC.createProject, + ); + + const projectDocRef = build5Db().doc(COL.PROJECT, newProject.uid); + const project = await projectDocRef.get(); expect(project?.name).toBe(dummyProject.name); expect(project?.contactEmail).toBe(dummyProject.contactEmail); expect(project?.deactivated).toBe(false); expect(project?.config?.billing).toBe(ProjectBilling.VOLUME_BASED); - const projectAdminDocRef = projectDocRef.collection(SUB_COL.ADMINS).doc(guardian); - const projectAdmin = await projectAdminDocRef.get(); + const projectAdminDocRef = build5Db().doc( + COL.PROJECT, + newProject.uid, + SUB_COL.ADMINS, + guardian, + ); + const projectAdmin = await projectAdminDocRef.get(); expect(projectAdmin?.uid).toBe(guardian); expect(projectAdmin?.parentCol).toBe(COL.PROJECT); expect(projectAdmin?.parentId).toBe(project?.uid); - const networks = Object.values(project!.otr!).map((o) => o.network); expect(networks.sort()).toEqual(AVAILABLE_NETWORKS.sort()); - for (const [uid, otr] of Object.entries(project?.otr!)) { - const docRef = build5Db().doc(`${COL.TRANSACTION}/${uid}`); + const docRef = build5Db().doc(COL.TRANSACTION, uid); const otrOrder = await docRef.get(); expect(otrOrder.uid).toBe(uid); expect(otrOrder.network).toBe(otr.network); @@ -87,8 +81,12 @@ describe('Project create', () => { contactEmail: 'myemail@gmail.com', config: { billing: ProjectBilling.VOLUME_BASED, tiers: [1, 2, 3, 4] }, }; - mockWalletReturnValue(walletSpy, guardian, dummyProject); - await expectThrow(testEnv.wrap(createProject)({}), WenError.invalid_params.key); + + mockWalletReturnValue(guardian, dummyProject); + await expectThrow( + testEnv.wrap(WEN_FUNC.createProject), + WenError.invalid_params.key, + ); }); it('Should create token based project', async () => { @@ -96,39 +94,42 @@ describe('Project create', () => { name: 'My project', contactEmail: 'myemail@gmail.com', config: { - billing: ProjectBilling.TOKEN_BASE, + billing: PgProjectBilling.TOKEN_BASED, tiers: [1, 2, 3, 4, 5], tokenTradingFeeDiscountPercentage: [0, 0, 0, 0, 0], nativeTokenSymbol: token.symbol, }, }; - mockWalletReturnValue(walletSpy, guardian, dummyProject); - const { project: newProject } = await testEnv.wrap(createProject)({}); - - const projectDocRef = build5Db().doc(`${COL.PROJECT}/${newProject.uid}`); - const project = await projectDocRef.get(); + mockWalletReturnValue(guardian, dummyProject); + const { project: newProject } = await testEnv.wrap( + WEN_FUNC.createProject, + ); + const projectDocRef = build5Db().doc(COL.PROJECT, newProject.uid); + const project = await projectDocRef.get(); expect(project?.name).toBe(dummyProject.name); expect(project?.contactEmail).toBe(dummyProject.contactEmail); expect(project?.deactivated).toBe(false); - expect(project?.config?.billing).toBe(ProjectBilling.TOKEN_BASE); + expect(project?.config?.billing).toBe(ProjectBilling.TOKEN_BASED); expect(project?.config?.tiers).toEqual(dummyProject.config.tiers); expect(project?.config?.tokenTradingFeeDiscountPercentage).toEqual( dummyProject.config.tokenTradingFeeDiscountPercentage, ); expect(project?.config?.nativeTokenSymbol).toBe(dummyProject.config.nativeTokenSymbol); expect(project?.config?.nativeTokenUid).toBe(token.uid); - - const projectAdminDocRef = projectDocRef.collection(SUB_COL.ADMINS).doc(guardian); - const adminGuardian = await projectAdminDocRef.get(); + const projectAdminDocRef = build5Db().doc( + COL.PROJECT, + newProject.uid, + SUB_COL.ADMINS, + guardian, + ); + const adminGuardian = await projectAdminDocRef.get(); expect(adminGuardian?.uid).toBe(guardian); expect(adminGuardian?.parentCol).toBe(COL.PROJECT); expect(adminGuardian?.parentId).toBe(project?.uid); - const networks = Object.values(project!.otr!).map((o) => o.network); expect(networks.sort()).toEqual(AVAILABLE_NETWORKS.sort()); - for (const [uid, otr] of Object.entries(project?.otr!)) { - const docRef = build5Db().doc(`${COL.TRANSACTION}/${uid}`); + const docRef = build5Db().doc(COL.TRANSACTION, uid); const otrOrder = await docRef.get(); expect(otrOrder.uid).toBe(uid); expect(otrOrder.network).toBe(otr.network); @@ -139,33 +140,25 @@ describe('Project create', () => { }); it('Should create project without project id', async () => { - const wallet = await getWallet(Network.RMS); - const address = await wallet.getNewIotaAddressDetails(); - - const nonce = getRandomNonce(); - const userDocRef = build5Db().doc(`${COL.MEMBER}/${address.bech32}`); - await userDocRef.create({ uid: address.bech32, nonce }); - - const secretManager = getSecretManager(address.mnemonic); - const signature = await secretManager.signEd25519(utf8ToHex(nonce), { - coinType: CoinType.IOTA, - }); - const request = { - address: address.bech32, - projectApiKey: '', - signature: signature.signature, - publicKey: { - hex: signature.publicKey, - network: Network.RMS, - }, - body: { - name: 'My project', - contactEmail: 'myemail@gmail.com', - config: { billing: ProjectBilling.VOLUME_BASED }, + const dummyProject = { + name: 'My project', + contactEmail: 'myemail@gmail.com', + config: { + billing: PgProjectBilling.TOKEN_BASED, + tiers: [1, 2, 3, 4, 5], + tokenTradingFeeDiscountPercentage: [0, 0, 0, 0, 0], + nativeTokenSymbol: token.symbol, }, }; - const url = 'http://127.0.0.1:5001/soonaverse-dev/us-central1/https-createproject'; - const response = await axios.post(url, request); - expect(response.data.token).toBeDefined(); + mockWalletReturnValue(guardian, dummyProject, ''); + const { project: newProject } = await testEnv.wrap( + WEN_FUNC.createProject, + ); + const projectDocRef = build5Db().doc(COL.PROJECT, newProject.uid); + const project = await projectDocRef.get(); + expect(project?.name).toBe(dummyProject.name); + expect(project?.contactEmail).toBe(dummyProject.contactEmail); + expect(project?.deactivated).toBe(false); + expect(project?.config?.billing).toBe(ProjectBilling.TOKEN_BASED); }); }); diff --git a/packages/functions/test/controls/project/project.deactivate.spec.ts b/packages/functions/test/controls/project/project.deactivate.spec.ts index b24baf313f..e44ca81cbd 100644 --- a/packages/functions/test/controls/project/project.deactivate.spec.ts +++ b/packages/functions/test/controls/project/project.deactivate.spec.ts @@ -1,34 +1,50 @@ import { build5Db } from '@build-5/database'; -import { COL, Project, SOON_PROJECT_ID, WenError } from '@build-5/interfaces'; -import { deactivateProject } from '../../../src/runtime/firebase/project/index'; -import * as wallet from '../../../src/utils/wallet.utils'; -import { SOON_PROJ_GUARDIAN, testEnv } from '../../set-up'; -import { createMember, expectThrow, mockWalletReturnValue } from '../common'; +import { + COL, + Project, + ProjectBilling, + ProjectCreateResponse, + SUB_COL, + WEN_FUNC, + WenError, +} from '@build-5/interfaces'; +import { mockWalletReturnValue, testEnv } from '../../set-up'; +import { expectThrow } from '../common'; describe('Project create', () => { - let walletSpy: any; let guardian: string; + let project: Project; + let token: string; beforeEach(async () => { - walletSpy = jest.spyOn(wallet, 'decodeAuth'); - guardian = await createMember(walletSpy); + guardian = await testEnv.createMember(); + const dummyProject = { + name: 'My project', + contactEmail: 'myemail@gmail.com', + config: { billing: ProjectBilling.VOLUME_BASED }, + }; + mockWalletReturnValue(guardian, dummyProject); + const { project: newProject } = await testEnv.wrap( + WEN_FUNC.createProject, + ); + project = newProject; + const apiKey = await build5Db().collection(COL.PROJECT, newProject.uid, SUB_COL._API_KEY).get(); + token = apiKey[0].token; }); it('Should deactivate project', async () => { - mockWalletReturnValue(walletSpy, SOON_PROJ_GUARDIAN, {}); - await testEnv.wrap(deactivateProject)({}); - - const projectDocRef = build5Db().doc(`${COL.PROJECT}/${SOON_PROJECT_ID}`); - const projectData = await projectDocRef.get(); + mockWalletReturnValue(guardian, {}, undefined, token); + await testEnv.wrap(WEN_FUNC.deactivateProject); + const projectDocRef = build5Db().doc(COL.PROJECT, project.uid); + const projectData = await projectDocRef.get(); expect(projectData?.deactivated).toBe(true); - - await projectDocRef.update({ deactivated: false }); }); it('Should throw, not guardian of the project', async () => { - mockWalletReturnValue(walletSpy, guardian, {}); + const random = await testEnv.createMember(); + mockWalletReturnValue(random, {}, undefined, token); await expectThrow( - testEnv.wrap(deactivateProject)({}), + testEnv.wrap(WEN_FUNC.deactivateProject), WenError.you_are_not_admin_of_project.key, ); }); diff --git a/packages/functions/test/controls/proposal.spec.ts b/packages/functions/test/controls/proposal.spec.ts index ddc0577f4f..df75ba0ff9 100644 --- a/packages/functions/test/controls/proposal.spec.ts +++ b/packages/functions/test/controls/proposal.spec.ts @@ -1,5 +1,8 @@ -import { build5Db } from '@build-5/database'; +import { PgAccess, PgNetwork, PgTokenStatus, build5Db } from '@build-5/database'; import { + Award, + AwardApproveParticipantResponse, + AwardParticipant, COL, Network, NetworkAddress, @@ -11,6 +14,7 @@ import { Space, Token, TokenStatus, + Transaction, WEN_FUNC, WenError, } from '@build-5/interfaces'; @@ -18,28 +22,8 @@ import dayjs from 'dayjs'; import { serverTime } from '../../src/utils/dateTime.utils'; import * as wallet from '../../src/utils/wallet.utils'; import { getRandomEthAddress } from '../../src/utils/wallet.utils'; -import { MEDIA, testEnv } from '../set-up'; -import { - approveAwardParticipant, - awardParticipate, - createAward, -} from './../../src/runtime/firebase/award/index'; -import { - approveProposal, - createProposal, - rejectProposal, - voteOnProposal, -} from './../../src/runtime/firebase/proposal/index'; -import { createSpace, joinSpace } from './../../src/runtime/firebase/space/index'; -import { - addGuardianToSpace, - createMember, - expectThrow, - getRandomSymbol, - mockWalletReturnValue, -} from './common'; - -let walletSpy: any; +import { MEDIA, mockWalletReturnValue, testEnv } from '../set-up'; +import { addGuardianToSpace, expectThrow, getRandomSymbol } from './common'; const dummyBody = (space: string) => ({ name: 'All 4 HORNET', @@ -69,26 +53,26 @@ describe('ProposalController: ' + WEN_FUNC.rejectProposal + ' NATIVE', () => { let body: any; beforeEach(async () => { - walletSpy = jest.spyOn(wallet, 'decodeAuth'); - member = await createMember(walletSpy); - mockWalletReturnValue(walletSpy, member, { name: 'Space A' }); - space = await testEnv.wrap(createSpace)({}); - expect(space?.uid).toBeDefined(); + member = await testEnv.createMember(); + space = await testEnv.createSpace(member); body = dummyBody(space.uid); const tokenId = wallet.getRandomEthAddress(); - await build5Db().doc(`${COL.TOKEN}/${tokenId}`).create({ - project: SOON_PROJECT_ID, - uid: tokenId, - space: space.uid, - status: TokenStatus.MINTED, - approved: true, - }); + await build5Db() + .doc(COL.TOKEN, tokenId) + .create({ + links: [] as URL[], + project: SOON_PROJECT_ID, + uid: tokenId, + space: space.uid, + status: TokenStatus.MINTED, + approved: true, + } as Token); }); it('successfully create proposal with name', async () => { - mockWalletReturnValue(walletSpy, member, body); - const cProposal = await testEnv.wrap(createProposal)({}); + mockWalletReturnValue(member, body); + const cProposal = await testEnv.wrap(WEN_FUNC.createProposal); expect(cProposal?.uid).toBeDefined(); expect(cProposal?.name).toEqual(body.name); expect(cProposal?.additionalInfo).toEqual(body.additionalInfo); @@ -96,82 +80,94 @@ describe('ProposalController: ' + WEN_FUNC.rejectProposal + ' NATIVE', () => { expect(cProposal?.questions).toBeDefined(); expect(cProposal?.createdOn).toBeDefined(); expect(cProposal?.updatedOn).toBeDefined(); - walletSpy.mockRestore(); }); describe('Proposal validations', () => { it('empty body', async () => { - mockWalletReturnValue(walletSpy, member, {}); - await expectThrow(testEnv.wrap(createProposal)({}), WenError.invalid_params.key); + mockWalletReturnValue(member, {}); + await expectThrow( + testEnv.wrap(WEN_FUNC.createProposal), + WenError.invalid_params.key, + ); }); it('missing name', async () => { delete body.name; - mockWalletReturnValue(walletSpy, member, body); - await expectThrow(testEnv.wrap(createProposal)({}), WenError.invalid_params.key); + mockWalletReturnValue(member, body); + await expectThrow( + testEnv.wrap(WEN_FUNC.createProposal), + WenError.invalid_params.key, + ); }); it('no questions', async () => { body.questions = []; - mockWalletReturnValue(walletSpy, member, body); - await expectThrow(testEnv.wrap(createProposal)({}), WenError.invalid_params.key); + mockWalletReturnValue(member, body); + await expectThrow( + testEnv.wrap(WEN_FUNC.createProposal), + WenError.invalid_params.key, + ); }); it('only one answer', async () => { delete body.questions[0].answers[1]; - mockWalletReturnValue(walletSpy, member, body); - await expectThrow(testEnv.wrap(createProposal)({}), WenError.invalid_params.key); + mockWalletReturnValue(member, body); + await expectThrow( + testEnv.wrap(WEN_FUNC.createProposal), + WenError.invalid_params.key, + ); }); it('invalid type', async () => { body.type = 2; - mockWalletReturnValue(walletSpy, member, body); - await expectThrow(testEnv.wrap(createProposal)({}), WenError.invalid_params.key); + mockWalletReturnValue(member, body); + await expectThrow( + testEnv.wrap(WEN_FUNC.createProposal), + WenError.invalid_params.key, + ); }); }); ['approve', 'reject'].forEach((s) => { - const command = s === 'approve' ? approveProposal : rejectProposal; + const command = s === 'approve' ? WEN_FUNC.approveProposal : WEN_FUNC.rejectProposal; const field = s === 'approve' ? 'approved' : 'rejected'; it(s + ' proposal', async () => { - mockWalletReturnValue(walletSpy, member, body); - const cProposal = await testEnv.wrap(createProposal)({}); + mockWalletReturnValue(member, body); + const cProposal = await testEnv.wrap(WEN_FUNC.createProposal); expect(cProposal?.uid).toBeDefined(); - mockWalletReturnValue(walletSpy, member, { uid: cProposal.uid }); - const uProposal = await testEnv.wrap(command)({}); + mockWalletReturnValue(member, { uid: cProposal.uid }); + const uProposal = await testEnv.wrap(command); expect(uProposal?.uid).toBeDefined(); expect(uProposal?.[field]).toEqual(true); - walletSpy.mockRestore(); }); it('fail to ' + s + ' proposal (not guardian)', async () => { - mockWalletReturnValue(walletSpy, member, body); - const cProposal = await testEnv.wrap(createProposal)({}); + mockWalletReturnValue(member, body); + const cProposal = await testEnv.wrap(WEN_FUNC.createProposal); expect(cProposal?.uid).toBeDefined(); - mockWalletReturnValue(walletSpy, wallet.getRandomEthAddress(), { uid: cProposal.uid }); - await expectThrow(testEnv.wrap(command)({}), WenError.you_are_not_guardian_of_space.key); - walletSpy.mockRestore(); + const randomUser = await testEnv.createMember(); + mockWalletReturnValue(randomUser, { uid: cProposal.uid }); + await expectThrow(testEnv.wrap(command), WenError.you_are_not_guardian_of_space.key); }); it(s + ' proposal by other guardian (not creator)', async () => { - const guardian2 = wallet.getRandomEthAddress(); - mockWalletReturnValue(walletSpy, guardian2, { uid: space.uid }); - const jSpace = await testEnv.wrap(joinSpace)({}); + const guardian2 = await testEnv.createMember(); + mockWalletReturnValue(guardian2, { uid: space.uid }); + const jSpace = await testEnv.wrap(WEN_FUNC.joinSpace); expect(jSpace).toBeDefined(); expect(jSpace.createdOn).toBeDefined(); expect(jSpace.uid).toEqual(guardian2); await addGuardianToSpace(space.uid, guardian2); - mockWalletReturnValue(walletSpy, member, body); - const cProposal = await testEnv.wrap(createProposal)({}); + mockWalletReturnValue(member, body); + const cProposal = await testEnv.wrap(WEN_FUNC.createProposal); expect(cProposal?.uid).toBeDefined(); - mockWalletReturnValue(walletSpy, guardian2, { uid: cProposal.uid }); - const result = await testEnv.wrap(command)({}); + mockWalletReturnValue(guardian2, { uid: cProposal.uid }); + const result = await testEnv.wrap(command); expect(result?.uid).toBeDefined(); expect(result?.[field]).toEqual(true); - walletSpy.mockRestore(); }); }); }); @@ -182,17 +178,17 @@ describe('ProposalController: ' + WEN_FUNC.createProposal + ' MEMBERS', () => { let token: Token; const cSpace = async (address: NetworkAddress) => { - mockWalletReturnValue(walletSpy, address, { name: 'Space A' }); - const space = await testEnv.wrap(createSpace)({}); + mockWalletReturnValue(address, { name: 'Space A' }); + space = await testEnv.wrap(WEN_FUNC.createSpace); expect(space?.uid).toBeDefined(); return space as Space; }; const jSpace = async (address: NetworkAddress, space: Space) => { - mockWalletReturnValue(walletSpy, address, { uid: space.uid }); - const jSpace = await testEnv.wrap(joinSpace)({}); + mockWalletReturnValue(address, { uid: space.uid }); + const jSpace = await testEnv.wrap(WEN_FUNC.joinSpace); expect(jSpace?.uid).toBeDefined(); - return jSpace as Space; + return jSpace; }; const cProposal = ( @@ -221,20 +217,20 @@ describe('ProposalController: ' + WEN_FUNC.createProposal + ' MEMBERS', () => { }, ], }; - mockWalletReturnValue(walletSpy, address, proposal); - return testEnv.wrap(createProposal)({}); + mockWalletReturnValue(address, proposal); + return testEnv.wrap(WEN_FUNC.createProposal); }; const apprProposal = async (address: NetworkAddress, proposal: any) => { - mockWalletReturnValue(walletSpy, address, { uid: proposal.uid }); - const pr = await testEnv.wrap(approveProposal)({}); + mockWalletReturnValue(address, { uid: proposal.uid }); + const pr = await testEnv.wrap(WEN_FUNC.approveProposal); expect(proposal?.uid).toBeDefined(); return pr; }; const vote = async (address: NetworkAddress, proposal: any, value: number) => { - mockWalletReturnValue(walletSpy, address, { uid: proposal.uid, value }); - const pr = await testEnv.wrap(voteOnProposal)({}); + mockWalletReturnValue(address, { uid: proposal.uid, value }); + const pr = await testEnv.wrap(WEN_FUNC.voteOnProposal); expect(proposal?.uid).toBeDefined(); return pr; }; @@ -246,7 +242,7 @@ describe('ProposalController: ' + WEN_FUNC.createProposal + ' MEMBERS', () => { tokenSymbol: string, tokenReward = 0, ) => { - mockWalletReturnValue(walletSpy, address, { + mockWalletReturnValue(address, { name: 'Award A', description: 'Finish this and that', space: space?.uid, @@ -262,19 +258,21 @@ describe('ProposalController: ' + WEN_FUNC.createProposal + ' MEMBERS', () => { }, network: Network.RMS, }); - const award = await testEnv.wrap(createAward)({}); + const award = await testEnv.wrap(WEN_FUNC.createAward); expect(award?.uid).toBeDefined(); - await build5Db().doc(`${COL.AWARD}/${award.uid}`).update({ approved: true, address: '' }); + await build5Db().doc(COL.AWARD, award.uid).update({ approved: true, address: '' }); // Participate - mockWalletReturnValue(walletSpy, address, { uid: award?.uid }); - const returnsParti = await testEnv.wrap(awardParticipate)({}); + mockWalletReturnValue(address, { uid: award?.uid }); + const returnsParti = await testEnv.wrap(WEN_FUNC.participateAward); expect(returnsParti?.uid).toBeDefined(); // Approve - mockWalletReturnValue(walletSpy, guardian, { award: award.uid, members: [address] }); - const returns2 = await testEnv.wrap(approveAwardParticipant)({}); + mockWalletReturnValue(guardian, { award: award.uid, members: [address] }); + const returns2 = await testEnv.wrap( + WEN_FUNC.approveParticipantAward, + ); expect(Object.keys(returns2?.badges).length).toBe(1); return award; @@ -284,8 +282,7 @@ describe('ProposalController: ' + WEN_FUNC.createProposal + ' MEMBERS', () => { // Disable start date validation. ProposalStartDateMin.value = -60 * 60; RelatedRecordsResponse.status = true; - walletSpy = jest.spyOn(wallet, 'decodeAuth'); - memberId = await createMember(walletSpy); + memberId = await testEnv.createMember(); space = await cSpace(memberId); token = await saveBaseToken(space.uid, memberId); @@ -311,13 +308,12 @@ describe('ProposalController: ' + WEN_FUNC.createProposal + ' MEMBERS', () => { expect(vResult?.payload?.weight).toEqual(1); await vote(memberId, proposal, 2); - const proposalDocRef = build5Db().doc(`${COL.PROPOSAL}/${proposal.uid}`); + const proposalDocRef = build5Db().doc(COL.PROPOSAL, proposal.uid); proposal = await proposalDocRef.get(); - expect(proposal.results.answers[2]).toBe(1); }); - it('create proposal, approve & vote twice on different ', async () => { + it('create proposal, approve & vote twice on different', async () => { await giveBadge(memberId, memberId, space, token.symbol, 10); let proposal: Proposal = await cProposal(memberId, space, ProposalType.MEMBERS); @@ -326,9 +322,10 @@ describe('ProposalController: ' + WEN_FUNC.createProposal + ' MEMBERS', () => { const vResult = await vote(memberId, proposal, 2); expect(vResult?.payload).toBeDefined(); expect(vResult?.payload?.weight).toEqual(1); + await vote(memberId, proposal, 1); - const proposalDocRef = build5Db().doc(`${COL.PROPOSAL}/${proposal.uid}`); + const proposalDocRef = build5Db().doc(COL.PROPOSAL, proposal.uid); proposal = await proposalDocRef.get(); expect(proposal.results.answers[2]).toBe(0); @@ -336,14 +333,14 @@ describe('ProposalController: ' + WEN_FUNC.createProposal + ' MEMBERS', () => { }); it('create proposal, approve & vote - 7 ppl all same', async () => { - const memberId = await createMember(walletSpy); - const memberId1 = await createMember(walletSpy); - const memberId2 = await createMember(walletSpy); - const memberId3 = await createMember(walletSpy); - const memberId4 = await createMember(walletSpy); - const memberId5 = await createMember(walletSpy); - const memberId6 = await createMember(walletSpy); - const memberId7 = await createMember(walletSpy); + const memberId = await testEnv.createMember(); + const memberId1 = await testEnv.createMember(); + const memberId2 = await testEnv.createMember(); + const memberId3 = await testEnv.createMember(); + const memberId4 = await testEnv.createMember(); + const memberId5 = await testEnv.createMember(); + const memberId6 = await testEnv.createMember(); + const memberId7 = await testEnv.createMember(); const space = await cSpace(memberId); await jSpace(memberId1, space); await jSpace(memberId2, space); @@ -367,8 +364,8 @@ describe('ProposalController: ' + WEN_FUNC.createProposal + ' MEMBERS', () => { expect(v?.payload).toBeDefined(); expect(v?.payload?.weight).toEqual(1); - const proposalDocRef = build5Db().doc(`${COL.PROPOSAL}/${proposal.uid}`); - proposal = await proposalDocRef.get(); + const proposalDocRef = build5Db().doc(COL.PROPOSAL, proposal.uid); + proposal = (await proposalDocRef.get())!; expect(proposal.results.answers['1']).toEqual(7); expect(proposal.results.voted).toEqual(7); expect(proposal.results.total).toEqual(8); @@ -376,14 +373,14 @@ describe('ProposalController: ' + WEN_FUNC.createProposal + ' MEMBERS', () => { }); it('create proposal, approve & vote - 7 ppl 4/3', async () => { - const memberId = await createMember(walletSpy); - const memberId1 = await createMember(walletSpy); - const memberId2 = await createMember(walletSpy); - const memberId3 = await createMember(walletSpy); - const memberId4 = await createMember(walletSpy); - const memberId5 = await createMember(walletSpy); - const memberId6 = await createMember(walletSpy); - const memberId7 = await createMember(walletSpy); + const memberId = await testEnv.createMember(); + const memberId1 = await testEnv.createMember(); + const memberId2 = await testEnv.createMember(); + const memberId3 = await testEnv.createMember(); + const memberId4 = await testEnv.createMember(); + const memberId5 = await testEnv.createMember(); + const memberId6 = await testEnv.createMember(); + const memberId7 = await testEnv.createMember(); const space = await cSpace(memberId); await jSpace(memberId1, space); await jSpace(memberId2, space); @@ -406,8 +403,8 @@ describe('ProposalController: ' + WEN_FUNC.createProposal + ' MEMBERS', () => { expect(v?.payload).toBeDefined(); expect(v?.payload?.weight).toEqual(1); - const proposalDocRef = build5Db().doc(`${COL.PROPOSAL}/${proposal.uid}`); - proposal = await proposalDocRef.get(); + const proposalDocRef = build5Db().doc(COL.PROPOSAL, proposal.uid); + proposal = (await proposalDocRef.get())!; expect(proposal.results.answers['1']).toEqual(4); expect(proposal.results.answers['2']).toEqual(3); expect(proposal.results.voted).toEqual(7); @@ -416,12 +413,12 @@ describe('ProposalController: ' + WEN_FUNC.createProposal + ' MEMBERS', () => { }); it('create proposal, approve & vote - 4 ppl badges', async () => { - const memberId = await createMember(walletSpy); - const memberId1 = await createMember(walletSpy); - const memberId2 = await createMember(walletSpy); - const memberId3 = await createMember(walletSpy); - const memberId4 = await createMember(walletSpy); - const memberId5 = await createMember(walletSpy); + const memberId = await testEnv.createMember(); + const memberId1 = await testEnv.createMember(); + const memberId2 = await testEnv.createMember(); + const memberId3 = await testEnv.createMember(); + const memberId4 = await testEnv.createMember(); + const memberId5 = await testEnv.createMember(); const space = await cSpace(memberId); await jSpace(memberId1, space); await jSpace(memberId2, space); @@ -455,8 +452,8 @@ describe('ProposalController: ' + WEN_FUNC.createProposal + ' MEMBERS', () => { expect(v?.payload).toBeDefined(); expect(v?.payload?.weight).toEqual(1); - const proposalDocRef = build5Db().doc(`${COL.PROPOSAL}/${proposal.uid}`); - proposal = await proposalDocRef.get(); + const proposalDocRef = build5Db().doc(COL.PROPOSAL, proposal.uid); + proposal = (await proposalDocRef.get())!; expect(proposal.results.answers['1']).toEqual(2); expect(proposal.results.answers['2']).toEqual(3); expect(proposal.results.voted).toEqual(5); @@ -470,19 +467,18 @@ export const saveBaseToken = async (space: string, guardian: string) => { project: SOON_PROJECT_ID, symbol: getRandomSymbol(), approved: true, - updatedOn: serverTime(), - createdOn: serverTime(), + updatedOn: serverTime().toDate(), + createdOn: serverTime().toDate(), space, uid: getRandomEthAddress(), createdBy: guardian, name: 'MyToken', - status: TokenStatus.BASE, - access: 0, + status: PgTokenStatus.BASE, + access: PgAccess.OPEN, icon: MEDIA, - mintingData: { - network: Network.RMS, - }, + mintingData_network: PgNetwork.RMS, }; - await build5Db().doc(`${COL.TOKEN}/${token.uid}`).set(token); - return token as Token; + const docRef = build5Db().doc(COL.TOKEN, token.uid); + await docRef.upsert(token); + return (await docRef.get())!; }; diff --git a/packages/functions/test/controls/space.spec.ts b/packages/functions/test/controls/space.spec.ts index 8613f80782..a5e3dc56bc 100644 --- a/packages/functions/test/controls/space.spec.ts +++ b/packages/functions/test/controls/space.spec.ts @@ -1,4 +1,4 @@ -import { build5Db } from '@build-5/database'; +import { PgTokenStatus, PgTransactionType, build5Db } from '@build-5/database'; import { ADD_REMOVE_GUARDIAN_THRESHOLD_PERCENTAGE, COL, @@ -9,42 +9,16 @@ import { SOON_PROJECT_ID, SUB_COL, Space, - StakeType, - TokenStatus, - Transaction, - TransactionType, + SpaceMember, UPDATE_SPACE_THRESHOLD_PERCENTAGE, WEN_FUNC, WenError, } from '@build-5/interfaces'; import dayjs from 'dayjs'; import { tail } from 'lodash'; -import { voteOnProposal } from '../../src/runtime/firebase/proposal'; -import { - acceptMemberSpace, - addGuardian, - blockMember, - createSpace, - declineMemberSpace, - joinSpace, - leaveSpace, - removeGuardian, - unblockMember, - updateSpace, -} from '../../src/runtime/firebase/space'; import * as wallet from '../../src/utils/wallet.utils'; -import { testEnv } from '../set-up'; -import { - addGuardianToSpace, - createMember, - createSpace as createSpaceFunc, - expectThrow, - mockWalletReturnValue, - removeGuardianFromSpace, - wait, -} from './common'; - -let walletSpy: any; +import { mockWalletReturnValue, testEnv } from '../set-up'; +import { addGuardianToSpace, expectThrow, removeGuardianFromSpace, wait } from './common'; const assertCreatedOnAndId = (data: any, uid: string) => { expect(data).toBeDefined(); @@ -53,65 +27,53 @@ const assertCreatedOnAndId = (data: any, uid: string) => { }; const joinSpaceFunc = async (member: string, uid: string) => { - mockWalletReturnValue(walletSpy, member, { uid }); - const jSpace = await testEnv.wrap(joinSpace)({}); + mockWalletReturnValue(member, { uid }); + const jSpace = await testEnv.wrap(WEN_FUNC.joinSpace); assertCreatedOnAndId(jSpace, member); }; -/** - * TODO - * at_least_one_guardian_must_be_in_the_space - */ -describe('SpaceController: ' + WEN_FUNC.createSpace, () => { - it('successfully create space', async () => { - const dummyAddress = wallet.getRandomEthAddress(); - walletSpy = jest.spyOn(wallet, 'decodeAuth'); - mockWalletReturnValue(walletSpy, dummyAddress, {}); - - const returns = await testEnv.wrap(createSpace)({}); - expect(returns?.uid).toBeDefined(); - expect(returns?.createdOn).toBeDefined(); - expect(returns?.updatedOn).toBeDefined(); - - // am I member and guardian. - expect(returns.members).toBeDefined(); - expect(returns.members[dummyAddress]).toBeDefined(); - expect(returns.guardians).toBeDefined(); - expect(returns.guardians[dummyAddress]).toBeDefined(); - expect(returns?.totalGuardians).toEqual(1); - expect(returns?.totalMembers).toEqual(1); - expect(returns?.totalPendingMembers).toEqual(0); - walletSpy.mockRestore(); - }); - - it('successfully create space with name', async () => { - walletSpy = jest.spyOn(wallet, 'decodeAuth'); - mockWalletReturnValue(walletSpy, wallet.getRandomEthAddress(), { - name: 'Space ABC', - about: 'very cool', +/** * TODO * at_least_one_guardian_must_be_in_the_space */ describe( + 'SpaceController: ' + WEN_FUNC.createSpace, + () => { + let member: string; + beforeEach(async () => { + member = await testEnv.createMember(); }); - const returns = await testEnv.wrap(createSpace)({}); - expect(returns?.uid).toBeDefined(); - expect(returns?.name).toEqual('Space ABC'); - expect(returns?.about).toEqual('very cool'); - expect(returns?.totalGuardians).toEqual(1); - expect(returns?.totalMembers).toEqual(1); - walletSpy.mockRestore(); - }); -}); + it('successfully create space', async () => { + mockWalletReturnValue(member, {}); + const space = await testEnv.wrap(WEN_FUNC.createSpace); + expect(space.uid).toBeDefined(); + expect(space.createdOn).toBeDefined(); + expect(space.updatedOn).toBeDefined(); + expect(space.totalGuardians).toEqual(1); + expect(space.totalMembers).toEqual(1); + expect(space.totalPendingMembers).toEqual(0); + }); + + it('successfully create space with name', async () => { + mockWalletReturnValue(member, { + name: 'Space ABC', + about: 'very cool', + }); + const space = await testEnv.wrap(WEN_FUNC.createSpace); + expect(space.uid).toBeDefined(); + expect(space.name).toEqual('Space ABC'); + expect(space.about).toEqual('very cool'); + expect(space.totalGuardians).toEqual(1); + expect(space.totalMembers).toEqual(1); + }); + }, +); describe('SpaceController: ' + WEN_FUNC.updateSpace, () => { let guardian: string; let member: string; let space: Space; - beforeEach(async () => { - walletSpy = jest.spyOn(wallet, 'decodeAuth'); - guardian = await createMember(walletSpy); - member = await createMember(walletSpy); - space = await createSpaceFunc(walletSpy, guardian); - + guardian = await testEnv.createMember(); + member = await testEnv.createMember(); + space = await testEnv.createSpace(guardian); await addGuardianToSpace(space.uid, member); }); @@ -123,41 +85,29 @@ describe('SpaceController: ' + WEN_FUNC.updateSpace, () => { twitter: 'asdasd', discord: 'adamkun1233', }; - const owner = await build5Db().doc(`${COL.MEMBER}/${guardian}`).get(); - mockWalletReturnValue(walletSpy, guardian, updateParams); - const proposal = await testEnv.wrap(updateSpace)({}); - + const owner = await build5Db().doc(COL.MEMBER, guardian).get(); + mockWalletReturnValue(guardian, updateParams); + const proposal = await testEnv.wrap(WEN_FUNC.updateSpace); expect(proposal.type).toBe(ProposalType.EDIT_SPACE); expect(proposal.approved).toBe(true); expect(proposal.results?.total).toBe(2); expect(proposal.results?.voted).toBe(1); expect(proposal.results?.answers).toEqual({ [1]: 1 }); expect(proposal.additionalInfo).toBe( - `${owner.name} wants to edit the space. ` + + `${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`, ); expect(proposal.name).toBe('Edit space'); - - // TODO - I'm running out of time and need to release this. - // expect(proposal.questions[0].additionalInfo).toBe( - // 'Changes requested.
' + - // 'Name: abc (previously: Space A)
' + - // 'Discord: adamkun1233 (previously: None)
' + - // 'Github: sadas (previously: None)
' + - // 'Twitter: asdasd (previously: None)
', - // ); - - space = await build5Db().doc(`${COL.SPACE}/${space.uid}`).get(); + // TODO - I'm running out of time and need to release this. // expect(proposal.questions[0].additionalInfo).toBe( // 'Changes requested.
' + // 'Name: abc (previously: Space A)
' + // 'Discord: adamkun1233 (previously: None)
' + // 'Github: sadas (previously: None)
' + // 'Twitter: asdasd (previously: None)
', // ); + space = await build5Db().doc(COL.SPACE, space.uid).get(); const updatedOn = space.updatedOn; - mockWalletReturnValue(walletSpy, member, { uid: proposal.uid, value: 1 }); - await testEnv.wrap(voteOnProposal)({}); - + mockWalletReturnValue(member, { uid: proposal.uid, value: 1 }); + await testEnv.wrap(WEN_FUNC.voteOnProposal); await wait(async () => { - space = await build5Db().doc(`${COL.SPACE}/${space.uid}`).get(); + space = await build5Db().doc(COL.SPACE, space.uid).get(); return dayjs(updatedOn?.toDate()).isBefore(dayjs(space.updatedOn?.toDate())); }); - expect(space.name).toBe(updateParams.name); expect(space.github).toBe(updateParams.github); expect(space.twitter).toBe(updateParams.twitter); @@ -166,34 +116,32 @@ describe('SpaceController: ' + WEN_FUNC.updateSpace, () => { it('failed to update space - invalid URL', async () => { const updateParams = { uid: space?.uid, name: 'abc', twitter: 'WRONG URL' }; - mockWalletReturnValue(walletSpy, guardian, updateParams); - await expectThrow(testEnv.wrap(updateSpace)({}), WenError.invalid_params.key); - walletSpy.mockRestore(); + mockWalletReturnValue(guardian, updateParams); + await expectThrow(testEnv.wrap(WEN_FUNC.updateSpace), WenError.invalid_params.key); }); it('failed to update space - missing UID', async () => { - mockWalletReturnValue(walletSpy, guardian, { name: 'abc' }); - await expectThrow(testEnv.wrap(updateSpace)({}), WenError.invalid_params.key); - walletSpy.mockRestore(); + mockWalletReturnValue(guardian, { name: 'abc' }); + await expectThrow(testEnv.wrap(WEN_FUNC.updateSpace), WenError.invalid_params.key); }); it('failed to update space - does not exists', async () => { - mockWalletReturnValue(walletSpy, guardian, { uid: guardian, name: 'abc' }); - await expectThrow(testEnv.wrap(updateSpace)({}), WenError.space_does_not_exists.key); - walletSpy.mockRestore(); + mockWalletReturnValue(guardian, { uid: guardian, name: 'abc' }); + await expectThrow(testEnv.wrap(WEN_FUNC.updateSpace), WenError.space_does_not_exists.key); }); it('Should only allow one ongoing edit proposal', async () => { const updateParams = { uid: space?.uid, name: 'new name' }; - mockWalletReturnValue(walletSpy, guardian, updateParams); - const proposal = await testEnv.wrap(updateSpace)({}); - await expectThrow(testEnv.wrap(updateSpace)({}), WenError.ongoing_proposal.key); + mockWalletReturnValue(guardian, updateParams); + const proposal = await testEnv.wrap(WEN_FUNC.updateSpace); - mockWalletReturnValue(walletSpy, member, { uid: proposal.uid, value: 1 }); - await testEnv.wrap(voteOnProposal)({}); + mockWalletReturnValue(guardian, updateParams); + await expectThrow(testEnv.wrap(WEN_FUNC.updateSpace), WenError.ongoing_proposal.key); + mockWalletReturnValue(member, { uid: proposal.uid, value: 1 }); + await testEnv.wrap(WEN_FUNC.voteOnProposal); await wait(async () => { - space = await build5Db().doc(`${COL.SPACE}/${space.uid}`).get(); + space = await build5Db().doc(COL.SPACE, space.uid).get(); return space.name === 'new name'; }); }); @@ -205,102 +153,113 @@ describe('SpaceController: member management', () => { let space: Space; beforeEach(async () => { - walletSpy = jest.spyOn(wallet, 'decodeAuth'); - guardian = wallet.getRandomEthAddress(); - member = wallet.getRandomEthAddress(); - mockWalletReturnValue(walletSpy, guardian, { name: 'This space rocks' }); - space = await testEnv.wrap(createSpace)({}); - expect(space?.uid).toBeDefined(); + guardian = await testEnv.createMember(); + member = await testEnv.createMember(); + mockWalletReturnValue(guardian, { name: 'This space rocks' }); + space = await testEnv.wrap(WEN_FUNC.createSpace); }); it('successfully join space', async () => { await joinSpaceFunc(member, space.uid); - const memberDocRef = build5Db().doc(`${COL.MEMBER}/${member}`); + const memberDocRef = build5Db().doc(COL.MEMBER, member); const memberData = await memberDocRef.get(); expect((memberData.spaces || {})[space.uid].isMember).toBe(true); }); it('fail to join space - already in', async () => { - mockWalletReturnValue(walletSpy, guardian, { uid: space.uid }); - await expectThrow(testEnv.wrap(joinSpace)({}), WenError.you_are_already_part_of_space.key); + mockWalletReturnValue(guardian, { uid: space.uid }); + await expectThrow( + testEnv.wrap(WEN_FUNC.joinSpace), + WenError.you_are_already_part_of_space.key, + ); }); it('successfully leave space', async () => { await joinSpaceFunc(member, space.uid); - const lSpace = await testEnv.wrap(leaveSpace)({}); + mockWalletReturnValue(member, { uid: space.uid }); + const lSpace = await testEnv.wrap<{ status: string }>(WEN_FUNC.leaveSpace); expect(lSpace).toBeDefined(); expect(lSpace.status).toEqual('success'); - const memberDocRef = build5Db().doc(`${COL.MEMBER}/${member}`); + const memberDocRef = build5Db().doc(COL.MEMBER, member); const memberData = await memberDocRef.get(); expect((memberData.spaces || {})[space.uid].isMember).toBe(false); }); it('fail to leave space - as only guardian', async () => { await joinSpaceFunc(member, space.uid); - mockWalletReturnValue(walletSpy, guardian, { uid: space.uid }); + mockWalletReturnValue(guardian, { uid: space.uid }); await expectThrow( - testEnv.wrap(leaveSpace)({}), + testEnv.wrap(WEN_FUNC.leaveSpace), WenError.at_least_one_guardian_must_be_in_the_space.key, ); }); it('fail to leave space - as only member', async () => { - mockWalletReturnValue(walletSpy, guardian, { uid: space.uid }); + mockWalletReturnValue(guardian, { uid: space.uid }); await expectThrow( - testEnv.wrap(leaveSpace)({}), + testEnv.wrap(WEN_FUNC.leaveSpace), WenError.at_least_one_member_must_be_in_the_space.key, ); }); it('fail to leave space where Im not in', async () => { - mockWalletReturnValue(walletSpy, member, { uid: space.uid }); - await expectThrow(testEnv.wrap(leaveSpace)({}), WenError.you_are_not_part_of_the_space.key); + mockWalletReturnValue(member, { uid: space.uid }); + await expectThrow( + testEnv.wrap(WEN_FUNC.leaveSpace), + WenError.you_are_not_part_of_the_space.key, + ); }); it('fail to make guardian - must be member', async () => { - mockWalletReturnValue(walletSpy, guardian, { uid: space.uid, member }); - await expectThrow(testEnv.wrap(addGuardian)({}), WenError.member_is_not_part_of_the_space.key); + mockWalletReturnValue(guardian, { uid: space.uid, member }); + await expectThrow( + testEnv.wrap(WEN_FUNC.addGuardianSpace), + WenError.member_is_not_part_of_the_space.key, + ); }); it('fail to make guardian - already is', async () => { - mockWalletReturnValue(walletSpy, guardian, { uid: space.uid, member: guardian }); + mockWalletReturnValue(guardian, { uid: space.uid, member: guardian }); await expectThrow( - testEnv.wrap(addGuardian)({}), + testEnv.wrap(WEN_FUNC.addGuardianSpace), WenError.member_is_already_guardian_of_space.key, ); }); it('successfully block member', async () => { await joinSpaceFunc(member, space.uid); - mockWalletReturnValue(walletSpy, guardian, { uid: space.uid, member }); - const blockMemberResult = await testEnv.wrap(blockMember)({}); + mockWalletReturnValue(guardian, { uid: space.uid, member }); + const blockMemberResult = await testEnv.wrap(WEN_FUNC.blockMemberSpace); assertCreatedOnAndId(blockMemberResult, member); - const spaceDocRef = build5Db().doc(`${COL.SPACE}/${space.uid}`); + const spaceDocRef = build5Db().doc(COL.SPACE, space.uid); space = await spaceDocRef.get(); expect(space.totalGuardians).toBe(1); expect(space.totalMembers).toBe(1); - const guardianCount = await spaceDocRef.collection(SUB_COL.GUARDIANS).count(); + const guardianCount = await build5Db() + .collection(COL.SPACE, space.uid, SUB_COL.GUARDIANS) + .count(); expect(guardianCount).toBe(1); - const memberCount = await spaceDocRef.collection(SUB_COL.MEMBERS).count(); + const memberCount = await build5Db().collection(COL.SPACE, space.uid, SUB_COL.MEMBERS).count(); expect(memberCount).toBe(1); }); it('block member and unblock', async () => { await joinSpaceFunc(member, space.uid); - mockWalletReturnValue(walletSpy, guardian, { uid: space.uid, member }); - const bMember = await testEnv.wrap(blockMember)({}); + mockWalletReturnValue(guardian, { uid: space.uid, member }); + const bMember = await testEnv.wrap(WEN_FUNC.blockMemberSpace); assertCreatedOnAndId(bMember, member); - const spaceDocRef = build5Db().doc(`${COL.SPACE}/${space.uid}`); - const blockedDocRef = spaceDocRef.collection(SUB_COL.BLOCKED_MEMBERS).doc(member); + const spaceDocRef = build5Db().doc(COL.SPACE, space.uid); + const blockedDocRef = build5Db().doc(COL.SPACE, space.uid, SUB_COL.BLOCKED_MEMBERS, member); let blocked = await blockedDocRef.get(); expect(blocked).toBeDefined(); - const ubMember = await testEnv.wrap(unblockMember)({}); + mockWalletReturnValue(guardian, { uid: space.uid, member }); + const ubMember = await testEnv.wrap<{ status: string }>(WEN_FUNC.unblockMemberSpace); expect(ubMember).toBeDefined(); expect(ubMember.status).toEqual('success'); @@ -308,10 +267,12 @@ describe('SpaceController: member management', () => { expect(space.totalGuardians).toBe(1); expect(space.totalMembers).toBe(1); - const guardianCount = await spaceDocRef.collection(SUB_COL.GUARDIANS).count(); + const guardianCount = await build5Db() + .collection(COL.SPACE, space.uid, SUB_COL.GUARDIANS) + .count(); expect(guardianCount).toBe(1); - const memberCount = await spaceDocRef.collection(SUB_COL.MEMBERS).count(); + const memberCount = await build5Db().collection(COL.SPACE, space.uid, SUB_COL.MEMBERS).count(); expect(memberCount).toBe(1); blocked = await blockedDocRef.get(); @@ -319,36 +280,37 @@ describe('SpaceController: member management', () => { }); it('fail to block member - if its the only one', async () => { - mockWalletReturnValue(walletSpy, guardian, { uid: space.uid, member: guardian }); + mockWalletReturnValue(guardian, { uid: space.uid, member: guardian }); await expectThrow( - testEnv.wrap(blockMember)({}), + testEnv.wrap(WEN_FUNC.blockMemberSpace), WenError.at_least_one_member_must_be_in_the_space.key, ); }); it('fail to block myself if Im only guardian', async () => { await joinSpaceFunc(member, space.uid); - mockWalletReturnValue(walletSpy, guardian, { uid: space.uid, member: guardian }); - await expectThrow(testEnv.wrap(blockMember)({}), WenError.can_not_block_guardian.key); + mockWalletReturnValue(guardian, { uid: space.uid, member: guardian }); + await expectThrow(testEnv.wrap(WEN_FUNC.blockMemberSpace), WenError.can_not_block_guardian.key); }); it('successfully block member and unable to join space', async () => { await joinSpaceFunc(member, space.uid); - - mockWalletReturnValue(walletSpy, guardian, { uid: space.uid, member }); - const bMember = await testEnv.wrap(blockMember)({}); + mockWalletReturnValue(guardian, { uid: space.uid, member }); + const bMember = await testEnv.wrap(WEN_FUNC.blockMemberSpace); assertCreatedOnAndId(bMember, member); - mockWalletReturnValue(walletSpy, member, { uid: space.uid }); - await expectThrow(testEnv.wrap(joinSpace)({}), WenError.you_are_not_allowed_to_join_space.key); + mockWalletReturnValue(member, { uid: space.uid }); + await expectThrow( + testEnv.wrap(WEN_FUNC.joinSpace), + WenError.you_are_not_allowed_to_join_space.key, + ); }); describe('SpaceController: member management - NOT OPEN', () => { beforeEach(async () => { - walletSpy = jest.spyOn(wallet, 'decodeAuth'); - guardian = await createMember(walletSpy); - member = await createMember(walletSpy); - space = await createSpaceFunc(walletSpy, guardian); - await build5Db().doc(`${COL.SPACE}/${space.uid}`).update({ open: false }); + guardian = await testEnv.createMember(); + member = await testEnv.createMember(); + space = await testEnv.createSpace(guardian); + await build5Db().doc(COL.SPACE, space.uid).update({ open: false }); }); it('successfully join space', async () => { @@ -357,91 +319,76 @@ describe('SpaceController: member management', () => { it('successfully join space and fail to accept - NOT GUARDIAN', async () => { await joinSpaceFunc(member, space.uid); - - mockWalletReturnValue(walletSpy, member, { uid: space.uid, member }); + mockWalletReturnValue(member, { uid: space.uid, member }); await expectThrow( - testEnv.wrap(acceptMemberSpace)({}), + testEnv.wrap(WEN_FUNC.acceptMemberSpace), WenError.you_are_not_guardian_of_space.key, ); }); it('successfully join space and be accepted', async () => { await joinSpaceFunc(member, space.uid); - - mockWalletReturnValue(walletSpy, guardian, { uid: space.uid, member }); - const aSpace = await testEnv.wrap(acceptMemberSpace)({}); + mockWalletReturnValue(guardian, { uid: space.uid, member }); + const aSpace = await testEnv.wrap(WEN_FUNC.acceptMemberSpace); assertCreatedOnAndId(aSpace, member); }); it('join space, edit space and still able to accept', async () => { await joinSpaceFunc(member, space.uid); - - const guardian2 = await createMember(walletSpy); + const guardian2 = await testEnv.createMember(); await addGuardianToSpace(space.uid, guardian2); const name = 'This space rocks rocks'; - mockWalletReturnValue(walletSpy, guardian, { - uid: space.uid, - name, - open: false, - }); - const proposal = await testEnv.wrap(updateSpace)({}); - - mockWalletReturnValue(walletSpy, guardian2, { uid: proposal.uid, value: 1 }); - await testEnv.wrap(voteOnProposal)({}); - + mockWalletReturnValue(guardian, { uid: space.uid, name, open: false }); + const proposal = await testEnv.wrap(WEN_FUNC.updateSpace); + mockWalletReturnValue(guardian2, { uid: proposal.uid, value: 1 }); + await testEnv.wrap(WEN_FUNC.voteOnProposal); await wait(async () => { - space = await build5Db().doc(`${COL.SPACE}/${space.uid}`).get(); + space = await build5Db().doc(COL.SPACE, space.uid).get(); return space.name === name; }); - - mockWalletReturnValue(walletSpy, guardian, { uid: space.uid, member }); - const aSpace = await testEnv.wrap(acceptMemberSpace)({}); + mockWalletReturnValue(guardian, { uid: space.uid, member }); + const aSpace = await testEnv.wrap(WEN_FUNC.acceptMemberSpace); assertCreatedOnAndId(aSpace, member); }); it('join space, edit space to open and it should no longer be able to accept', async () => { await joinSpaceFunc(member, space.uid); - - const guardian2 = await createMember(walletSpy); + const guardian2 = await testEnv.createMember(); await addGuardianToSpace(space.uid, guardian2); - const name = 'This space rocks rocks'; - mockWalletReturnValue(walletSpy, guardian, { - uid: space.uid, - name, - open: true, - }); - const proposal = await testEnv.wrap(updateSpace)({}); - - mockWalletReturnValue(walletSpy, guardian2, { uid: proposal.uid, value: 1 }); - await testEnv.wrap(voteOnProposal)({}); - + mockWalletReturnValue(guardian, { uid: space.uid, name, open: true }); + const proposal = await testEnv.wrap(WEN_FUNC.updateSpace); + mockWalletReturnValue(guardian2, { uid: proposal.uid, value: 1 }); + await testEnv.wrap(WEN_FUNC.voteOnProposal); await wait(async () => { - space = await build5Db().doc(`${COL.SPACE}/${space.uid}`).get(); + space = await build5Db().doc(COL.SPACE, space.uid).get(); return space.name === name; }); - mockWalletReturnValue(walletSpy, guardian, { uid: space.uid, member }); + mockWalletReturnValue(guardian, { uid: space.uid, member }); await expectThrow( - testEnv.wrap(acceptMemberSpace)({}), + testEnv.wrap(WEN_FUNC.acceptMemberSpace), WenError.member_did_not_request_to_join.key, ); }); it('successfully join space and be rejected', async () => { await joinSpaceFunc(member, space.uid); - - mockWalletReturnValue(walletSpy, guardian, { uid: space.uid, member }); - const declineMemberResult = await testEnv.wrap(declineMemberSpace)({}); + mockWalletReturnValue(guardian, { uid: space.uid, member }); + const declineMemberResult = await testEnv.wrap<{ status: string }>( + WEN_FUNC.declineMemberSpace, + ); expect(declineMemberResult).toBeDefined(); expect(declineMemberResult.status).toEqual('success'); }); it('Should throw on second time when member ask to join', async () => { await joinSpaceFunc(member, space.uid); - - mockWalletReturnValue(walletSpy, member, { uid: space.uid }); - await expectThrow(testEnv.wrap(joinSpace)({}), WenError.member_already_knocking.key); + mockWalletReturnValue(member, { uid: space.uid }); + await expectThrow( + testEnv.wrap(WEN_FUNC.joinSpace), + WenError.member_already_knocking.key, + ); }); }); }); @@ -453,139 +400,137 @@ describe('Add guardian', () => { let space: Space; beforeEach(async () => { - walletSpy = jest.spyOn(wallet, 'decodeAuth'); - let promises: any[] = Array.from(Array(guardianCount)).map(() => createMember(walletSpy)); + let promises: any[] = Array.from(Array(guardianCount)).map(() => testEnv.createMember()); guardians = await Promise.all(promises); - member = await createMember(walletSpy); - space = await createSpaceFunc(walletSpy, guardians[0]); - + member = await testEnv.createMember(); + space = await testEnv.createSpace(guardians[0]); promises = tail(guardians).map(async (guardian) => addGuardianToSpace(space.uid, guardian)); await Promise.all(promises); }); it('Should throw, not guardian of the space', async () => { - mockWalletReturnValue(walletSpy, member, { uid: space.uid, member }); - await expectThrow(testEnv.wrap(addGuardian)({}), WenError.you_are_not_guardian_of_space.key); - mockWalletReturnValue(walletSpy, guardians[0], { uid: wallet.getRandomEthAddress(), member }); - await expectThrow(testEnv.wrap(addGuardian)({}), WenError.you_are_not_guardian_of_space.key); + mockWalletReturnValue(member, { uid: space.uid, member }); + await expectThrow( + testEnv.wrap(WEN_FUNC.addGuardianSpace), + WenError.you_are_not_guardian_of_space.key, + ); + mockWalletReturnValue(guardians[0], { uid: wallet.getRandomEthAddress(), member }); + await expectThrow( + testEnv.wrap(WEN_FUNC.addGuardianSpace), + WenError.you_are_not_guardian_of_space.key, + ); }); it('Should throw, member not part of space', async () => { - mockWalletReturnValue(walletSpy, guardians[0], { uid: space.uid, member }); - await expectThrow(testEnv.wrap(addGuardian)({}), WenError.member_is_not_part_of_the_space.key); + mockWalletReturnValue(guardians[0], { uid: space.uid, member }); + await expectThrow( + testEnv.wrap(WEN_FUNC.addGuardianSpace), + WenError.member_is_not_part_of_the_space.key, + ); }); it('Should throw, member already guardian', async () => { - mockWalletReturnValue(walletSpy, guardians[0], { uid: space.uid, member: guardians[0] }); + mockWalletReturnValue(guardians[0], { + uid: space.uid, + member: guardians[0], + }); await expectThrow( - testEnv.wrap(addGuardian)({}), + testEnv.wrap(WEN_FUNC.addGuardianSpace), WenError.member_is_already_guardian_of_space.key, ); }); const createProposal = async (type: ProposalType, resultTotal: number) => { - mockWalletReturnValue(walletSpy, guardians[0], { uid: space.uid, member }); - const proposal: Proposal = await testEnv.wrap( - type === ProposalType.ADD_GUARDIAN ? addGuardian : removeGuardian, - )({}); - - const guardianData = await build5Db().doc(`${COL.MEMBER}/${guardians[0]}`).get(); - const memberData = await build5Db().doc(`${COL.MEMBER}/${member}`).get(); - + const wenFunc = + type === ProposalType.ADD_GUARDIAN ? WEN_FUNC.addGuardianSpace : WEN_FUNC.removeGuardianSpace; + mockWalletReturnValue(guardians[0], { uid: space.uid, member }); + const proposal = await testEnv.wrap(wenFunc); + const guardianData = await build5Db().doc(COL.MEMBER, guardians[0]).get(); + const memberData = await build5Db().doc(COL.MEMBER, member).get(); expect(proposal.type).toBe(type); expect(proposal.approved).toBe(true); expect(proposal.results?.total).toBe(resultTotal); expect(proposal.results?.voted).toBe(1); expect(proposal.results?.answers).toEqual({ [1]: 1 }); expect(proposal.additionalInfo).toBe( - `${guardianData.name} wants to ${type === ProposalType.ADD_GUARDIAN ? 'add' : 'remove'} ${ - memberData.name - } as guardian. ` + + `${guardianData.uid} wants to ${type === ProposalType.ADD_GUARDIAN ? 'add' : 'remove'} ${memberData.name} as guardian. ` + `Request created on ${dayjs().format('MM/DD/YYYY')}. ` + `${ADD_REMOVE_GUARDIAN_THRESHOLD_PERCENTAGE} % must agree for this action to proceed`, ); expect(proposal.name).toBe(`${type === ProposalType.ADD_GUARDIAN ? 'Add' : 'Remove'} guardian`); - const voteTransaction = await build5Db() .collection(COL.TRANSACTION) .where('member', '==', guardians[0]) - .where('type', '==', TransactionType.VOTE) - .where('payload.proposalId', '==', proposal.uid) - .get(); + .where('type', '==', PgTransactionType.VOTE) + .where('payload_proposalId', '==', proposal.uid) + .get(); expect(voteTransaction.length).toBe(1); - const proposalMember = ( - await build5Db() - .doc(`${COL.PROPOSAL}/${proposal.uid}/${SUB_COL.MEMBERS}/${guardians[0]}`) - .get() + await build5Db().doc(COL.PROPOSAL, proposal.uid, SUB_COL.MEMBERS, guardians[0]).get() ); expect(proposalMember.voted).toBe(true); expect((proposalMember as any).tranId).toBe(voteTransaction[0]?.uid); - return proposal; }; - it('Should add guardian to space after vote, than remove it', async () => { - mockWalletReturnValue(walletSpy, member, { uid: space?.uid }); - await testEnv.wrap(joinSpace)({}); - + it('Should add guardian to space after vote, then remove it', async () => { + mockWalletReturnValue(member, { uid: space?.uid }); + await testEnv.wrap(WEN_FUNC.joinSpace); const proposal = await createProposal(ProposalType.ADD_GUARDIAN, 3); - mockWalletReturnValue(walletSpy, guardians[1], { uid: proposal.uid, value: 0 }); await new Promise((resolve) => setTimeout(resolve, 2000)); - await testEnv.wrap(voteOnProposal)({}); - mockWalletReturnValue(walletSpy, guardians[2], { uid: proposal.uid, value: 1 }); - await testEnv.wrap(voteOnProposal)({}); + mockWalletReturnValue(guardians[1], { uid: proposal.uid, value: 0 }); + await testEnv.wrap(WEN_FUNC.voteOnProposal); + mockWalletReturnValue(guardians[2], { uid: proposal.uid, value: 1 }); + await testEnv.wrap(WEN_FUNC.voteOnProposal); await wait(async () => { - const spaceDocRef = build5Db().doc(`${COL.SPACE}/${space.uid}`); + const spaceDocRef = build5Db().doc(COL.SPACE, space.uid); space = await spaceDocRef.get(); - const guardian = await spaceDocRef.collection(SUB_COL.GUARDIANS).doc(member).get(); + const guardian = await build5Db().doc(COL.SPACE, space.uid, SUB_COL.GUARDIANS, member).get(); return space.totalGuardians === guardianCount + 1 && guardian !== undefined; }); - mockWalletReturnValue(walletSpy, guardians[0], { uid: proposal.uid, value: 0 }); - await expectThrow(testEnv.wrap(voteOnProposal)({}), WenError.vote_is_no_longer_active.key); - + mockWalletReturnValue(guardians[0], { uid: proposal.uid, value: 0 }); + await expectThrow(testEnv.wrap(WEN_FUNC.voteOnProposal), WenError.vote_is_no_longer_active.key); const removeProposal = await createProposal(ProposalType.REMOVE_GUARDIAN, 4); - - mockWalletReturnValue(walletSpy, guardians[1], { uid: removeProposal.uid, value: 1 }); - await testEnv.wrap(voteOnProposal)({}); - mockWalletReturnValue(walletSpy, guardians[2], { uid: removeProposal.uid, value: 1 }); - await testEnv.wrap(voteOnProposal)({}); - + mockWalletReturnValue(guardians[1], { uid: removeProposal.uid, value: 1 }); + await testEnv.wrap(WEN_FUNC.voteOnProposal); + mockWalletReturnValue(guardians[2], { uid: removeProposal.uid, value: 1 }); + await testEnv.wrap(WEN_FUNC.voteOnProposal); await wait(async () => { - const spaceDocRef = build5Db().doc(`${COL.SPACE}/${space.uid}`); + const spaceDocRef = build5Db().doc(COL.SPACE, space.uid); space = await spaceDocRef.get(); - const guardian = await spaceDocRef.collection(SUB_COL.GUARDIANS).doc(member).get(); + const guardian = await build5Db().doc(COL.SPACE, space.uid, SUB_COL.GUARDIANS, member).get(); return space.totalGuardians === guardianCount && guardian === undefined; }); - mockWalletReturnValue(walletSpy, guardians[0], { uid: removeProposal.uid, value: 0 }); - await expectThrow(testEnv.wrap(voteOnProposal)({}), WenError.vote_is_no_longer_active.key); + mockWalletReturnValue(guardians[0], { uid: removeProposal.uid, value: 0 }); + await expectThrow(testEnv.wrap(WEN_FUNC.voteOnProposal), WenError.vote_is_no_longer_active.key); }); it('Should add guardian to space only after threshold reached', async () => { - mockWalletReturnValue(walletSpy, member, { uid: space?.uid }); - await testEnv.wrap(joinSpace)({}); - + mockWalletReturnValue(member, { uid: space?.uid }); + await testEnv.wrap(WEN_FUNC.joinSpace); const proposal = await createProposal(ProposalType.ADD_GUARDIAN, 3); - mockWalletReturnValue(walletSpy, guardians[1], { uid: proposal.uid, value: 0 }); - await testEnv.wrap(voteOnProposal)({}); - mockWalletReturnValue(walletSpy, guardians[2], { uid: proposal.uid, value: 0 }); - await testEnv.wrap(voteOnProposal)({}); + mockWalletReturnValue(guardians[1], { uid: proposal.uid, value: 0 }); + await testEnv.wrap(WEN_FUNC.voteOnProposal); + mockWalletReturnValue(guardians[2], { uid: proposal.uid, value: 0 }); + await testEnv.wrap(WEN_FUNC.voteOnProposal); await new Promise((resolve) => setTimeout(resolve, 2000)); - mockWalletReturnValue(walletSpy, guardians[1], { uid: proposal.uid, value: 1 }); - await testEnv.wrap(voteOnProposal)({}); + + mockWalletReturnValue(guardians[1], { uid: proposal.uid, value: 1 }); + await testEnv.wrap(WEN_FUNC.voteOnProposal); await wait(async () => { - const spaceDocRef = build5Db().doc(`${COL.SPACE}/${space.uid}`); + const spaceDocRef = build5Db().doc(COL.SPACE, space.uid); space = await spaceDocRef.get(); - const guardian = await spaceDocRef.collection(SUB_COL.GUARDIANS).doc(member).get(); + const guardian = await build5Db().doc(COL.SPACE, space.uid, SUB_COL.GUARDIANS, member).get(); return space.totalGuardians === guardianCount + 1 && guardian !== undefined; }); - mockWalletReturnValue(walletSpy, guardians[0], { uid: proposal.uid, value: 0 }); - await expectThrow(testEnv.wrap(voteOnProposal)({}), WenError.vote_is_no_longer_active.key); + + mockWalletReturnValue(guardians[0], { uid: proposal.uid, value: 0 }); + await expectThrow(testEnv.wrap(WEN_FUNC.voteOnProposal), WenError.vote_is_no_longer_active.key); }); it('Should add guardian to space when only one guardiand exists', async () => { @@ -593,67 +538,62 @@ describe('Add guardian', () => { removeGuardianFromSpace(space.uid, guardian), ); await Promise.all(promises); - - mockWalletReturnValue(walletSpy, member, { uid: space?.uid }); - await testEnv.wrap(joinSpace)({}); - + mockWalletReturnValue(member, { uid: space?.uid }); + await testEnv.wrap(WEN_FUNC.joinSpace); await createProposal(ProposalType.ADD_GUARDIAN, 1); - await wait(async () => { - const spaceDocRef = build5Db().doc(`${COL.SPACE}/${space.uid}`); + const spaceDocRef = build5Db().doc(COL.SPACE, space.uid); space = await spaceDocRef.get(); - const guardian = await spaceDocRef.collection(SUB_COL.GUARDIANS).doc(member).get(); + const guardian = await build5Db().doc(COL.SPACE, space.uid, SUB_COL.GUARDIANS, member).get(); return space.totalGuardians === 2 && guardian !== undefined; }); }); it('Should only allow one ongoing add/remove proposal', async () => { - mockWalletReturnValue(walletSpy, member, { uid: space?.uid }); - await testEnv.wrap(joinSpace)({}); - + mockWalletReturnValue(member, { uid: space?.uid }); + await testEnv.wrap(WEN_FUNC.joinSpace); let proposal = await createProposal(ProposalType.ADD_GUARDIAN, 3); await expectThrow(createProposal(ProposalType.ADD_GUARDIAN, 3), WenError.ongoing_proposal.key); - mockWalletReturnValue(walletSpy, guardians[1], { uid: proposal.uid, value: 1 }); - await testEnv.wrap(voteOnProposal)({}); - + mockWalletReturnValue(guardians[1], { uid: proposal.uid, value: 1 }); + await testEnv.wrap(WEN_FUNC.voteOnProposal); await wait(async () => { - const spaceDocRef = build5Db().doc(`${COL.SPACE}/${space.uid}`); + const spaceDocRef = build5Db().doc(COL.SPACE, space.uid); space = await spaceDocRef.get(); - const guardian = await spaceDocRef.collection(SUB_COL.GUARDIANS).doc(member).get(); + const guardian = await build5Db().doc(COL.SPACE, space.uid, SUB_COL.GUARDIANS, member).get(); return space.totalGuardians === guardianCount + 1 && guardian !== undefined; }); - await expectThrow( createProposal(ProposalType.ADD_GUARDIAN, 3), WenError.member_is_already_guardian_of_space.key, ); - const removeProposal = await createProposal(ProposalType.REMOVE_GUARDIAN, 4); await expectThrow( createProposal(ProposalType.REMOVE_GUARDIAN, 4), WenError.ongoing_proposal.key, ); - mockWalletReturnValue(walletSpy, guardians[1], { uid: removeProposal.uid, value: 1 }); - await testEnv.wrap(voteOnProposal)({}); - mockWalletReturnValue(walletSpy, guardians[2], { uid: removeProposal.uid, value: 1 }); - await testEnv.wrap(voteOnProposal)({}); + + mockWalletReturnValue(guardians[1], { uid: removeProposal.uid, value: 1 }); + await testEnv.wrap(WEN_FUNC.voteOnProposal); + + mockWalletReturnValue(guardians[2], { uid: removeProposal.uid, value: 1 }); + await testEnv.wrap(WEN_FUNC.voteOnProposal); await wait(async () => { - const spaceDocRef = build5Db().doc(`${COL.SPACE}/${space.uid}`); + const spaceDocRef = build5Db().doc(COL.SPACE, space.uid); space = await spaceDocRef.get(); - const guardian = await spaceDocRef.collection(SUB_COL.GUARDIANS).doc(member).get(); + const guardian = await build5Db().doc(COL.SPACE, space.uid, SUB_COL.GUARDIANS, member).get(); return space.totalGuardians === guardianCount && guardian === undefined; }); proposal = await createProposal(ProposalType.ADD_GUARDIAN, 3); await expectThrow(createProposal(ProposalType.ADD_GUARDIAN, 3), WenError.ongoing_proposal.key); - mockWalletReturnValue(walletSpy, guardians[1], { uid: proposal.uid, value: 1 }); - await testEnv.wrap(voteOnProposal)({}); + mockWalletReturnValue(guardians[1], { uid: proposal.uid, value: 1 }); + await testEnv.wrap(WEN_FUNC.voteOnProposal); await wait(async () => { - const spaceDocRef = build5Db().doc(`${COL.SPACE}/${space.uid}`); + const spaceDocRef = build5Db().doc(COL.SPACE, space.uid); space = await spaceDocRef.get(); - const guardian = await spaceDocRef.collection(SUB_COL.GUARDIANS).doc(member).get(); + const guardian = await build5Db().doc(COL.SPACE, space.uid, SUB_COL.GUARDIANS, member).get(); return space.totalGuardians === guardianCount + 1 && guardian !== undefined; }); }); @@ -667,153 +607,130 @@ describe('Token based space', () => { let token: string; beforeEach(async () => { - walletSpy = jest.spyOn(wallet, 'decodeAuth'); - guardian = await createMember(walletSpy); - guardian2 = await createMember(walletSpy); - member = await createMember(walletSpy); - space = await createSpaceFunc(walletSpy, guardian); + guardian = await testEnv.createMember(); + guardian2 = await testEnv.createMember(); + member = await testEnv.createMember(); + space = await testEnv.createSpace(guardian); await addGuardianToSpace(space.uid, guardian2); - token = wallet.getRandomEthAddress(); - await build5Db().doc(`${COL.TOKEN}/${token}`).set({ + await build5Db().doc(COL.TOKEN, token).upsert({ project: SOON_PROJECT_ID, - status: TokenStatus.MINTED, + status: PgTokenStatus.MINTED, space: space.uid, - uid: token, approved: true, }); - - mockWalletReturnValue(walletSpy, member, { uid: space?.uid }); - await testEnv.wrap(joinSpace)({}); + mockWalletReturnValue(member, { uid: space?.uid }); + await testEnv.wrap(WEN_FUNC.joinSpace); }); it('Should make space token based, can not update access further but can update others', async () => { await wait(async () => { - space = await build5Db().doc(`${COL.SPACE}/${space.uid}`).get(); + space = await build5Db().doc(COL.SPACE, space.uid).get(); return space.totalGuardians === 2 && space.totalMembers === 3; }); - - const updateParams = { - uid: space?.uid, - tokenBased: true, - minStakedValue: 100, - }; - mockWalletReturnValue(walletSpy, guardian, updateParams); - const proposal = await testEnv.wrap(updateSpace)({}); - - mockWalletReturnValue(walletSpy, guardian2, { uid: proposal.uid, value: 1 }); - await testEnv.wrap(voteOnProposal)({}); - + const updateParams = { uid: space?.uid, tokenBased: true, minStakedValue: 100 }; + mockWalletReturnValue(guardian, updateParams); + const proposal = await testEnv.wrap(WEN_FUNC.updateSpace); + mockWalletReturnValue(guardian2, { uid: proposal.uid, value: 1 }); + await testEnv.wrap(WEN_FUNC.voteOnProposal); await wait(async () => { - space = await build5Db().doc(`${COL.SPACE}/${space.uid}`).get(); + space = await build5Db().doc(COL.SPACE, space.uid).get(); return space.tokenBased === true && space.minStakedValue === updateParams.minStakedValue; }); expect(space.totalGuardians).toBe(1); expect(space.totalMembers).toBe(1); - await addGuardianToSpace(space.uid, guardian); await addGuardianToSpace(space.uid, guardian2); - mockWalletReturnValue(walletSpy, guardian, updateParams); + mockWalletReturnValue(guardian, updateParams); await expectThrow( - testEnv.wrap(updateSpace)({}), + testEnv.wrap(WEN_FUNC.updateSpace), WenError.token_based_space_access_can_not_be_edited.key, ); - mockWalletReturnValue(walletSpy, guardian, { uid: space.uid, open: false }); + + mockWalletReturnValue(guardian, { uid: space.uid, open: false }); await expectThrow( - testEnv.wrap(updateSpace)({}), + testEnv.wrap(WEN_FUNC.updateSpace), WenError.token_based_space_access_can_not_be_edited.key, ); const name = 'second update'; - mockWalletReturnValue(walletSpy, guardian, { uid: space.uid, name }); - const proposal2 = await testEnv.wrap(updateSpace)({}); - mockWalletReturnValue(walletSpy, guardian2, { uid: proposal2.uid, value: 1 }); - await testEnv.wrap(voteOnProposal)({}); - + mockWalletReturnValue(guardian, { uid: space.uid, name }); + const proposal2 = await testEnv.wrap(WEN_FUNC.updateSpace); + mockWalletReturnValue(guardian2, { uid: proposal2.uid, value: 1 }); + await testEnv.wrap(WEN_FUNC.voteOnProposal); await wait(async () => { - space = await build5Db().doc(`${COL.SPACE}/${space.uid}`).get(); + space = await build5Db().doc(COL.SPACE, space.uid).get(); return space.name === name; }); }); it('Should join token based space', async () => { - const updateParams = { - uid: space?.uid, - tokenBased: true, - minStakedValue: 100, - }; - mockWalletReturnValue(walletSpy, guardian, updateParams); - const proposal = await testEnv.wrap(updateSpace)({}); + const updateParams = { uid: space?.uid, tokenBased: true, minStakedValue: 100 }; + mockWalletReturnValue(guardian, updateParams); + const proposal = await testEnv.wrap(WEN_FUNC.updateSpace); - mockWalletReturnValue(walletSpy, guardian2, { uid: proposal.uid, value: 1 }); - await testEnv.wrap(voteOnProposal)({}); + mockWalletReturnValue(guardian2, { uid: proposal.uid, value: 1 }); + await testEnv.wrap(WEN_FUNC.voteOnProposal); await wait(async () => { - space = await build5Db().doc(`${COL.SPACE}/${space.uid}`).get(); + space = await build5Db().doc(COL.SPACE, space.uid).get(); return space.tokenBased === true && space.minStakedValue === updateParams.minStakedValue; }); - const newMember = await createMember(walletSpy); + const newMember = await testEnv.createMember(); await build5Db() - .doc(`${COL.TOKEN}/${token}/${SUB_COL.DISTRIBUTION}/${newMember}`) - .set({ stakes: { [StakeType.DYNAMIC]: { value: 200 } } }); - mockWalletReturnValue(walletSpy, newMember, { uid: space?.uid }); - await testEnv.wrap(joinSpace)({}); + .doc(COL.TOKEN, token, SUB_COL.DISTRIBUTION, newMember) + .upsert({ stakes_dynamic_value: 200 }); + mockWalletReturnValue(newMember, { uid: space?.uid }); + await testEnv.wrap(WEN_FUNC.joinSpace); await wait(async () => { - space = await build5Db().doc(`${COL.SPACE}/${space.uid}`).get(); + space = await build5Db().doc(COL.SPACE, space.uid).get(); return space.totalMembers === 2 && space.totalGuardians === 1; }); }); it('Should not remove member as it has enough stakes', async () => { await build5Db() - .doc(`${COL.TOKEN}/${token}/${SUB_COL.DISTRIBUTION}/${member}`) - .set({ stakes: { [StakeType.DYNAMIC]: { value: 200 } } }); + .doc(COL.TOKEN, token, SUB_COL.DISTRIBUTION, member) + .upsert({ stakes_dynamic_value: 200 }); + const updateParams = { uid: space?.uid, tokenBased: true, minStakedValue: 100 }; - const updateParams = { - uid: space?.uid, - tokenBased: true, - minStakedValue: 100, - }; - mockWalletReturnValue(walletSpy, guardian, updateParams); - const proposal = await testEnv.wrap(updateSpace)({}); + mockWalletReturnValue(guardian, updateParams); + const proposal = await testEnv.wrap(WEN_FUNC.updateSpace); - mockWalletReturnValue(walletSpy, guardian2, { uid: proposal.uid, value: 1 }); - await testEnv.wrap(voteOnProposal)({}); + mockWalletReturnValue(guardian2, { uid: proposal.uid, value: 1 }); + await testEnv.wrap(WEN_FUNC.voteOnProposal); await wait(async () => { - space = await build5Db().doc(`${COL.SPACE}/${space.uid}`).get(); + space = await build5Db().doc(COL.SPACE, space.uid).get(); return space.tokenBased === true && space.minStakedValue === updateParams.minStakedValue; }); + expect(space.totalMembers).toBe(2); expect(space.totalGuardians).toBe(1); }); it('Should not remove guardians as they have enough stakes', async () => { await build5Db() - .doc(`${COL.TOKEN}/${token}/${SUB_COL.DISTRIBUTION}/${guardian}`) - .set({ stakes: { [StakeType.DYNAMIC]: { value: 200 } } }); + .doc(COL.TOKEN, token, SUB_COL.DISTRIBUTION, guardian) + .upsert({ stakes_dynamic_value: 200 }); await build5Db() - .doc(`${COL.TOKEN}/${token}/${SUB_COL.DISTRIBUTION}/${guardian2}`) - .set({ stakes: { [StakeType.DYNAMIC]: { value: 200 } } }); + .doc(COL.TOKEN, token, SUB_COL.DISTRIBUTION, guardian2) + .upsert({ stakes_dynamic_value: 200 }); + const updateParams = { uid: space?.uid, tokenBased: true, minStakedValue: 100 }; - const updateParams = { - uid: space?.uid, - tokenBased: true, - minStakedValue: 100, - }; - mockWalletReturnValue(walletSpy, guardian, updateParams); - const proposal = await testEnv.wrap(updateSpace)({}); - - mockWalletReturnValue(walletSpy, guardian2, { uid: proposal.uid, value: 1 }); - await testEnv.wrap(voteOnProposal)({}); + mockWalletReturnValue(guardian, updateParams); + const proposal = await testEnv.wrap(WEN_FUNC.updateSpace); + mockWalletReturnValue(guardian2, { uid: proposal.uid, value: 1 }); + await testEnv.wrap(WEN_FUNC.voteOnProposal); await wait(async () => { - space = await build5Db().doc(`${COL.SPACE}/${space.uid}`).get(); + space = await build5Db().doc(COL.SPACE, space.uid).get(); return space.tokenBased === true && space.minStakedValue === updateParams.minStakedValue; }); + expect(space.totalMembers).toBe(2); expect(space.totalGuardians).toBe(2); }); diff --git a/packages/functions/test/controls/stake.reward.spec.ts b/packages/functions/test/controls/stake.reward.spec.ts index b7b3da89a7..94329227e6 100644 --- a/packages/functions/test/controls/stake.reward.spec.ts +++ b/packages/functions/test/controls/stake.reward.spec.ts @@ -1,29 +1,37 @@ import { build5Db } from '@build-5/database'; -import { COL, SOON_PROJECT_ID, Space, StakeReward, WenError } from '@build-5/interfaces'; +import { + COL, + SOON_PROJECT_ID, + Space, + StakeReward, + Token, + WEN_FUNC, + WenError, +} from '@build-5/interfaces'; import dayjs from 'dayjs'; -import { stakeReward } from '../../src/runtime/firebase/stake'; import { dateToTimestamp } from '../../src/utils/dateTime.utils'; import * as wallet from '../../src/utils/wallet.utils'; -import { testEnv } from '../set-up'; -import { createMember, createSpace, expectThrow, mockWalletReturnValue } from './common'; +import { mockWalletReturnValue, testEnv } from '../set-up'; +import { expectThrow } from './common'; describe('Stake reward controller', () => { - let walletSpy: any; let guardian: string; let space: Space; let token: string; beforeEach(async () => { - walletSpy = jest.spyOn(wallet, 'decodeAuth'); - guardian = await createMember(walletSpy); - space = await createSpace(walletSpy, guardian); + guardian = await testEnv.createMember(); + space = await testEnv.createSpace(guardian); token = wallet.getRandomEthAddress(); - await build5Db().doc(`${COL.TOKEN}/${token}`).create({ - project: SOON_PROJECT_ID, - uid: token, - space: space.uid, - }); + await build5Db() + .doc(COL.TOKEN, token) + .create({ + project: SOON_PROJECT_ID, + uid: token, + space: space.uid, + links: [] as URL[], + } as Token); }); it('Should throw, token does not exist', async () => { @@ -35,12 +43,12 @@ describe('Stake reward controller', () => { tokensToDistribute: 100, }, ]; - mockWalletReturnValue(walletSpy, guardian, { token: wallet.getRandomEthAddress(), items }); - await expectThrow(testEnv.wrap(stakeReward)({}), WenError.token_does_not_exist.key); + mockWalletReturnValue(guardian, { token: wallet.getRandomEthAddress(), items }); + await expectThrow(testEnv.wrap(WEN_FUNC.stakeReward), WenError.token_does_not_exist.key); }); it('Should throw, not guardian', async () => { - await build5Db().doc(`${COL.TOKEN}/${token}`).update({ space: wallet.getRandomEthAddress() }); + await build5Db().doc(COL.TOKEN, token).update({ space: wallet.getRandomEthAddress() }); const items = [ { startDate: dayjs().valueOf(), @@ -49,8 +57,11 @@ describe('Stake reward controller', () => { tokensToDistribute: 100, }, ]; - mockWalletReturnValue(walletSpy, guardian, { token, items }); - await expectThrow(testEnv.wrap(stakeReward)({}), WenError.you_are_not_guardian_of_space.key); + mockWalletReturnValue(guardian, { token, items }); + await expectThrow( + testEnv.wrap(WEN_FUNC.stakeReward), + WenError.you_are_not_guardian_of_space.key, + ); }); it('Should create rewards', async () => { @@ -63,11 +74,12 @@ describe('Stake reward controller', () => { tokensToDistribute: 100, }, ]; - mockWalletReturnValue(walletSpy, guardian, { token, items: [items[0], items[0]] }); - const stakeRewards: StakeReward[] = await testEnv.wrap(stakeReward)({}); + mockWalletReturnValue(guardian, { token, items: [items[0], items[0]] }); + const stakeRewards: StakeReward[] = await testEnv.wrap(WEN_FUNC.stakeReward); expect(stakeRewards.length).toBe(2); - for (const stakeReward of stakeRewards) { + for (let stakeReward of stakeRewards) { + stakeReward = (await build5Db().doc(COL.STAKE_REWARD, stakeReward.uid).get())!; expect(stakeReward.uid).toBeDefined(); expect(stakeReward.token).toBe(token); expect( @@ -99,8 +111,8 @@ describe('Stake reward controller', () => { tokensToDistribute: 100, }, ]; - mockWalletReturnValue(walletSpy, guardian, { token, items }); - await expectThrow(testEnv.wrap(stakeReward)({}), WenError.invalid_params.key); + mockWalletReturnValue(guardian, { token, items }); + await expectThrow(testEnv.wrap(WEN_FUNC.stakeReward), WenError.invalid_params.key); }); it('Should throw, vesting date before end date', async () => { @@ -113,7 +125,7 @@ describe('Stake reward controller', () => { tokensToDistribute: 100, }, ]; - mockWalletReturnValue(walletSpy, guardian, { token, items }); - await expectThrow(testEnv.wrap(stakeReward)({}), WenError.invalid_params.key); + mockWalletReturnValue(guardian, { token, items }); + await expectThrow(testEnv.wrap(WEN_FUNC.stakeReward), WenError.invalid_params.key); }); }); diff --git a/packages/functions/test/controls/stamp.control.spec.ts b/packages/functions/test/controls/stamp.control.spec.ts index 1657ffff45..fd64d668b3 100644 --- a/packages/functions/test/controls/stamp.control.spec.ts +++ b/packages/functions/test/controls/stamp.control.spec.ts @@ -6,40 +6,32 @@ import { SOON_PROJECT_ID, STAMP_COST_PER_MB, SUB_COL, - SpaceGuardian, - Stamp, Transaction, TransactionPayloadType, TransactionType, TransactionValidationType, + WEN_FUNC, } from '@build-5/interfaces'; -import { stamp as stampFunc } from '../../src/runtime/firebase/stamp'; import { EMPTY_ALIAS_ID } from '../../src/utils/token-minting-utils/alias.utils'; import * as wallet from '../../src/utils/wallet.utils'; -import { testEnv } from '../set-up'; -import { createMember, mockWalletReturnValue } from './common'; +import { mockWalletReturnValue, testEnv } from '../set-up'; describe('Stamp control', () => { - let walletSpy: any; let member: string; let dowloadUrl: string; - beforeAll(async () => { - walletSpy = jest.spyOn(wallet, 'decodeAuth'); - }); - beforeEach(async () => { const bucket = build5Storage().bucket(Bucket.DEV); const destination = `nft/${wallet.getRandomEthAddress()}/image.jpeg`; dowloadUrl = await bucket.upload('./test/puppy.jpeg', destination, { contentType: 'image/jpeg', }); - member = await createMember(walletSpy); + member = await testEnv.createMember(); }); it('Should create stamp order', async () => { - mockWalletReturnValue(walletSpy, member, { network: Network.RMS, file: dowloadUrl }); - const order = (await testEnv.wrap(stampFunc)({})) as Transaction; + mockWalletReturnValue(member, { network: Network.RMS, file: dowloadUrl }); + const order = await testEnv.wrap(WEN_FUNC.stamp); expect(order.project).toBe(SOON_PROJECT_ID); expect(order.type).toBe(TransactionType.ORDER); expect(order.member).toBe(member); @@ -51,10 +43,10 @@ describe('Stamp control', () => { expect(order.payload.stamp).toBeDefined(); expect(order.payload.aliasId).toBe(''); expect(order.payload.aliasOutputAmount).toBe(53700); - expect(order.payload.nftOutputAmount).toBe(107700); + expect(order.payload.nftOutputAmount).toBe(104500); - const stampDocRef = build5Db().doc(`${COL.STAMP}/${order.payload.stamp}`); - const stamp = await stampDocRef.get(); + const stampDocRef = build5Db().doc(COL.STAMP, order.payload.stamp!); + const stamp = await stampDocRef.get(); expect(stamp?.space).toBe(order.space); expect(stamp?.build5Url).toBe(dowloadUrl); expect(stamp?.originUri).toBe(dowloadUrl); @@ -68,9 +60,8 @@ describe('Stamp control', () => { expect(stamp?.aliasId).toBe(EMPTY_ALIAS_ID); expect(stamp?.nftId).toBeUndefined(); - const spaceDocRef = build5Db().doc(`${COL.SPACE}/${order.space}`); - const guardianDocRef = spaceDocRef.collection(SUB_COL.GUARDIANS).doc(member); - const guardian = await guardianDocRef.get(); + const guardianDocRef = build5Db().doc(COL.SPACE, order.space!, SUB_COL.GUARDIANS, member); + const guardian = await guardianDocRef.get(); expect(guardian).toBeDefined(); }); }); 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 d316f65166..d522ac9290 100644 --- a/packages/functions/test/controls/token-distribution-auto-trigger.spec.ts +++ b/packages/functions/test/controls/token-distribution-auto-trigger.spec.ts @@ -1,4 +1,4 @@ -import { build5Db } from '@build-5/database'; +import { build5Db, PgTransactionType } from '@build-5/database'; import { COL, Member, @@ -12,26 +12,16 @@ import { TokenDistribution, TokenStatus, Transaction, - TransactionType, + WEN_FUNC, } from '@build-5/interfaces'; import dayjs from 'dayjs'; import bigDecimal from 'js-big-decimal'; import { isEmpty } from 'lodash'; -import { orderToken } from '../../src/runtime/firebase/token/base'; import { getAddress } from '../../src/utils/address.utils'; import { dateToTimestamp, serverTime } from '../../src/utils/dateTime.utils'; import * as wallet from '../../src/utils/wallet.utils'; -import { testEnv } from '../set-up'; -import { - createMember, - createSpace, - getRandomSymbol, - mockWalletReturnValue, - submitMilestoneFunc, - tokenProcessed, -} from './common'; - -let walletSpy: any; +import { mockWalletReturnValue, testEnv } from '../set-up'; +import { getRandomSymbol, submitMilestoneFunc, tokenProcessed } from './common'; interface Inputs { readonly totalDeposit: number[]; @@ -79,9 +69,9 @@ const scenarios = [ }, ]; -const submitTokenOrderFunc = async (spy: string, address: NetworkAddress, params: T) => { - mockWalletReturnValue(spy, address, params); - const order = await testEnv.wrap(orderToken)({}); +const submitTokenOrderFunc = async (address: NetworkAddress, params: T) => { + mockWalletReturnValue(address, params); + const order = await testEnv.wrap(WEN_FUNC.orderToken); expect(order?.createdOn).toBeDefined(); return order; }; @@ -120,14 +110,13 @@ describe('Token trigger test', () => { let members: string[]; beforeAll(async () => { - walletSpy = jest.spyOn(wallet, 'decodeAuth'); - guardian = await createMember(walletSpy); - space = await createSpace(walletSpy, guardian); + guardian = await testEnv.createMember(); + space = await testEnv.createSpace(guardian); const maxMembers = scenarios.reduce( (max, scenario) => Math.max(max, scenario.totalDeposit.length), 0, ); - const memberPromises = Array.from(Array(maxMembers)).map(() => createMember(walletSpy)); + const memberPromises = Array.from(Array(maxMembers)).map(() => testEnv.createMember()); members = await Promise.all(memberPromises); }); @@ -139,10 +128,10 @@ describe('Token trigger test', () => { input.publicPercentage, guardian, ); - await build5Db().doc(`${COL.TOKEN}/${token.uid}`).create(token); + await build5Db().doc(COL.TOKEN, token.uid).create(token); const orderPromises = input.totalDeposit.map(async (_, i) => { - const order = await submitTokenOrderFunc(walletSpy, members[i], { token: token.uid }); + const order = await submitTokenOrderFunc(members[i], { token: token.uid }); await submitMilestoneFunc( order, Number(bigDecimal.multiply(input.totalDeposit[i], MIN_IOTA_AMOUNT)), @@ -154,7 +143,7 @@ describe('Token trigger test', () => { await tokenProcessed(token.uid, input.totalDeposit.length, true); - const tokenData = await build5Db().doc(`${COL.TOKEN}/${token.uid}`).get(); + const tokenData = await build5Db().doc(COL.TOKEN, token.uid).get(); expect(tokenData.tokensOrdered).toBe( input.totalDeposit.reduce( (sum, act) => sum + (act * MIN_IOTA_AMOUNT) / tokenData.pricePerToken, @@ -165,7 +154,7 @@ describe('Token trigger test', () => { for (let i = 0; i < input.totalDeposit.length; ++i) { const member = members[i]; const distribution = ( - await build5Db().doc(`${COL.TOKEN}/${token.uid}/${SUB_COL.DISTRIBUTION}/${member}`).get() + await build5Db().doc(COL.TOKEN, token.uid, SUB_COL.DISTRIBUTION, member).get() ); const refundedAmount = Number(bigDecimal.multiply(input.refundedAmount[i], MIN_IOTA_AMOUNT)); expect(distribution.totalDeposit).toBe( @@ -181,9 +170,7 @@ describe('Token trigger test', () => { expect(distribution.billPaymentId).toBeDefined(); } if (distribution.billPaymentId) { - const paymentDoc = await build5Db() - .doc(`${COL.TRANSACTION}/${distribution.billPaymentId}`) - .get(); + const paymentDoc = await build5Db().doc(COL.TRANSACTION, distribution.billPaymentId).get(); expect(paymentDoc !== undefined).toBe(true); const paidAmount = isEmpty(input.paymentAmount) ? input.totalPaid[i] @@ -196,8 +183,8 @@ describe('Token trigger test', () => { } if (distribution.creditPaymentId) { const creditPaymentDoc = await build5Db() - .doc(`${COL.TRANSACTION}/${distribution.creditPaymentId}`) - .get(); + .doc(COL.TRANSACTION, distribution.creditPaymentId) + .get(); expect(creditPaymentDoc !== undefined).toBe(true); const creditAmount = isEmpty(input.creditAmount) ? input.refundedAmount[i] @@ -205,7 +192,7 @@ describe('Token trigger test', () => { expect(creditPaymentDoc?.payload?.amount).toBe( Number(bigDecimal.multiply(creditAmount, MIN_IOTA_AMOUNT)), ); - const memberData = await build5Db().doc(`${COL.MEMBER}/${member}`).get(); + const memberData = await build5Db().doc(COL.MEMBER, member).get(); expect(creditPaymentDoc?.payload?.sourceAddress).toBe(orders[i].payload?.targetAddress); expect(creditPaymentDoc?.payload?.targetAddress).toBe(getAddress(memberData, Network.IOTA)); } @@ -213,14 +200,14 @@ describe('Token trigger test', () => { }); it('Should should create two and credit third', async () => { - members.push(await createMember(walletSpy)); + members.push(await testEnv.createMember()); token = dummyToken(10, space, MIN_IOTA_AMOUNT, 100, guardian); - await build5Db().doc(`${COL.TOKEN}/${token.uid}`).create(token); + await build5Db().doc(COL.TOKEN, token.uid).create(token); const orderPromises = members .map(() => 7) .map(async (totalDeposit, i) => { - const order = await submitTokenOrderFunc(walletSpy, members[i], { token: token.uid }); + const order = await submitTokenOrderFunc(members[i], { token: token.uid }); await submitMilestoneFunc( order, Number(bigDecimal.multiply(totalDeposit, MIN_IOTA_AMOUNT)), @@ -231,13 +218,12 @@ describe('Token trigger test', () => { await Promise.all(orderPromises); await tokenProcessed(token.uid, 2, true); - const tokenData = await build5Db().doc(`${COL.TOKEN}/${token.uid}`).get(); + const tokenData = await build5Db().doc(COL.TOKEN, token.uid).get(); expect(tokenData.tokensOrdered).toBe(14); const distributions = await build5Db() - .doc(`${COL.TOKEN}/${token.uid}`) - .collection(SUB_COL.DISTRIBUTION) - .get(); + .collection(COL.TOKEN, token.uid, SUB_COL.DISTRIBUTION) + .get(); expect(distributions.length).toBe(2); distributions.forEach((d) => { expect(d.totalDeposit).toBe(7 * MIN_IOTA_AMOUNT); @@ -248,9 +234,9 @@ describe('Token trigger test', () => { const credit = await build5Db() .collection(COL.TRANSACTION) - .where('member', 'in', members) - .where('type', '==', TransactionType.CREDIT) - .where('payload.amount', '==', 7 * MIN_IOTA_AMOUNT) + .where('type', '==', PgTransactionType.CREDIT) + .where('payload_amount', '==', 7 * MIN_IOTA_AMOUNT) + .whereIn('member', members) .get(); expect(credit.length).toBe(1); }); diff --git a/packages/functions/test/controls/token-distribution.spec.ts b/packages/functions/test/controls/token-distribution.spec.ts index 6209d0d956..d2e81154ce 100644 --- a/packages/functions/test/controls/token-distribution.spec.ts +++ b/packages/functions/test/controls/token-distribution.spec.ts @@ -1,4 +1,4 @@ -import { build5Db } from '@build-5/database'; +import { PgTokenStatus, PgTransactionType, build5Db } from '@build-5/database'; import { COL, MIN_IOTA_AMOUNT, @@ -14,28 +14,22 @@ import { TokenStatus, Transaction, TransactionPayloadType, - TransactionType, + WEN_FUNC, } from '@build-5/interfaces'; import dayjs from 'dayjs'; import bigDecimal from 'js-big-decimal'; import { isEmpty } from 'lodash'; -import { orderToken } from '../../src/runtime/firebase/token/base'; import { getAddress } from '../../src/utils/address.utils'; import { dateToTimestamp, serverTime } from '../../src/utils/dateTime.utils'; import * as wallet from '../../src/utils/wallet.utils'; -import { testEnv } from '../set-up'; +import { mockWalletReturnValue, testEnv } from '../set-up'; import { - createMember, createRoyaltySpaces, - createSpace, getRandomSymbol, - mockWalletReturnValue, submitMilestoneFunc, tokenProcessed, } from './common'; -let walletSpy: any; - interface Inputs { readonly totalDeposit: number[]; readonly totalPaid: number[]; @@ -296,9 +290,9 @@ const scenarios = [ custom, ]; -const submitTokenOrderFunc = async (spy: string, address: NetworkAddress, params: T) => { - mockWalletReturnValue(spy, address, params); - const order = await testEnv.wrap(orderToken)({}); +const submitTokenOrderFunc = async (address: NetworkAddress, params: T) => { + mockWalletReturnValue(address, params); + const order = await testEnv.wrap(WEN_FUNC.orderToken); expect(order?.createdOn).toBeDefined(); return order; }; @@ -337,21 +331,20 @@ describe('Token trigger test', () => { beforeAll(async () => { await createRoyaltySpaces(); - walletSpy = jest.spyOn(wallet, 'decodeAuth'); - guardian = await createMember(walletSpy); - space = await createSpace(walletSpy, guardian); + guardian = await testEnv.createMember(); + space = await testEnv.createSpace(guardian); const maxMembers = scenarios.reduce( (max, scenario) => Math.max(max, scenario.totalDeposit.length), 0, ); - const memberPromises = Array.from(Array(maxMembers)).map(() => createMember(walletSpy)); + const memberPromises = Array.from(Array(maxMembers)).map(() => testEnv.createMember()); members = await Promise.all(memberPromises); }); beforeEach(async () => { await build5Db() - .doc(`${COL.SYSTEM}/${SYSTEM_CONFIG_DOC_ID}`) - .set({ tokenPurchaseFeePercentage: build5Db().deleteField() }, true); + .doc(COL.SYSTEM, SYSTEM_CONFIG_DOC_ID) + .upsert({ tokenPurchaseFeePercentage: undefined }); }); it.each(scenarios)('Should buy tokens', async (input: Inputs) => { @@ -362,10 +355,9 @@ describe('Token trigger test', () => { input.publicPercentage, guardian, ); - await build5Db().doc(`${COL.TOKEN}/${token.uid}`).create(token); - + await build5Db().doc(COL.TOKEN, token.uid).create(token); const orderPromises = Array.from(Array(input.totalDeposit.length)).map(async (_, i) => { - const order = await submitTokenOrderFunc(walletSpy, members[i], { token: token.uid }); + const order = await submitTokenOrderFunc(members[i], { token: token.uid }); await submitMilestoneFunc( order, Number(bigDecimal.multiply(input.totalDeposit[i], MIN_IOTA_AMOUNT)), @@ -374,13 +366,13 @@ describe('Token trigger test', () => { }); const orders = await Promise.all(orderPromises); - await build5Db().doc(`${COL.TOKEN}/${token.uid}`).update({ status: TokenStatus.PROCESSING }); + await build5Db().doc(COL.TOKEN, token.uid).update({ status: PgTokenStatus.PROCESSING }); await tokenProcessed(token.uid, input.totalDeposit.length, true); for (let i = 0; i < input.totalDeposit.length; ++i) { const member = members[i]; const distribution = ( - await build5Db().doc(`${COL.TOKEN}/${token.uid}/${SUB_COL.DISTRIBUTION}/${member}`).get() + await build5Db().doc(COL.TOKEN, token.uid, SUB_COL.DISTRIBUTION, member).get() ); const refundedAmount = Number(bigDecimal.multiply(input.refundedAmount[i], MIN_IOTA_AMOUNT)); expect(distribution.totalDeposit).toBe( @@ -397,9 +389,7 @@ describe('Token trigger test', () => { } if (distribution.billPaymentId) { - const paymentDoc = await build5Db() - .doc(`${COL.TRANSACTION}/${distribution.billPaymentId}`) - .get(); + const paymentDoc = await build5Db().doc(COL.TRANSACTION, distribution.billPaymentId).get(); expect(paymentDoc !== undefined).toBe(true); const paidAmount = isEmpty(input.paymentAmount) ? input.totalPaid[i] @@ -421,22 +411,20 @@ describe('Token trigger test', () => { if (supposedRoyaltyAmount < MIN_IOTA_AMOUNT) { expect(distribution.royaltyBillPaymentId).toBe(''); } else { - const royaltySpace = ( - await build5Db().doc(`${COL.SPACE}/${TOKEN_SALE_TEST.spaceone}`).get() - ); - const royaltyPayment = ( - await build5Db().doc(`${COL.TRANSACTION}/${distribution.royaltyBillPaymentId}`).get() - ); - expect(royaltyPayment.payload.amount).toBe(Math.floor(supposedRoyaltyAmount)); - expect(royaltyPayment.payload.targetAddress).toBe( - getAddress(royaltySpace, royaltyPayment.network!), + const royaltySpace = await build5Db().doc(COL.SPACE, TOKEN_SALE_TEST.spaceone).get(); + const royaltyPayment = await build5Db() + .doc(COL.TRANSACTION, distribution.royaltyBillPaymentId!) + .get(); + expect(royaltyPayment!.payload.amount).toBe(Math.floor(supposedRoyaltyAmount)); + expect(royaltyPayment!.payload.targetAddress).toBe( + getAddress(royaltySpace, royaltyPayment!.network!), ); } if (distribution.creditPaymentId) { const creditPaymentDoc = await build5Db() - .doc(`${COL.TRANSACTION}/${distribution.creditPaymentId}`) - .get(); + .doc(COL.TRANSACTION, distribution.creditPaymentId) + .get(); expect(creditPaymentDoc !== undefined).toBe(true); const creditAmount = isEmpty(input.creditAmount) ? input.refundedAmount[i] @@ -444,7 +432,7 @@ describe('Token trigger test', () => { expect(creditPaymentDoc?.payload?.amount).toBe( Number(bigDecimal.multiply(creditAmount, MIN_IOTA_AMOUNT)), ); - const memberData = await build5Db().doc(`${COL.MEMBER}/${member}`).get(); + const memberData = await build5Db().doc(COL.MEMBER, member).get(); expect(creditPaymentDoc?.payload?.sourceAddress).toBe(orders[i].payload?.targetAddress); expect(creditPaymentDoc?.payload?.targetAddress).toBe(getAddress(memberData, Network.IOTA)); } @@ -453,29 +441,29 @@ describe('Token trigger test', () => { it('Should refund everyone if public sale is set to zero', async () => { token = dummyToken(100, space, MIN_IOTA_AMOUNT, 10, guardian); - await build5Db().doc(`${COL.TOKEN}/${token.uid}`).create(token); + await build5Db().doc(COL.TOKEN, token.uid).create(token); const totalDeposits = [2, 3]; const orderPromises = totalDeposits.map(async (totalDeposit, i) => { - const order = await submitTokenOrderFunc(walletSpy, members[i], { token: token.uid }); + const order = await submitTokenOrderFunc(members[i], { token: token.uid }); await submitMilestoneFunc(order, Number(bigDecimal.multiply(totalDeposit, MIN_IOTA_AMOUNT))); return order; }); await Promise.all(orderPromises); await build5Db() - .doc(`${COL.TOKEN}/${token.uid}`) + .doc(COL.TOKEN, token.uid) .update({ - status: TokenStatus.PROCESSING, - allocations: [{ title: 'Public sale', isPublicSale: true, percentage: 0 }], + status: PgTokenStatus.PROCESSING, + allocations: JSON.stringify([{ title: 'Public sale', isPublicSale: true, percentage: 0 }]), }); await tokenProcessed(token.uid, totalDeposits.length, true); for (let i = 0; i < totalDeposits.length; ++i) { const member = members[i]; const distribution = ( - await build5Db().doc(`${COL.TOKEN}/${token.uid}/${SUB_COL.DISTRIBUTION}/${member}`).get() + await build5Db().doc(COL.TOKEN, token.uid, SUB_COL.DISTRIBUTION, member).get() ); const refundedAmount = Number(bigDecimal.multiply(totalDeposits[i], MIN_IOTA_AMOUNT)); expect(distribution.totalDeposit).toBe( @@ -495,32 +483,29 @@ describe('Token trigger test', () => { { isMember: false, fee: 5 }, ])('Custom fees', async ({ isMember, fee }: { isMember: boolean; fee: number }) => { if (isMember) { - await build5Db() - .doc(`${COL.MEMBER}/${members[0]}`) - .update({ tokenPurchaseFeePercentage: fee }); + await build5Db().doc(COL.MEMBER, members[0]).update({ tokenPurchaseFeePercentage: fee }); } else { await build5Db() - .doc(`${COL.SYSTEM}/${SYSTEM_CONFIG_DOC_ID}`) - .set({ tokenPurchaseFeePercentage: fee }); + .doc(COL.SYSTEM, SYSTEM_CONFIG_DOC_ID) + .upsert({ tokenPurchaseFeePercentage: fee }); } const totalPaid = 100 * MIN_IOTA_AMOUNT; token = dummyToken(100, space, MIN_IOTA_AMOUNT, 100, guardian); - await build5Db().doc(`${COL.TOKEN}/${token.uid}`).create(token); + await build5Db().doc(COL.TOKEN, token.uid).create(token); - const order = await submitTokenOrderFunc(walletSpy, members[0], { token: token.uid }); + const order = await submitTokenOrderFunc(members[0], { token: token.uid }); await submitMilestoneFunc(order, totalPaid); - await build5Db().doc(`${COL.TOKEN}/${token.uid}`).update({ status: TokenStatus.PROCESSING }); + await build5Db().doc(COL.TOKEN, token.uid).update({ status: PgTokenStatus.PROCESSING }); await tokenProcessed(token.uid, 1, true); const billPayments = await build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.BILL_PAYMENT) + .where('type', '==', PgTransactionType.BILL_PAYMENT) .where('member', '==', members[0]) - .where('payload.token', '==', token.uid) - .get(); - + .where('payload_token', '==', token.uid) + .get(); const billPaymentToSpace = billPayments.find( (bp) => bp.payload.amount === totalPaid * (1 - fee / 100), ); @@ -535,8 +520,6 @@ describe('Token trigger test', () => { expect(billPayments.filter((bp) => bp.payload.royalty).length).toBe(0); } - await build5Db() - .doc(`${COL.MEMBER}/${members[0]}`) - .set({ tokenPurchaseFeePercentage: build5Db().deleteField() }, true); + await build5Db().doc(COL.MEMBER, members[0]).upsert({ tokenPurchaseFeePercentage: undefined }); }); }); diff --git a/packages/functions/test/controls/token-trade.buy.spec.ts b/packages/functions/test/controls/token-trade.buy.spec.ts index 1f67fa3477..513dd48c88 100644 --- a/packages/functions/test/controls/token-trade.buy.spec.ts +++ b/packages/functions/test/controls/token-trade.buy.spec.ts @@ -1,4 +1,10 @@ -import { build5Db } from '@build-5/database'; +import { + PgTokenStatus, + PgTokenTradeOrderType, + PgTransactionPayloadType, + PgTransactionType, + build5Db, +} from '@build-5/database'; import { COL, MIN_IOTA_AMOUNT, @@ -10,43 +16,33 @@ import { TokenTradeOrderStatus, TokenTradeOrderType, Transaction, - TransactionPayloadType, - TransactionType, + WEN_FUNC, WenError, } from '@build-5/interfaces'; -import { cancelTradeOrder, tradeToken } from '../../src/runtime/firebase/token/trading'; +import { tradeTokenControl } from '../../src/controls/token-trading/token-trade.controller'; import * as wallet from '../../src/utils/wallet.utils'; -import { testEnv } from '../set-up'; -import { - createMember, - expectThrow, - getRandomSymbol, - mockIpCheck, - mockWalletReturnValue, - submitMilestoneFunc, -} from './common'; - -let walletSpy: any; +import { mockWalletReturnValue, testEnv } from '../set-up'; +import { expectThrow, getRandomSymbol, mockIpCheck, submitMilestoneFunc } from './common'; describe('Trade controller, buy token', () => { let memberAddress: NetworkAddress; let token: Token; beforeEach(async () => { - walletSpy = jest.spyOn(wallet, 'decodeAuth'); - memberAddress = await createMember(walletSpy); + memberAddress = await testEnv.createMember(); const tokenId = wallet.getRandomEthAddress(); - token = { + const tokenUpsert = { project: SOON_PROJECT_ID, uid: tokenId, symbol: getRandomSymbol(), name: 'MyToken', space: 'myspace', - status: TokenStatus.AVAILABLE, + status: PgTokenStatus.AVAILABLE, approved: true, }; - await build5Db().doc(`${COL.TOKEN}/${tokenId}`).set(token); + await build5Db().doc(COL.TOKEN, tokenId).upsert(tokenUpsert); + token = (await build5Db().doc(COL.TOKEN, tokenId).get())!; }); it('Should create buy order and cancel it', async () => { @@ -56,13 +52,13 @@ describe('Trade controller, buy token', () => { count: 5, type: TokenTradeOrderType.BUY, }; - mockWalletReturnValue(walletSpy, memberAddress, request); - const order = await testEnv.wrap(tradeToken)({}); + mockWalletReturnValue(memberAddress, request); + const order = await testEnv.wrap(WEN_FUNC.tradeToken); await submitMilestoneFunc(order, MIN_IOTA_AMOUNT * 5); const buySnap = await build5Db() .collection(COL.TOKEN_MARKET) - .where('type', '==', TokenTradeOrderType.BUY) + .where('type', '==', PgTokenTradeOrderType.BUY) .where('owner', '==', memberAddress) .get(); expect(buySnap.length).toBe(1); @@ -73,16 +69,16 @@ describe('Trade controller, buy token', () => { expect(buy.tokenStatus).toBe(TokenStatus.AVAILABLE); const cancelRequest = { uid: buy.uid }; - mockWalletReturnValue(walletSpy, memberAddress, cancelRequest); - const cancelled = await testEnv.wrap(cancelTradeOrder)({}); + mockWalletReturnValue(memberAddress, cancelRequest); + const cancelled = await testEnv.wrap(WEN_FUNC.cancelTradeOrder); expect(cancelled.status).toBe(TokenTradeOrderStatus.CANCELLED); const creditSnap = await build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.CREDIT) + .where('type', '==', PgTransactionType.CREDIT) .where('member', '==', memberAddress) - .where('payload.type', '==', TransactionPayloadType.TOKEN_BUY) - .get(); + .where('payload_type', '==', PgTransactionPayloadType.TOKEN_BUY) + .get(); expect(creditSnap.length).toBe(1); expect(creditSnap[0]?.payload?.amount).toBe(5 * MIN_IOTA_AMOUNT); }); @@ -94,8 +90,8 @@ describe('Trade controller, buy token', () => { count: 5, type: TokenTradeOrderType.BUY, }; - mockWalletReturnValue(walletSpy, memberAddress, request); - const order = await testEnv.wrap(tradeToken)({}); + mockWalletReturnValue(memberAddress, request); + const order = await testEnv.wrap(WEN_FUNC.tradeToken); await submitMilestoneFunc(order, MIN_IOTA_AMOUNT * 5); await submitMilestoneFunc(order, MIN_IOTA_AMOUNT * 5); @@ -108,23 +104,26 @@ describe('Trade controller, buy token', () => { const creditSnap = await build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.CREDIT) + .where('type', '==', PgTransactionType.CREDIT) .where('member', '==', memberAddress) - .where('payload.amount', '==', 5 * MIN_IOTA_AMOUNT) + .where('payload_amount', '==', 5 * MIN_IOTA_AMOUNT) .get(); expect(creditSnap.length).toBe(1); }); it('Should throw, token not approved', async () => { - await build5Db().doc(`${COL.TOKEN}/${token.uid}`).update({ approved: false }); + await build5Db().doc(COL.TOKEN, token.uid).update({ approved: false }); const request = { symbol: token.symbol, price: MIN_IOTA_AMOUNT, count: 5, type: TokenTradeOrderType.BUY, }; - mockWalletReturnValue(walletSpy, memberAddress, request); - await expectThrow(testEnv.wrap(tradeToken)({}), WenError.token_does_not_exist.key); + mockWalletReturnValue(memberAddress, request); + await expectThrow( + testEnv.wrap(WEN_FUNC.tradeToken), + WenError.token_does_not_exist.key, + ); }); it('Should fail, country blocked by default', async () => { @@ -135,8 +134,9 @@ describe('Trade controller, buy token', () => { count: 5, type: TokenTradeOrderType.BUY, }; - mockWalletReturnValue(walletSpy, memberAddress, request); - await expectThrow(testEnv.wrap(tradeToken)({}), WenError.blocked_country.key); + mockWalletReturnValue(memberAddress, request); + const call = testEnv.mockWrap(tradeTokenControl); + await expectThrow(call, WenError.blocked_country.key); }); it('Should fail, country blocked for token', async () => { @@ -147,7 +147,8 @@ describe('Trade controller, buy token', () => { count: 5, type: TokenTradeOrderType.BUY, }; - mockWalletReturnValue(walletSpy, memberAddress, request); - await expectThrow(testEnv.wrap(tradeToken)({}), WenError.blocked_country.key); + mockWalletReturnValue(memberAddress, request); + const call = testEnv.mockWrap(tradeTokenControl); + await expectThrow(call, WenError.blocked_country.key); }); }); diff --git a/packages/functions/test/controls/token-trade.sell.spec.ts b/packages/functions/test/controls/token-trade.sell.spec.ts index b64485bef1..e1412cdd79 100644 --- a/packages/functions/test/controls/token-trade.sell.spec.ts +++ b/packages/functions/test/controls/token-trade.sell.spec.ts @@ -1,4 +1,4 @@ -import { build5Db } from '@build-5/database'; +import { build5Db, PgTokenStatus } from '@build-5/database'; import { COL, MIN_IOTA_AMOUNT, @@ -7,55 +7,42 @@ import { Space, SUB_COL, Token, - TokenDistribution, TokenStatus, TokenTradeOrder, TokenTradeOrderStatus, TokenTradeOrderType, + Transaction, + WEN_FUNC, WenError, } from '@build-5/interfaces'; import dayjs from 'dayjs'; -import { enableTokenTrading } from '../../src/runtime/firebase/token/base'; -import { cancelTradeOrder, tradeToken } from '../../src/runtime/firebase/token/trading'; +import { tradeTokenControl } from '../../src/controls/token-trading/token-trade.controller'; import * as wallet from '../../src/utils/wallet.utils'; -import { testEnv } from '../set-up'; -import { - createMember, - createSpace, - expectThrow, - getRandomSymbol, - mockIpCheck, - mockWalletReturnValue, - wait, -} from './common'; - -let walletSpy: any; +import { mockWalletReturnValue, testEnv } from '../set-up'; +import { expectThrow, getRandomSymbol, mockIpCheck, wait } from './common'; describe('Trade controller, sell token', () => { let memberAddress: NetworkAddress; let token: Token; let space: Space; - beforeEach(async () => { - walletSpy = jest.spyOn(wallet, 'decodeAuth'); - memberAddress = await createMember(walletSpy); - space = await createSpace(walletSpy, memberAddress); - + memberAddress = await testEnv.createMember(); + space = await testEnv.createSpace(memberAddress); const tokenId = wallet.getRandomEthAddress(); - token = { + const upserToken = { project: SOON_PROJECT_ID, uid: tokenId, symbol: getRandomSymbol(), name: 'MyToken', - status: TokenStatus.AVAILABLE, + status: PgTokenStatus.AVAILABLE, approved: true, space: space.uid, }; - await build5Db().doc(`${COL.TOKEN}/${tokenId}`).set(token); - const distribution = { tokenOwned: 10 }; + await build5Db().doc(COL.TOKEN, tokenId).upsert(upserToken); + token = (await build5Db().doc(COL.TOKEN, tokenId).get())!; await build5Db() - .doc(`${COL.TOKEN}/${tokenId}/${SUB_COL.DISTRIBUTION}/${memberAddress}`) - .set(distribution); + .doc(COL.TOKEN, tokenId, SUB_COL.DISTRIBUTION, memberAddress) + .upsert({ tokenOwned: 10 }); }); it('Should create sell order and cancel it', async () => { @@ -65,33 +52,29 @@ describe('Trade controller, sell token', () => { count: 5, type: TokenTradeOrderType.SELL, }; - mockWalletReturnValue(walletSpy, memberAddress, request); - const sell = await testEnv.wrap(tradeToken)({}); + mockWalletReturnValue(memberAddress, request); + const sell = await testEnv.wrap(WEN_FUNC.tradeToken); expect(sell.count).toBe(5); expect(sell.price).toBe(MIN_IOTA_AMOUNT); expect(sell.tokenStatus).toBe(TokenStatus.AVAILABLE); - const distribution = await build5Db() - .doc(`${COL.TOKEN}/${token.uid}/${SUB_COL.DISTRIBUTION}/${memberAddress}`) - .get(); + .doc(COL.TOKEN, token.uid, SUB_COL.DISTRIBUTION, memberAddress) + .get(); expect(distribution?.lockedForSale).toBe(5); - await wait(async () => { - const doc = await build5Db().doc(`${COL.TOKEN_MARKET}/${sell.uid}`).get(); + const doc = await build5Db().doc(COL.TOKEN_MARKET, sell.uid).get(); return ( doc.updatedOn !== undefined && dayjs(doc.updatedOn.toDate()).isAfter(doc.createdOn!.toDate()) ); }); - const cancelRequest = { uid: sell.uid }; - mockWalletReturnValue(walletSpy, memberAddress, cancelRequest); - const cancelled = await testEnv.wrap(cancelTradeOrder)({}); + mockWalletReturnValue(memberAddress, cancelRequest); + const cancelled = await testEnv.wrap(WEN_FUNC.cancelTradeOrder); expect(cancelled.status).toBe(TokenTradeOrderStatus.CANCELLED); - const cancelledDistribution = await build5Db() - .doc(`${COL.TOKEN}/${token.uid}/${SUB_COL.DISTRIBUTION}/${memberAddress}`) - .get(); + .doc(COL.TOKEN, token.uid, SUB_COL.DISTRIBUTION, memberAddress) + .get(); expect(cancelledDistribution?.lockedForSale).toBe(0); }); @@ -102,8 +85,8 @@ describe('Trade controller, sell token', () => { count: 11, type: TokenTradeOrderType.SELL, }; - mockWalletReturnValue(walletSpy, memberAddress, request); - await expectThrow(testEnv.wrap(tradeToken)({}), WenError.no_available_tokens_for_sale.key); + mockWalletReturnValue(memberAddress, request); + await expectThrow(testEnv.wrap(WEN_FUNC.tradeToken), WenError.no_available_tokens_for_sale.key); }); it('Should create, total price too low', async () => { @@ -113,108 +96,107 @@ describe('Trade controller, sell token', () => { count: 1, type: TokenTradeOrderType.SELL, }; - mockWalletReturnValue(walletSpy, memberAddress, request); - const sellOrder = await testEnv.wrap(tradeToken)({}); + mockWalletReturnValue(memberAddress, request); + const sellOrder = await testEnv.wrap(WEN_FUNC.tradeToken); expect(sellOrder.price).toBe(MIN_IOTA_AMOUNT / 2); }); it('Should throw on one, not enough tokens', async () => { - mockWalletReturnValue(walletSpy, memberAddress, { + mockWalletReturnValue(memberAddress, { symbol: token.symbol, price: MIN_IOTA_AMOUNT, count: 8, type: TokenTradeOrderType.SELL, }); - await testEnv.wrap(tradeToken)({}); - mockWalletReturnValue(walletSpy, memberAddress, { + await testEnv.wrap(WEN_FUNC.tradeToken); + mockWalletReturnValue(memberAddress, { symbol: token.symbol, price: MIN_IOTA_AMOUNT, count: 8, type: TokenTradeOrderType.SELL, }); - await expectThrow(testEnv.wrap(tradeToken)({}), WenError.no_available_tokens_for_sale.key); + await expectThrow(testEnv.wrap(WEN_FUNC.tradeToken), WenError.no_available_tokens_for_sale.key); }); it('Should throw, not enough tokens even after cancels', async () => { - mockWalletReturnValue(walletSpy, memberAddress, { + mockWalletReturnValue(memberAddress, { symbol: token.symbol, price: MIN_IOTA_AMOUNT, count: 5, type: TokenTradeOrderType.SELL, }); - const sell = await testEnv.wrap(tradeToken)({}); - mockWalletReturnValue(walletSpy, memberAddress, { + const sell = await testEnv.wrap(WEN_FUNC.tradeToken); + + mockWalletReturnValue(memberAddress, { symbol: token.symbol, price: MIN_IOTA_AMOUNT as any, count: 5, type: TokenTradeOrderType.SELL, }); - await testEnv.wrap(tradeToken)({}); + await testEnv.wrap(WEN_FUNC.tradeToken); - mockWalletReturnValue(walletSpy, memberAddress, { + mockWalletReturnValue(memberAddress, { symbol: token.symbol, price: MIN_IOTA_AMOUNT, count: 8, type: TokenTradeOrderType.SELL, }); - await expectThrow(testEnv.wrap(tradeToken)({}), WenError.no_available_tokens_for_sale.key); - + await expectThrow(testEnv.wrap(WEN_FUNC.tradeToken), WenError.no_available_tokens_for_sale.key); const cancelRequest = { uid: sell.uid }; - mockWalletReturnValue(walletSpy, memberAddress, cancelRequest); - await testEnv.wrap(cancelTradeOrder)({}); - + mockWalletReturnValue(memberAddress, cancelRequest); + await testEnv.wrap(WEN_FUNC.cancelTradeOrder); const distribution = await build5Db() - .doc(`${COL.TOKEN}/${token.uid}/${SUB_COL.DISTRIBUTION}/${memberAddress}`) - .get(); + .doc(COL.TOKEN, token.uid, SUB_COL.DISTRIBUTION, memberAddress) + .get(); expect(distribution?.lockedForSale).toBe(5); - mockWalletReturnValue(walletSpy, memberAddress, { + mockWalletReturnValue(memberAddress, { symbol: token.symbol, price: MIN_IOTA_AMOUNT, count: 8, type: TokenTradeOrderType.SELL, }); - await expectThrow(testEnv.wrap(tradeToken)({}), WenError.no_available_tokens_for_sale.key); + await expectThrow(testEnv.wrap(WEN_FUNC.tradeToken), WenError.no_available_tokens_for_sale.key); }); it('Should update sale lock properly', async () => { - const distDocRef = build5Db().doc( - `${COL.TOKEN}/${token.uid}/${SUB_COL.DISTRIBUTION}/${memberAddress}`, - ); + const distDocRef = build5Db().doc(COL.TOKEN, token.uid, SUB_COL.DISTRIBUTION, memberAddress); const count = 3; const sells = [] as any[]; for (let i = 0; i < count; ++i) { - mockWalletReturnValue(walletSpy, memberAddress, { + mockWalletReturnValue(memberAddress, { symbol: token.symbol, price: MIN_IOTA_AMOUNT, count: 1, type: TokenTradeOrderType.SELL, }); - sells.push(await testEnv.wrap(tradeToken)({})); + sells.push(await testEnv.wrap(WEN_FUNC.tradeToken)); } + await wait(async () => { - const distribution = await distDocRef.get(); + const distribution = await distDocRef.get(); return distribution?.lockedForSale === count; }); for (let i = 0; i < count; ++i) { const cancelRequest = { uid: sells[i].uid }; - mockWalletReturnValue(walletSpy, memberAddress, cancelRequest); - await testEnv.wrap(cancelTradeOrder)({}); - const distribution = await distDocRef.get(); + mockWalletReturnValue(memberAddress, cancelRequest); + await testEnv.wrap(WEN_FUNC.cancelTradeOrder); + const distribution = await distDocRef.get(); expect(distribution?.lockedForSale).toBe(count - i - 1); } }); it('Should throw, token not approved', async () => { - await build5Db().doc(`${COL.TOKEN}/${token.uid}`).update({ approved: false }); - mockWalletReturnValue(walletSpy, memberAddress, { + await build5Db().doc(COL.TOKEN, token.uid).update({ approved: false }); + + mockWalletReturnValue(memberAddress, { symbol: token.symbol, price: MIN_IOTA_AMOUNT, count: 8, type: TokenTradeOrderType.SELL, }); - await expectThrow(testEnv.wrap(tradeToken)({}), WenError.token_does_not_exist.key); + await expectThrow(testEnv.wrap(WEN_FUNC.tradeToken), WenError.token_does_not_exist.key); }); it('Should throw, precision too much', async () => { @@ -224,18 +206,18 @@ describe('Trade controller, sell token', () => { count: 5, type: TokenTradeOrderType.SELL, }; - mockWalletReturnValue(walletSpy, memberAddress, request); - const sell = await testEnv.wrap(tradeToken)({}); + mockWalletReturnValue(memberAddress, request); + const sell = await testEnv.wrap(WEN_FUNC.tradeToken); expect(sell.count).toBe(5); - const request2 = { symbol: token.symbol, - price: MIN_IOTA_AMOUNT + 0.1234567, + price: MIN_IOTA_AMOUNT + 0.1543267, count: 5, type: TokenTradeOrderType.SELL, }; - mockWalletReturnValue(walletSpy, memberAddress, request2); - await expectThrow(testEnv.wrap(tradeToken)({}), WenError.invalid_params.key); + + mockWalletReturnValue(memberAddress, request2); + await expectThrow(testEnv.wrap(WEN_FUNC.tradeToken), WenError.invalid_params.key); }); it('Should fail, country blocked by default', async () => { @@ -246,8 +228,10 @@ describe('Trade controller, sell token', () => { count: 5, type: TokenTradeOrderType.SELL, }; - mockWalletReturnValue(walletSpy, memberAddress, request); - await expectThrow(testEnv.wrap(tradeToken)({}), WenError.blocked_country.key); + + mockWalletReturnValue(memberAddress, request); + const call = testEnv.mockWrap(tradeTokenControl); + await expectThrow(call, WenError.blocked_country.key); }); it('Should fail, country blocked for token', async () => { @@ -258,28 +242,25 @@ describe('Trade controller, sell token', () => { count: 5, type: TokenTradeOrderType.SELL, }; - mockWalletReturnValue(walletSpy, memberAddress, request); - await expectThrow(testEnv.wrap(tradeToken)({}), WenError.blocked_country.key); + mockWalletReturnValue(memberAddress, request); + const call = testEnv.mockWrap(tradeTokenControl); + await expectThrow(call, WenError.blocked_country.key); }); it('Should fail first, tading disabled, then succeeed', async () => { - await build5Db() - .doc(`${COL.TOKEN}/${token.uid}`) - .update({ tradingDisabled: true, public: true }); + await build5Db().doc(COL.TOKEN, token.uid).update({ tradingDisabled: true, public: true }); const request = { symbol: token.symbol, price: MIN_IOTA_AMOUNT, count: 5, type: TokenTradeOrderType.SELL, }; - mockWalletReturnValue(walletSpy, memberAddress, request); - await expectThrow(testEnv.wrap(tradeToken)({}), WenError.token_trading_disabled.key); - - mockWalletReturnValue(walletSpy, memberAddress, { uid: token.uid }); - await testEnv.wrap(enableTokenTrading)({}); - - mockWalletReturnValue(walletSpy, memberAddress, request); - const sell = await testEnv.wrap(tradeToken)({}); + mockWalletReturnValue(memberAddress, request); + await expectThrow(testEnv.wrap(WEN_FUNC.tradeToken), WenError.token_trading_disabled.key); + mockWalletReturnValue(memberAddress, { uid: token.uid }); + await testEnv.wrap(WEN_FUNC.enableTokenTrading); + mockWalletReturnValue(memberAddress, request); + const sell = await testEnv.wrap(WEN_FUNC.tradeToken); expect(sell.count).toBe(5); expect(sell.price).toBe(MIN_IOTA_AMOUNT); expect(sell.tokenStatus).toBe(TokenStatus.AVAILABLE); diff --git a/packages/functions/test/controls/token-trade.trigger.spec.ts b/packages/functions/test/controls/token-trade.trigger.spec.ts index 0a7d4c82e5..c41c0175eb 100644 --- a/packages/functions/test/controls/token-trade.trigger.spec.ts +++ b/packages/functions/test/controls/token-trade.trigger.spec.ts @@ -1,4 +1,10 @@ -import { build5Db } from '@build-5/database'; +import { + PgTokenStatus, + PgTokenTradeOrderType, + PgTransactionPayloadType, + PgTransactionType, + build5Db, +} from '@build-5/database'; import { COL, CreditPaymentReason, @@ -10,63 +16,47 @@ import { SOON_PROJECT_ID, SUB_COL, SYSTEM_CONFIG_DOC_ID, - StakeType, TOKEN_SALE_TEST, Token, TokenDistribution, TokenPurchase, - TokenStats, TokenStatus, TokenTradeOrder, TokenTradeOrderStatus, TokenTradeOrderType, Transaction, TransactionPayloadType, - TransactionType, + WEN_FUNC, } from '@build-5/interfaces'; import bigDecimal from 'js-big-decimal'; import { isEmpty } from 'lodash'; -import { cancelTradeOrder, tradeToken } from '../../src/runtime/firebase/token/trading'; import { TOKEN_TRADE_ORDER_FETCH_LIMIT } from '../../src/triggers/token-trading/match-token'; import { getAddress } from '../../src/utils/address.utils'; import { serverTime } from '../../src/utils/dateTime.utils'; import * as wallet from '../../src/utils/wallet.utils'; -import { soonTokenId, testEnv } from '../set-up'; -import { - createMember, - createRoyaltySpaces, - getRandomSymbol, - mockWalletReturnValue, - submitMilestoneFunc, - wait, -} from './common'; - -let walletSpy: any; +import { mockWalletReturnValue, soonTokenId, testEnv } from '../set-up'; +import { createRoyaltySpaces, getRandomSymbol, submitMilestoneFunc, wait } from './common'; const buyTokenFunc = async (memberAddress: NetworkAddress, request: any) => { - mockWalletReturnValue(walletSpy, memberAddress, { ...request, type: TokenTradeOrderType.BUY }); - const order = await testEnv.wrap(tradeToken)({}); + mockWalletReturnValue(memberAddress, { ...request, type: TokenTradeOrderType.BUY }); + const order = await testEnv.wrap(WEN_FUNC.tradeToken); await submitMilestoneFunc( order, Number(bigDecimal.floor(bigDecimal.multiply(request.price, request.count))), ); return order; }; - const assertVolumeTotal = async (tokenId: string, volumeTotal: number) => { - const statDoc = build5Db().doc(`${COL.TOKEN}/${tokenId}/${SUB_COL.STATS}/${tokenId}`); - await wait(async () => (await statDoc.get())?.volumeTotal === volumeTotal); + const statDoc = build5Db().doc(COL.TOKEN, tokenId, SUB_COL.STATS, tokenId); + await wait(async () => (await statDoc.get())?.volumeTotal === volumeTotal); }; - const getBillPayments = (member: string) => build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.BILL_PAYMENT) + .where('type', '==', PgTransactionType.BILL_PAYMENT) .where('member', '==', member) - .get(); - + .get(); const { percentage, spaceonepercentage } = TOKEN_SALE_TEST; - const getRoyaltyDistribution = (amount: number) => { const spaceOne = amount * (percentage / 100) * (spaceonepercentage / 100); const spaceTwo = amount * (percentage / 100) * (1 - spaceonepercentage / 100); @@ -82,10 +72,8 @@ const getRoyaltyDistribution = (amount: number) => { describe('Trade trigger', () => { let seller: string; let buyer: string; - let token: Token; const tokenCount = 400; - const saveSellToDb = async (count: number, price: number) => { const data = { project: SOON_PROJECT_ID, @@ -102,7 +90,7 @@ describe('Trade trigger', () => { fulfilled: 0, status: TokenTradeOrderStatus.ACTIVE, }; - await build5Db().doc(`${COL.TOKEN_MARKET}/${data.uid}`).create(data); + await build5Db().doc(COL.TOKEN_MARKET, data.uid).create(data); }; beforeAll(async () => { @@ -110,84 +98,74 @@ describe('Trade trigger', () => { }); beforeEach(async () => { - walletSpy = jest.spyOn(wallet, 'decodeAuth'); - seller = await createMember(walletSpy); - buyer = await createMember(walletSpy); - + seller = await testEnv.createMember(); + buyer = await testEnv.createMember(); const tokenId = wallet.getRandomEthAddress(); - token = { + const tokenUpsert = { project: SOON_PROJECT_ID, uid: tokenId, symbol: getRandomSymbol(), name: 'MyToken', space: 'myspace', - status: TokenStatus.PRE_MINTED, + status: PgTokenStatus.PRE_MINTED, approved: true, }; - await build5Db().doc(`${COL.TOKEN}/${tokenId}`).set(token); - const distribution = { tokenOwned: tokenCount * 3 }; - await build5Db() - .doc(`${COL.TOKEN}/${tokenId}/${SUB_COL.DISTRIBUTION}/${seller}`) - .set(distribution); - + await build5Db().doc(COL.TOKEN, tokenId).upsert(tokenUpsert); + token = (await build5Db().doc(COL.TOKEN, tokenId).get())!; + const distribution = { tokenOwned: tokenCount * 3 }; + await build5Db().doc(COL.TOKEN, tokenId, SUB_COL.DISTRIBUTION, seller).upsert(distribution); await build5Db() - .doc(`${COL.SYSTEM}/${SYSTEM_CONFIG_DOC_ID}`) - .set({ tokenTradingFeePercentage: build5Db().deleteField() }, true); + .doc(COL.SYSTEM, SYSTEM_CONFIG_DOC_ID) + .upsert({ tokenTradingFeePercentage: undefined }); }); it('Should fulfill buy with one sell', async () => { - mockWalletReturnValue(walletSpy, seller, { + mockWalletReturnValue(seller, { symbol: token.symbol, price: MIN_IOTA_AMOUNT, count: tokenCount, type: TokenTradeOrderType.SELL, }); - await testEnv.wrap(tradeToken)({}); - + await testEnv.wrap(WEN_FUNC.tradeToken); const request = { symbol: token.symbol, price: MIN_IOTA_AMOUNT, count: tokenCount }; const order = await buyTokenFunc(buyer, request); - await wait(async () => { const buySnap = await build5Db() .collection(COL.TOKEN_MARKET) - .where('type', '==', TokenTradeOrderType.BUY) + .where('type', '==', PgTokenTradeOrderType.BUY) .where('owner', '==', buyer) - .get(); + .get(); return buySnap[0].fulfilled === tokenCount; }); - const buySnap = await build5Db() .collection(COL.TOKEN_MARKET) - .where('type', '==', TokenTradeOrderType.BUY) + .where('type', '==', PgTokenTradeOrderType.BUY) .where('owner', '==', buyer) .get(); expect(buySnap.length).toBe(1); const buy = buySnap[0]; expect(buy.status).toBe(TokenTradeOrderStatus.SETTLED); expect(buy.tokenStatus).toBe(TokenStatus.PRE_MINTED); - const sellSnap = await build5Db() .collection(COL.TOKEN_MARKET) - .where('type', '==', TokenTradeOrderType.SELL) + .where('type', '==', PgTokenTradeOrderType.SELL) .where('owner', '==', seller) .get(); expect(sellSnap.length).toBe(1); const sell = sellSnap[0]; expect(sell.status).toBe(TokenTradeOrderStatus.SETTLED); expect(sell.tokenStatus).toBe(TokenStatus.PRE_MINTED); - const sellDistribution = ( - await build5Db().doc(`${COL.TOKEN}/${token.uid}/${SUB_COL.DISTRIBUTION}/${seller}`).get() + await build5Db().doc(COL.TOKEN, token.uid, SUB_COL.DISTRIBUTION, seller).get() ); expect(sellDistribution.lockedForSale).toBe(0); expect(sellDistribution.sold).toBe(tokenCount); expect(sellDistribution.tokenOwned).toBe(2 * tokenCount); const buyDistribution = ( - await build5Db().doc(`${COL.TOKEN}/${token.uid}/${SUB_COL.DISTRIBUTION}/${buyer}`).get() + await build5Db().doc(COL.TOKEN, token.uid, SUB_COL.DISTRIBUTION, buyer).get() ); expect(buyDistribution.totalPurchased).toBe(tokenCount); expect(buyDistribution.tokenOwned).toBe(tokenCount); - const purchases = await build5Db() .collection(COL.TOKEN_PURCHASE) .where('buy', '==', buy.uid) @@ -200,17 +178,15 @@ describe('Trade trigger', () => { expect(purchase.count).toBe(tokenCount); expect(purchase.tokenStatus).toBe(TokenStatus.PRE_MINTED); expect(purchase.sellerTier).toBe(0); - expect(purchase.sellerTokenTradingFeePercentage).toBeNull(); - - const sellerData = await build5Db().doc(`${COL.MEMBER}/${seller}`).get(); - const billPaymentDocRef = build5Db().doc(`${COL.TRANSACTION}/${purchase.billPaymentId}`); + expect(purchase.sellerTokenTradingFeePercentage).toBeUndefined(); + const sellerData = await build5Db().doc(COL.MEMBER, seller).get(); + const billPaymentDocRef = build5Db().doc(COL.TRANSACTION, purchase.billPaymentId!); const billPayment = await billPaymentDocRef.get(); expect(billPayment.payload.sourceAddress).toBe(order.payload.targetAddress); expect(billPayment.payload.targetAddress).toBe(getAddress(sellerData, Network.IOTA)); expect(billPayment.payload.token).toBe(token.uid); expect(billPayment.payload.tokenSymbol).toBe(token.symbol); expect(billPayment.payload.type).toBe(TransactionPayloadType.PRE_MINTED_TOKEN_TRADE); - const paymentSnap = await getBillPayments(buyer); expect(paymentSnap.length).toBe(3); const payments = paymentSnap.sort((a, b) => a.payload.amount! - b.payload.amount!); @@ -218,71 +194,62 @@ describe('Trade trigger', () => { getRoyaltyDistribution(MIN_IOTA_AMOUNT * tokenCount), ); expect(payments.map((d) => d.ignoreWallet)).toEqual([false, false, undefined]); - payments.forEach((p) => { expect(p?.payload?.previousOwner).toBe(buyer); expect(p?.member).toBe(buyer); }); - await assertVolumeTotal(token.uid, tokenCount); }); it('Should fulfill buy with one sell, same owner', async () => { buyer = seller; - - mockWalletReturnValue(walletSpy, seller, { + mockWalletReturnValue(seller, { symbol: token.symbol, price: MIN_IOTA_AMOUNT, count: tokenCount, type: TokenTradeOrderType.SELL, }); - await testEnv.wrap(tradeToken)({}); - + await testEnv.wrap(WEN_FUNC.tradeToken); const request = { symbol: token.symbol, price: MIN_IOTA_AMOUNT, count: tokenCount }; const order = await buyTokenFunc(buyer, request); - await wait(async () => { const buySnap = await build5Db() .collection(COL.TOKEN_MARKET) - .where('type', '==', TokenTradeOrderType.BUY) + .where('type', '==', PgTokenTradeOrderType.BUY) .where('owner', '==', buyer) - .get(); + .get(); return buySnap[0].fulfilled === tokenCount; }); - const buySnap = await build5Db() .collection(COL.TOKEN_MARKET) - .where('type', '==', TokenTradeOrderType.BUY) + .where('type', '==', PgTokenTradeOrderType.BUY) .where('owner', '==', buyer) .get(); expect(buySnap.length).toBe(1); const buy = buySnap[0]; expect(buy.status).toBe(TokenTradeOrderStatus.SETTLED); const buyDistribution = ( - await build5Db().doc(`${COL.TOKEN}/${token.uid}/${SUB_COL.DISTRIBUTION}/${buyer}`).get() + await build5Db().doc(COL.TOKEN, token.uid, SUB_COL.DISTRIBUTION, buyer).get() ); expect(buyDistribution.totalPurchased).toBe(tokenCount); expect(buyDistribution.tokenOwned).toBe(3 * tokenCount); - const purchase = await build5Db() .collection(COL.TOKEN_PURCHASE) .where('buy', '==', buy.uid) - .get(); + .get(); expect(purchase.length).toBe(1); expect(purchase[0].buy).toBe(buy.uid); expect(purchase[0].sell).toBeDefined(); expect(purchase[0].price).toBe(MIN_IOTA_AMOUNT); expect(purchase[0].count).toBe(tokenCount); - - const sellerData = await build5Db().doc(`${COL.MEMBER}/${seller}`).get(); - const billPaymentDocRef = build5Db().doc(`${COL.TRANSACTION}/${purchase[0].billPaymentId}`); + const sellerData = await build5Db().doc(COL.MEMBER, seller).get(); + const billPaymentDocRef = build5Db().doc(COL.TRANSACTION, purchase[0].billPaymentId!); const billPayment = await billPaymentDocRef.get(); expect(billPayment.payload.sourceAddress).toBe(order.payload.targetAddress); expect(billPayment.payload.targetAddress).toBe(getAddress(sellerData, Network.IOTA)); expect(billPayment.payload.token).toBe(token.uid); expect(billPayment.payload.tokenSymbol).toBe(token.symbol); expect(billPayment.payload.type).toBe(TransactionPayloadType.PRE_MINTED_TOKEN_TRADE); - const paymentSnap = await getBillPayments(buyer); expect(paymentSnap.length).toBe(3); const payments = paymentSnap.sort((a, b) => a.payload.amount! - b.payload.amount!); @@ -290,62 +257,55 @@ describe('Trade trigger', () => { getRoyaltyDistribution(MIN_IOTA_AMOUNT * tokenCount), ); expect(payments.map((d) => d.ignoreWallet)).toEqual([false, false, undefined]); - payments.forEach((p) => { expect(p?.payload?.previousOwner).toBe(seller); expect(p?.member).toBe(buyer); }); - await assertVolumeTotal(token.uid, tokenCount); }); it('Should fulfill buy with two sell and credit owner', async () => { - mockWalletReturnValue(walletSpy, seller, { + mockWalletReturnValue(seller, { symbol: token.symbol, price: MIN_IOTA_AMOUNT, count: tokenCount, type: TokenTradeOrderType.SELL, }); - await testEnv.wrap(tradeToken)({}); - mockWalletReturnValue(walletSpy, seller, { + await testEnv.wrap(WEN_FUNC.tradeToken); + mockWalletReturnValue(seller, { symbol: token.symbol, price: MIN_IOTA_AMOUNT, count: tokenCount, type: TokenTradeOrderType.SELL, }); - await testEnv.wrap(tradeToken)({}); - + await testEnv.wrap(WEN_FUNC.tradeToken); const request = { symbol: token.symbol, price: MIN_IOTA_AMOUNT * 2, count: 2 * tokenCount }; const order = await buyTokenFunc(buyer, request); - await wait(async () => { const buySnap = await build5Db() .collection(COL.TOKEN_MARKET) - .where('type', '==', TokenTradeOrderType.BUY) + .where('type', '==', PgTokenTradeOrderType.BUY) .where('owner', '==', buyer) - .get(); + .get(); return buySnap[0].fulfilled === 2 * tokenCount; }); - const buySnap = await build5Db() .collection(COL.TOKEN_MARKET) - .where('type', '==', TokenTradeOrderType.BUY) + .where('type', '==', PgTokenTradeOrderType.BUY) .where('owner', '==', buyer) - .get(); + .get(); expect(buySnap.length).toBe(1); const buy = buySnap[0]; expect(buy.status).toBe(TokenTradeOrderStatus.SETTLED); - const credit = ( - await build5Db().doc(`${COL.TRANSACTION}/${buy.creditTransactionId}`).get() + await build5Db().doc(COL.TRANSACTION, buy.creditTransactionId!).get() ); expect(credit.payload.amount).toBe(MIN_IOTA_AMOUNT * 2 * tokenCount); expect(credit.payload.sourceTransaction).toContain(buySnap[0].paymentTransactionId); expect(credit?.payload?.sourceAddress).toBe(order.payload.targetAddress); - const buyerData = await build5Db().doc(`${COL.MEMBER}/${buyer}`).get(); + const buyerData = await build5Db().doc(COL.MEMBER, buyer).get(); expect(credit?.payload?.targetAddress).toBe(getAddress(buyerData, Network.IOTA)); expect(credit.network).toBe(DEFAULT_NETWORK); - const paymentSnap = await getBillPayments(buyer); expect(paymentSnap.length).toBe(6); const amounts = paymentSnap.map((d) => d.payload.amount!).sort((a, b) => a - b); @@ -356,7 +316,6 @@ describe('Trade trigger', () => { ].sort((a, b) => a - b), ); paymentSnap.forEach((doc) => expect(doc?.network).toBe(DEFAULT_NETWORK)); - await assertVolumeTotal(token.uid, 2 * tokenCount); }); @@ -364,80 +323,73 @@ describe('Trade trigger', () => { const request = { symbol: token.symbol, price: MIN_IOTA_AMOUNT, count: tokenCount }; await buyTokenFunc(buyer, request); await buyTokenFunc(buyer, request); - - mockWalletReturnValue(walletSpy, seller, { + mockWalletReturnValue(seller, { symbol: token.symbol, price: MIN_IOTA_AMOUNT, count: 2 * tokenCount, type: TokenTradeOrderType.SELL, }); - await testEnv.wrap(tradeToken)({}); - + await testEnv.wrap(WEN_FUNC.tradeToken); await wait(async () => { const sellSnap = await build5Db() .collection(COL.TOKEN_MARKET) - .where('type', '==', TokenTradeOrderType.SELL) + .where('type', '==', PgTokenTradeOrderType.SELL) .where('owner', '==', seller) - .get(); + .get(); return sellSnap[0].fulfilled === 2 * tokenCount; }); - const sellSnap = await build5Db() .collection(COL.TOKEN_MARKET) - .where('type', '==', TokenTradeOrderType.SELL) + .where('type', '==', PgTokenTradeOrderType.SELL) .where('owner', '==', seller) .get(); expect(sellSnap.length).toBe(1); const sell = sellSnap[0]; expect(sell.status).toBe(TokenTradeOrderStatus.SETTLED); expect(sell.fulfilled).toBe(2 * tokenCount); - await assertVolumeTotal(token.uid, 2 * tokenCount); }); it('Should sell tokens in two transactions', async () => { - mockWalletReturnValue(walletSpy, seller, { + mockWalletReturnValue(seller, { symbol: token.symbol, price: MIN_IOTA_AMOUNT, count: 2 * tokenCount, type: TokenTradeOrderType.SELL, }); - await testEnv.wrap(tradeToken)({}); + await testEnv.wrap(WEN_FUNC.tradeToken); await buyTokenFunc(buyer, { symbol: token.symbol, price: MIN_IOTA_AMOUNT, count: 2 * tokenCount, }); - - mockWalletReturnValue(walletSpy, seller, { + mockWalletReturnValue(seller, { symbol: token.symbol, price: MIN_IOTA_AMOUNT, count: tokenCount, type: TokenTradeOrderType.SELL, }); - await testEnv.wrap(tradeToken)({}); + await testEnv.wrap(WEN_FUNC.tradeToken); await buyTokenFunc(buyer, { symbol: token.symbol, price: MIN_IOTA_AMOUNT, count: tokenCount }); - await wait(async () => { const distribution = ( - await build5Db().doc(`${COL.TOKEN}/${token.uid}/${SUB_COL.DISTRIBUTION}/${seller}`).get() + await build5Db().doc(COL.TOKEN, token.uid, SUB_COL.DISTRIBUTION, seller).get() ); return distribution.tokenOwned === 0 && distribution.sold === 3 * tokenCount; }); }); it('Should buy in parallel', async () => { - mockWalletReturnValue(walletSpy, seller, { + mockWalletReturnValue(seller, { symbol: token.symbol, price: MIN_IOTA_AMOUNT, count: 2 * tokenCount, type: TokenTradeOrderType.SELL, }); - await testEnv.wrap(tradeToken)({}); + await testEnv.wrap(WEN_FUNC.tradeToken); const request = { symbol: token.symbol, price: MIN_IOTA_AMOUNT, count: tokenCount }; const promises = [buyTokenFunc(buyer, request), buyTokenFunc(buyer, request)]; await Promise.all(promises); - await wait(async () => { const allSettled = ( await build5Db().collection(COL.TOKEN_MARKET).where('owner', '==', buyer).get() @@ -446,10 +398,10 @@ describe('Trade trigger', () => { .reduce((sum, act) => sum && act.status === TokenTradeOrderStatus.SETTLED, true); return allSettled; }); - - const sales = ( - await build5Db().collection(COL.TOKEN_MARKET).where('owner', 'in', [seller, buyer]).get() - ).map((d) => d); + const sales = [ + ...(await build5Db().collection(COL.TOKEN_MARKET).where('owner', '==', seller).get()), + ...(await build5Db().collection(COL.TOKEN_MARKET).where('owner', '==', buyer).get()), + ].map((d) => d); expect(sales.length).toBe(3); const buyFulfillmentCount = sales.reduce( (sum, sale) => sum + (sale.type === TokenTradeOrderType.BUY ? sale.fulfilled : 0), @@ -461,16 +413,13 @@ describe('Trade trigger', () => { 0, ); expect(sellFulfillmentCount).toBe(2 * tokenCount); - await assertVolumeTotal(token.uid, 2 * tokenCount); }); it('Should buy and sell in parallel', async () => { - const distributionDocRef = build5Db().doc( - `${COL.TOKEN}/${token.uid}/${SUB_COL.DISTRIBUTION}/${seller}`, - ); - const distribution = { tokenOwned: 3 * tokenCount }; - await distributionDocRef.set(distribution); + const distributionDocRef = build5Db().doc(COL.TOKEN, token.uid, SUB_COL.DISTRIBUTION, seller); + const distribution = { tokenOwned: 3 * tokenCount }; + await distributionDocRef.upsert(distribution); const sellTokenFunc = async (count: number, price: number) => { const sellDocId = wallet.getRandomEthAddress(); const data = { @@ -488,12 +437,9 @@ describe('Trade trigger', () => { status: TokenTradeOrderStatus.ACTIVE, createdOn: serverTime(), }; - await build5Db().doc(`${COL.TOKEN_MARKET}/${sellDocId}`).create(data); - await distributionDocRef.update({ - lockedForSale: build5Db().inc(count), - }); + await build5Db().doc(COL.TOKEN_MARKET, sellDocId).create(data); + await distributionDocRef.update({ lockedForSale: build5Db().inc(count) }); }; - const buyRequest = { symbol: token.symbol, price: MIN_IOTA_AMOUNT, count: tokenCount }; const promises = [ buyTokenFunc(buyer, buyRequest), @@ -503,36 +449,33 @@ describe('Trade trigger', () => { sellTokenFunc(tokenCount, MIN_IOTA_AMOUNT), ]; await Promise.all(promises); - await wait(async () => { - const allSettled = ( - await build5Db().collection(COL.TOKEN_MARKET).where('owner', 'in', [seller, buyer]).get() - ) + const allSettled = [ + ...(await build5Db().collection(COL.TOKEN_MARKET).where('owner', '==', seller).get()), + ...(await build5Db().collection(COL.TOKEN_MARKET).where('owner', '==', buyer).get()), + ] .map((d) => d) .reduce((sum, act) => sum && act.status === TokenTradeOrderStatus.SETTLED, true); return allSettled; }); - - const sales = ( - await build5Db().collection(COL.TOKEN_MARKET).where('owner', 'in', [seller, buyer]).get() - ).map((d) => d); - + const sales = [ + ...(await build5Db().collection(COL.TOKEN_MARKET).where('owner', '==', seller).get()), + ...(await build5Db().collection(COL.TOKEN_MARKET).where('owner', '==', buyer).get()), + ].map((d) => d); const allSettled = sales.reduce( (sum, act) => sum && act.status === TokenTradeOrderStatus.SETTLED, true, ); expect(allSettled).toBe(true); - const sellDistribution = await distributionDocRef.get(); expect(sellDistribution.sold).toBe(3 * tokenCount); expect(sellDistribution.lockedForSale).toBe(0); expect(sellDistribution.tokenOwned).toBe(0); const buyDistribution = ( - await build5Db().doc(`${COL.TOKEN}/${token.uid}/${SUB_COL.DISTRIBUTION}/${buyer}`).get() + await build5Db().doc(COL.TOKEN, token.uid, SUB_COL.DISTRIBUTION, buyer).get() ); expect(buyDistribution.totalPurchased).toBe(3 * tokenCount); expect(buyDistribution.tokenOwned).toBe(3 * tokenCount); - const paymentSnap = await getBillPayments(buyer); expect(paymentSnap.length).toBe(9); const amounts = paymentSnap.map((d) => d.payload.amount!).sort((a, b) => a - b); @@ -540,140 +483,120 @@ describe('Trade trigger', () => { expect(amounts).toEqual( [...sortedAmount, ...sortedAmount, ...sortedAmount].sort((a, b) => a - b), ); - await assertVolumeTotal(token.uid, 3 * tokenCount); }); it('Should cancel buy after half fulfilled', async () => { - mockWalletReturnValue(walletSpy, seller, { + mockWalletReturnValue(seller, { symbol: token.symbol, price: MIN_IOTA_AMOUNT, count: tokenCount, type: TokenTradeOrderType.SELL, }); - await testEnv.wrap(tradeToken)({}); + await testEnv.wrap(WEN_FUNC.tradeToken); await buyTokenFunc(buyer, { symbol: token.symbol, price: MIN_IOTA_AMOUNT, count: 2 * tokenCount, }); - await wait(async () => { const snap = await build5Db() .collection(COL.TOKEN_MARKET) .where('owner', '==', buyer) - .where('type', '==', TokenTradeOrderType.BUY) - .get(); + .where('type', '==', PgTokenTradeOrderType.BUY) + .get(); return snap[0].fulfilled === tokenCount; }); - const snap = await build5Db() .collection(COL.TOKEN_MARKET) .where('owner', '==', buyer) - .where('type', '==', TokenTradeOrderType.BUY) - .get(); - mockWalletReturnValue(walletSpy, buyer, { uid: snap[0].uid }); - const cancelled = await testEnv.wrap(cancelTradeOrder)({}); + .where('type', '==', PgTokenTradeOrderType.BUY) + .get(); + mockWalletReturnValue(buyer, { uid: snap[0].uid }); + const cancelled = await testEnv.wrap(WEN_FUNC.cancelTradeOrder); expect(cancelled.status).toBe(TokenTradeOrderStatus.PARTIALLY_SETTLED_AND_CANCELLED); - const creditSnap = await build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.CREDIT) + .where('type', '==', PgTransactionType.CREDIT) .where('member', '==', buyer) - .where('payload.type', '==', TransactionPayloadType.TOKEN_BUY) - .get(); + .where('payload_type', '==', PgTransactionPayloadType.TOKEN_BUY) + .get(); expect(creditSnap.length).toBe(1); expect(creditSnap[0]?.payload?.amount).toBe(tokenCount * MIN_IOTA_AMOUNT); expect(creditSnap[0]?.payload?.reason).toBe(CreditPaymentReason.TRADE_CANCELLED); - await assertVolumeTotal(token.uid, tokenCount); }); it('Should cancel buy after half fulfilled, decimal values', async () => { const tokenCount = 7; - mockWalletReturnValue(walletSpy, seller, { + mockWalletReturnValue(seller, { symbol: token.symbol, price: MIN_IOTA_AMOUNT + 0.1, count: tokenCount, type: TokenTradeOrderType.SELL, }); - await testEnv.wrap(tradeToken)({}); + await testEnv.wrap(WEN_FUNC.tradeToken); await buyTokenFunc(buyer, { symbol: token.symbol, price: MIN_IOTA_AMOUNT + 0.1, count: 2 * tokenCount, }); - await wait(async () => { return ( - ( - await build5Db() - .collection(COL.TOKEN_MARKET) - .where('owner', '==', buyer) - .get() - )[0]?.fulfilled === tokenCount + (await build5Db().collection(COL.TOKEN_MARKET).where('owner', '==', buyer).get())[0] + ?.fulfilled === tokenCount ); }); - const buyQuery = build5Db() .collection(COL.TOKEN_MARKET) - .where('type', '==', TokenTradeOrderType.BUY) + .where('type', '==', PgTokenTradeOrderType.BUY) .where('owner', '==', buyer); const buySnap = await buyQuery.get(); expect(buySnap.length).toBe(1); const buy = buySnap[0]; - - mockWalletReturnValue(walletSpy, buyer, { uid: buy.uid }); - const cancelled = await testEnv.wrap(cancelTradeOrder)({}); + mockWalletReturnValue(buyer, { uid: buy.uid }); + const cancelled = await testEnv.wrap(WEN_FUNC.cancelTradeOrder); expect(cancelled.status).toBe(TokenTradeOrderStatus.PARTIALLY_SETTLED_AND_CANCELLED); - const creditSnap = await build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.CREDIT) + .where('type', '==', PgTransactionType.CREDIT) .where('member', '==', buyer) - .where('payload.type', '==', TransactionPayloadType.TOKEN_BUY) - .get(); + .where('payload_type', '==', PgTransactionPayloadType.TOKEN_BUY) + .get(); expect(creditSnap.length).toBe(1); expect(creditSnap[0]?.payload?.amount).toBe(tokenCount * MIN_IOTA_AMOUNT + 1); expect(creditSnap[0]?.payload?.reason).toBe(CreditPaymentReason.TRADE_CANCELLED); }); it('Should settle after second run on more than batch limit', async () => { - const distribution = { tokenOwned: 70 * tokenCount }; - await build5Db() - .doc(`${COL.TOKEN}/${token.uid}/${SUB_COL.DISTRIBUTION}/${seller}`) - .set(distribution); - + const distribution = { tokenOwned: 70 * tokenCount }; + await build5Db().doc(COL.TOKEN, token.uid, SUB_COL.DISTRIBUTION, seller).upsert(distribution); const promises = Array.from(Array(TOKEN_TRADE_ORDER_FETCH_LIMIT + 50)).map(() => saveSellToDb(1, MIN_IOTA_AMOUNT), ); await Promise.all(promises); - const count = TOKEN_TRADE_ORDER_FETCH_LIMIT + 20; - const request = { symbol: token.symbol, price: MIN_IOTA_AMOUNT, count }; await buyTokenFunc(buyer, request); - await wait(async () => { return ( ( await build5Db() .collection(COL.TOKEN_MARKET) - .where('type', '==', TokenTradeOrderType.BUY) + .where('type', '==', PgTokenTradeOrderType.BUY) .where('owner', '==', buyer) - .get() + .get() )[0].status === TokenTradeOrderStatus.SETTLED ); }); const bu = await build5Db() .collection(COL.TOKEN_MARKET) - .where('type', '==', TokenTradeOrderType.BUY) + .where('type', '==', PgTokenTradeOrderType.BUY) .where('owner', '==', buyer) - .get(); + .get(); expect(bu.length).toBe(1); expect(bu[0]?.fulfilled).toBe(count); expect(bu[0]?.status).toBe(TokenTradeOrderStatus.SETTLED); - const purchases = await build5Db() .collection(COL.TOKEN_PURCHASE) .where('buy', '==', bu[0]?.uid) @@ -685,30 +608,27 @@ describe('Trade trigger', () => { const promises = Array.from(Array(100)).map(() => saveSellToDb(1, 1)); await Promise.all(promises); await saveSellToDb(1, MIN_IOTA_AMOUNT); - const request = { symbol: token.symbol, price: MIN_IOTA_AMOUNT, count: 1 }; await buyTokenFunc(buyer, request); - await wait(async () => { return ( ( await build5Db() .collection(COL.TOKEN_MARKET) - .where('type', '==', TokenTradeOrderType.BUY) + .where('type', '==', PgTokenTradeOrderType.BUY) .where('owner', '==', buyer) - .get() + .get() )[0].status === TokenTradeOrderStatus.SETTLED ); }); const bu = await build5Db() .collection(COL.TOKEN_MARKET) - .where('type', '==', TokenTradeOrderType.BUY) + .where('type', '==', PgTokenTradeOrderType.BUY) .where('owner', '==', buyer) - .get(); + .get(); expect(bu.length).toBe(1); expect(bu[0]?.fulfilled).toBe(1); expect(bu[0]?.status).toBe(TokenTradeOrderStatus.SETTLED); - const purchases = await build5Db() .collection(COL.TOKEN_PURCHASE) .where('buy', '==', bu[0]?.uid) @@ -717,28 +637,24 @@ describe('Trade trigger', () => { }); it('Should not fill buy, balance would be less then MIN_IOTA_AMOUNT and order not fulfilled', async () => { - mockWalletReturnValue(walletSpy, seller, { + mockWalletReturnValue(seller, { symbol: token.symbol, price: MIN_IOTA_AMOUNT / 2, count: 2 * tokenCount - 1, type: TokenTradeOrderType.SELL, }); - await testEnv.wrap(tradeToken)({}); - + await testEnv.wrap(WEN_FUNC.tradeToken); await buyTokenFunc(buyer, { symbol: token.symbol, price: MIN_IOTA_AMOUNT / 2, count: 2 * tokenCount, }); - const orderQuery = build5Db().collection(COL.TOKEN_MARKET).where('token', '==', token.uid); await wait(async () => { const snap = await orderQuery.get(); return snap.length === 2; }); - await new Promise((resolve) => setTimeout(resolve, 2000)); - const purchase = await build5Db() .collection(COL.TOKEN_PURCHASE) .where('token', '==', token.uid) @@ -747,48 +663,41 @@ describe('Trade trigger', () => { }); it('Should fill buy and send dust to space one', async () => { - mockWalletReturnValue(walletSpy, seller, { + mockWalletReturnValue(seller, { symbol: token.symbol, price: MIN_IOTA_AMOUNT / 2, count: 2 * tokenCount, type: TokenTradeOrderType.SELL, }); - await testEnv.wrap(tradeToken)({}); - + await testEnv.wrap(WEN_FUNC.tradeToken); await buyTokenFunc(buyer, { symbol: token.symbol, price: MIN_IOTA_AMOUNT / 2 + 1, count: 2 * tokenCount, }); - const purchaseQuery = build5Db().collection(COL.TOKEN_PURCHASE).where('token', '==', token.uid); await wait(async () => { const snap = await purchaseQuery.get(); return snap.length === 1; }); - const purchase = (await purchaseQuery.get())[0]; expect(purchase.count).toBe(2 * tokenCount); expect(purchase.price).toBe(MIN_IOTA_AMOUNT / 2); - const billPayments = ( await build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.BILL_PAYMENT) - .where('payload.token', '==', token.uid) + .where('type', '==', PgTransactionType.BILL_PAYMENT) + .where('payload_token', '==', token.uid) .get() ).map((d) => d); - const billPaymentToSeller = billPayments.find( (bp) => bp.payload.amount === (MIN_IOTA_AMOUNT / 2) * (2 * tokenCount) * 0.975, ); expect(billPaymentToSeller).toBeDefined(); - const billPaymentToSpaceOne = billPayments.find( (bp) => bp.payload.amount === (MIN_IOTA_AMOUNT / 2) * (2 * tokenCount) * 0.025 * 0.1 + 800, ); expect(billPaymentToSpaceOne).toBeDefined(); - const billPaymentToSpaceTwo = billPayments.find( (bp) => bp.payload.amount === (MIN_IOTA_AMOUNT / 2) * (2 * tokenCount) * 0.025 * 0.9, ); @@ -799,41 +708,27 @@ describe('Trade trigger', () => { 'Should not create royalty payments as percentage is zero', async (isMember: boolean) => { if (isMember) { - await build5Db().doc(`${COL.MEMBER}/${seller}`).update({ tokenTradingFeePercentage: 0 }); + await build5Db().doc(COL.MEMBER, seller).update({ tokenTradingFeePercentage: 0 }); await build5Db() - .collection(COL.TOKEN) - .doc(soonTokenId) - .collection(SUB_COL.DISTRIBUTION) - .doc(seller) - .set( - { - stakes: { - [StakeType.DYNAMIC]: { - value: 15000 * MIN_IOTA_AMOUNT, - }, - }, - }, - true, - ); + .doc(COL.TOKEN, soonTokenId, SUB_COL.DISTRIBUTION, seller) + .upsert({ stakes_dynamic_value: 15000 * MIN_IOTA_AMOUNT }); } else { await build5Db() - .doc(`${COL.SYSTEM}/${SYSTEM_CONFIG_DOC_ID}`) - .set({ tokenTradingFeePercentage: 0 }); + .doc(COL.SYSTEM, SYSTEM_CONFIG_DOC_ID) + .upsert({ tokenTradingFeePercentage: 0 }); } - mockWalletReturnValue(walletSpy, seller, { + mockWalletReturnValue(seller, { symbol: token.symbol, price: MIN_IOTA_AMOUNT / 2, count: 2 * tokenCount, type: TokenTradeOrderType.SELL, }); - await testEnv.wrap(tradeToken)({}); - + await testEnv.wrap(WEN_FUNC.tradeToken); await buyTokenFunc(buyer, { symbol: token.symbol, price: MIN_IOTA_AMOUNT / 2, count: 2 * tokenCount, }); - const purchaseQuery = build5Db() .collection(COL.TOKEN_PURCHASE) .where('token', '==', token.uid); @@ -841,7 +736,6 @@ describe('Trade trigger', () => { const snap = await purchaseQuery.get(); return snap.length === 1; }); - const purchase = (await purchaseQuery.get())[0]; expect(purchase.count).toBe(2 * tokenCount); expect(purchase.price).toBe(MIN_IOTA_AMOUNT / 2); @@ -849,16 +743,14 @@ describe('Trade trigger', () => { expect(purchase.sellerTier).toBe(4); expect(purchase.sellerTokenTradingFeePercentage).toBe(0); } - const billPayments = ( await build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.BILL_PAYMENT) - .where('payload.token', '==', token.uid) + .where('type', '==', PgTransactionType.BILL_PAYMENT) + .where('payload_token', '==', token.uid) .get() ).map((d) => d); expect(billPayments.length).toBe(1); - const billPaymentToSeller = billPayments.find( (bp) => bp.payload.amount === (MIN_IOTA_AMOUNT / 2) * (2 * tokenCount), ); @@ -867,93 +759,80 @@ describe('Trade trigger', () => { ); it('Should create royalty payments only with dust', async () => { - await build5Db().doc(`${COL.MEMBER}/${seller}`).update({ tokenTradingFeePercentage: 0 }); - mockWalletReturnValue(walletSpy, seller, { + await build5Db().doc(COL.MEMBER, seller).update({ tokenTradingFeePercentage: 0 }); + mockWalletReturnValue(seller, { symbol: token.symbol, price: MIN_IOTA_AMOUNT / 2, count: 2 * tokenCount, type: TokenTradeOrderType.SELL, }); - await testEnv.wrap(tradeToken)({}); - + await testEnv.wrap(WEN_FUNC.tradeToken); await buyTokenFunc(buyer, { symbol: token.symbol, price: MIN_IOTA_AMOUNT / 2 + 1, count: 2 * tokenCount, }); - const purchaseQuery = build5Db().collection(COL.TOKEN_PURCHASE).where('token', '==', token.uid); await wait(async () => { const snap = await purchaseQuery.get(); return snap.length === 1; }); - const purchase = (await purchaseQuery.get())[0]; expect(purchase.count).toBe(2 * tokenCount); expect(purchase.price).toBe(MIN_IOTA_AMOUNT / 2); - const billPayments = ( await build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.BILL_PAYMENT) - .where('payload.token', '==', token.uid) + .where('type', '==', PgTransactionType.BILL_PAYMENT) + .where('payload_token', '==', token.uid) .get() ).map((d) => d); expect(billPayments.length).toBe(2); - const billPaymentToSeller = billPayments.find( (bp) => bp.payload.amount === (MIN_IOTA_AMOUNT / 2) * (2 * tokenCount) + 800, ); expect(billPaymentToSeller).toBeDefined(); - const billPaymentToSpaceOne = billPayments.find((bp) => bp.payload.amount === 800); expect(billPaymentToSpaceOne).toBeDefined(); }); it('Should fill buy and send dust to space one', async () => { - await build5Db().doc(`${COL.MEMBER}/${seller}`).update({ tokenTradingFeePercentage: 1 }); - mockWalletReturnValue(walletSpy, seller, { + await build5Db().doc(COL.MEMBER, seller).update({ tokenTradingFeePercentage: 1 }); + mockWalletReturnValue(seller, { symbol: token.symbol, price: MIN_IOTA_AMOUNT / 2, count: 2 * tokenCount, type: TokenTradeOrderType.SELL, }); - await testEnv.wrap(tradeToken)({}); - + await testEnv.wrap(WEN_FUNC.tradeToken); await buyTokenFunc(buyer, { symbol: token.symbol, price: MIN_IOTA_AMOUNT / 2, count: 2 * tokenCount, }); - const purchaseQuery = build5Db().collection(COL.TOKEN_PURCHASE).where('token', '==', token.uid); await wait(async () => { const snap = await purchaseQuery.get(); return snap.length === 1; }); - const purchase = (await purchaseQuery.get())[0]; expect(purchase.count).toBe(2 * tokenCount); expect(purchase.price).toBe(MIN_IOTA_AMOUNT / 2); - const billPayments = ( await build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.BILL_PAYMENT) - .where('payload.token', '==', token.uid) + .where('type', '==', PgTransactionType.BILL_PAYMENT) + .where('payload_token', '==', token.uid) .get() ).map((d) => d); - const billPaymentToSpaceOne = billPayments.find( (bp) => bp.payload.amount === (MIN_IOTA_AMOUNT / 2) * (2 * tokenCount) * 0.01 * 0.1, ); expect(billPaymentToSpaceOne).toBeDefined(); - const billPaymentToSpaceTwo = billPayments.find( (bp) => bp.payload.amount === (MIN_IOTA_AMOUNT / 2) * (2 * tokenCount) * 0.01 * 0.9, ); expect(billPaymentToSpaceTwo).toBeDefined(); - const billPaymentToSeller = billPayments.find( (bp) => bp.payload.amount === @@ -970,24 +849,23 @@ describe('Trade trigger', () => { it('Should fulfill buy but only create one space bill payment', async () => { const tokenCount = 100; - mockWalletReturnValue(walletSpy, seller, { + mockWalletReturnValue(seller, { symbol: token.symbol, price: MIN_IOTA_AMOUNT, count: tokenCount, type: TokenTradeOrderType.SELL, }); - await testEnv.wrap(tradeToken)({}); + await testEnv.wrap(WEN_FUNC.tradeToken); const request = { symbol: token.symbol, price: MIN_IOTA_AMOUNT, count: tokenCount }; await buyTokenFunc(buyer, request); - await wait(async () => { return ( ( await build5Db() .collection(COL.TOKEN_MARKET) - .where('type', '==', TokenTradeOrderType.BUY) + .where('type', '==', PgTokenTradeOrderType.BUY) .where('owner', '==', buyer) - .get() + .get() )[0].status === TokenTradeOrderStatus.SETTLED ); }); @@ -1001,31 +879,25 @@ describe('Trade trigger', () => { }); it('Should cancel sell after half fulfilled', async () => { - mockWalletReturnValue(walletSpy, seller, { + mockWalletReturnValue(seller, { symbol: token.symbol, price: MIN_IOTA_AMOUNT, count: 10, type: TokenTradeOrderType.SELL, }); - const sell = await testEnv.wrap(tradeToken)({}); + const sell = await testEnv.wrap(WEN_FUNC.tradeToken); await buyTokenFunc(buyer, { symbol: token.symbol, price: MIN_IOTA_AMOUNT, count: 5 }); - await wait(async () => { return ( - ( - await build5Db() - .collection(COL.TOKEN_MARKET) - .where('owner', '==', buyer) - .get() - )[0]?.fulfilled === 5 + (await build5Db().collection(COL.TOKEN_MARKET).where('owner', '==', buyer).get())[0] + ?.fulfilled === 5 ); }); - mockWalletReturnValue(walletSpy, seller, { uid: sell.uid }); - const cancelled = await testEnv.wrap(cancelTradeOrder)({}); + mockWalletReturnValue(seller, { uid: sell.uid }); + const cancelled = await testEnv.wrap(WEN_FUNC.cancelTradeOrder); expect(cancelled.status).toBe(TokenTradeOrderStatus.PARTIALLY_SETTLED_AND_CANCELLED); - const sellDistribution = ( - await build5Db().doc(`${COL.TOKEN}/${token.uid}/${SUB_COL.DISTRIBUTION}/${seller}`).get() + await build5Db().doc(COL.TOKEN, token.uid, SUB_COL.DISTRIBUTION, seller).get() ); expect(sellDistribution.lockedForSale).toBe(0); expect(sellDistribution.sold).toBe(5); @@ -1033,37 +905,29 @@ describe('Trade trigger', () => { }); it('Should fulfill buy with lowest sell', async () => { - mockWalletReturnValue(walletSpy, seller, { + mockWalletReturnValue(seller, { symbol: token.symbol, price: 2 * MIN_IOTA_AMOUNT, count: 10, type: TokenTradeOrderType.SELL, }); - await testEnv.wrap(tradeToken)({}); - mockWalletReturnValue(walletSpy, seller, { + await testEnv.wrap(WEN_FUNC.tradeToken); + + mockWalletReturnValue(seller, { symbol: token.symbol, price: MIN_IOTA_AMOUNT, count: 10, type: TokenTradeOrderType.SELL, }); - await testEnv.wrap(tradeToken)({}); + await testEnv.wrap(WEN_FUNC.tradeToken); await buyTokenFunc(buyer, { symbol: token.symbol, price: 2 * MIN_IOTA_AMOUNT, count: 10 }); - await wait(async () => { return ( - ( - await build5Db() - .collection(COL.TOKEN_MARKET) - .where('owner', '==', buyer) - .get() - )[0]?.fulfilled === 10 + (await build5Db().collection(COL.TOKEN_MARKET).where('owner', '==', buyer).get())[0] + ?.fulfilled === 10 ); }); - - const buys = await build5Db() - .collection(COL.TOKEN_MARKET) - .where('owner', '==', buyer) - .get(); + const buys = await build5Db().collection(COL.TOKEN_MARKET).where('owner', '==', buyer).get(); const purchase = ( (await build5Db().collection(COL.TOKEN_PURCHASE).where('buy', '==', buys[0].uid).get())[0] ); @@ -1074,30 +938,23 @@ describe('Trade trigger', () => { await buyTokenFunc(buyer, { symbol: token.symbol, price: 2 * MIN_IOTA_AMOUNT, count: 10 }); await buyTokenFunc(buyer, { symbol: token.symbol, price: MIN_IOTA_AMOUNT, count: 10 }); await wait(async () => { - const snap = await build5Db() - .collection(COL.TOKEN_MARKET) - .where('owner', '==', buyer) - .get(); + const snap = await build5Db().collection(COL.TOKEN_MARKET).where('owner', '==', buyer).get(); const wasUpdated = snap.reduce((acc, act) => acc && !isEmpty(act.updatedOn), true); return snap.length === 2 && wasUpdated; }); - mockWalletReturnValue(walletSpy, seller, { + mockWalletReturnValue(seller, { symbol: token.symbol, price: MIN_IOTA_AMOUNT, count: 10, type: TokenTradeOrderType.SELL, }); - const sell = await testEnv.wrap(tradeToken)({}); + const sell = await testEnv.wrap(WEN_FUNC.tradeToken); await wait(async () => { return ( - ( - await build5Db() - .collection(COL.TOKEN_MARKET) - .where('owner', '==', seller) - .get() - )[0]?.fulfilled === 10 + (await build5Db().collection(COL.TOKEN_MARKET).where('owner', '==', seller).get())[0] + ?.fulfilled === 10 ); }); @@ -1108,14 +965,13 @@ describe('Trade trigger', () => { }); it('Should fulfill low price sell with high price buy', async () => { - mockWalletReturnValue(walletSpy, seller, { + mockWalletReturnValue(seller, { symbol: token.symbol, price: MIN_IOTA_AMOUNT / 2, count: 100, type: TokenTradeOrderType.SELL, }); - await testEnv.wrap(tradeToken)({}); - + await testEnv.wrap(WEN_FUNC.tradeToken); const order = await buyTokenFunc(buyer, { symbol: token.symbol, price: MIN_IOTA_AMOUNT, @@ -1126,7 +982,7 @@ describe('Trade trigger', () => { .collection(COL.TOKEN_MARKET) .where('orderTransactionId', '==', order.uid); await wait(async () => { - const buySnap = await buyQuery.get(); + const buySnap = await buyQuery.get(); return buySnap[0].fulfilled === 99; }); @@ -1135,11 +991,12 @@ describe('Trade trigger', () => { price: 2 * MIN_IOTA_AMOUNT, count: 1, }); + const buyQuery2 = build5Db() .collection(COL.TOKEN_MARKET) .where('orderTransactionId', '==', order2.uid); await wait(async () => { - const buySnap = await buyQuery2.get(); + const buySnap = await buyQuery2.get(); return buySnap[0].fulfilled === 1; }); @@ -1147,6 +1004,7 @@ describe('Trade trigger', () => { const purchase = ( await build5Db().collection(COL.TOKEN_PURCHASE).where('buy', '==', buy.uid).get() )[0] as TokenPurchase; + expect(purchase.price).toBe(2 * MIN_IOTA_AMOUNT); }); }); 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 5bfe700b00..1334525a30 100644 --- a/packages/functions/test/controls/token.expired.sale.cron.spec.ts +++ b/packages/functions/test/controls/token.expired.sale.cron.spec.ts @@ -1,12 +1,10 @@ -import { build5Db } from '@build-5/database'; +import { PgTokenStatus, PgTokenTradeOrderStatus, build5Db } from '@build-5/database'; import { COL, MIN_IOTA_AMOUNT, SOON_PROJECT_ID, SUB_COL, Token, - TokenDistribution, - TokenStatus, TokenTradeOrder, TokenTradeOrderStatus, TokenTradeOrderType, @@ -15,34 +13,28 @@ import dayjs from 'dayjs'; import { cancelExpiredSale } from '../../src/cron/token.cron'; import { dateToTimestamp } from '../../src/utils/dateTime.utils'; import * as wallet from '../../src/utils/wallet.utils'; -import { createMember, getRandomSymbol, wait } from './common'; - -let walletSpy: any; +import { testEnv } from '../set-up'; +import { getRandomSymbol, wait } from './common'; describe('Expired sales cron', () => { let seller: string; - let token: Token; - beforeEach(async () => { - walletSpy = jest.spyOn(wallet, 'decodeAuth'); - seller = await createMember(walletSpy); - + seller = await testEnv.createMember(); const tokenId = wallet.getRandomEthAddress(); - token = { + const tokenUpsert = { project: SOON_PROJECT_ID, uid: tokenId, symbol: getRandomSymbol(), name: 'MyToken', space: 'myspace', - status: TokenStatus.PRE_MINTED, + status: PgTokenStatus.PRE_MINTED, approved: true, }; - await build5Db().doc(`${COL.TOKEN}/${tokenId}`).set(token); - const distribution = { tokenOwned: 1000 }; - await build5Db() - .doc(`${COL.TOKEN}/${tokenId}/${SUB_COL.DISTRIBUTION}/${seller}`) - .set(distribution); + await build5Db().doc(COL.TOKEN, tokenId).upsert(tokenUpsert); + token = (await build5Db().doc(COL.TOKEN, tokenId).get())!; + const distribution = { tokenOwned: 1000 }; + await build5Db().doc(COL.TOKEN, tokenId, SUB_COL.DISTRIBUTION, seller).upsert(distribution); }); it('Should cancel all expired sales', async () => { @@ -71,33 +63,30 @@ describe('Expired sales cron', () => { ) => { const sells = Array.from(Array(count)).map(() => getDummySell(status, type)); const batch = build5Db().batch(); - sells.forEach((s) => batch.create(build5Db().doc(`${COL.TOKEN_MARKET}/${s.uid}`), s)); + const promises = sells.map((s) => batch.create(build5Db().doc(COL.TOKEN_MARKET, s.uid), s)); + await Promise.all(promises); await batch.commit(); return sells; }; - await createSales(TokenTradeOrderStatus.ACTIVE, TokenTradeOrderType.SELL, salesCount); await createSales(TokenTradeOrderStatus.SETTLED, TokenTradeOrderType.SELL, 3); - await wait(async () => { const snap = await build5Db() .collection(COL.TOKEN_MARKET) .where('owner', '==', seller) - .where('status', '==', TokenTradeOrderStatus.ACTIVE) - .get(); + .where('status', '==', PgTokenTradeOrderStatus.ACTIVE) + .get(); const processed = snap.reduce( (sum, act) => sum && (act).updatedOn !== undefined, true, ); return processed; }); - await cancelExpiredSale(); - const snap = await build5Db() .collection(COL.TOKEN_MARKET) .where('owner', '==', seller) - .where('status', '==', TokenTradeOrderStatus.EXPIRED) + .where('status', '==', PgTokenTradeOrderStatus.EXPIRED) .get(); expect(snap.length).toBe(salesCount); }); diff --git a/packages/functions/test/controls/token.order.spec.ts b/packages/functions/test/controls/token.order.spec.ts index 26e2a6bbce..bb8ea3aad5 100644 --- a/packages/functions/test/controls/token.order.spec.ts +++ b/packages/functions/test/controls/token.order.spec.ts @@ -1,6 +1,5 @@ -import { build5Db } from '@build-5/database'; +import { PgAccess, PgTokenStatus, build5Db } from '@build-5/database'; import { - Access, COL, MIN_IOTA_AMOUNT, NetworkAddress, @@ -9,59 +8,43 @@ import { Space, Token, TokenDistribution, - TokenStatus, + Transaction, WEN_FUNC, WenError, } from '@build-5/interfaces'; import dayjs from 'dayjs'; -import { joinSpace } from '../../src/runtime/firebase/space'; -import { creditToken, orderToken } from '../../src/runtime/firebase/token/base'; -import { dateToTimestamp, serverTime } from '../../src/utils/dateTime.utils'; +import { orderTokenControl } from '../../src/controls/token/token.order'; +import { serverTime } from '../../src/utils/dateTime.utils'; import * as wallet from '../../src/utils/wallet.utils'; -import { MEDIA, testEnv } from '../set-up'; -import { - createMember, - createSpace, - expectThrow, - getRandomSymbol, - mockIpCheck, - mockWalletReturnValue, - submitMilestoneFunc, -} from './common'; - -let walletSpy: any; +import { MEDIA, mockWalletReturnValue, testEnv } from '../set-up'; +import { expectThrow, getRandomSymbol, mockIpCheck, submitMilestoneFunc } from './common'; -const submitTokenOrderFunc = async (spy: string, address: NetworkAddress, params: T) => { - mockWalletReturnValue(spy, address, params); - const order = await testEnv.wrap(orderToken)({}); +const submitTokenOrderFunc = async (address: NetworkAddress, params: T) => { + mockWalletReturnValue(address, params); + const order = await testEnv.wrap(WEN_FUNC.orderToken); expect(order?.createdOn).toBeDefined(); return order; }; - -const submitCreditTokenFunc = async (spy: string, address: NetworkAddress, params: T) => { - mockWalletReturnValue(spy, address, params); - const order = await testEnv.wrap(creditToken)({}); +const submitCreditTokenFunc = async (address: NetworkAddress, params: T) => { + mockWalletReturnValue(address, params); + const order = await testEnv.wrap(WEN_FUNC.creditToken); expect(order?.createdOn).toBeDefined(); return order; }; - const assertOrderedTokensCount = async (tokenId: string, expected: number) => { - const token = await build5Db().doc(`${COL.TOKEN}/${tokenId}`).get(); + const token = await build5Db().doc(COL.TOKEN, tokenId).get(); expect(token.tokensOrdered).toBe(expected); }; describe('Token controller: ' + WEN_FUNC.orderToken, () => { - let memberAddress: NetworkAddress; + let member: NetworkAddress; let space: Space; let token: Token; - beforeEach(async () => { - walletSpy = jest.spyOn(wallet, 'decodeAuth'); - memberAddress = await createMember(walletSpy); - space = await createSpace(walletSpy, memberAddress); - + member = await testEnv.createMember(); + space = await testEnv.createSpace(member); const tokenId = wallet.getRandomEthAddress(); - token = { + const tokenUpsert = { project: SOON_PROJECT_ID, symbol: getRandomSymbol(), totalSupply: 1000, @@ -69,233 +52,223 @@ describe('Token controller: ' + WEN_FUNC.orderToken, () => { rejected: false, icon: MEDIA, overviewGraphics: MEDIA, - updatedOn: serverTime(), - createdOn: serverTime(), + updatedOn: serverTime().toDate(), + createdOn: serverTime().toDate(), space: space.uid, uid: tokenId, pricePerToken: MIN_IOTA_AMOUNT, - allocations: [ + allocations: JSON.stringify([ { title: 'Public sale', isPublicSale: true, percentage: 50 }, { title: 'Private', percentage: 50 }, - ], - createdBy: memberAddress, + ]), + createdBy: member, name: 'MyToken', saleLength: 86400000 * 2, - saleStartDate: dateToTimestamp(dayjs().subtract(1, 'd').toDate()), + saleStartDate: dayjs().subtract(1, 'd').toDate(), links: [], - status: TokenStatus.AVAILABLE, + status: PgTokenStatus.AVAILABLE, totalDeposit: 0, totalAirdropped: 0, termsAndConditions: 'https://wen.soonaverse.com/token/terms-and-conditions', - access: 0, + access: PgAccess.OPEN, decimals: 6, }; - await build5Db().doc(`${COL.TOKEN}/${token.uid}`).set(token); + await build5Db().doc(COL.TOKEN, tokenId).upsert(tokenUpsert); + token = (await build5Db().doc(COL.TOKEN, tokenId).get())!; }); it('Should create token order', async () => { - const order = await submitTokenOrderFunc(walletSpy, memberAddress, { token: token.uid }); + const order = await submitTokenOrderFunc(member, { token: token.uid }); await submitMilestoneFunc(order); - const distribution = await build5Db() - .doc(`${COL.TOKEN}/${token.uid}/${SUB_COL.DISTRIBUTION}/${memberAddress}`) - .get(); + .doc(COL.TOKEN, token.uid, SUB_COL.DISTRIBUTION, member) + .get(); expect(distribution?.totalDeposit).toBe(MIN_IOTA_AMOUNT); await assertOrderedTokensCount(token.uid, 1); }); it('Should order more token', async () => { - const order = await submitTokenOrderFunc(walletSpy, memberAddress, { token: token.uid }); + const order = await submitTokenOrderFunc(member, { token: token.uid }); await submitMilestoneFunc(order); - - const order2 = await submitTokenOrderFunc(walletSpy, memberAddress, { token: token.uid }); + const order2 = await submitTokenOrderFunc(member, { token: token.uid }); await submitMilestoneFunc(order2); - const distribution = await build5Db() - .doc(`${COL.TOKEN}/${token.uid}/${SUB_COL.DISTRIBUTION}/${memberAddress}`) - .get(); + .doc(COL.TOKEN, token.uid, SUB_COL.DISTRIBUTION, member) + .get(); expect(distribution?.totalDeposit).toBe(MIN_IOTA_AMOUNT * 2); await assertOrderedTokensCount(token.uid, 2); }); it('Should create token order and should credit some amount', async () => { for (const _ of [0, 1]) { - const order = await submitTokenOrderFunc(walletSpy, memberAddress, { token: token.uid }); + const order = await submitTokenOrderFunc(member, { token: token.uid }); await submitMilestoneFunc(order); } - const distribution = await build5Db() - .doc(`${COL.TOKEN}/${token.uid}/${SUB_COL.DISTRIBUTION}/${memberAddress}`) - .get(); + .doc(COL.TOKEN, token.uid, SUB_COL.DISTRIBUTION, member) + .get(); expect(distribution?.totalDeposit).toBe(MIN_IOTA_AMOUNT * 2); - await build5Db() - .doc(`${COL.TOKEN}/${token.uid}`) + .doc(COL.TOKEN, token.uid) .update({ - saleStartDate: dateToTimestamp(dayjs().subtract(3, 'd').toDate()), - coolDownEnd: dateToTimestamp(dayjs().add(1, 'd').toDate()), + saleStartDate: dayjs().subtract(3, 'd').toDate(), + coolDownEnd: dayjs().add(1, 'd').toDate(), }); - - await submitCreditTokenFunc(walletSpy, memberAddress, { - token: token.uid, - amount: MIN_IOTA_AMOUNT, - }); - + await submitCreditTokenFunc(member, { token: token.uid, amount: MIN_IOTA_AMOUNT }); const updatedDistribution = await build5Db() - .doc(`${COL.TOKEN}/${token.uid}/${SUB_COL.DISTRIBUTION}/${memberAddress}`) - .get(); + .doc(COL.TOKEN, token.uid, SUB_COL.DISTRIBUTION, member) + .get(); expect(updatedDistribution?.totalDeposit).toBe(MIN_IOTA_AMOUNT); - - const updatedToken = await build5Db().doc(`${COL.TOKEN}/${token.uid}`).get(); + const updatedToken = await build5Db().doc(COL.TOKEN, token.uid).get(); expect(updatedToken?.totalDeposit).toBe(MIN_IOTA_AMOUNT); - await assertOrderedTokensCount(token.uid, 1); }); it('Should create token order and should credit all amount', async () => { - const order = await submitTokenOrderFunc(walletSpy, memberAddress, { token: token.uid }); + const order = await submitTokenOrderFunc(member, { token: token.uid }); await submitMilestoneFunc(order); - const distribution = await build5Db() - .doc(`${COL.TOKEN}/${token.uid}/${SUB_COL.DISTRIBUTION}/${memberAddress}`) - .get(); + .doc(COL.TOKEN, token.uid, SUB_COL.DISTRIBUTION, member) + .get(); expect(distribution?.totalDeposit).toBe(MIN_IOTA_AMOUNT); - await build5Db() - .doc(`${COL.TOKEN}/${token.uid}`) + .doc(COL.TOKEN, token.uid) .update({ - saleStartDate: dateToTimestamp(dayjs().subtract(3, 'd').toDate()), - coolDownEnd: dateToTimestamp(dayjs().add(1, 'd').toDate()), + saleStartDate: dayjs().subtract(3, 'd').toDate(), + coolDownEnd: dayjs().add(1, 'd').toDate(), }); - - await submitCreditTokenFunc(walletSpy, memberAddress, { - token: token.uid, - amount: MIN_IOTA_AMOUNT, - }); - + await submitCreditTokenFunc(member, { token: token.uid, amount: MIN_IOTA_AMOUNT }); const updatedDistribution = await build5Db() - .doc(`${COL.TOKEN}/${token.uid}/${SUB_COL.DISTRIBUTION}/${memberAddress}`) - .get(); + .doc(COL.TOKEN, token.uid, SUB_COL.DISTRIBUTION, member) + .get(); expect(updatedDistribution?.totalDeposit).toBe(0); - - const updatedToken = await build5Db().doc(`${COL.TOKEN}/${token.uid}`).get(); + const updatedToken = await build5Db().doc(COL.TOKEN, token.uid).get(); expect(updatedToken?.totalDeposit).toBe(0); await assertOrderedTokensCount(token.uid, 0); }); it('Should create token order and should fail credit, not in cool down period', async () => { - const order = await submitTokenOrderFunc(walletSpy, memberAddress, { token: token.uid }); + const order = await submitTokenOrderFunc(member, { token: token.uid }); await submitMilestoneFunc(order); - await build5Db() - .doc(`${COL.TOKEN}/${token.uid}`) + .doc(COL.TOKEN, token.uid) .update({ - saleStartDate: dateToTimestamp(dayjs().subtract(3, 'd').toDate()), - coolDownEnd: dateToTimestamp(dayjs().subtract(1, 'm').toDate()), + saleStartDate: dayjs().subtract(3, 'd').toDate(), + coolDownEnd: dayjs().subtract(1, 'm').toDate(), }); - - mockWalletReturnValue(walletSpy, memberAddress, { token: token.uid, amount: MIN_IOTA_AMOUNT }); - await expectThrow(testEnv.wrap(creditToken)({}), WenError.token_not_in_cool_down_period.key); + mockWalletReturnValue(member, { token: token.uid, amount: MIN_IOTA_AMOUNT }); + await expectThrow( + testEnv.wrap(WEN_FUNC.creditToken), + WenError.token_not_in_cool_down_period.key, + ); }); it('Should throw, amount too much to refund', async () => { - const order = await submitTokenOrderFunc(walletSpy, memberAddress, { token: token.uid }); + const order = await submitTokenOrderFunc(member, { token: token.uid }); await submitMilestoneFunc(order); - const distribution = await build5Db() - .doc(`${COL.TOKEN}/${token.uid}/${SUB_COL.DISTRIBUTION}/${memberAddress}`) - .get(); + .doc(COL.TOKEN, token.uid, SUB_COL.DISTRIBUTION, member) + .get(); expect(distribution?.totalDeposit).toBe(token.pricePerToken); - - mockWalletReturnValue(walletSpy, memberAddress, { + mockWalletReturnValue(member, { token: token.uid, amount: MIN_IOTA_AMOUNT * 4, }); - await expectThrow(testEnv.wrap(creditToken)({}), WenError.not_enough_funds.key); + await expectThrow(testEnv.wrap(WEN_FUNC.creditToken), WenError.not_enough_funds.key); }); it('Should throw, amount too much to refund after second credit', async () => { - const order = await submitTokenOrderFunc(walletSpy, memberAddress, { token: token.uid }); + const order = await submitTokenOrderFunc(member, { token: token.uid }); await submitMilestoneFunc(order); - await build5Db() - .doc(`${COL.TOKEN}/${token.uid}`) + .doc(COL.TOKEN, token.uid) .update({ - saleStartDate: dateToTimestamp(dayjs().subtract(3, 'd').toDate()), - coolDownEnd: dateToTimestamp(dayjs().add(1, 'd').toDate()), + saleStartDate: dayjs().subtract(3, 'd').toDate(), + coolDownEnd: dayjs().add(1, 'd').toDate(), }); - - mockWalletReturnValue(walletSpy, memberAddress, { + mockWalletReturnValue(member, { token: token.uid, amount: token.pricePerToken, }); - await testEnv.wrap(creditToken)({}); - - mockWalletReturnValue(walletSpy, memberAddress, { + await testEnv.wrap(WEN_FUNC.creditToken); + mockWalletReturnValue(member, { token: token.uid, amount: token.pricePerToken, }); - await expectThrow(testEnv.wrap(creditToken)({}), WenError.not_enough_funds.key); + await expectThrow(testEnv.wrap(WEN_FUNC.creditToken), WenError.not_enough_funds.key); }); it('Should allow only for members', async () => { - await build5Db().doc(`${COL.TOKEN}/${token.uid}`).update({ access: Access.MEMBERS_ONLY }); - mockWalletReturnValue(walletSpy, memberAddress, { token: token.uid }); - await testEnv.wrap(orderToken)({}); - const newMember = await createMember(walletSpy); - mockWalletReturnValue(walletSpy, newMember, { token: token.uid }); - await expectThrow(testEnv.wrap(orderToken)({}), WenError.you_are_not_part_of_space.key); + await build5Db().doc(COL.TOKEN, token.uid).update({ access: PgAccess.MEMBERS_ONLY }); + mockWalletReturnValue(member, { token: token.uid }); + await testEnv.wrap(WEN_FUNC.orderToken); + const newMember = await testEnv.createMember(); + mockWalletReturnValue(newMember, { token: token.uid }); + await expectThrow( + testEnv.wrap(WEN_FUNC.orderToken), + WenError.you_are_not_part_of_space.key, + ); }); it('Should allow only for guardians', async () => { - await build5Db().doc(`${COL.TOKEN}/${token.uid}`).update({ access: Access.GUARDIANS_ONLY }); - - const newMember = await createMember(walletSpy); - mockWalletReturnValue(walletSpy, newMember, { uid: space.uid }); - await testEnv.wrap(joinSpace)({}); - - mockWalletReturnValue(walletSpy, memberAddress, { token: token.uid }); - await testEnv.wrap(orderToken)({}); - - mockWalletReturnValue(walletSpy, newMember, { token: token.uid }); - await expectThrow(testEnv.wrap(orderToken)({}), WenError.you_are_not_guardian_of_space.key); + await build5Db().doc(COL.TOKEN, token.uid).update({ access: PgAccess.GUARDIANS_ONLY }); + const newMember = await testEnv.createMember(); + mockWalletReturnValue(newMember, { uid: space.uid }); + await testEnv.wrap(WEN_FUNC.joinSpace); + mockWalletReturnValue(member, { token: token.uid }); + await testEnv.wrap(WEN_FUNC.orderToken); + + mockWalletReturnValue(newMember, { token: token.uid }); + await expectThrow( + testEnv.wrap(WEN_FUNC.orderToken), + WenError.you_are_not_guardian_of_space.key, + ); }); it('Should throw, no badge so can not access', async () => { await build5Db() - .doc(`${COL.TOKEN}/${token.uid}`) - .update({ access: Access.MEMBERS_WITH_BADGE, accessAwards: [wallet.getRandomEthAddress()] }); - mockWalletReturnValue(walletSpy, memberAddress, { token: token.uid }); - await expectThrow(testEnv.wrap(orderToken)({}), WenError.you_dont_have_required_badge.key); + .doc(COL.TOKEN, token.uid) + .update({ + access: PgAccess.MEMBERS_WITH_BADGE, + accessAwards: [wallet.getRandomEthAddress()], + }); + + mockWalletReturnValue(member, { token: token.uid }); + await expectThrow( + testEnv.wrap(WEN_FUNC.orderToken), + WenError.you_dont_have_required_badge.key, + ); }); it('Should throw, no nft so can not access', async () => { await build5Db() - .doc(`${COL.TOKEN}/${token.uid}`) + .doc(COL.TOKEN, token.uid) .update({ - access: Access.MEMBERS_WITH_NFT_FROM_COLLECTION, + access: PgAccess.MEMBERS_WITH_NFT_FROM_COLLECTION, accessCollections: [wallet.getRandomEthAddress()], }); - mockWalletReturnValue(walletSpy, memberAddress, { token: token.uid }); - await expectThrow(testEnv.wrap(orderToken)({}), WenError.you_dont_have_required_NFTs.key); + + mockWalletReturnValue(member, { token: token.uid }); + await expectThrow( + testEnv.wrap(WEN_FUNC.orderToken), + WenError.you_dont_have_required_NFTs.key, + ); }); + it('Should create token order and should credit, not leave less then MIN amount', async () => { - const order = await submitTokenOrderFunc(walletSpy, memberAddress, { token: token.uid }); + const order = await submitTokenOrderFunc(member, { token: token.uid }); await submitMilestoneFunc(order, 1.5 * MIN_IOTA_AMOUNT); - const distribution = await build5Db() - .doc(`${COL.TOKEN}/${token.uid}/${SUB_COL.DISTRIBUTION}/${memberAddress}`) - .get(); + .doc(COL.TOKEN, token.uid, SUB_COL.DISTRIBUTION, member) + .get(); expect(distribution?.totalDeposit).toBe(1.5 * MIN_IOTA_AMOUNT); - await build5Db() - .doc(`${COL.TOKEN}/${token.uid}`) + .doc(COL.TOKEN, token.uid) .update({ - saleStartDate: dateToTimestamp(dayjs().subtract(3, 'd').toDate()), - coolDownEnd: dateToTimestamp(dayjs().add(1, 'd').toDate()), + saleStartDate: dayjs().subtract(3, 'd').toDate(), + coolDownEnd: dayjs().add(1, 'd').toDate(), }); - - const credit = await submitCreditTokenFunc(walletSpy, memberAddress, { + const credit = await submitCreditTokenFunc(member, { token: token.uid, amount: MIN_IOTA_AMOUNT, }); @@ -304,17 +277,14 @@ describe('Token controller: ' + WEN_FUNC.orderToken, () => { it('Should create order and deposit in parallel', async () => { const array = Array.from(Array(10)); - const order = await submitTokenOrderFunc(walletSpy, memberAddress, { token: token.uid }); + const order = await submitTokenOrderFunc(member, { token: token.uid }); const amounts = array.map((_, index) => (index + 1) * MIN_IOTA_AMOUNT); const total = array.reduce((sum, _, index) => sum + (index + 1) * MIN_IOTA_AMOUNT, 0); const deposit = async (amount: number) => submitMilestoneFunc(order, amount); - const promises = amounts.map(deposit); await Promise.all(promises); const distribution = ( - await build5Db() - .doc(`${COL.TOKEN}/${token.uid}/${SUB_COL.DISTRIBUTION}/${memberAddress}`) - .get() + await build5Db().doc(COL.TOKEN, token.uid, SUB_COL.DISTRIBUTION, member).get() ); expect(distribution.totalDeposit).toBe(total); await assertOrderedTokensCount(token.uid, total / MIN_IOTA_AMOUNT); @@ -322,25 +292,25 @@ describe('Token controller: ' + WEN_FUNC.orderToken, () => { it('Should fail, country blocked by default', async () => { mockIpCheck(true, { common: ['HU'] }, { countryCode: 'HU' }); - await expectThrow( - submitTokenOrderFunc(walletSpy, memberAddress, { token: token.uid }), - WenError.blocked_country.key, - ); + + mockWalletReturnValue(member, { token: token.uid }); + const call = testEnv.mockWrap(orderTokenControl); + await expectThrow(call, WenError.blocked_country.key); }); it('Should fail, country blocked for entity', async () => { mockIpCheck(true, { common: ['USA'], [token.uid]: ['USA', 'HU'] }, { countryCode: 'HU' }); - await expectThrow( - submitTokenOrderFunc(walletSpy, memberAddress, { token: token.uid }), - WenError.blocked_country.key, - ); + + mockWalletReturnValue(member, { token: token.uid }); + const call = testEnv.mockWrap(orderTokenControl); + await expectThrow(call, WenError.blocked_country.key); }); it('Should fail, country blocked for token', async () => { mockIpCheck(true, { common: ['USA'], token: ['HU'] }, { countryCode: 'HU' }); - await expectThrow( - submitTokenOrderFunc(walletSpy, memberAddress, { token: token.uid }), - WenError.blocked_country.key, - ); + + mockWalletReturnValue(member, { token: token.uid }); + const call = testEnv.mockWrap(orderTokenControl); + await expectThrow(call, WenError.blocked_country.key); }); }); diff --git a/packages/functions/test/controls/token/token.airdrop.claim.spec.ts b/packages/functions/test/controls/token/token.airdrop.claim.spec.ts index a89d268c92..bb40474fac 100644 --- a/packages/functions/test/controls/token/token.airdrop.claim.spec.ts +++ b/packages/functions/test/controls/token/token.airdrop.claim.spec.ts @@ -1,39 +1,21 @@ -import { build5Db } from '@build-5/database'; +import { PgTokenStatus, PgTransactionType, build5Db } from '@build-5/database'; import { COL, SUB_COL, Space, Token, TokenAllocation, - TokenDistribution, TokenDrop, TokenDropStatus, - TokenStatus, Transaction, TransactionPayloadType, TransactionType, + WEN_FUNC, WenError, } from '@build-5/interfaces'; import dayjs from 'dayjs'; -import { - airdropToken, - claimAirdroppedToken, - createToken, -} from '../../../src/runtime/firebase/token/base'; -import * as wallet from '../../../src/utils/wallet.utils'; -import { MEDIA, testEnv } from '../../set-up'; -import { - createMember, - createSpace, - expectThrow, - getRandomSymbol, - mockWalletReturnValue, - submitMilestoneFunc, - wait, -} from '../common'; - -let walletSpy: any; - +import { MEDIA, mockWalletReturnValue, testEnv } from '../../set-up'; +import { expectThrow, getRandomSymbol, submitMilestoneFunc, wait } from '../common'; const dummyToken = (space: string) => ({ name: 'MyToken', @@ -47,7 +29,6 @@ const dummyToken = (space: string) => access: 0, decimals: 6, }) as any; - const waitAllClaimed = (token: string, claimExpected?: number) => wait(async () => { const airdrops = await getAirdropsForToken(token); @@ -61,9 +42,8 @@ describe('Claim airdropped token test', () => { let token: Token; beforeEach(async () => { - walletSpy = jest.spyOn(wallet, 'decodeAuth'); - guardian = await createMember(walletSpy); - space = await createSpace(walletSpy, guardian); + guardian = await testEnv.createMember(); + space = await testEnv.createSpace(guardian); const dummyTokenData = dummyToken(space.uid); dummyTokenData.saleStartDate = dayjs().add(8, 'day').toDate(); dummyTokenData.saleLength = 86400000; @@ -72,27 +52,25 @@ describe('Claim airdropped token test', () => { { title: 'Private', percentage: 90 }, { title: 'Public', percentage: 10, isPublicSale: true }, ]; - mockWalletReturnValue(walletSpy, guardian, dummyTokenData); - token = await testEnv.wrap(createToken)({}); - await build5Db().doc(`${COL.TOKEN}/${token.uid}`).update({ approved: true }); + mockWalletReturnValue(guardian, dummyTokenData); + token = await testEnv.wrap(WEN_FUNC.createToken); + await build5Db().doc(COL.TOKEN, token.uid).update({ approved: true }); }); - const airdrop = async () => { const airdropRequest = { token: token.uid, drops: [{ count: 450, recipient: guardian, vestingAt: dayjs().toDate() }], }; - mockWalletReturnValue(walletSpy, guardian, airdropRequest); - await testEnv.wrap(airdropToken)({}); + mockWalletReturnValue(guardian, airdropRequest); + await testEnv.wrap(WEN_FUNC.airdropToken); }; - it('Should claim token', async () => { await airdrop(); - mockWalletReturnValue(walletSpy, guardian, { token: token.uid }); - const order = await testEnv.wrap(claimAirdroppedToken)({}); + mockWalletReturnValue(guardian, { token: token.uid }); + const order = await testEnv.wrap(WEN_FUNC.claimAirdroppedToken); await submitMilestoneFunc(order); - const orderTran = await build5Db().doc(`${COL.TRANSACTION}/${order.uid}`).get(); + const orderTran = await build5Db().doc(COL.TRANSACTION, order.uid).get(); expect(orderTran.member).toBe(guardian); expect(orderTran.payload.type).toBe(TransactionPayloadType.TOKEN_AIRDROP); @@ -100,15 +78,13 @@ describe('Claim airdropped token test', () => { const paymentsSnap = await build5Db() .collection(COL.TRANSACTION) - .where('payload.sourceTransaction', 'array-contains', orderTran.uid) - .get(); + .where('payload_sourceTransaction', 'array-contains', orderTran.uid! as any) + .get(); const types = paymentsSnap.map((d) => d.type).sort(); expect(types).toEqual([TransactionType.BILL_PAYMENT, TransactionType.PAYMENT]); - const distirbutionDocRef = build5Db().doc( - `${COL.TOKEN}/${token.uid}/${SUB_COL.DISTRIBUTION}/${guardian}`, - ); - const distribution = await distirbutionDocRef.get(); + const distirbutionDocRef = build5Db().doc(COL.TOKEN, token.uid, SUB_COL.DISTRIBUTION, guardian); + const distribution = await distirbutionDocRef.get(); expect(distribution?.tokenClaimed).toBe(450); expect(distribution?.tokenOwned).toBe(450); @@ -120,12 +96,11 @@ describe('Claim airdropped token test', () => { it('Should claim multiple drops token', async () => { await airdrop(); await airdrop(); - - mockWalletReturnValue(walletSpy, guardian, { token: token.uid }); - const order = await testEnv.wrap(claimAirdroppedToken)({}); + mockWalletReturnValue(guardian, { token: token.uid }); + const order = await testEnv.wrap(WEN_FUNC.claimAirdroppedToken); await submitMilestoneFunc(order); - const orderTran = await build5Db().doc(`${COL.TRANSACTION}/${order.uid}`).get(); + const orderTran = await build5Db().doc(COL.TRANSACTION, order.uid).get(); expect(orderTran.member).toBe(guardian); expect(orderTran.payload.type).toBe(TransactionPayloadType.TOKEN_AIRDROP); @@ -133,22 +108,18 @@ describe('Claim airdropped token test', () => { const paymentsSnap = await build5Db() .collection(COL.TRANSACTION) - .where('payload.sourceTransaction', 'array-contains', orderTran.uid) - .get(); + .where('payload_sourceTransaction', 'array-contains', orderTran.uid as any) + .get(); const types = paymentsSnap.map((d) => d.type).sort(); expect(types).toEqual([ TransactionType.BILL_PAYMENT, TransactionType.BILL_PAYMENT, TransactionType.PAYMENT, ]); - - const distirbutionDocRef = build5Db().doc( - `${COL.TOKEN}/${token.uid}/${SUB_COL.DISTRIBUTION}/${guardian}`, - ); - const distribution = await distirbutionDocRef.get(); + const distirbutionDocRef = build5Db().doc(COL.TOKEN, token.uid, SUB_COL.DISTRIBUTION, guardian); + const distribution = await distirbutionDocRef.get(); expect(distribution?.tokenClaimed).toBe(900); expect(distribution?.tokenOwned).toBe(900); - const airdrops = await getAirdropsForToken(token.uid); expect(airdrops.length).toBe(2); expect(airdrops[0].status).toBe(TokenDropStatus.CLAIMED); @@ -161,38 +132,32 @@ describe('Claim airdropped token test', () => { token: token.uid, drops: [{ count: 450, recipient: guardian, vestingAt: dayjs().add(1, 'd').toDate() }], }; - mockWalletReturnValue(walletSpy, guardian, airdropRequest); - await testEnv.wrap(airdropToken)({}); - - mockWalletReturnValue(walletSpy, guardian, { token: token.uid }); - const order = await testEnv.wrap(claimAirdroppedToken)({}); + mockWalletReturnValue(guardian, airdropRequest); + await testEnv.wrap(WEN_FUNC.airdropToken); + mockWalletReturnValue(guardian, { token: token.uid }); + const order = await testEnv.wrap(WEN_FUNC.claimAirdroppedToken); await submitMilestoneFunc(order); - - const orderTran = await build5Db().doc(`${COL.TRANSACTION}/${order.uid}`).get(); + const orderTran = await build5Db().doc(COL.TRANSACTION, order.uid).get(); expect(orderTran.member).toBe(guardian); expect(orderTran.payload.type).toBe(TransactionPayloadType.TOKEN_AIRDROP); await waitAllClaimed(token.uid, 1); - const paymentsSnap = await build5Db() .collection(COL.TRANSACTION) - .where('payload.sourceTransaction', 'array-contains', orderTran.uid) - .get(); + .where('payload_sourceTransaction', 'array-contains', orderTran.uid as any) + .get(); const types = paymentsSnap.map((d) => d.type).sort(); expect(types).toEqual([TransactionType.BILL_PAYMENT, TransactionType.PAYMENT]); - - const distirbutionDocRef = build5Db().doc( - `${COL.TOKEN}/${token.uid}/${SUB_COL.DISTRIBUTION}/${guardian}`, - ); - const distribution = await distirbutionDocRef.get(); + const distirbutionDocRef = build5Db().doc(COL.TOKEN, token.uid, SUB_COL.DISTRIBUTION, guardian); + const distribution = await distirbutionDocRef.get(); expect(distribution?.tokenClaimed).toBe(450); expect(distribution?.tokenOwned).toBe(450); }); it('Should claim same in parallel', async () => { await airdrop(); - mockWalletReturnValue(walletSpy, guardian, { token: token.uid }); const claimToken = async () => { - const order = await testEnv.wrap(claimAirdroppedToken)({}); + mockWalletReturnValue(guardian, { token: token.uid }); + const order = await testEnv.wrap(WEN_FUNC.claimAirdroppedToken); await new Promise((r) => setTimeout(r, 1000)); await submitMilestoneFunc(order); return order; @@ -200,28 +165,23 @@ describe('Claim airdropped token test', () => { const promises = [claimToken(), claimToken()]; await Promise.all(promises); await waitAllClaimed(token.uid); - - const distirbutionDocRef = build5Db().doc( - `${COL.TOKEN}/${token.uid}/${SUB_COL.DISTRIBUTION}/${guardian}`, - ); - const distribution = await distirbutionDocRef.get(); + const distirbutionDocRef = build5Db().doc(COL.TOKEN, token.uid, SUB_COL.DISTRIBUTION, guardian); + const distribution = await distirbutionDocRef.get(); expect(distribution?.tokenClaimed).toBe(450); expect(distribution?.tokenOwned).toBe(450); - const creditSnap = await build5Db() .collection(COL.TRANSACTION) .where('member', '==', guardian) - .where('type', '==', TransactionType.CREDIT) - .where('payload.token', '==', token.uid) + .where('type', '==', PgTransactionType.CREDIT) + .where('payload_token', '==', token.uid) .get(); expect(creditSnap.length).toBe(2); - const billPaymentSnap = await build5Db() .collection(COL.TRANSACTION) .where('member', '==', guardian) - .where('type', '==', TransactionType.BILL_PAYMENT) - .where('payload.token', '==', token.uid) - .get(); + .where('type', '==', PgTransactionType.BILL_PAYMENT) + .where('payload_token', '==', token.uid) + .get(); expect(billPaymentSnap.length).toBe(1); const billPayment = billPaymentSnap[0]!; expect(billPayment.payload.token).toBe(token.uid); @@ -230,9 +190,12 @@ describe('Claim airdropped token test', () => { }); it('Should throw, token is minted', async () => { - mockWalletReturnValue(walletSpy, guardian, { token: token.uid }); - await build5Db().doc(`${COL.TOKEN}/${token.uid}`).update({ status: TokenStatus.MINTED }); - await expectThrow(testEnv.wrap(claimAirdroppedToken)({}), WenError.token_in_invalid_status.key); + await build5Db().doc(COL.TOKEN, token.uid).update({ status: PgTokenStatus.MINTED }); + mockWalletReturnValue(guardian, { token: token.uid }); + await expectThrow( + testEnv.wrap(WEN_FUNC.claimAirdroppedToken), + WenError.token_in_invalid_status.key, + ); }); it('Should claim 700', async () => { @@ -246,20 +209,17 @@ describe('Claim airdropped token test', () => { .toDate(), })), }; - mockWalletReturnValue(walletSpy, guardian, airdropRequest); - await testEnv.wrap(airdropToken)({}); - - mockWalletReturnValue(walletSpy, guardian, { token: token.uid }); - const order = await testEnv.wrap(claimAirdroppedToken)({}); + mockWalletReturnValue(guardian, airdropRequest); + await testEnv.wrap(WEN_FUNC.airdropToken); + mockWalletReturnValue(guardian, { token: token.uid }); + const order = await testEnv.wrap(WEN_FUNC.claimAirdroppedToken); await submitMilestoneFunc(order); - - const orderTran = await build5Db().doc(`${COL.TRANSACTION}/${order.uid}`).get(); + const orderTran = await build5Db().doc(COL.TRANSACTION, order.uid).get(); expect(orderTran.member).toBe(guardian); expect(orderTran.payload.type).toBe(TransactionPayloadType.TOKEN_AIRDROP); await waitAllClaimed(token.uid, 700); }); }); - const getAirdropsForToken = async (token: string) => { const snap = await build5Db().collection(COL.AIRDROP).where('token', '==', token).get(); return snap.map((d) => d as TokenDrop); diff --git a/packages/functions/test/controls/token/token.airdrop.spec.ts b/packages/functions/test/controls/token/token.airdrop.spec.ts index dfaedf359a..236df3dec6 100644 --- a/packages/functions/test/controls/token/token.airdrop.spec.ts +++ b/packages/functions/test/controls/token/token.airdrop.spec.ts @@ -6,22 +6,12 @@ import { TokenAllocation, TokenDrop, TokenDropStatus, + WEN_FUNC, WenError, } from '@build-5/interfaces'; import dayjs from 'dayjs'; -import { airdropToken, createToken } from '../../../src/runtime/firebase/token/base'; -import { dateToTimestamp } from '../../../src/utils/dateTime.utils'; -import * as wallet from '../../../src/utils/wallet.utils'; -import { MEDIA, testEnv } from '../../set-up'; -import { - createMember, - createSpace, - expectThrow, - getRandomSymbol, - mockWalletReturnValue, -} from '../common'; - -let walletSpy: any; +import { MEDIA, mockWalletReturnValue, testEnv } from '../../set-up'; +import { expectThrow, getRandomSymbol } from '../common'; const dummyToken = (space: string) => ({ @@ -44,9 +34,8 @@ describe('Token airdrop test', () => { let token: Token; beforeEach(async () => { - walletSpy = jest.spyOn(wallet, 'decodeAuth'); - guardian = await createMember(walletSpy); - space = await createSpace(walletSpy, guardian); + guardian = await testEnv.createMember(); + space = await testEnv.createSpace(guardian); const dummyTokenData = dummyToken(space.uid); dummyTokenData.saleStartDate = dayjs().add(8, 'day').toDate(); dummyTokenData.saleLength = 86400000; @@ -55,20 +44,20 @@ describe('Token airdrop test', () => { { title: 'Private', percentage: 90 }, { title: 'Public', percentage: 10, isPublicSale: true }, ]; - mockWalletReturnValue(walletSpy, guardian, dummyTokenData); - token = await testEnv.wrap(createToken)({}); - member = await createMember(walletSpy); - await build5Db().doc(`${COL.TOKEN}/${token.uid}`).update({ approved: true }); + mockWalletReturnValue(guardian, dummyTokenData); + token = await testEnv.wrap(WEN_FUNC.createToken); + member = await testEnv.createMember(); + await build5Db().doc(COL.TOKEN, token.uid).update({ approved: true }); }); it('Should fail, token not approved', async () => { - await build5Db().doc(`${COL.TOKEN}/${token.uid}`).update({ approved: false }); + await build5Db().doc(COL.TOKEN, token.uid).update({ approved: false }); const airdropRequest = { token: token.uid, drops: [{ count: 900, recipient: guardian, vestingAt: dayjs().toDate() }], }; - mockWalletReturnValue(walletSpy, guardian, airdropRequest); - await expectThrow(testEnv.wrap(airdropToken)({}), WenError.token_not_approved.key); + mockWalletReturnValue(guardian, airdropRequest); + await expectThrow(testEnv.wrap(WEN_FUNC.airdropToken), WenError.token_not_approved.key); }); it('Should airdrop token', async () => { @@ -77,13 +66,12 @@ describe('Token airdrop test', () => { token: token.uid, drops: [{ count: 900, recipient: guardian, vestingAt }], }; - mockWalletReturnValue(walletSpy, guardian, airdropRequest); - await testEnv.wrap(airdropToken)({}); - + mockWalletReturnValue(guardian, airdropRequest); + await testEnv.wrap(WEN_FUNC.airdropToken); const airdrops = await getAirdropsForMember(guardian); expect(airdrops.length).toBe(1); expect(airdrops[0].count).toBe(900); - expect(airdrops[0].vestingAt).toEqual(dateToTimestamp(vestingAt)); + expect(airdrops[0].vestingAt.toDate()).toEqual(vestingAt); expect(airdrops[0].member).toBe(guardian); expect(airdrops[0].token).toBe(token.uid); expect(airdrops[0].createdBy).toBe(guardian); @@ -91,26 +79,24 @@ describe('Token airdrop test', () => { }); it('Should airdrop token with no space', async () => { - await build5Db().doc(`${COL.TOKEN}/${token.uid}`).update({ space: '' }); + await build5Db().doc(COL.TOKEN, token.uid).update({ space: '' }); const vestingAt = dayjs().toDate(); const airdropRequest = { token: token.uid, drops: [{ count: 900, recipient: guardian, vestingAt }], }; - mockWalletReturnValue(walletSpy, member, airdropRequest); + mockWalletReturnValue(member, airdropRequest); await expectThrow( - testEnv.wrap(airdropToken)({}), + testEnv.wrap(WEN_FUNC.airdropToken), WenError.you_must_be_the_creator_of_this_token.key, ); - - mockWalletReturnValue(walletSpy, guardian, airdropRequest); - await testEnv.wrap(airdropToken)({}); - + mockWalletReturnValue(guardian, airdropRequest); + await testEnv.wrap(WEN_FUNC.airdropToken); const airdrops = await getAirdropsForMember(guardian); expect(airdrops.length).toBe(1); expect(airdrops[0].count).toBe(900); - expect(airdrops[0].vestingAt).toEqual(dateToTimestamp(vestingAt)); + expect(airdrops[0].vestingAt.toDate()).toEqual(vestingAt); expect(airdrops[0].member).toBe(guardian); expect(airdrops[0].token).toBe(token.uid); expect(airdrops[0].createdBy).toBe(guardian); @@ -123,9 +109,8 @@ describe('Token airdrop test', () => { token: token.uid, drops: Array.from(Array(900)).map(() => ({ count: 1, recipient: guardian, vestingAt })), }; - mockWalletReturnValue(walletSpy, guardian, airdropRequest); - await testEnv.wrap(airdropToken)({}); - + mockWalletReturnValue(guardian, airdropRequest); + await testEnv.wrap(WEN_FUNC.airdropToken); const airdrops = await getAirdropsForMember(guardian); expect(airdrops.length).toBe(900); }); @@ -139,16 +124,15 @@ describe('Token airdrop test', () => { { count: 100, recipient: member, vestingAt }, ], }; - mockWalletReturnValue(walletSpy, guardian, airdropRequest); - await testEnv.wrap(airdropToken)({}); - + mockWalletReturnValue(guardian, airdropRequest); + await testEnv.wrap(WEN_FUNC.airdropToken); const airdrops = (await getAirdropsForToken(token.uid)).sort((a, b) => b.count - a.count); expect(airdrops.length).toBe(2); expect(airdrops[0].count).toBe(800); - expect(airdrops[0].vestingAt).toEqual(dateToTimestamp(vestingAt)); + expect(airdrops[0].vestingAt.toDate()).toEqual(vestingAt); expect(airdrops[0].member).toBe(guardian); expect(airdrops[1].count).toBe(100); - expect(airdrops[1].vestingAt).toEqual(dateToTimestamp(vestingAt)); + expect(airdrops[1].vestingAt.toDate()).toEqual(vestingAt); expect(airdrops[1].member).toBe(member); }); @@ -157,17 +141,18 @@ describe('Token airdrop test', () => { token: token.uid, drops: [{ count: 1000, recipient: guardian, vestingAt: dayjs().toDate() }], }; - mockWalletReturnValue(walletSpy, guardian, airdropRequest); - await expectThrow(testEnv.wrap(airdropToken)({}), WenError.no_tokens_available_for_airdrop.key); + + mockWalletReturnValue(guardian, airdropRequest); + await expectThrow( + testEnv.wrap(WEN_FUNC.airdropToken), + WenError.no_tokens_available_for_airdrop.key, + ); }); it('Should throw, no vesting', async () => { - const airdropRequest = { - token: token.uid, - drops: [{ count: 1000, recipient: guardian }], - }; - mockWalletReturnValue(walletSpy, guardian, airdropRequest); - await expectThrow(testEnv.wrap(airdropToken)({}), WenError.invalid_params.key); + const airdropRequest = { token: token.uid, drops: [{ count: 1000, recipient: guardian }] }; + mockWalletReturnValue(guardian, airdropRequest); + await expectThrow(testEnv.wrap(WEN_FUNC.airdropToken), WenError.invalid_params.key); }); it('Should throw, not guardian', async () => { @@ -175,8 +160,12 @@ describe('Token airdrop test', () => { token: token.uid, drops: [{ count: 50, recipient: guardian, vestingAt: dayjs().toDate() }], }; - mockWalletReturnValue(walletSpy, member, airdropRequest); - await expectThrow(testEnv.wrap(airdropToken)({}), WenError.you_are_not_guardian_of_space.key); + + mockWalletReturnValue(member, airdropRequest); + await expectThrow( + testEnv.wrap(WEN_FUNC.airdropToken), + WenError.you_are_not_guardian_of_space.key, + ); }); it('Should throw at second drop', async () => { @@ -185,20 +174,23 @@ describe('Token airdrop test', () => { token: token.uid, drops: [{ count: 900, recipient: guardian, vestingAt: vestingAt.toDate() }], }; - mockWalletReturnValue(walletSpy, guardian, airdropRequest); - await testEnv.wrap(airdropToken)({}); + mockWalletReturnValue(guardian, airdropRequest); + await testEnv.wrap(WEN_FUNC.airdropToken); const airdrops = await getAirdropsForMember(guardian); expect(airdrops.length).toBe(1); expect(airdrops[0].count).toBe(900); - expect(airdrops[0].vestingAt).toEqual(dateToTimestamp(vestingAt)); + expect(airdrops[0].vestingAt.toDate()).toEqual(vestingAt.toDate()); expect(airdrops[0].member).toBe(guardian); - const airdropRequest2 = { token: token.uid, drops: [{ count: 100, recipient: guardian, vestingAt: dayjs().toDate() }], }; - mockWalletReturnValue(walletSpy, guardian, airdropRequest2); - await expectThrow(testEnv.wrap(airdropToken)({}), WenError.no_tokens_available_for_airdrop.key); + + mockWalletReturnValue(guardian, airdropRequest2); + await expectThrow( + testEnv.wrap(WEN_FUNC.airdropToken), + WenError.no_tokens_available_for_airdrop.key, + ); }); it('Should drop multiple for same user', async () => { @@ -210,10 +202,10 @@ describe('Token airdrop test', () => { { count: 50, recipient: member, vestingAt }, ], }; - mockWalletReturnValue(walletSpy, guardian, airdropRequest); - await testEnv.wrap(airdropToken)({}); - await testEnv.wrap(airdropToken)({}); - + mockWalletReturnValue(guardian, airdropRequest); + await testEnv.wrap(WEN_FUNC.airdropToken); + mockWalletReturnValue(guardian, airdropRequest); + await testEnv.wrap(WEN_FUNC.airdropToken); const guardianDrops = await getAirdropsForMember(guardian); expect(guardianDrops.length).toBe(2); const memberDrops = await getAirdropsForMember(member); diff --git a/packages/functions/test/controls/token/token.cancel.pub.sale.spec.ts b/packages/functions/test/controls/token/token.cancel.pub.sale.spec.ts index a7a92e1847..2ecd89d5e3 100644 --- a/packages/functions/test/controls/token/token.cancel.pub.sale.spec.ts +++ b/packages/functions/test/controls/token/token.cancel.pub.sale.spec.ts @@ -1,74 +1,62 @@ -import { build5Db } from '@build-5/database'; +import { + PgAccess, + PgTokenStatus, + PgTransactionPayloadType, + PgTransactionType, + build5Db, +} from '@build-5/database'; import { COL, MIN_IOTA_AMOUNT, NetworkAddress, SOON_PROJECT_ID, - Space, SUB_COL, + Space, Token, TokenDistribution, TokenStatus, Transaction, - TransactionPayloadType, - TransactionType, WEN_FUNC, } from '@build-5/interfaces'; import dayjs from 'dayjs'; -import { - cancelPublicSale, - orderToken, - setTokenAvailableForSale, -} from '../../../src/runtime/firebase/token/base/index'; import { dateToTimestamp, serverTime } from '../../../src/utils/dateTime.utils'; import * as wallet from '../../../src/utils/wallet.utils'; -import { MEDIA, testEnv } from '../../set-up'; -import { - createMember, - createSpace, - getRandomSymbol, - mockWalletReturnValue, - submitMilestoneFunc, - wait, -} from '../common'; - -let walletSpy: any; +import { MEDIA, mockWalletReturnValue, testEnv } from '../../set-up'; +import { getRandomSymbol, submitMilestoneFunc, wait } from '../common'; -const submitTokenOrderFunc = async (spy: string, address: NetworkAddress, params: T) => { - mockWalletReturnValue(spy, address, params); - const order = await testEnv.wrap(orderToken)({}); +const submitTokenOrderFunc = async (address: NetworkAddress, params: T) => { + mockWalletReturnValue(address, params); + const order = await testEnv.wrap(WEN_FUNC.orderToken); expect(order?.createdOn).toBeDefined(); return order; }; - const setAvailableOrderAndCancelSale = async ( token: Token, memberAddress: NetworkAddress, miotas: number, ) => { - const tokenDocRef = build5Db().doc(`${COL.TOKEN}/${token.uid}`); + const tokenDocRef = build5Db().doc(COL.TOKEN, token.uid); const distributionDocRef = build5Db().doc( - `${COL.TOKEN}/${token.uid}/${SUB_COL.DISTRIBUTION}/${memberAddress}`, + COL.TOKEN, + token.uid, + SUB_COL.DISTRIBUTION, + memberAddress, ); await tokenDocRef.update({ saleLength: 86400000 * 2, - saleStartDate: dateToTimestamp(dayjs().subtract(1, 'd').toDate()), - coolDownEnd: dateToTimestamp( - dayjs() - .subtract(1, 'd') - .add(86400000 * 2, 'ms') - .toDate(), - ), + saleStartDate: dayjs().subtract(1, 'd').toDate(), + coolDownEnd: dayjs() + .subtract(1, 'd') + .add(86400000 * 2, 'ms') + .toDate(), }); - const order = await submitTokenOrderFunc(walletSpy, memberAddress, { token: token.uid }); + const order = await submitTokenOrderFunc(memberAddress, { token: token.uid }); await submitMilestoneFunc(order, miotas * MIN_IOTA_AMOUNT); - const distribution = await distributionDocRef.get(); expect(distribution.totalDeposit).toBe(miotas * MIN_IOTA_AMOUNT); - - mockWalletReturnValue(walletSpy, memberAddress, { token: token.uid }); - await testEnv.wrap(cancelPublicSale)({}); - await wait(async () => (await tokenDocRef.get())?.status === TokenStatus.AVAILABLE); + mockWalletReturnValue(memberAddress, { token: token.uid }); + await testEnv.wrap(WEN_FUNC.cancelPublicSale); + await wait(async () => (await tokenDocRef.get())?.status === TokenStatus.AVAILABLE); const tokenData = await tokenDocRef.get(); expect(tokenData.saleStartDate).toBeUndefined(); }; @@ -77,13 +65,11 @@ describe('Token controller: ' + WEN_FUNC.cancelPublicSale, () => { let memberAddress: NetworkAddress; let space: Space; let token: any; - beforeEach(async () => { - walletSpy = jest.spyOn(wallet, 'decodeAuth'); - memberAddress = await createMember(walletSpy); - space = await createSpace(walletSpy, memberAddress); + memberAddress = await testEnv.createMember(); + space = await testEnv.createSpace(memberAddress); const tokenId = wallet.getRandomEthAddress(); - token = { + const tokenUpsert = { project: SOON_PROJECT_ID, symbol: getRandomSymbol(), totalSupply: 10, @@ -91,30 +77,34 @@ describe('Token controller: ' + WEN_FUNC.cancelPublicSale, () => { rejected: false, icon: MEDIA, overviewGraphics: MEDIA, - updatedOn: serverTime(), - createdOn: serverTime(), + updatedOn: serverTime().toDate(), + createdOn: serverTime().toDate(), space: space.uid, uid: tokenId, pricePerToken: MIN_IOTA_AMOUNT, - allocations: [ + allocations: JSON.stringify([ { title: 'Public sale', isPublicSale: true, percentage: 50 }, { title: 'Private', percentage: 50 }, - ], + ]), createdBy: memberAddress, name: 'MyToken', links: [], - status: TokenStatus.AVAILABLE, + status: PgTokenStatus.AVAILABLE, totalDeposit: 0, totalAirdropped: 0, termsAndConditions: 'https://wen.soonaverse.com/token/terms-and-conditions', - access: 0, + access: PgAccess.OPEN, }; - await build5Db().doc(`${COL.TOKEN}/${token.uid}`).set(token); + await build5Db().doc(COL.TOKEN, tokenId).upsert(tokenUpsert); + token = (await build5Db().doc(COL.TOKEN, tokenId).get())!; }); it('Should cancel public sale and refund buyers twice', async () => { const distributionDocRef = build5Db().doc( - `${COL.TOKEN}/${token.uid}/${SUB_COL.DISTRIBUTION}/${memberAddress}`, + COL.TOKEN, + token.uid, + SUB_COL.DISTRIBUTION, + memberAddress, ); await setAvailableOrderAndCancelSale(token, memberAddress, 5); await setAvailableOrderAndCancelSale(token, memberAddress, 6); @@ -122,10 +112,10 @@ describe('Token controller: ' + WEN_FUNC.cancelPublicSale, () => { expect(distribution.totalDeposit).toBe(0); const creditDocs = await build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.CREDIT) - .where('payload.type', '==', TransactionPayloadType.TOKEN_PURCHASE) + .where('type', '==', PgTransactionType.CREDIT) + .where('payload_type', '==', PgTransactionPayloadType.TOKEN_PURCHASE) .where('member', '==', memberAddress) - .get(); + .get(); expect(creditDocs.map((d) => d?.payload?.amount!).sort((a, b) => a - b)).toEqual([ 5 * MIN_IOTA_AMOUNT, 6 * MIN_IOTA_AMOUNT, @@ -134,7 +124,10 @@ describe('Token controller: ' + WEN_FUNC.cancelPublicSale, () => { it('Should cancel public sale and refund buyers twice, then finish sale', async () => { const distributionDocRef = build5Db().doc( - `${COL.TOKEN}/${token.uid}/${SUB_COL.DISTRIBUTION}/${memberAddress}`, + COL.TOKEN, + token.uid, + SUB_COL.DISTRIBUTION, + memberAddress, ); await setAvailableOrderAndCancelSale(token, memberAddress, 5); await setAvailableOrderAndCancelSale(token, memberAddress, 6); @@ -142,32 +135,27 @@ describe('Token controller: ' + WEN_FUNC.cancelPublicSale, () => { expect(distribution.totalDeposit).toBe(0); const creditDocs = await build5Db() .collection(COL.TRANSACTION) - .where('type', '==', TransactionType.CREDIT) - .where('payload.type', '==', TransactionPayloadType.TOKEN_PURCHASE) + .where('type', '==', PgTransactionType.CREDIT) + .where('payload_type', '==', PgTransactionPayloadType.TOKEN_PURCHASE) .where('member', '==', memberAddress) - .get(); + .get(); expect(creditDocs.map((d) => d?.payload?.amount!).sort((a, b) => a - b)).toEqual([ 5 * MIN_IOTA_AMOUNT, 6 * MIN_IOTA_AMOUNT, ]); - - const tokenDocRef = build5Db().doc(`${COL.TOKEN}/${token.uid}`); + const tokenDocRef = build5Db().doc(COL.TOKEN, token.uid); await tokenDocRef.update({ saleLength: 86400000 * 2, - saleStartDate: dateToTimestamp(dayjs().subtract(1, 'd').toDate()), - coolDownEnd: dateToTimestamp( - dayjs() - .subtract(1, 'd') - .add(86400000 * 2, 'ms') - .toDate(), - ), + saleStartDate: dayjs().subtract(1, 'd').toDate(), + coolDownEnd: dayjs() + .subtract(1, 'd') + .add(86400000 * 2, 'ms') + .toDate(), }); - const order = await submitTokenOrderFunc(walletSpy, memberAddress, { token: token.uid }); + const order = await submitTokenOrderFunc(memberAddress, { token: token.uid }); await submitMilestoneFunc(order, 7 * MIN_IOTA_AMOUNT); - - await tokenDocRef.update({ status: TokenStatus.PROCESSING }); - await wait(async () => (await tokenDocRef.get())?.status === TokenStatus.PRE_MINTED); - + await tokenDocRef.update({ status: PgTokenStatus.PROCESSING }); + await wait(async () => (await tokenDocRef.get())?.status === TokenStatus.PRE_MINTED); distribution = await distributionDocRef.get(); expect(distribution.totalPaid).toBe(5 * MIN_IOTA_AMOUNT); expect(distribution.refundedAmount).toBe(2 * MIN_IOTA_AMOUNT); @@ -181,23 +169,22 @@ describe('Token controller: ' + WEN_FUNC.cancelPublicSale, () => { coolDownLength: 86400000, }; await build5Db() - .doc(`${COL.TOKEN}/${token.uid}`) + .doc(COL.TOKEN, token.uid) .update({ - allocations: [{ title: 'public', percentage: 100, isPublicSale: true }], + allocations: JSON.stringify([{ title: 'public', percentage: 100, isPublicSale: true }]), public: true, }); const updateData = { token: token.uid, ...publicTime, pricePerToken: MIN_IOTA_AMOUNT }; - mockWalletReturnValue(walletSpy, memberAddress, updateData); - const result = await testEnv.wrap(setTokenAvailableForSale)({}); - expect(result?.saleStartDate.toDate()).toEqual( + mockWalletReturnValue(memberAddress, updateData); + const result = await testEnv.wrap(WEN_FUNC.setTokenAvailableForSale); + token = await build5Db().doc(COL.TOKEN, result.uid).get(); + expect(token.saleStartDate!.toDate()).toEqual( dateToTimestamp(dayjs(publicTime.saleStartDate), true).toDate(), ); - - mockWalletReturnValue(walletSpy, memberAddress, { token: token.uid }); - await testEnv.wrap(cancelPublicSale)({}); - + mockWalletReturnValue(memberAddress, { token: token.uid }); + await testEnv.wrap(WEN_FUNC.cancelPublicSale); await wait(async () => { - const tokenData = await build5Db().doc(`${COL.TOKEN}/${token.uid}`).get(); + const tokenData = await build5Db().doc(COL.TOKEN, token.uid).get(); return tokenData.status === TokenStatus.AVAILABLE; }); }); diff --git a/packages/functions/test/controls/token/token.create.spec.ts b/packages/functions/test/controls/token/token.create.spec.ts index ad6c09c6d7..e5882fa88b 100644 --- a/packages/functions/test/controls/token/token.create.spec.ts +++ b/packages/functions/test/controls/token/token.create.spec.ts @@ -1,35 +1,22 @@ import { build5Db } from '@build-5/database'; import { Access, - Bucket, COL, MAX_TOTAL_TOKEN_SUPPLY, MIN_IOTA_AMOUNT, NetworkAddress, SUB_COL, Space, - StakeType, + Token, TokenAllocation, WEN_FUNC, WenError, } from '@build-5/interfaces'; import dayjs from 'dayjs'; -import { createToken } from '../../../src/runtime/firebase/token/base'; import { dateToTimestamp } from '../../../src/utils/dateTime.utils'; import * as wallet from '../../../src/utils/wallet.utils'; -import { MEDIA, soonTokenId, testEnv } from '../../set-up'; -import { - createMember, - createSpace, - expectThrow, - getRandomSymbol, - mockWalletReturnValue, - setProdTiers, - setTestTiers, -} from '../common'; - -let walletSpy: any; - +import { MEDIA, mockWalletReturnValue, soonTokenId, testEnv } from '../../set-up'; +import { expectThrow, getRandomSymbol, setProdTiers, setTestTiers } from '../common'; const dummyToken = (space: string) => ({ name: 'MyToken', @@ -48,17 +35,15 @@ describe('Token controller: ' + WEN_FUNC.createToken, () => { let memberAddress: NetworkAddress; let space: Space; let token: any; - beforeEach(async () => { - walletSpy = jest.spyOn(wallet, 'decodeAuth'); - memberAddress = await createMember(walletSpy); - space = await createSpace(walletSpy, memberAddress); + memberAddress = await testEnv.createMember(); + space = await testEnv.createSpace(memberAddress); token = dummyToken(space.uid); }); it('Should create token', async () => { - mockWalletReturnValue(walletSpy, memberAddress, token); - const result = await testEnv.wrap(createToken)({}); + mockWalletReturnValue(memberAddress, token); + const result = await testEnv.wrap(WEN_FUNC.createToken); expect(result?.uid).toBeDefined(); expect(result.tradingDisabled).toBe(true); expect(result.decimals).toBe(5); @@ -66,8 +51,8 @@ describe('Token controller: ' + WEN_FUNC.createToken, () => { it('Should create token without space', async () => { delete token.space; - mockWalletReturnValue(walletSpy, memberAddress, token); - const result = await testEnv.wrap(createToken)({}); + mockWalletReturnValue(memberAddress, token); + const result = await testEnv.wrap(WEN_FUNC.createToken); expect(result?.uid).toBeDefined(); expect(result.tradingDisabled).toBe(true); expect(result.decimals).toBe(5); @@ -75,182 +60,176 @@ describe('Token controller: ' + WEN_FUNC.createToken, () => { }); it('Should create token with $ prefix', async () => { - mockWalletReturnValue(walletSpy, memberAddress, { ...token, symbol: '$' + token.symbol }); - const result = await testEnv.wrap(createToken)({}); + mockWalletReturnValue(memberAddress, { ...token, symbol: '$' + token.symbol }); + const result = await testEnv.wrap(WEN_FUNC.createToken); expect(result?.uid).toBeDefined(); expect(result.tradingDisabled).toBe(true); expect(result.decimals).toBe(5); }); it('Should throw, invalid icon url', async () => { - mockWalletReturnValue(walletSpy, memberAddress, { ...token, icon: 'asd' }); - await expectThrow(testEnv.wrap(createToken)({}), WenError.invalid_params.key); - - mockWalletReturnValue(walletSpy, memberAddress, { - ...token, - icon: `https://firebasestorage.googleapis.com/v0/b/${Bucket.DEV}/o/`, - }); - await expectThrow(testEnv.wrap(createToken)({}), WenError.invalid_params.key); + mockWalletReturnValue(memberAddress, { ...token, icon: 'some-icon-url' }); + await expectThrow(testEnv.wrap(WEN_FUNC.createToken), WenError.invalid_params.key); + mockWalletReturnValue(memberAddress, { ...token, icon: `invalid-icon-url` }); + await expectThrow(testEnv.wrap(WEN_FUNC.createToken), WenError.invalid_params.key); }); it('Should create token, verify soon', async () => { await build5Db() - .doc(`${COL.TOKEN}/${soonTokenId}/${SUB_COL.DISTRIBUTION}/${memberAddress}`) - .create({ - stakes: { - [StakeType.DYNAMIC]: { - value: 10 * MIN_IOTA_AMOUNT, - }, - }, - }); - - mockWalletReturnValue(walletSpy, memberAddress, token); + .doc(COL.TOKEN, soonTokenId, SUB_COL.DISTRIBUTION, memberAddress) + .upsert({ stakes_dynamic_value: 10 * MIN_IOTA_AMOUNT }); await setProdTiers(); - const result = await testEnv.wrap(createToken)({}); + mockWalletReturnValue(memberAddress, token); + const result = await testEnv.wrap(WEN_FUNC.createToken); expect(result?.uid).toBeDefined(); await setTestTiers(); }); it('Should create token with max token supply', async () => { - mockWalletReturnValue(walletSpy, memberAddress, { - ...token, - totalSupply: MAX_TOTAL_TOKEN_SUPPLY, - }); - const result = await testEnv.wrap(createToken)({}); + mockWalletReturnValue(memberAddress, { ...token, totalSupply: MAX_TOTAL_TOKEN_SUPPLY }); + const result = await testEnv.wrap(WEN_FUNC.createToken); expect(result?.uid).toBeDefined(); }); it('Should create, one public sale', async () => { - token.allocations = [{ title: 'asd', percentage: 100, isPublicSale: true }]; + token.allocations = [{ title: 'name', percentage: 100, isPublicSale: true }]; const saleStartDate = dayjs().add(8, 'day'); token.saleStartDate = saleStartDate.toDate(); token.saleLength = 86400000; token.coolDownLength = 86400000; token.autoProcessAt100Percent = true; - mockWalletReturnValue(walletSpy, memberAddress, token); - const result = await testEnv.wrap(createToken)({}); - expect(result?.uid).toBeDefined(); - expect(result?.saleStartDate.toDate()).toEqual(dateToTimestamp(saleStartDate, true).toDate()); - expect(result?.saleLength).toBe(86400000); - expect(result?.coolDownEnd.toDate()).toEqual( - dateToTimestamp( - dayjs(saleStartDate).add(token.saleLength + token.coolDownLength, 'ms'), - true, - ).toDate(), + mockWalletReturnValue(memberAddress, token); + const result = await testEnv.wrap(WEN_FUNC.createToken); + token = await build5Db().doc(COL.TOKEN, result.uid).get(); + expect(token.uid).toBeDefined(); + expect(token.saleStartDate!.toDate()).toEqual(dateToTimestamp(saleStartDate, true).toDate()); + expect(token.saleLength).toBe(86400000); + expect(token.coolDownEnd!.toDate()).toEqual( + dateToTimestamp(dayjs(saleStartDate).add(token.saleLength + 86400000, 'ms'), true).toDate(), ); - expect(result?.autoProcessAt100Percent).toBe(true); + expect(token.autoProcessAt100Percent).toBe(true); }); it('Should create, one public sale, no cooldown period', async () => { - token.allocations = [{ title: 'asd', percentage: 100, isPublicSale: true }]; + token.allocations = [{ title: 'name', percentage: 100, isPublicSale: true }]; const saleStartDate = dayjs().add(8, 'day'); token.saleStartDate = saleStartDate.toDate(); token.saleLength = 86400000; token.coolDownLength = 0; - mockWalletReturnValue(walletSpy, memberAddress, token); - const result = await testEnv.wrap(createToken)({}); - expect(result?.uid).toBeDefined(); - expect(result?.saleStartDate.toDate()).toEqual(dateToTimestamp(saleStartDate, true).toDate()); - expect(result?.saleLength).toBe(86400000); - expect(result?.coolDownEnd.toDate()).toEqual( + mockWalletReturnValue(memberAddress, token); + const result = await testEnv.wrap(WEN_FUNC.createToken); + token = await build5Db().doc(COL.TOKEN, result.uid).get(); + expect(token.uid).toBeDefined(); + expect(token.saleStartDate!.toDate()).toEqual(dateToTimestamp(saleStartDate, true).toDate()); + expect(token.saleLength).toBe(86400000); + expect(token.coolDownEnd!.toDate()).toEqual( dateToTimestamp(dayjs(saleStartDate).add(token.saleLength, 'ms'), true).toDate(), ); }); it('Should not allow two tokens', async () => { - mockWalletReturnValue(walletSpy, memberAddress, token); - await testEnv.wrap(createToken)({}); - mockWalletReturnValue(walletSpy, memberAddress, dummyToken(space.uid)); - await expectThrow(testEnv.wrap(createToken)({}), WenError.token_already_exists_for_space.key); + mockWalletReturnValue(memberAddress, token); + await testEnv.wrap(WEN_FUNC.createToken); + + mockWalletReturnValue(memberAddress, dummyToken(space.uid)); + await expectThrow( + testEnv.wrap(WEN_FUNC.createToken), + WenError.token_already_exists_for_space.key, + ); }); it('Should only allow two tokens if first rejected', async () => { - mockWalletReturnValue(walletSpy, memberAddress, token); - const cToken = await testEnv.wrap(createToken)({}); - await build5Db().doc(`${COL.TOKEN}/${cToken.uid}`).update({ approved: false, rejected: true }); - mockWalletReturnValue(walletSpy, memberAddress, dummyToken(space.uid)); - const secondToken = await testEnv.wrap(createToken)({}); + mockWalletReturnValue(memberAddress, token); + const cToken = await testEnv.wrap(WEN_FUNC.createToken); + await build5Db().doc(COL.TOKEN, cToken.uid).update({ approved: false, rejected: true }); + mockWalletReturnValue(memberAddress, dummyToken(space.uid)); + const secondToken = await testEnv.wrap(WEN_FUNC.createToken); expect(secondToken.uid).toBeDefined(); }); it('Should throw, no name', async () => { delete token.name; - mockWalletReturnValue(walletSpy, memberAddress, token); + mockWalletReturnValue(memberAddress, token); await expectThrow( - testEnv.wrap(createToken)({}), + testEnv.wrap(WEN_FUNC.createToken), WenError.invalid_params.key, - 'Invalid params. "name" is required. ', + '"name" is required. ', ); }); it('Should throw, no terms and conditions', async () => { delete token.termsAndConditions; - mockWalletReturnValue(walletSpy, memberAddress, token); - const result = await testEnv.wrap(createToken)({}); + mockWalletReturnValue(memberAddress, token); + const result = await testEnv.wrap(WEN_FUNC.createToken); expect(result).toBeDefined(); }); it('Should throw, no symbol', async () => { delete token.symbol; - mockWalletReturnValue(walletSpy, memberAddress, token); - await expectThrow(testEnv.wrap(createToken)({}), WenError.invalid_params.key); + mockWalletReturnValue(memberAddress, token); + await expectThrow(testEnv.wrap(WEN_FUNC.createToken), WenError.invalid_params.key); }); it('Should throw, no totalSupply', async () => { delete token.totalSupply; - mockWalletReturnValue(walletSpy, memberAddress, token); - await expectThrow(testEnv.wrap(createToken)({}), WenError.invalid_params.key); + mockWalletReturnValue(memberAddress, token); + await expectThrow(testEnv.wrap(WEN_FUNC.createToken), WenError.invalid_params.key); }); it('Should work with no allocations', async () => { delete token.allocations; - mockWalletReturnValue(walletSpy, memberAddress, token); - const result = await testEnv.wrap(createToken)({}); + mockWalletReturnValue(memberAddress, token); + const result = await testEnv.wrap(WEN_FUNC.createToken); expect(result).toBeDefined(); }); it('Should throw, wrong total percentage', async () => { token.allocations = [ - { title: 'asd', percentage: 50 }, + { title: 'name', percentage: 50 }, { title: 'ccc', percentage: 40 }, ]; - mockWalletReturnValue(walletSpy, memberAddress, token); + + mockWalletReturnValue(memberAddress, token); await expectThrow( - testEnv.wrap(createToken)({}), + testEnv.wrap(WEN_FUNC.createToken), WenError.invalid_params.key, - 'Invalid params. "allocations" contains an invalid value. Allocations percentage sum must be 100', + '"allocations" contains an invalid value. Allocations percentage sum must be 100', ); }); it('Should throw, more then one public sale', async () => { token.allocations = [ - { title: 'asd', percentage: 50, isPublicSale: true }, + { title: 'name', percentage: 50, isPublicSale: true }, { title: 'ccc', percentage: 50, isPublicSale: true }, ]; - mockWalletReturnValue(walletSpy, memberAddress, token); + mockWalletReturnValue(memberAddress, token); await expectThrow( - testEnv.wrap(createToken)({}), + testEnv.wrap(WEN_FUNC.createToken), WenError.invalid_params.key, - 'Invalid params. "allocations" contains a duplicate value. Only one public sale is allowed', + '"allocations" contains a duplicate value. Only one public sale is allowed', ); }); it('Should throw, past start date', async () => { token.startDate = dayjs().subtract(1, 'd').toDate(); - mockWalletReturnValue(walletSpy, memberAddress, token); - await expectThrow(testEnv.wrap(createToken)({}), WenError.invalid_params.key); + mockWalletReturnValue(memberAddress, token); + await expectThrow(testEnv.wrap(WEN_FUNC.createToken), WenError.invalid_params.key); }); it('Should throw, creator is not guardian', async () => { - mockWalletReturnValue(walletSpy, wallet.getRandomEthAddress(), token); - await expectThrow(testEnv.wrap(createToken)({}), WenError.you_are_not_guardian_of_space.key); + const random = await testEnv.createMember(); + mockWalletReturnValue(random, token); + await expectThrow( + testEnv.wrap(WEN_FUNC.createToken), + WenError.you_are_not_guardian_of_space.key, + ); }); it('Should create with public sale but no date', async () => { const token: any = dummyToken(space.uid); - token.allocations = [{ title: 'asd', percentage: 100, isPublicSale: true }]; - mockWalletReturnValue(walletSpy, memberAddress, token); - const result = await testEnv.wrap(createToken)({}); + token.allocations = [{ title: 'name', percentage: 100, isPublicSale: true }]; + mockWalletReturnValue(memberAddress, token); + const result = await testEnv.wrap(WEN_FUNC.createToken); expect(result?.uid).toBeDefined(); }); @@ -259,64 +238,64 @@ describe('Token controller: ' + WEN_FUNC.createToken, () => { token.saleStartDate = dayjs().add(8, 'd').toDate(); token.saleLength = 86400000; token.coolDownLength = 86400000; - mockWalletReturnValue(walletSpy, memberAddress, token); - await expectThrow(testEnv.wrap(createToken)({}), WenError.no_token_public_sale.key); + mockWalletReturnValue(memberAddress, token); + await expectThrow(testEnv.wrap(WEN_FUNC.createToken), WenError.no_token_public_sale.key); }); it('Should throw, when public sale data is incomplete', async () => { const token: any = dummyToken(space.uid); - token.allocations = [{ title: 'asd', percentage: 100, isPublicSale: true }]; - + token.allocations = [{ title: 'name', percentage: 100, isPublicSale: true }]; token.saleStartDate = dayjs().add(8, 'd').toDate(); - mockWalletReturnValue(walletSpy, memberAddress, token); - await expectThrow(testEnv.wrap(createToken)({}), WenError.invalid_params.key); - + mockWalletReturnValue(memberAddress, token); + await expectThrow(testEnv.wrap(WEN_FUNC.createToken), WenError.invalid_params.key); token.saleLength = 86400000; - mockWalletReturnValue(walletSpy, memberAddress, token); - await expectThrow(testEnv.wrap(createToken)({}), WenError.invalid_params.key); - + mockWalletReturnValue(memberAddress, token); + await expectThrow(testEnv.wrap(WEN_FUNC.createToken), WenError.invalid_params.key); token.coolDownLength = 86400000; - mockWalletReturnValue(walletSpy, memberAddress, token); - const result = await testEnv.wrap(createToken)({}); + mockWalletReturnValue(memberAddress, token); + const result = await testEnv.wrap(WEN_FUNC.createToken); expect(result?.uid).toBeDefined(); }); it('Should throw, token symbol not unique', async () => { - mockWalletReturnValue(walletSpy, memberAddress, token); - await testEnv.wrap(createToken)({}); - const space = await createSpace(walletSpy, memberAddress); + mockWalletReturnValue(memberAddress, token); + await testEnv.wrap(WEN_FUNC.createToken); + const space = await testEnv.createSpace(memberAddress); const data = dummyToken(space.uid); - mockWalletReturnValue(walletSpy, memberAddress, { ...data, symbol: token.symbol }); + + mockWalletReturnValue(memberAddress, { ...data, symbol: token.symbol }); await expectThrow( - testEnv.wrap(createToken)({}), + testEnv.wrap(WEN_FUNC.createToken), WenError.token_symbol_must_be_globally_unique.key, ); }); it('Should not throw, token symbol not unique but prev token is rejected', async () => { - mockWalletReturnValue(walletSpy, memberAddress, token); - const newToken = await testEnv.wrap(createToken)({}); - await build5Db().doc(`${COL.TOKEN}/${newToken.uid}`).update({ rejected: true }); - - const space = await createSpace(walletSpy, memberAddress); - mockWalletReturnValue(walletSpy, memberAddress, { + mockWalletReturnValue(memberAddress, token); + const newToken = await testEnv.wrap(WEN_FUNC.createToken); + await build5Db().doc(COL.TOKEN, newToken.uid).update({ rejected: true }); + const space = await testEnv.createSpace(memberAddress); + mockWalletReturnValue(memberAddress, { ...dummyToken(space.uid), symbol: token.symbol, }); - await testEnv.wrap(createToken)({}); + await testEnv.wrap(WEN_FUNC.createToken); }); it('Should throw, space does not exist', async () => { token.space = wallet.getRandomEthAddress(); - mockWalletReturnValue(walletSpy, memberAddress, token); - await expectThrow(testEnv.wrap(createToken)({}), WenError.you_are_not_guardian_of_space.key); + mockWalletReturnValue(memberAddress, token); + await expectThrow( + testEnv.wrap(WEN_FUNC.createToken), + WenError.you_are_not_guardian_of_space.key, + ); }); it('Should create with short description', async () => { token.shortDescriptionTitle = 'shortDescriptionTitle'; token.shortDescription = 'shortDescription'; - mockWalletReturnValue(walletSpy, memberAddress, token); - const result = await testEnv.wrap(createToken)({}); + mockWalletReturnValue(memberAddress, token); + const result = await testEnv.wrap(WEN_FUNC.createToken); expect(result.shortDescriptionTitle).toBe('shortDescriptionTitle'); expect(result.shortDescription).toBe('shortDescription'); }); @@ -324,27 +303,27 @@ describe('Token controller: ' + WEN_FUNC.createToken, () => { it('Should throw, accessAwards required if access is MEMBERS_WITH_BADGE', async () => { token.access = Access.MEMBERS_WITH_BADGE; token.accessAwards = [wallet.getRandomEthAddress()]; - mockWalletReturnValue(walletSpy, memberAddress, token); - await testEnv.wrap(createToken)({}); + mockWalletReturnValue(memberAddress, token); + await testEnv.wrap(WEN_FUNC.createToken); token.accessAwards = []; - mockWalletReturnValue(walletSpy, memberAddress, token); - await expectThrow(testEnv.wrap(createToken)({}), WenError.invalid_params.key); + mockWalletReturnValue(memberAddress, token); + await expectThrow(testEnv.wrap(WEN_FUNC.createToken), WenError.invalid_params.key); }); it('Should throw, accessCollections required if access is MEMBERS_WITH_NFT_FROM_COLLECTION', async () => { token.access = Access.MEMBERS_WITH_NFT_FROM_COLLECTION; token.accessCollections = [wallet.getRandomEthAddress()]; - mockWalletReturnValue(walletSpy, memberAddress, token); - await testEnv.wrap(createToken)({}); + mockWalletReturnValue(memberAddress, token); + await testEnv.wrap(WEN_FUNC.createToken); token.accessCollections = []; - mockWalletReturnValue(walletSpy, memberAddress, token); - await expectThrow(testEnv.wrap(createToken)({}), WenError.invalid_params.key); + mockWalletReturnValue(memberAddress, token); + await expectThrow(testEnv.wrap(WEN_FUNC.createToken), WenError.invalid_params.key); }); it('Should throw, no tokens staked', async () => { - mockWalletReturnValue(walletSpy, memberAddress, token); await setProdTiers(); - await expectThrow(testEnv.wrap(createToken)({}), WenError.no_staked_soon.key); + mockWalletReturnValue(memberAddress, token); + await expectThrow(testEnv.wrap(WEN_FUNC.createToken), WenError.no_staked_soon.key); await setTestTiers(); }); }); diff --git a/packages/functions/test/controls/token/token.order.and.claim.air.spec.ts b/packages/functions/test/controls/token/token.order.and.claim.air.spec.ts index 6d3701e5ae..67e63ffc82 100644 --- a/packages/functions/test/controls/token/token.order.and.claim.air.spec.ts +++ b/packages/functions/test/controls/token/token.order.and.claim.air.spec.ts @@ -1,40 +1,24 @@ -import { build5Db } from '@build-5/database'; +import { PgAccess, PgTokenDropStatus, PgTokenStatus, build5Db } from '@build-5/database'; import { COL, MIN_IOTA_AMOUNT, NetworkAddress, SOON_PROJECT_ID, - Space, SUB_COL, + Space, Token, - TokenDistribution, - TokenDropStatus, - TokenStatus, + Transaction, + WEN_FUNC, } from '@build-5/interfaces'; import dayjs from 'dayjs'; -import { - airdropToken, - claimAirdroppedToken, - orderToken, -} from '../../../src/runtime/firebase/token/base'; -import { dateToTimestamp, serverTime } from '../../../src/utils/dateTime.utils'; +import { serverTime } from '../../../src/utils/dateTime.utils'; import * as wallet from '../../../src/utils/wallet.utils'; -import { MEDIA, testEnv } from '../../set-up'; -import { - createMember, - createSpace, - getRandomSymbol, - mockWalletReturnValue, - submitMilestoneFunc, - tokenProcessed, - wait, -} from '../common'; +import { MEDIA, mockWalletReturnValue, testEnv } from '../../set-up'; +import { getRandomSymbol, submitMilestoneFunc, tokenProcessed, wait } from '../common'; -let walletSpy: any; - -const submitTokenOrderFunc = async (spy: string, address: NetworkAddress, params: T) => { - mockWalletReturnValue(spy, address, params); - const order = await testEnv.wrap(orderToken)({}); +const submitTokenOrderFunc = async (address: NetworkAddress, params: T) => { + mockWalletReturnValue(address, params); + const order = await testEnv.wrap(WEN_FUNC.orderToken); expect(order?.createdOn).toBeDefined(); return order; }; @@ -43,14 +27,11 @@ describe('Order and claim airdropped token test', () => { let memberAddress: NetworkAddress; let space: Space; let token: Token; - beforeEach(async () => { - walletSpy = jest.spyOn(wallet, 'decodeAuth'); - memberAddress = await createMember(walletSpy); - space = await createSpace(walletSpy, memberAddress); - + memberAddress = await testEnv.createMember(); + space = await testEnv.createSpace(memberAddress); const tokenId = wallet.getRandomEthAddress(); - token = { + const tokenUpsert = { project: SOON_PROJECT_ID, symbol: getRandomSymbol(), totalSupply: 10, @@ -58,64 +39,62 @@ describe('Order and claim airdropped token test', () => { rejected: false, icon: MEDIA, overviewGraphics: MEDIA, - updatedOn: serverTime(), - createdOn: serverTime(), + updatedOn: serverTime().toDate(), + createdOn: serverTime().toDate(), space: space.uid, uid: tokenId, pricePerToken: MIN_IOTA_AMOUNT, - allocations: [ + allocations: JSON.stringify([ { title: 'Public sale', isPublicSale: true, percentage: 50 }, { title: 'Private', percentage: 50 }, - ], + ]), createdBy: memberAddress, name: 'MyToken', saleLength: 86400000 * 2, - saleStartDate: dateToTimestamp(dayjs().subtract(1, 'd').toDate()), + saleStartDate: dayjs().subtract(1, 'd').toDate(), links: [], - status: TokenStatus.AVAILABLE, + status: PgTokenStatus.AVAILABLE, totalDeposit: 0, totalAirdropped: 0, termsAndConditions: 'https://wen.soonaverse.com/token/terms-and-conditions', - access: 0, + access: PgAccess.OPEN, decimals: 6, }; - await build5Db().doc(`${COL.TOKEN}/${token.uid}`).set(token); - + await build5Db().doc(COL.TOKEN, tokenId).upsert(tokenUpsert); + token = (await build5Db().doc(COL.TOKEN, tokenId).get())!; const airdropRequest = { token: token.uid, drops: [{ count: 5, recipient: memberAddress, vestingAt: dayjs().toDate() }], }; - mockWalletReturnValue(walletSpy, memberAddress, airdropRequest); - await testEnv.wrap(airdropToken)({}); + mockWalletReturnValue(memberAddress, airdropRequest); + await testEnv.wrap(WEN_FUNC.airdropToken); }); it('Should order and claim dropped', async () => { const distributionDocRef = build5Db().doc( - `${COL.TOKEN}/${token.uid}/${SUB_COL.DISTRIBUTION}/${memberAddress}`, + COL.TOKEN, + token.uid, + SUB_COL.DISTRIBUTION, + memberAddress, ); - let distribution = await distributionDocRef.get(); - expect(distribution.totalUnclaimedAirdrop).toBe(5); - - const order = await submitTokenOrderFunc(walletSpy, memberAddress, { token: token.uid }); + let distribution = await distributionDocRef.get(); + expect(distribution!.totalUnclaimedAirdrop).toBe(5); + const order = await submitTokenOrderFunc(memberAddress, { token: token.uid }); await submitMilestoneFunc(order, 5 * token.pricePerToken); - - mockWalletReturnValue(walletSpy, memberAddress, { token: token.uid }); - const claimOrder = await testEnv.wrap(claimAirdroppedToken)({}); + mockWalletReturnValue(memberAddress, { token: token.uid }); + const claimOrder = await testEnv.wrap(WEN_FUNC.claimAirdroppedToken); await submitMilestoneFunc(claimOrder); - await wait(async () => { const snap = await build5Db() .collection(COL.AIRDROP) .where('member', '==', memberAddress) - .where('status', '==', TokenDropStatus.CLAIMED) + .where('status', '==', PgTokenDropStatus.CLAIMED) .get(); return snap.length === 1; }); - - await build5Db().doc(`${COL.TOKEN}/${token.uid}`).update({ status: TokenStatus.PROCESSING }); + await build5Db().doc(COL.TOKEN, token.uid).update({ status: PgTokenStatus.PROCESSING }); await tokenProcessed(token.uid, 1, true); - - distribution = await distributionDocRef.get(); + distribution = (await distributionDocRef.get())!; expect(distribution.tokenClaimed).toBe(5); expect(distribution.totalPaid).toBe(5 * token.pricePerToken); expect(distribution.tokenOwned).toBe(10); diff --git a/packages/functions/test/controls/token/token.rank.spec.ts b/packages/functions/test/controls/token/token.rank.spec.ts index 3c6cc83a11..95bab30f8f 100644 --- a/packages/functions/test/controls/token/token.rank.spec.ts +++ b/packages/functions/test/controls/token/token.rank.spec.ts @@ -1,32 +1,27 @@ import { build5Db } from '@build-5/database'; import { COL, + Rank, RANKING_TEST, Space, SUB_COL, Token, TokenAllocation, TokenStats, + WEN_FUNC, WenError, } from '@build-5/interfaces'; -import { rankController } from '../../../src/runtime/firebase/rank'; -import { createToken } from '../../../src/runtime/firebase/token/base'; import * as wallet from '../../../src/utils/wallet.utils'; -import { MEDIA, testEnv } from '../../set-up'; +import { MEDIA, mockWalletReturnValue, testEnv } from '../../set-up'; import { - createMember, createRoyaltySpaces, - createSpace, expectThrow, getRandomSymbol, - mockWalletReturnValue, setProdTiers, setTestTiers, wait, } from '../common'; -let walletSpy: any; - const dummyToken = (space: string) => ({ name: 'MyToken', @@ -51,75 +46,72 @@ describe('Token rank test', () => { }); beforeEach(async () => { - walletSpy = jest.spyOn(wallet, 'decodeAuth'); - member = await createMember(walletSpy); - space = await createSpace(walletSpy, member); - mockWalletReturnValue(walletSpy, member, dummyToken(space.uid)); - token = await testEnv.wrap(createToken)({}); - - await build5Db() - .doc(`${COL.SPACE}/${RANKING_TEST.tokenSpace}/${SUB_COL.GUARDIANS}/${member}`) - .set({ - uid: member, - parentId: RANKING_TEST.tokenSpace, - parentCol: COL.SPACE, - }); + member = await testEnv.createMember(); + space = await testEnv.createSpace(member); + + mockWalletReturnValue(member, dummyToken(space.uid)); + token = await testEnv.wrap(WEN_FUNC.createToken); + + await build5Db().doc(COL.SPACE, RANKING_TEST.tokenSpace, SUB_COL.GUARDIANS, member).upsert({ + parentId: RANKING_TEST.tokenSpace, + }); }); it('Should throw, no token', async () => { - mockWalletReturnValue(walletSpy, member, { + mockWalletReturnValue(member, { collection: COL.TOKEN, uid: wallet.getRandomEthAddress(), rank: 1, }); - await expectThrow(testEnv.wrap(rankController)({}), WenError.token_does_not_exist.key); + await expectThrow(testEnv.wrap(WEN_FUNC.rankController), WenError.token_does_not_exist.key); }); it('Should throw, invalid rank', async () => { - mockWalletReturnValue(walletSpy, member, { + mockWalletReturnValue(member, { collection: COL.TOKEN, uid: token.uid, rank: 200, }); - await expectThrow(testEnv.wrap(rankController)({}), WenError.invalid_params.key); + await expectThrow(testEnv.wrap(WEN_FUNC.rankController), WenError.invalid_params.key); }); it('Should throw, no soons staked', async () => { await setProdTiers(); - mockWalletReturnValue(walletSpy, member, { + mockWalletReturnValue(member, { collection: COL.TOKEN, uid: token.uid, rank: 1, }); - await expectThrow(testEnv.wrap(rankController)({}), WenError.no_staked_soon.key); + await expectThrow(testEnv.wrap(WEN_FUNC.rankController), WenError.no_staked_soon.key); await setTestTiers(); }); it('Should throw, not space member', async () => { - await build5Db() - .doc(`${COL.SPACE}/${RANKING_TEST.tokenSpace}/${SUB_COL.GUARDIANS}/${member}`) - .delete(); + await build5Db().doc(COL.SPACE, RANKING_TEST.tokenSpace, SUB_COL.GUARDIANS, member).delete(); - mockWalletReturnValue(walletSpy, member, { + mockWalletReturnValue(member, { collection: COL.TOKEN, uid: token.uid, rank: 1, }); - await expectThrow(testEnv.wrap(rankController)({}), WenError.you_are_not_guardian_of_space.key); + await expectThrow( + testEnv.wrap(WEN_FUNC.rankController), + WenError.you_are_not_guardian_of_space.key, + ); }); const validateStats = async (count: number, sum: number) => { await wait(async () => { - const tokenDocRef = build5Db().doc(`${COL.TOKEN}/${token.uid}`); - const statsDocRef = tokenDocRef.collection(SUB_COL.STATS).doc(token.uid); + const statsDocRef = build5Db().doc(COL.TOKEN, token.uid, SUB_COL.STATS, token.uid); const stats = await statsDocRef.get(); const statsAreCorrect = stats?.ranks?.count === count && stats?.ranks?.sum === sum && stats?.ranks?.avg === Number((stats?.ranks?.sum! / stats?.ranks?.count!).toFixed(3)); + const tokenDocRef = build5Db().doc(COL.TOKEN, token.uid); token = await tokenDocRef.get(); return ( statsAreCorrect && @@ -131,12 +123,12 @@ describe('Token rank test', () => { }; const sendRank = async (rankValue: number) => { - mockWalletReturnValue(walletSpy, member, { + mockWalletReturnValue(member, { collection: COL.TOKEN, uid: token.uid, rank: rankValue, }); - const rank = await testEnv.wrap(rankController)({}); + const rank = await testEnv.wrap(WEN_FUNC.rankController); expect(rank.uid).toBe(member); expect(rank.parentId).toBe(token.uid); expect(rank.parentCol).toBe(COL.TOKEN); diff --git a/packages/functions/test/controls/token/token.set.to.sale.spec.ts b/packages/functions/test/controls/token/token.set.to.sale.spec.ts index a72d78ea30..deace5daa1 100644 --- a/packages/functions/test/controls/token/token.set.to.sale.spec.ts +++ b/packages/functions/test/controls/token/token.set.to.sale.spec.ts @@ -4,25 +4,15 @@ import { MIN_IOTA_AMOUNT, NetworkAddress, Space, + Token, TokenAllocation, WEN_FUNC, WenError, } from '@build-5/interfaces'; import dayjs from 'dayjs'; -import { createToken, setTokenAvailableForSale } from '../../../src/runtime/firebase/token/base'; import { dateToTimestamp } from '../../../src/utils/dateTime.utils'; -import * as wallet from '../../../src/utils/wallet.utils'; -import { MEDIA, testEnv } from '../../set-up'; -import { - createMember, - createSpace, - expectThrow, - getRandomSymbol, - mockWalletReturnValue, -} from '../common'; - -let walletSpy: any; - +import { MEDIA, mockWalletReturnValue, testEnv } from '../../set-up'; +import { expectThrow, getRandomSymbol } from '../common'; const dummyToken = (space: string) => ({ name: 'MyToken', @@ -46,131 +36,141 @@ describe('Token controller: ' + WEN_FUNC.setTokenAvailableForSale, () => { saleLength: 86400000 * 2, coolDownLength: 86400000, }; - beforeEach(async () => { - walletSpy = jest.spyOn(wallet, 'decodeAuth'); - memberAddress = await createMember(walletSpy); - space = await createSpace(walletSpy, memberAddress); - mockWalletReturnValue(walletSpy, memberAddress, dummyToken(space.uid)); - token = await testEnv.wrap(createToken)({}); - await build5Db().doc(`${COL.TOKEN}/${token.uid}`).update({ approved: true }); + memberAddress = await testEnv.createMember(); + space = await testEnv.createSpace(memberAddress); + mockWalletReturnValue(memberAddress, dummyToken(space.uid)); + token = await testEnv.wrap(WEN_FUNC.createToken); + await build5Db().doc(COL.TOKEN, token.uid).update({ approved: true }); }); it('Should throw, not approved', async () => { - await build5Db().doc(`${COL.TOKEN}/${token.uid}`).update({ approved: false }); + await build5Db().doc(COL.TOKEN, token.uid).update({ approved: false }); const updateData = { token: token.uid, ...publicTime, pricePerToken: MIN_IOTA_AMOUNT }; - mockWalletReturnValue(walletSpy, memberAddress, updateData); - await expectThrow(testEnv.wrap(setTokenAvailableForSale)({}), WenError.token_not_approved.key); + mockWalletReturnValue(memberAddress, updateData); + await expectThrow( + testEnv.wrap(WEN_FUNC.setTokenAvailableForSale), + WenError.token_not_approved.key, + ); }); it('Should throw, rejected', async () => { - await build5Db().doc(`${COL.TOKEN}/${token.uid}`).update({ approved: true, rejected: true }); + await build5Db().doc(COL.TOKEN, token.uid).update({ approved: true, rejected: true }); const updateData = { token: token.uid, ...publicTime, pricePerToken: MIN_IOTA_AMOUNT }; - mockWalletReturnValue(walletSpy, memberAddress, updateData); - await expectThrow(testEnv.wrap(setTokenAvailableForSale)({}), WenError.token_not_approved.key); + mockWalletReturnValue(memberAddress, updateData); + await expectThrow( + testEnv.wrap(WEN_FUNC.setTokenAvailableForSale), + WenError.token_not_approved.key, + ); }); it('Should throw, not on public sale', async () => { const updateData = { token: token.uid, ...publicTime, pricePerToken: MIN_IOTA_AMOUNT }; - mockWalletReturnValue(walletSpy, memberAddress, updateData); + mockWalletReturnValue(memberAddress, updateData); await expectThrow( - testEnv.wrap(setTokenAvailableForSale)({}), + testEnv.wrap(WEN_FUNC.setTokenAvailableForSale), WenError.no_token_public_sale.key, ); }); it('Should throw, not guardian', async () => { + const random = await testEnv.createMember(); const updateData = { token: token.uid, ...publicTime, pricePerToken: MIN_IOTA_AMOUNT }; - mockWalletReturnValue(walletSpy, wallet.getRandomEthAddress(), updateData); + mockWalletReturnValue(random, updateData); await expectThrow( - testEnv.wrap(setTokenAvailableForSale)({}), + testEnv.wrap(WEN_FUNC.setTokenAvailableForSale), WenError.you_are_not_guardian_of_space.key, ); }); it('Should throw, no space', async () => { - const tokenDocRef = build5Db().doc(`${COL.TOKEN}/${token.uid}`); + const tokenDocRef = build5Db().doc(COL.TOKEN, token.uid); await tokenDocRef.update({ space: '', - allocations: [{ title: 'public', percentage: 100, isPublicSale: true }], + allocations: JSON.stringify([{ title: 'public', percentage: 100, isPublicSale: true }]), }); const updateData = { token: token.uid, ...publicTime, pricePerToken: MIN_IOTA_AMOUNT }; - mockWalletReturnValue(walletSpy, memberAddress, updateData); + mockWalletReturnValue(memberAddress, updateData); await expectThrow( - testEnv.wrap(setTokenAvailableForSale)({}), + testEnv.wrap(WEN_FUNC.setTokenAvailableForSale), WenError.token_must_have_space.key, ); }); it('Should set public availability', async () => { await build5Db() - .doc(`${COL.TOKEN}/${token.uid}`) - .update({ allocations: [{ title: 'public', percentage: 100, isPublicSale: true }] }); + .doc(COL.TOKEN, token.uid) + .update({ + allocations: JSON.stringify([{ title: 'public', percentage: 100, isPublicSale: true }]), + }); const updateData = { token: token.uid, ...publicTime, autoProcessAt100Percent: true, pricePerToken: MIN_IOTA_AMOUNT, }; - mockWalletReturnValue(walletSpy, memberAddress, updateData); - const result = await testEnv.wrap(setTokenAvailableForSale)({}); - expect(result?.uid).toBeDefined(); - expect(result?.saleStartDate.toDate()).toEqual( + mockWalletReturnValue(memberAddress, updateData); + const result = await testEnv.wrap(WEN_FUNC.setTokenAvailableForSale); + token = await build5Db().doc(COL.TOKEN, result.uid).get(); + expect(token.uid).toBeDefined(); + expect(token.saleStartDate!.toDate()).toEqual( dateToTimestamp(dayjs(publicTime.saleStartDate), true).toDate(), ); - expect(result?.saleLength).toBe(2 * 86400000); - expect(result?.coolDownEnd.toDate()).toEqual( + expect(token.saleLength).toBe(2 * 86400000); + expect(token.coolDownEnd!.toDate()).toEqual( dateToTimestamp( dayjs(publicTime.saleStartDate).add(86400000 * 2 + 86400000, 'ms'), true, ).toDate(), ); - expect(result?.autoProcessAt100Percent).toBe(true); + expect(token.autoProcessAt100Percent).toBe(true); }); it('Should throw, can not set public availability twice', async () => { await build5Db() - .doc(`${COL.TOKEN}/${token.uid}`) - .update({ allocations: [{ title: 'public', percentage: 100, isPublicSale: true }] }); - mockWalletReturnValue(walletSpy, memberAddress, { + .doc(COL.TOKEN, token.uid) + .update({ + allocations: JSON.stringify([{ title: 'public', percentage: 100, isPublicSale: true }]), + }); + mockWalletReturnValue(memberAddress, { token: token.uid, ...publicTime, pricePerToken: MIN_IOTA_AMOUNT, }); - await testEnv.wrap(setTokenAvailableForSale)({}); - - mockWalletReturnValue(walletSpy, memberAddress, { + await testEnv.wrap(WEN_FUNC.setTokenAvailableForSale); + mockWalletReturnValue(memberAddress, { token: token.uid, ...publicTime, pricePerToken: MIN_IOTA_AMOUNT, }); await expectThrow( - testEnv.wrap(setTokenAvailableForSale)({}), + testEnv.wrap(WEN_FUNC.setTokenAvailableForSale), WenError.public_sale_already_set.key, ); }); it('Should set no cool down length', async () => { - const docRef = build5Db().doc(`${COL.TOKEN}/${token.uid}`); + const docRef = build5Db().doc(COL.TOKEN, token.uid); await docRef.update({ - allocations: [{ title: 'public', percentage: 100, isPublicSale: true }], + allocations: JSON.stringify([{ title: 'public', percentage: 100, isPublicSale: true }]), }); const publicTime = { saleStartDate: dayjs().toDate(), saleLength: 86400000 * 2, coolDownLength: 0, }; - mockWalletReturnValue(walletSpy, memberAddress, { + mockWalletReturnValue(memberAddress, { token: token.uid, ...publicTime, pricePerToken: MIN_IOTA_AMOUNT, }); - const result = await testEnv.wrap(setTokenAvailableForSale)({}); - expect(result?.saleStartDate.toDate()).toEqual( + const result = await testEnv.wrap(WEN_FUNC.setTokenAvailableForSale); + token = await build5Db().doc(COL.TOKEN, result.uid).get(); + expect(token.saleStartDate!.toDate()).toEqual( dateToTimestamp(dayjs(publicTime.saleStartDate), true).toDate(), ); - expect(result?.saleLength).toBe(publicTime.saleLength); - expect(result?.coolDownEnd.toDate()).toEqual( + expect(token.saleLength).toBe(publicTime.saleLength); + expect(token.coolDownEnd!.toDate()).toEqual( dateToTimestamp( dayjs(publicTime.saleStartDate).add(publicTime.saleLength, 'ms'), true, diff --git a/packages/functions/test/controls/token/token.update.spec.ts b/packages/functions/test/controls/token/token.update.spec.ts index 33476e13b4..350a449a61 100644 --- a/packages/functions/test/controls/token/token.update.spec.ts +++ b/packages/functions/test/controls/token/token.update.spec.ts @@ -1,27 +1,16 @@ -import { build5Db } from '@build-5/database'; +import { PgTokenStatus, build5Db } from '@build-5/database'; import { COL, MIN_IOTA_AMOUNT, NetworkAddress, Space, + Token, TokenAllocation, - TokenStatus, WEN_FUNC, WenError, } from '@build-5/interfaces'; -import { createToken, updateToken } from '../../../src/runtime/firebase/token/base'; -import * as wallet from '../../../src/utils/wallet.utils'; -import { MEDIA, testEnv } from '../../set-up'; -import { - createMember, - createSpace, - expectThrow, - getRandomSymbol, - mockWalletReturnValue, -} from '../common'; - -let walletSpy: any; - +import { MEDIA, mockWalletReturnValue, testEnv } from '../../set-up'; +import { expectThrow, getRandomSymbol } from '../common'; const dummyToken = (space: string) => ({ name: 'MyToken', @@ -39,23 +28,20 @@ const dummyToken = (space: string) => describe('Token controller: ' + WEN_FUNC.updateToken, () => { let memberAddress: NetworkAddress; let space: Space; - let token: any; - + let token: Token; const data = { - shortDescriptionTitle: null, - shortDescription: null, - name: null, - uid: null, - title: null, - description: null, + shortDescriptionTitle: undefined, + shortDescription: undefined, + name: undefined, + uid: undefined, + title: undefined, + description: undefined, }; - beforeEach(async () => { - walletSpy = jest.spyOn(wallet, 'decodeAuth'); - memberAddress = await createMember(walletSpy); - space = await createSpace(walletSpy, memberAddress); - mockWalletReturnValue(walletSpy, memberAddress, dummyToken(space.uid)); - token = await testEnv.wrap(createToken)({}); + memberAddress = await testEnv.createMember(); + space = await testEnv.createSpace(memberAddress); + mockWalletReturnValue(memberAddress, dummyToken(space.uid)); + token = await testEnv.wrap(WEN_FUNC.createToken); }); it('Should update token', async () => { @@ -67,8 +53,8 @@ describe('Token controller: ' + WEN_FUNC.updateToken, () => { description: 'description', pricePerToken: 2 * MIN_IOTA_AMOUNT, }; - mockWalletReturnValue(walletSpy, memberAddress, updateData); - const result = await testEnv.wrap(updateToken)({}); + mockWalletReturnValue(memberAddress, updateData); + const result = await testEnv.wrap(WEN_FUNC.updateToken); expect(result.name).toBe(updateData.name); expect(result.title).toBe(updateData.title); expect(result.description).toBe(updateData.description); @@ -76,7 +62,7 @@ describe('Token controller: ' + WEN_FUNC.updateToken, () => { }); it('Should update token, no space', async () => { - await build5Db().doc(`${COL.TOKEN}/${token.uid}`).update({ space: '' }); + await build5Db().doc(COL.TOKEN, token.uid).update({ space: '' }); const updateData = { ...data, name: 'TokenName2', @@ -85,14 +71,15 @@ describe('Token controller: ' + WEN_FUNC.updateToken, () => { description: 'description', pricePerToken: 2 * MIN_IOTA_AMOUNT, }; - mockWalletReturnValue(walletSpy, wallet.getRandomEthAddress(), updateData); + const random = await testEnv.createMember(); + + mockWalletReturnValue(random, updateData); await expectThrow( - testEnv.wrap(updateToken)({}), + testEnv.wrap(WEN_FUNC.updateToken), WenError.you_must_be_the_creator_of_this_token.key, ); - - mockWalletReturnValue(walletSpy, memberAddress, updateData); - const result = await testEnv.wrap(updateToken)({}); + mockWalletReturnValue(memberAddress, updateData); + const result = await testEnv.wrap(WEN_FUNC.updateToken); expect(result.name).toBe(updateData.name); expect(result.title).toBe(updateData.title); expect(result.description).toBe(updateData.description); @@ -101,11 +88,12 @@ describe('Token controller: ' + WEN_FUNC.updateToken, () => { it('Should update token - remove description', async () => { const updateData = { ...data, name: token.name, uid: token.uid, title: 'title2' }; - mockWalletReturnValue(walletSpy, memberAddress, updateData); - const result = await testEnv.wrap(updateToken)({}); - expect(result.name).toBe(token.name); - expect(result.title).toBe(updateData.title); - expect(result.description).toBe(updateData.description); + mockWalletReturnValue(memberAddress, updateData); + const result = await testEnv.wrap(WEN_FUNC.updateToken); + token = (await build5Db().doc(COL.TOKEN, result.uid).get())!; + expect(token.name).toBe(token.name); + expect(token.title).toBe(updateData.title); + expect(token.description).toBe(updateData.description); }); it('Should throw, not owner', async () => { @@ -116,8 +104,13 @@ describe('Token controller: ' + WEN_FUNC.updateToken, () => { title: 'title', description: 'description', }; - mockWalletReturnValue(walletSpy, wallet.getRandomEthAddress(), updateData); - await expectThrow(testEnv.wrap(updateToken)({}), WenError.you_are_not_guardian_of_space.key); + const random = await testEnv.createMember(); + + mockWalletReturnValue(random, updateData); + await expectThrow( + testEnv.wrap(WEN_FUNC.updateToken), + WenError.you_are_not_guardian_of_space.key, + ); }); it('Should throw, not guardian', async () => { @@ -128,34 +121,33 @@ describe('Token controller: ' + WEN_FUNC.updateToken, () => { title: 'title', description: 'description', }; - mockWalletReturnValue(walletSpy, wallet.getRandomEthAddress(), updateData); - await expectThrow(testEnv.wrap(updateToken)({}), WenError.you_are_not_guardian_of_space.key); + const random = await testEnv.createMember(); + mockWalletReturnValue(random, updateData); + await expectThrow( + testEnv.wrap(WEN_FUNC.updateToken), + WenError.you_are_not_guardian_of_space.key, + ); }); it('Should update short description', async () => { const updateData = { ...data, name: token.name, uid: token.uid, title: 'title2' }; - mockWalletReturnValue(walletSpy, memberAddress, updateData); - - await build5Db().doc(`${COL.TOKEN}/${token.uid}`).update({ status: TokenStatus.CANCEL_SALE }); - await expectThrow(testEnv.wrap(updateToken)({}), WenError.token_in_invalid_status.key); - await build5Db().doc(`${COL.TOKEN}/${token.uid}`).update({ status: TokenStatus.BASE }); - await expectThrow(testEnv.wrap(updateToken)({}), WenError.token_in_invalid_status.key); - - await build5Db().doc(`${COL.TOKEN}/${token.uid}`).update({ status: TokenStatus.AVAILABLE }); - const result = await testEnv.wrap(updateToken)({}); + await build5Db().doc(COL.TOKEN, token.uid).update({ status: PgTokenStatus.BASE }); + mockWalletReturnValue(memberAddress, updateData); + await expectThrow( + testEnv.wrap(WEN_FUNC.updateToken), + WenError.token_in_invalid_status.key, + ); + await build5Db().doc(COL.TOKEN, token.uid).update({ status: PgTokenStatus.AVAILABLE }); + mockWalletReturnValue(memberAddress, updateData); + const result = await testEnv.wrap(WEN_FUNC.updateToken); expect(result.name).toBe(token.name); }); it('Should throw, token minted', async () => { - await build5Db().doc(`${COL.TOKEN}/${token.uid}`).update({ status: TokenStatus.MINTED }); - const updateData = { - ...data, - name: 'TokenName2', - uid: token.uid, - title: 'title', - }; - mockWalletReturnValue(walletSpy, memberAddress, updateData); - await expectThrow(testEnv.wrap(updateToken)({}), WenError.invalid_params.key); + await build5Db().doc(COL.TOKEN, token.uid).update({ status: PgTokenStatus.MINTED }); + const updateData = { ...data, name: 'TokenName2', uid: token.uid, title: 'title' }; + mockWalletReturnValue(memberAddress, updateData); + await expectThrow(testEnv.wrap(WEN_FUNC.updateToken), WenError.invalid_params.key); }); }); diff --git a/packages/functions/test/controls/token/token.vote.spec.ts b/packages/functions/test/controls/token/token.vote.spec.ts index 1244ec4e50..9f4d231b56 100644 --- a/packages/functions/test/controls/token/token.vote.spec.ts +++ b/packages/functions/test/controls/token/token.vote.spec.ts @@ -4,26 +4,16 @@ import { NetworkAddress, Space, SUB_COL, + Token, TokenAllocation, TokenStats, + Vote, + WEN_FUNC, WenError, } from '@build-5/interfaces'; -import { createToken } from '../../../src/runtime/firebase/token/base'; -import { voteController } from '../../../src/runtime/firebase/vote'; -import * as wallet from '../../../src/utils/wallet.utils'; -import { MEDIA, testEnv } from '../../set-up'; -import { - createMember, - createSpace, - expectThrow, - getRandomSymbol, - mockWalletReturnValue, - setProdTiers, - setTestTiers, - wait, -} from '../common'; - -let walletSpy: any; +import { getRandomEthAddress } from '../../../src/utils/wallet.utils'; +import { MEDIA, mockWalletReturnValue, testEnv } from '../../set-up'; +import { expectThrow, getRandomSymbol, setProdTiers, setTestTiers, wait } from '../common'; const dummyToken = (space: string) => ({ @@ -45,45 +35,44 @@ describe('Token vote test', () => { let token: any; beforeEach(async () => { - walletSpy = jest.spyOn(wallet, 'decodeAuth'); - memberAddress = await createMember(walletSpy); - space = await createSpace(walletSpy, memberAddress); - mockWalletReturnValue(walletSpy, memberAddress, dummyToken(space.uid)); - token = await testEnv.wrap(createToken)({}); + memberAddress = await testEnv.createMember(); + space = await testEnv.createSpace(memberAddress); + mockWalletReturnValue(memberAddress, dummyToken(space.uid)); + token = await testEnv.wrap(WEN_FUNC.createToken); }); it('Should throw, no token', async () => { - mockWalletReturnValue(walletSpy, memberAddress, { + mockWalletReturnValue(memberAddress, { collection: COL.TOKEN, - uid: wallet.getRandomEthAddress(), + uid: getRandomEthAddress(), direction: 1, }); - await expectThrow(testEnv.wrap(voteController)({}), WenError.token_does_not_exist.key); + await expectThrow(testEnv.wrap(WEN_FUNC.voteController), WenError.token_does_not_exist.key); }); it('Should throw, invalid direction', async () => { - mockWalletReturnValue(walletSpy, memberAddress, { + mockWalletReturnValue(memberAddress, { collection: COL.TOKEN, uid: token.uid, direction: 2, }); - await expectThrow(testEnv.wrap(voteController)({}), WenError.invalid_params.key); + await expectThrow(testEnv.wrap(WEN_FUNC.voteController), WenError.invalid_params.key); }); it('Should throw, no soons staked', async () => { - mockWalletReturnValue(walletSpy, memberAddress, { + await setProdTiers(); + mockWalletReturnValue(memberAddress, { collection: COL.TOKEN, uid: token.uid, direction: 1, }); - await setProdTiers(); - await expectThrow(testEnv.wrap(voteController)({}), WenError.no_staked_soon.key); + await expectThrow(testEnv.wrap(WEN_FUNC.voteController), WenError.no_staked_soon.key); await setTestTiers(); }); const validateStats = async (upvotes: number, downvotes: number, diff: number) => { await wait(async () => { - const statsDocRef = build5Db().doc(`${COL.TOKEN}/${token.uid}/${SUB_COL.STATS}/${token.uid}`); + const statsDocRef = build5Db().doc(COL.TOKEN, token.uid, SUB_COL.STATS, token.uid); const stats = await statsDocRef.get(); return ( stats?.votes?.upvotes === upvotes && @@ -94,12 +83,13 @@ describe('Token vote test', () => { }; const sendVote = async (direction: number) => { - mockWalletReturnValue(walletSpy, memberAddress, { + mockWalletReturnValue(memberAddress, { collection: COL.TOKEN, uid: token.uid, direction, }); - const vote = await testEnv.wrap(voteController)({}); + const vote = await testEnv.wrap(WEN_FUNC.voteController); + expect(vote.uid).toBe(memberAddress); expect(vote.parentId).toBe(token.uid); expect(vote.parentCol).toBe(COL.TOKEN); @@ -112,13 +102,13 @@ describe('Token vote test', () => { await sendVote(-1); await validateStats(0, 1, -1); - - mockWalletReturnValue(walletSpy, memberAddress, { + mockWalletReturnValue(memberAddress, { collection: COL.TOKEN, uid: token.uid, direction: 0, }); - const vote = await testEnv.wrap(voteController)({}); - expect(vote).toBe(undefined); + const vote = await testEnv.wrap(WEN_FUNC.voteController); + + expect(vote).toEqual({}); }); }); diff --git a/packages/functions/test/controls/workflow-online.spec.ts b/packages/functions/test/controls/workflow-online.spec.ts deleted file mode 100644 index 5cbfd1f89a..0000000000 --- a/packages/functions/test/controls/workflow-online.spec.ts +++ /dev/null @@ -1,22 +0,0 @@ -import fs from 'fs'; - -describe('Workflow test', () => { - it('Test if workflow contains all files', async () => { - const buffer = fs.readFileSync('../../.github/workflows/functions_online-emulated-tests.yml'); - const workflowTxt = buffer.toString(); - - const glob = require('glob'); - const testFileNames = glob - .sync(`./test/**/*.spec.ts`) - .filter((f: any) => !f.includes('exclude')) - .filter((f: any) => !f.includes('only.spec.ts')) - .filter((f: any) => !f.includes('dbRoll')); - for (const testFileName of testFileNames) { - if (!workflowTxt.includes(testFileName)) { - throw Error( - `Action misses the following file: ${testFileName}. Pls run node workflow.build.js`, - ); - } - } - }); -}); diff --git a/packages/functions/test/controls/workflow.spec.ts b/packages/functions/test/controls/workflow.spec.ts index 685388bfd3..25f0f0b65a 100644 --- a/packages/functions/test/controls/workflow.spec.ts +++ b/packages/functions/test/controls/workflow.spec.ts @@ -4,7 +4,6 @@ describe('Workflow test', () => { it('Test if workflow contains all files', async () => { const buffer = fs.readFileSync('../../.github/workflows/functions_emulated-tests.yml'); const workflowTxt = buffer.toString(); - const glob = require('glob'); const testFileNames = glob .sync(`./test/**/*.spec.ts`) 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 c7e3d5a277..f26a9302aa 100644 --- a/packages/functions/test/cron/floor-price.cron.only.spec.ts +++ b/packages/functions/test/cron/floor-price.cron.only.spec.ts @@ -3,6 +3,7 @@ import { COL, Collection, MIN_IOTA_AMOUNT, + Nft, NftAccess, NftAvailable, SOON_PROJECT_ID, @@ -13,13 +14,8 @@ import { getRandomEthAddress } from '../../src/utils/wallet.utils'; describe('Collection floor price', () => { it('Should set collection floor price', async () => { const collection = getRandomEthAddress(); - const collectionDocRef = build5Db().doc(`${COL.COLLECTION}/${collection}`); - await collectionDocRef.create({ - project: SOON_PROJECT_ID, - uid: collection, - name: 'asd', - }); - + const collectionDocRef = build5Db().doc(COL.COLLECTION, collection); + await collectionDocRef.create({ project: SOON_PROJECT_ID, name: 'name' } as Collection); const promises = [ NftAvailable.AUCTION, NftAvailable.SALE, @@ -34,17 +30,16 @@ describe('Collection floor price', () => { saleAccess: NftAccess.OPEN, availablePrice: i * MIN_IOTA_AMOUNT, }; - await build5Db().doc(`${COL.NFT}/${nft.uid}`).create(nft); + await build5Db() + .doc(COL.NFT, nft.uid) + .create(nft as Nft); return nft; }); const nfts = await Promise.all(promises); - await updateFloorPriceOnCollections(); - let collectionData = await collectionDocRef.get(); expect(collectionData.floorPrice).toBe(MIN_IOTA_AMOUNT); - - await build5Db().doc(`${COL.NFT}/${nfts[1].uid}`).delete(); + await build5Db().doc(COL.NFT, nfts[1].uid).delete(); await updateFloorPriceOnCollections(); collectionData = await collectionDocRef.get(); expect(collectionData.floorPrice).toBe(2 * MIN_IOTA_AMOUNT); diff --git a/packages/functions/test/cron/nft-stake.cron.spec.ts b/packages/functions/test/cron/nft-stake.cron.spec.ts index ae5653f62f..13c4d955eb 100644 --- a/packages/functions/test/cron/nft-stake.cron.spec.ts +++ b/packages/functions/test/cron/nft-stake.cron.spec.ts @@ -6,16 +6,16 @@ import { dateToTimestamp } from '../../src/utils/dateTime.utils'; import { getRandomEthAddress } from '../../src/utils/wallet.utils'; describe('Expired nft stake cron', () => { + beforeAll(() => {}); it('Should process expired nft stake', async () => { const collection = getRandomEthAddress(); - const collectionDocRef = build5Db().doc(`${COL.COLLECTION}/${collection}`); + const collectionDocRef = build5Db().doc(COL.COLLECTION, collection); await collectionDocRef.create({ project: SOON_PROJECT_ID, uid: collection, - name: 'asd', + name: 'name', stakedNft: 2, - }); - + } as Collection); let nftStake: NftStake = { project: SOON_PROJECT_ID, uid: getRandomEthAddress(), @@ -33,17 +33,13 @@ describe('Expired nft stake cron', () => { uid: getRandomEthAddress(), expiresAt: dateToTimestamp(dayjs().add(2, 'd')), }; - await build5Db().doc(`${COL.NFT_STAKE}/${nonExpiredStake.uid}`).create(nonExpiredStake); - - const stakeDocRef = build5Db().doc(`${COL.NFT_STAKE}/${nftStake.uid}`); + await build5Db().doc(COL.NFT_STAKE, nonExpiredStake.uid).create(nonExpiredStake); + const stakeDocRef = build5Db().doc(COL.NFT_STAKE, nftStake.uid); await stakeDocRef.create(nftStake); - const promises = [processExpiredNftStakes(), processExpiredNftStakes()]; await Promise.all(promises); - const collectionData = await collectionDocRef.get(); expect(collectionData.stakedNft).toBe(1); - nftStake = await stakeDocRef.get(); expect(nftStake.expirationProcessed).toBe(true); }); diff --git a/packages/functions/test/cron/proposal.cron.spec.ts b/packages/functions/test/cron/proposal.cron.spec.ts index aa3ce39119..7dc707e981 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, SOON_PROJECT_ID } from '@build-5/interfaces'; +import { COL, ProposalType, 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'; @@ -10,10 +10,14 @@ describe('Set proposal completed', () => { const member = getRandomEthAddress(); const count = 600; const ids = Array.from(Array(count)).map(() => getRandomEthAddress()); - let batch = build5Db().batch(); for (let i = 0; i < count; ++i) { const proposal = { + name: 'proposal', + space: getRandomEthAddress(), + description: 'name', + type: ProposalType.ADD_GUARDIAN, + questions: [], project: SOON_PROJECT_ID, uid: ids[i], settings: { @@ -23,7 +27,7 @@ describe('Set proposal completed', () => { createdBy: member, completed: i < 550, }; - const docRef = build5Db().doc(`${COL.PROPOSAL}/${proposal.uid}`); + const docRef = build5Db().doc(COL.PROPOSAL, proposal.uid); batch.create(docRef, proposal); if (i > 0 && i % 499 === 0) { await batch.commit(); @@ -31,16 +35,13 @@ describe('Set proposal completed', () => { } } await batch.commit(); - await markExpiredProposalCompleted(); - const completed = await build5Db() .collection(COL.PROPOSAL) .where('createdBy', '==', member) .where('completed', '==', true) .get(); expect(completed.length).toBe(550); - const inProgress = await build5Db() .collection(COL.PROPOSAL) .where('createdBy', '==', member) diff --git a/packages/functions/test/notifier.ts b/packages/functions/test/notifier.ts new file mode 100644 index 0000000000..c39a8e01a0 --- /dev/null +++ b/packages/functions/test/notifier.ts @@ -0,0 +1,160 @@ +require('dotenv').config({ path: (__dirname + '/.env').replace('test/', '') }); +import { PgTransaction } from '@build-5/database'; +import { COL, getMilestoneCol, Network, SUB_COL } from '@build-5/interfaces'; +import { PubSub } from '@google-cloud/pubsub'; +import { Client } from '@iota/sdk'; +import axios from 'axios'; +import dayjs from 'dayjs'; +import Knex from 'knex'; +import { uniq } from 'lodash'; + +const knex = Knex({ + client: 'pg', + connection: { + user: process.env.DB_USER, + password: process.env.DB_USER_PWD, + database: process.env.DB_NAME, + host: process.env.DB_HOST, + port: Number(process.env.DB_PORT), + }, +}); + +const upsertQueue: any[] = []; + +const cleanAllTables = async () => { + const tables = await knex('information_schema.tables') + .select('table_name') + .where('table_schema', 'public'); // Filter by schema if needed + + for (const table of tables.map((row) => row.table_name)) { + if (table.includes('knex')) { + continue; + } + await knex(table).delete(); + } +}; + +const notifier = async () => { + await cleanAllTables(); + const connection = await knex.client.acquireConnection(); + + connection.query(`LISTEN trigger`); + connection.query(`LISTEN blocks`); + connection.query(`LISTEN onupsert`); + + connection.on('notification', async (data: any) => { + if (data.channel === 'blocks') { + await onBlockCreated(data); + return; + } + + if (data.channel === 'trigger') { + const [channel, changeId] = data.payload.split(':'); + if (channel === 'ontransactionwrite') { + await transactionToBlock(changeId); + } + await notifyTriggers(channel, changeId); + return; + } + + if (data.channel === 'onupsert') { + upsertQueue.push(JSON.parse(data.payload)); + } + }); + + process.stdin.resume(); +}; + +const notifyTriggers = async (channel: string, changeId: string) => { + const body = { message: { data: btoa(JSON.stringify({ processId: Number(changeId) })) } }; + for (let i = 0; i < 5; ++i) { + try { + await axios.post('http://localhost:8080/' + channel, body, { + headers: { 'Content-Type': 'application/json' }, + timeout: 3 * 60000, + }); + break; + } catch (error: any) { + if (error.code !== 'ECONNRESET') { + throw error; + } + } + } +}; + +const client = new Client({ nodes: ['https://rms1.svrs.io/'] }); + +const onBlockCreated = async (data: any) => { + const blockId = data.payload; + + const metadata = await getBlockMetadata(blockId); + if (metadata?.ledgerInclusionState !== 'included') { + return; + } + const block = await client.getBlock(blockId); + + await knex(`${getMilestoneCol(Network.RMS)}_${SUB_COL.TRANSACTIONS}`).insert({ + uid: blockId, + blockId, + parentId: metadata.referencedByMilestoneIndex + '', + milestone: metadata.referencedByMilestoneIndex + '', + createdOn: dayjs().toDate(), + payload: JSON.stringify(block.payload), + processed: false, + }); +}; + +const getBlockMetadata = async (blockId: string) => { + for (let attempt = 0; attempt < 1200; ++attempt) { + const metadata = await client.getBlockMetadata(blockId); + if (metadata.ledgerInclusionState) { + return metadata; + } + await new Promise((r) => setTimeout(r, 500)); + } + return; +}; + +const transactionToBlock = async (changeId: string) => { + const doc = await knex('changes') + .select('*') + .first() + .where({ uid: Number(changeId) }); + const transactionId = doc.change.uid; + + const transaction: PgTransaction = await knex(COL.TRANSACTION) + .select('*') + .first() + .where({ uid: transactionId }); + + const blockId = transaction.payload_walletReference_chainReference; + if (blockId && !blockId.startsWith('payment')) { + await knex('blocks').insert({ blockId }).onConflict().ignore(); + } +}; + +const pubSub = new PubSub(); + +const upserTopic = pubSub.topic('onupsert'); + +const postDataToPubSub = async () => { + const data = uniq(upsertQueue.splice(0)); + + const promises = data.map(async (d) => { + const pKey = d.parentId ? { uid: d.uid, parentId: d.parentId } : { uid: d.uid }; + const snap = await knex(d.table).select('*').where(pKey).first(); + if (!snap) { + return; + } + await upserTopic.publishMessage({ + data: Buffer.from(JSON.stringify(snap)), + attributes: { table: d.table }, + }); + }); + + await Promise.all(promises); +}; + +setInterval(postDataToPubSub, 500); + +notifier(); diff --git a/packages/functions/test/set-up.ts b/packages/functions/test/set-up.ts index e84f3ed0d4..15ef4c8721 100644 --- a/packages/functions/test/set-up.ts +++ b/packages/functions/test/set-up.ts @@ -1,158 +1,139 @@ +require('dotenv').config({ path: (__dirname + '/.env').replace('test/', '') }); import { build5Db } from '@build-5/database'; import { - Build5Request, COL, - MIN_IOTA_AMOUNT, Network, - ProjectAdmin, - ProjectBilling, SOON_PROJECT_ID, - SUB_COL, SendToManyTargets, - TokenStatus, + Space, + WEN_FUNC, } from '@build-5/interfaces'; -import dayjs from 'dayjs'; -import dotenv from 'dotenv'; -import express from 'express'; -import test from 'firebase-functions-test'; -import * as functions from 'firebase-functions/v2'; -import { isEmpty } from 'lodash'; +import { CoinType, utf8ToHex } from '@iota/sdk'; +import axios from 'axios'; +import { generateCustomTokenControl } from '../src/controls/auth/auth.control'; +import { Context } from '../src/controls/common'; +import { createMemberControl } from '../src/controls/member/member.create'; +import { MnemonicService } from '../src/services/wallet/mnemonic'; import { Wallet, WalletParams } from '../src/services/wallet/wallet'; import { AddressDetails, WalletService } from '../src/services/wallet/wallet.service'; -import { dateToTimestamp } from '../src/utils/dateTime.utils'; +import { getSecretManager } from '../src/utils/secret.manager.utils'; +import { getRandomEthAddress } from '../src/utils/wallet.utils'; -dotenv.config({ path: '.env.local' }); - -export const projectId = 'soonaverse-dev'; -process.env.GCLOUD_PROJECT = projectId; - -export const getConfig = () => { - if (process.env.LOCAL_TEST) { - process.env.FIRESTORE_EMULATOR_HOST = '127.0.0.1:8080'; - process.env.FIREBASE_STORAGE_EMULATOR_HOST = '127.0.0.1:9199'; - return { - projectId, - storageBucket: 'soonaverse-dev.appspot.com', - }; - } - return { - databaseURL: `https://${projectId}.firebaseio.com`, - projectId, - storageBucket: 'soonaverse-dev.appspot.com', - }; -}; +const tokens: { [key: string]: string } = {}; export const PROJECT_API_KEY = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJwcm9qZWN0IjoiMHg0NjIyM2VkZDQxNTc2MzVkZmM2Mzk5MTU1NjA5ZjMwMWRlY2JmZDg4IiwiaWF0IjoxNjk5MjgyMTQxfQ.Bd0IZNdtc3ne--CC1Bk5qDgWl4NojAsX64K1rCj-5Co'; -export const sendOnRequest = - (func: (req: functions.https.Request, response: express.Response) => void | Promise) => - async (body: any, address = '', customToken = '') => { - const wenReq: Build5Request = { - address, - customToken, - projectApiKey: PROJECT_API_KEY, - body, - }; - const req = { - ip: '127.0.0.1', - body: wenReq, - headers: { origin: true }, - } as any; - let error = false; - let response: any = undefined; - const res = { - status: (code: number) => { - if (code !== 200) { - error = true; - } - }, - send: (res: any) => { - response = res; - }, - setHeader: (key: any, value: any) => {}, - getHeader: (key: any) => {}, - } as any; - await func(req, res); - - for (let attempt = 0; attempt < 5000; ++attempt) { - if (response !== undefined) { - break; - } - await new Promise((r) => setTimeout(r, 100)); - } - - if (error) { - throw response; - } - return isEmpty(response) ? undefined : response; - }; - -export const testEnv = { - config: process.env.LOCAL_TEST - ? test(getConfig()) - : test(getConfig(), './test-service-account-key.json'), - wrap: sendOnRequest, +const mockk = { + address: '', + body: {} as any, + token: undefined as string | undefined, + projectApiKey: PROJECT_API_KEY, }; -export const MEDIA = - 'https://images-wen.soonaverse.com/0x0275dfc7c2624c0111d441a0819dccfd5e947c89%2F6stvhnutvg%2Ftoken_introductionary'; - -export const SOON_PROJ_GUARDIAN = '0x3d5d0b3f40c9438871b1c43d6b70117eeff77ad8'; +export const mockWalletReturnValue = ( + address: string, + body: any, + token?: string, + projectApiKey?: string, +) => { + mockk.address = address; + mockk.body = body; + mockk.token = token; + mockk.projectApiKey = projectApiKey !== undefined ? projectApiKey : PROJECT_API_KEY; +}; -export const soonTokenId = '0xa381bfccaf121e38e31362d85b5ad30cd7fc0d06'; -export const rmsTokenId = '0x52f27a34170900537acb61e5ff0fe94a2841ff52'; -export const atoiTokenId = '0x9c119bd60f7cadf3406c43cead6c8723012bca27'; +export const testEnv = { + wrap: async (func: WEN_FUNC) => { + try { + let request = { + address: mockk.address, + projectApiKey: mockk.projectApiKey, + signature: '', + publicKey: {}, + customToken: mockk.token || tokens[mockk.address], + body: mockk.body || {}, + }; + if (!request.customToken) { + const memberDocRef = build5Db().doc(COL.MEMBER, mockk.address); + const member = await memberDocRef.get(); + const mnemonic = await MnemonicService.get(mockk.address); + const secretManager = getSecretManager(mnemonic); + const signature = await secretManager.signEd25519(utf8ToHex(member?.nonce!), { + coinType: CoinType.IOTA, + }); + request = { + address: mockk.address, + projectApiKey: mockk.projectApiKey, + signature: signature.signature, + publicKey: { hex: signature.publicKey, network: Network.RMS }, + customToken: '', + body: mockk.body || {}, + }; + } + const payload = JSON.stringify(request, (_key, value) => + value === undefined ? null : value, + ); + const response = await axios.post('http://localhost:8080/' + func, payload, { + headers: { 'Content-Type': 'application/json' }, + }); + return response.data as T; + } catch (err: any) { + if (err.response?.data) { + throw err.response?.data; + } + throw err; + } + }, -const setup = async () => { - await build5Db().doc(`${COL.TOKEN}/${soonTokenId}`).set({ - project: SOON_PROJECT_ID, - uid: soonTokenId, - symbol: 'SOON', - }); - await build5Db() - .doc(`${COL.TOKEN}/${rmsTokenId}`) - .set({ + mockWrap: async (func: (context: Context) => Promise) => { + const request = { + ip: '127.0.0.1', + owner: mockk.address, + params: mockk.body || {}, project: SOON_PROJECT_ID, - symbol: 'RMS', - approved: true, - space: '', - uid: rmsTokenId, - name: 'RMS token', - status: TokenStatus.BASE, - access: 0, - icon: MEDIA, - mintingData: { - network: Network.RMS, - }, + headers: {}, + rawBody: {}, + }; + return (await func(request)) as T; + }, + + createMember: async () => { + const owner = getRandomEthAddress(); + mockWalletReturnValue(owner, undefined); + await testEnv.mockWrap(createMemberControl); + mockWalletReturnValue(owner, undefined); + const token = await testEnv.mockWrap(generateCustomTokenControl); + tokens[owner] = token; + const addresses = {} as any; + const promises = Object.values(Network).map(async (network) => { + const wallet = await getWallet(network); + const address = await wallet.getNewIotaAddressDetails(); + addresses[`${network}Address`] = address.bech32; }); - - const soonProject = { - uid: SOON_PROJECT_ID, - name: 'Soonaverse', - createdBy: SOON_PROJ_GUARDIAN, - deactivated: false, - config: { - billing: ProjectBilling.TOKEN_BASE, - tiers: [0, 0, 0, 0, 0].map((v) => v * MIN_IOTA_AMOUNT), - tokenTradingFeeDiscountPercentage: [0, 0, 0, 0, 0], - nativeTokenSymbol: 'SOON', - nativeTokenUid: soonTokenId, - }, - }; - const soonProjDocRef = build5Db().doc(`${COL.PROJECT}/${soonProject.uid}`); - await soonProjDocRef.set(soonProject); - - const adminDocRef = soonProjDocRef.collection(SUB_COL.ADMINS).doc(SOON_PROJ_GUARDIAN); - const admin: ProjectAdmin = { - uid: SOON_PROJ_GUARDIAN, - createdOn: dateToTimestamp(dayjs()), - parentCol: COL.PROJECT, - parentId: SOON_PROJECT_ID, - }; - await adminDocRef.set(admin); - - console.log('Setup env'); + await Promise.all(promises); + await build5Db().doc(COL.MEMBER, owner).update(addresses); + return owner; + }, + + createSpace: async (member: string) => { + mockWalletReturnValue(member, { name: 'Space A', bannerUrl: MEDIA }); + const space = await testEnv.wrap(WEN_FUNC.createSpace); + + const addresses = {} as any; + const promises = Object.values(Network).map(async (network) => { + const wallet = await getWallet(network); + const address = await wallet.getNewIotaAddressDetails(); + addresses[`${network}Address`] = address.bech32; + }); + await Promise.all(promises); + await build5Db().doc(COL.SPACE, space.uid).update(addresses); + return (await build5Db().doc(COL.SPACE, space.uid).get())!; + }, + + createBlock: async (blockId: string) => { + await build5Db().getCon()('blocks').insert({ blockId }); + }, }; export const wallets: { [key: string]: Wallet } = {}; @@ -166,7 +147,6 @@ class TestWallet extends Wallet { public getNewIotaAddressDetails = this.wallet.getNewIotaAddressDetails; public getIotaAddressDetails = this.wallet.getIotaAddressDetails; public getAddressDetails = this.wallet.getAddressDetails; - public bechAddressFromOutput = this.wallet.bechAddressFromOutput; public getOutputs = this.wallet.getOutputs; public creditLocked = this.wallet.creditLocked; @@ -179,16 +159,17 @@ class TestWallet extends Wallet { outputToConsume?: string | undefined, ) => { const blockId = await this.wallet.send(from, toAddress, amount, params, outputToConsume); - await build5Db().doc(`blocks/${blockId}`).create({ blockId }); + await build5Db().getCon()('blocks').insert({ blockId }); return blockId; }; + public sendToMany = async ( from: AddressDetails, targets: SendToManyTargets[], params: WalletParams, ) => { const blockId = await this.wallet.sendToMany(from, targets, params); - await build5Db().doc(`blocks/${blockId}`).create({ blockId }); + await build5Db().getCon()('blocks').insert({ blockId }); return blockId; }; } @@ -202,4 +183,9 @@ export const getWallet = async (network: Network) => { return wallets[network]; }; -export default setup; +export const MEDIA = + 'https://images-wen.soonaverse.com/0x0275dfc7c2624c0111d441a0819dccfd5e947c89%2F6stvhnutvg%2Ftoken_introductionary'; +export const SOON_PROJ_GUARDIAN = '0x3d5d0b3f40c9438871b1c43d6b70117eeff77ad8'; +export const soonTokenId = '0xa381bfccaf121e38e31362d85b5ad30cd7fc0d06'; +export const rmsTokenId = '0x52f27a34170900537acb61e5ff0fe94a2841ff52'; +export const atoiTokenId = '0x9c119bd60f7cadf3406c43cead6c8723012bca27'; diff --git a/packages/functions/test/stake/delete.stake.reward.spec.ts b/packages/functions/test/stake/delete.stake.reward.spec.ts index 8c6d401ac6..18e1d8322e 100644 --- a/packages/functions/test/stake/delete.stake.reward.spec.ts +++ b/packages/functions/test/stake/delete.stake.reward.spec.ts @@ -7,24 +7,15 @@ import { Space, StakeReward, StakeRewardStatus, + Token, + WEN_FUNC, WenError, } from '@build-5/interfaces'; import dayjs from 'dayjs'; -import { voteOnProposal } from '../../src/runtime/firebase/proposal'; -import { removeStakeReward } from '../../src/runtime/firebase/stake'; import { dateToTimestamp } from '../../src/utils/dateTime.utils'; import * as wallet from '../../src/utils/wallet.utils'; -import { - addGuardianToSpace, - createMember, - createSpace, - expectThrow, - mockWalletReturnValue, - wait, -} from '../controls/common'; -import { testEnv } from '../set-up'; - -let walletSpy: any; +import { addGuardianToSpace, expectThrow, wait } from '../controls/common'; +import { mockWalletReturnValue, testEnv } from '../set-up'; describe('Delete stake reward', () => { let guardian: string; @@ -33,19 +24,20 @@ describe('Delete stake reward', () => { let token: string; beforeEach(async () => { - walletSpy = jest.spyOn(wallet, 'decodeAuth'); - guardian = await createMember(walletSpy); - member = await createMember(walletSpy); - space = await createSpace(walletSpy, guardian); + guardian = await testEnv.createMember(); + member = await testEnv.createMember(); + space = await testEnv.createSpace(guardian); await addGuardianToSpace(space.uid, member); token = wallet.getRandomEthAddress(); - await build5Db().doc(`${COL.TOKEN}/${token}`).create({ - project: SOON_PROJECT_ID, - uid: token, - space: space.uid, - }); + await build5Db() + .doc(COL.TOKEN, token) + .create({ + project: SOON_PROJECT_ID, + space: space.uid, + links: [] as URL[], + } as Token); }); const createStakeRewards = async () => { @@ -73,14 +65,14 @@ describe('Delete stake reward', () => { }, ]; for (const stakeReward of stakeRewards) { - await build5Db().doc(`${COL.STAKE_REWARD}/${stakeReward.uid}`).create(stakeReward); + await build5Db().doc(COL.STAKE_REWARD, stakeReward.uid).create(stakeReward); } return stakeRewards; }; const getStakeRewards = async (stakeRewardIds: string[]) => { const promises = stakeRewardIds.map(async (stakeRewardId) => { - const docRef = build5Db().doc(`${COL.STAKE_REWARD}/${stakeRewardId}`); + const docRef = build5Db().doc(COL.STAKE_REWARD, stakeRewardId); return await docRef.get(); }); return await Promise.all(promises); @@ -89,10 +81,9 @@ describe('Delete stake reward', () => { it('Should create proposal and delete stake reward', async () => { const stakeRewards = await createStakeRewards(); const stakeRewardIds = stakeRewards.map((reward) => reward.uid); - mockWalletReturnValue(walletSpy, guardian, { - stakeRewardIds, - }); - let proposal: Proposal = await testEnv.wrap(removeStakeReward)({}); + mockWalletReturnValue(guardian, { stakeRewardIds }); + let proposal = await testEnv.wrap(WEN_FUNC.removeStakeReward); + proposal = (await build5Db().doc(COL.PROPOSAL, proposal.uid).get())!; expect(proposal.settings.stakeRewardIds!.sort()).toEqual(stakeRewardIds.sort()); expect( dayjs(proposal.settings.endDate.toDate()).isSame(dayjs(stakeRewards[1].startDate.toDate())), @@ -117,8 +108,8 @@ describe('Delete stake reward', () => { `| ${stakeRewards[0].tokensToDistribute} |`, ); - mockWalletReturnValue(walletSpy, member, { uid: proposal.uid, value: 1 }); - await testEnv.wrap(voteOnProposal)({}); + mockWalletReturnValue(member, { uid: proposal.uid, value: 1 }); + await testEnv.wrap(WEN_FUNC.voteOnProposal); await new Promise((resolve) => setTimeout(resolve, 1000)); await wait(async () => { @@ -130,48 +121,48 @@ describe('Delete stake reward', () => { return allDeleted; }); - proposal = await build5Db().doc(`${COL.PROPOSAL}/${proposal.uid}`).get(); + proposal = await build5Db().doc(COL.PROPOSAL, proposal.uid).get(); expect(dayjs(proposal.settings.endDate.toDate()).isBefore(dayjs())).toBe(true); }); it('Should throw, not guardian', async () => { - const tmp = await createMember(walletSpy); + const tmp = await testEnv.createMember(); const stakeRewards = await createStakeRewards(); const stakeRewardIds = stakeRewards.map((reward) => reward.uid); - mockWalletReturnValue(walletSpy, tmp, { stakeRewardIds }); + mockWalletReturnValue(tmp, { stakeRewardIds }); await expectThrow( - testEnv.wrap(removeStakeReward)({}), + testEnv.wrap(WEN_FUNC.removeStakeReward), WenError.you_are_not_guardian_of_space.key, ); }); it('Should throw, multiple tokens', async () => { const stakeRewards = await createStakeRewards(); - await build5Db().doc(`${COL.STAKE_REWARD}/${stakeRewards[0].uid}`).update({ token: 'asd' }); + await build5Db().doc(COL.STAKE_REWARD, stakeRewards[0].uid).update({ token: 'name' }); const stakeRewardIds = stakeRewards.map((reward) => reward.uid); - mockWalletReturnValue(walletSpy, guardian, { stakeRewardIds }); - await expectThrow(testEnv.wrap(removeStakeReward)({}), WenError.invalid_params.key); + mockWalletReturnValue(guardian, { stakeRewardIds }); + await expectThrow(testEnv.wrap(WEN_FUNC.removeStakeReward), WenError.invalid_params.key); }); it('Should throw, 2 ongoing proposals', async () => { const stakeRewards = await createStakeRewards(); const stakeRewardIds = stakeRewards.map((reward) => reward.uid); - mockWalletReturnValue(walletSpy, guardian, { stakeRewardIds }); - await testEnv.wrap(removeStakeReward)({}); + mockWalletReturnValue(guardian, { stakeRewardIds }); + await testEnv.wrap(WEN_FUNC.removeStakeReward); - mockWalletReturnValue(walletSpy, guardian, { stakeRewardIds }); - await expectThrow(testEnv.wrap(removeStakeReward)({}), WenError.ongoing_proposal.key); + mockWalletReturnValue(guardian, { stakeRewardIds }); + await expectThrow(testEnv.wrap(WEN_FUNC.removeStakeReward), WenError.ongoing_proposal.key); }); it('Should throw, stake reward expired', async () => { const stakeRewards = await createStakeRewards(); - const docRef = build5Db().doc(`${COL.STAKE_REWARD}/${stakeRewards[1].uid}`); - await docRef.update({ startDate: dateToTimestamp(dayjs().subtract(1, 'm')) }); + const docRef = build5Db().doc(COL.STAKE_REWARD, stakeRewards[1].uid); + await docRef.update({ startDate: dayjs().subtract(1, 'm').toDate() }); const stakeRewardIds = stakeRewards.map((reward) => reward.uid); - mockWalletReturnValue(walletSpy, guardian, { + mockWalletReturnValue(guardian, { stakeRewardIds, }); - await expectThrow(testEnv.wrap(removeStakeReward)({}), WenError.stake_reward_started.key); + await expectThrow(testEnv.wrap(WEN_FUNC.removeStakeReward), WenError.stake_reward_started.key); }); }); diff --git a/packages/functions/test/stake/stake.reward.cron.spec.ts b/packages/functions/test/stake/stake.reward.cron.spec.ts index 8ad6a2d130..053ff695b3 100644 --- a/packages/functions/test/stake/stake.reward.cron.spec.ts +++ b/packages/functions/test/stake/stake.reward.cron.spec.ts @@ -8,7 +8,6 @@ import { StakeType, } from '@build-5/interfaces'; import dayjs from 'dayjs'; -import { getStakedPerMember } from '../../src/cron/stakeReward.cron'; import { dateToTimestamp } from '../../src/utils/dateTime.utils'; import { getRandomEthAddress } from '../../src/utils/wallet.utils'; @@ -145,7 +144,7 @@ describe('Stake reward cron: getStakedPerMember', () => { orderId: '', billPaymentId: '', }; - await build5Db().doc(`${COL.STAKE}/${stake.uid}`).create(stake); + await build5Db().doc(COL.STAKE, stake.uid).create(stake); return stake; }; @@ -160,7 +159,7 @@ describe('Stake reward cron: getStakedPerMember', () => { token, status: StakeRewardStatus.UNPROCESSED, } as StakeReward; - await build5Db().doc(`${COL.STAKE_REWARD}/${stakeReward.uid}`).create(stakeReward); + await build5Db().doc(COL.STAKE_REWARD, stakeReward.uid).create(stakeReward); return stakeReward; }; @@ -169,7 +168,9 @@ describe('Stake reward cron: getStakedPerMember', () => { await createStake(stake.createdOn, stake.expiresAt); } const stakeReward = await createReward(reward.startDate, reward.endDate); - const stakedPerMember = await getStakedPerMember(stakeReward); + const stakedPerMember = await build5Db() + .collection(COL.STAKE) + .getStakeSumPerMember(stakeReward); expect(stakedPerMember[member]).toBe(expectedValue || undefined); }); }); diff --git a/packages/functions/test/storage/resize.img.spec.ts b/packages/functions/test/storage/resize.img.spec.ts index 6558690e28..f1cdd930a4 100644 --- a/packages/functions/test/storage/resize.img.spec.ts +++ b/packages/functions/test/storage/resize.img.spec.ts @@ -1,21 +1,32 @@ import { build5Storage } from '@build-5/database'; import { Bucket, ImageWidth } from '@build-5/interfaces'; +import axios from 'axios'; +import { WEN_STORAGE_TRIGGER } from '../../src/runtime/common'; import { getRandomEthAddress } from '../../src/utils/wallet.utils'; import { wait } from '../controls/common'; +const triggerResizer = async (name: string, contentType: string) => { + try { + await axios.post( + 'http://localhost:8080/' + WEN_STORAGE_TRIGGER.onUploadFinalized, + { name, bucket: Bucket.DEV, contentType, metadata: {} }, + { headers: { 'Content-Type': 'application/json' } }, + ); + } catch (err) { + console.log(err); + } +}; + describe('Resize img test', () => { it('Should resize img', async () => { - const name = 'nft/test/image'; + const folder = getRandomEthAddress(); + const name = `nft/${folder}/image`; const extensions = Object.values(ImageWidth) .map((size) => `_jpeg_${size}X${size}.webp`) .concat('.jpeg'); - const bucket = build5Storage().bucket(Bucket.DEV); - const destination = 'nft/test/image.jpeg'; - await bucket.upload('./test/puppy.jpeg', destination, { - contentType: 'image/jpeg', - }); - + await bucket.upload('./test/puppy.jpeg', name + '.jpeg', { contentType: 'image/jpeg' }); + await triggerResizer(name + '.jpeg', 'image/jpeg'); for (const extension of extensions) { await wait( async () => @@ -30,9 +41,8 @@ describe('Resize img test', () => { const id = getRandomEthAddress(); const bucket = build5Storage().bucket(Bucket.DEV); const destination = `nft/test/${id}.mov`; - await bucket.upload('./test/nft_video.mov', destination, { - contentType: 'video/quicktime', - }); + await bucket.upload('./test/nft_video.mov', destination, { contentType: 'video/quicktime' }); + await triggerResizer(destination, 'video/quicktime'); await wait( async () => await build5Storage().bucket(Bucket.DEV).exists(`nft/test/${id}_mov_preview.webp`), @@ -41,11 +51,11 @@ describe('Resize img test', () => { it.each(['png', 'jpeg'])('Should not override', async (extension: string) => { const name = 'nft/test/image'; - const bucket = build5Storage().bucket(Bucket.DEV); await bucket.upload('./test/puppy.jpeg', 'nft/test/image.' + extension, { contentType: 'image/' + extension, }); + await triggerResizer('nft/test/image.' + extension, 'image/' + extension); const extensions = Object.values(ImageWidth) .map((size) => `_${extension}_${size}X${size}.webp`) .concat(`.${extension}`); diff --git a/packages/functions/test/teardown.ts b/packages/functions/test/teardown.ts index 88f744bba7..27d7e30971 100644 --- a/packages/functions/test/teardown.ts +++ b/packages/functions/test/teardown.ts @@ -1,34 +1,13 @@ import { build5Db } from '@build-5/database'; -import { BaseRecord, COL } from '@build-5/interfaces'; -import { isEmpty } from 'lodash'; +import { tangleClients } from '../src/services/wallet/wallet.service'; +import { wallets } from './set-up'; -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 (isEmpty(data.project)) { - console.log(collection, data); - throw Error('Project not defined'); - } - } +afterAll(async () => { + await build5Db().destroy(); + for (const client of Object.values(wallets)) { + await client.client.destroy(); } -}; - -export default teardown; + for (const client of Object.values(tangleClients)) { + await client.destroy(); + } +}); diff --git a/packages/functions/workflow.build.js b/packages/functions/workflow.build.js index 3d49993bf0..6245984843 100644 --- a/packages/functions/workflow.build.js +++ b/packages/functions/workflow.build.js @@ -3,32 +3,19 @@ const fs = require('fs'); const { chunk } = require('lodash'); const tangleTestFile = '../../.github/workflows/functions_tangle-unit-tests.yml'; -const tangleOnlineTestFile = - '../../.github/workflows/functions_tangle-online-unit-tests_emulator.yml'; +('../../.github/workflows/functions_tangle-online-unit-tests_emulator.yml'); const emulatedTestFile = '../../.github/workflows/functions_emulated-tests.yml'; -const emulatedOnlineTestFile = '../../.github/workflows/functions_online-emulated-tests.yml'; const tangleTestFileName = 'Functions | Tangle - Emulated Unit Tests'; -const tangleOnlineTestFileName = 'Functions | Tangle - Online - Emulated Unit Tests'; const emulatedTestFileName = 'Functions | Emulated Unit Tests'; -const emulatedOnlineTestFileName = 'Functions | Online Emulated Unit Tests'; function setup(outputFile, title) { fs.writeFileSync(outputFile, `name: ${title}\n\n`); fs.appendFileSync(outputFile, 'on:\n'); fs.appendFileSync(outputFile, ' pull_request:\n'); fs.appendFileSync(outputFile, ' paths:\n'); - fs.appendFileSync(outputFile, ' - packages/functions/**\n\n'); -} - -function setupOnline(outputFile, title) { - fs.writeFileSync(outputFile, `name: ${title}\n\n`); - fs.appendFileSync(outputFile, 'on:\n'); - fs.appendFileSync(outputFile, ' workflow_run:\n'); - fs.appendFileSync(outputFile, ' workflows: ["Firebase Deploy DEV"]\n'); - fs.appendFileSync(outputFile, ' types: [completed]\n'); - fs.appendFileSync(outputFile, ' branches:\n'); - fs.appendFileSync(outputFile, ' - "develop"\n\n'); + fs.appendFileSync(outputFile, ' - packages/functions/**\n'); + fs.appendFileSync(outputFile, ' - packages/database/**\n\n'); } function init(outputFile) { @@ -36,14 +23,8 @@ function init(outputFile) { fs.appendFileSync(outputFile, ' npm-install:\n'); fs.appendFileSync(outputFile, ' runs-on: ubuntu-latest\n'); fs.appendFileSync(outputFile, ' timeout-minutes: 10\n'); + fs.appendFileSync(outputFile, ' steps:\n'); - // Foresight telemetry - // fs.appendFileSync(outputFile, ' - name: Collect Workflow Telemetry\n'); - // fs.appendFileSync(outputFile, ' uses: runforesight/foresight-workflow-kit-action@v1\n'); - // fs.appendFileSync(outputFile, ' if: ${{ always() }}\n'); - // fs.appendFileSync(outputFile, ' with:\n'); - // fs.appendFileSync(outputFile, ' api_key: ${{ secrets.FORESIGHT_KEY }}\n'); - // end fs.appendFileSync(outputFile, ' - uses: actions/checkout@v4\n'); fs.appendFileSync(outputFile, ' - uses: actions/setup-node@v4\n'); fs.appendFileSync(outputFile, ' with:\n'); @@ -64,19 +45,29 @@ function init(outputFile) { fs.appendFileSync(outputFile, ' run: npm run build:functions\n\n'); } -function job(outputFile, chunk, files, commandName) { +function job(outputFile, chunk, files) { fs.appendFileSync(outputFile, ` chunk_${chunk}:\n`); fs.appendFileSync(outputFile, ` needs: npm-install\n`); fs.appendFileSync(outputFile, ` runs-on: ubuntu-latest\n`); - fs.appendFileSync(outputFile, ` timeout-minutes: 20\n`); + fs.appendFileSync(outputFile, ` timeout-minutes: 20\n\n`); + + fs.appendFileSync(outputFile, ' services:\n'); + fs.appendFileSync(outputFile, ' postgres:\n'); + fs.appendFileSync(outputFile, ' image: postgres\n'); + fs.appendFileSync(outputFile, ' env:\n'); + fs.appendFileSync(outputFile, ' POSTGRES_DB: build5db\n'); + fs.appendFileSync(outputFile, ' POSTGRES_PASSWORD: postgres\n'); + fs.appendFileSync(outputFile, ' ports:\n'); + fs.appendFileSync(outputFile, ' - 5432:5432\n'); + + fs.appendFileSync(outputFile, ' options: >-\n'); + fs.appendFileSync(outputFile, ' --health-cmd pg_isready\n'); + fs.appendFileSync(outputFile, ' --health-interval 10s\n'); + fs.appendFileSync(outputFile, ' --health-timeout 5s\n'); + fs.appendFileSync(outputFile, ' --health-retries 5\n\n'); + fs.appendFileSync(outputFile, ` steps:\n`); - // // Foresight telemetry - // fs.appendFileSync(outputFile, ' - name: Collect Workflow Telemetry\n'); - // fs.appendFileSync(outputFile, ' uses: runforesight/foresight-workflow-kit-action@v1\n'); - // fs.appendFileSync(outputFile, ' if: ${{ always() }}\n'); - // fs.appendFileSync(outputFile, ' with:\n'); - // fs.appendFileSync(outputFile, ' api_key: ${{ secrets.FORESIGHT_KEY }}\n'); - // end + fs.appendFileSync(outputFile, ` - uses: actions/checkout@v4\n`); fs.appendFileSync(outputFile, ` - uses: actions/setup-node@v4\n`); fs.appendFileSync(outputFile, ` with:\n`); @@ -93,64 +84,20 @@ function job(outputFile, chunk, files, commandName) { ); fs.appendFileSync(outputFile, ` - name: Init\n`); - fs.appendFileSync(outputFile, ` run: |\n`); - fs.appendFileSync(outputFile, ` npm run build:functions\n`); - fs.appendFileSync(outputFile, ` npm install -g firebase-tools\n`); + fs.appendFileSync(outputFile, ` run: npm run build:functions\n`); fs.appendFileSync(outputFile, ` - name: Test\n`); fs.appendFileSync(outputFile, ` working-directory: packages/functions\n`); - fs.appendFileSync(outputFile, ` run: |\n`); - fs.appendFileSync( - outputFile, - ` export GOOGLE_APPLICATION_CREDENTIALS="./test-service-account-key.json"\n`, - ); - fs.appendFileSync(outputFile, ` npm run milestone-sync &\n`); - fs.appendFileSync(outputFile, ` firebase emulators:exec "\n`); + fs.appendFileSync(outputFile, ` npm run start &\n`); + fs.appendFileSync(outputFile, ` npm run notifier &\n`); + files.forEach((file, index) => { fs.appendFileSync( outputFile, - ` npm run ${commandName}:ci -- --forceExit --findRelatedTests ${file} ${ - index < files.length - 1 ? '&&' : '' - }\n`, + ` npm run test -- --findRelatedTests --forceExit ${file} ${index < files.length - 1 ? '&&' : ''}\n`, ); }); - fs.appendFileSync( - outputFile, - ` " --project dev --only functions,firestore,storage,ui,auth --export-on-exit=./firestore-data\n`, - ); - // Test reports collection via github action. - // fs.appendFileSync(outputFile, ` - name: Test Report\n`); - // fs.appendFileSync( - // outputFile, - // ` uses: phoenix-actions/test-reporting@f68b7c5fcffefd98dd230c686cca6c26683668c3\n`, - // ); - // fs.appendFileSync(outputFile, ` if: success() || failure()\n`); - // fs.appendFileSync(outputFile, ` with:\n`); - // fs.appendFileSync(outputFile, ` name: Tests results - chunk_${chunk}\n`); - // fs.appendFileSync(outputFile, ` path: packages/functions/reports/junit-*.xml\n`); - // fs.appendFileSync(outputFile, ` output-to: checks\n`); - // fs.appendFileSync(outputFile, ` reporter: jest-junit\n\n`); - - // Coverage & test results via foresight - fs.appendFileSync(outputFile, ` - name: Archive firestore data\n`); - fs.appendFileSync(outputFile, ` uses: actions/upload-artifact@v4\n`); - fs.appendFileSync(outputFile, ' if: ${{ failure() }}\n'); - fs.appendFileSync(outputFile, ` with:\n`); - fs.appendFileSync(outputFile, ` name: firestore-data-${commandName}-chunk_${chunk}\n`); - fs.appendFileSync(outputFile, ` path: ./packages/functions/firestore-data/\n`); - fs.appendFileSync(outputFile, ` retention-days: 1\n`); - - // fs.appendFileSync(outputFile, ` - name: Analyze Test and Coverage Results\n`); - // fs.appendFileSync(outputFile, ` uses: runforesight/foresight-test-kit-action@v1\n`); - // fs.appendFileSync(outputFile, ` if: \${{ always() }}\n`); - // fs.appendFileSync(outputFile, ` with:\n`); - // fs.appendFileSync(outputFile, ` api_key: \${{ secrets.FORESIGHT_KEY }}\n`); - // fs.appendFileSync(outputFile, ` test_format: JUNIT\n`); - // fs.appendFileSync(outputFile, ` test_framework: JEST\n`); - // fs.appendFileSync(outputFile, ` test_path: packages/functions/reports/test\n`); - // fs.appendFileSync(outputFile, ` coverage_format: COBERTURA/XML\n`); - // fs.appendFileSync(outputFile, ` coverage_path: packages/functions/reports/coverage\n\n`); } const tangleChunkSize = 3; @@ -163,46 +110,16 @@ function createTangleTest() { const only = files.filter((f) => f.includes('only.spec.ts')); const rest = files.filter((f) => !f.includes('only.spec.ts')); const restChunks = chunk(rest, tangleChunkSize); - restChunks.forEach((chunk, i) => job(tangleTestFile, i, chunk, 'test-tangle')); - chunk(only, 1).forEach((chunk, i) => - job(tangleTestFile, i + restChunks.length, chunk, 'test-tangle'), - ); -} - -function createTangleOnlineTest() { - setupOnline(tangleOnlineTestFile, tangleOnlineTestFileName); - init(tangleOnlineTestFile); - const files = glob - .sync(`./test-tangle/**/*.spec.ts`) - .filter((f) => !f.includes('only.spec.ts')) - .filter((f) => !f.includes('web3.spec')) - .filter((f) => !f.includes('dbRoll')); - chunk(files, tangleChunkSize).forEach((chunk, i) => - job(tangleOnlineTestFile, i, chunk, 'test-tangle-online'), - ); + restChunks.forEach((chunk, i) => job(tangleTestFile, i, chunk)); + chunk(only, 1).forEach((chunk, i) => job(tangleTestFile, i + restChunks.length, chunk)); } function createEmulatedTest() { setup(emulatedTestFile, emulatedTestFileName); init(emulatedTestFile); const files = glob.sync(`./test/**/*.spec.ts`).filter((f) => !f.includes('exclude')); - chunk(files, emulatorChunkSize).forEach((chunk, i) => job(emulatedTestFile, i, chunk, 'test')); -} - -function createEmulatedOnlineTest() { - setupOnline(emulatedOnlineTestFile, emulatedOnlineTestFileName); - 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) => - job(emulatedOnlineTestFile, i, chunk, 'test-online'), - ); + chunk(files, emulatorChunkSize).forEach((chunk, i) => job(emulatedTestFile, i, chunk)); } createTangleTest(); createEmulatedTest(); -createTangleOnlineTest(); -createEmulatedOnlineTest(); diff --git a/packages/interfaces/src/models/award.ts b/packages/interfaces/src/models/award.ts index 78227d6dca..3f2a297345 100644 --- a/packages/interfaces/src/models/award.ts +++ b/packages/interfaces/src/models/award.ts @@ -215,6 +215,10 @@ export interface Award extends BaseRecord { * Media status {@link MediaStatus} */ readonly mediaStatus?: MediaStatus; + /** + * @hidden + */ + readonly mediaUploadErrorCount?: number; /** * Is this legacy award? * @deprecated diff --git a/packages/interfaces/src/models/base.ts b/packages/interfaces/src/models/base.ts index 5624bd8756..abae7b95aa 100644 --- a/packages/interfaces/src/models/base.ts +++ b/packages/interfaces/src/models/base.ts @@ -138,6 +138,7 @@ export interface Base { } export interface BaseSubCollection { + uid?: string; project?: string; parentId: string; parentCol: string; diff --git a/packages/interfaces/src/models/collection.ts b/packages/interfaces/src/models/collection.ts index 3d36bd6432..57e93ac47b 100644 --- a/packages/interfaces/src/models/collection.ts +++ b/packages/interfaces/src/models/collection.ts @@ -227,6 +227,10 @@ export interface Collection extends CollectionBase { * Status of media upload to IFPS. */ mediaStatus?: MediaStatus; + /** + * @hidden + */ + mediaUploadErrorCount?: number; /** * Total number of staked NFTs */ diff --git a/packages/interfaces/src/models/index.ts b/packages/interfaces/src/models/index.ts index 6409411804..53f952b1c7 100644 --- a/packages/interfaces/src/models/index.ts +++ b/packages/interfaces/src/models/index.ts @@ -12,6 +12,7 @@ export * from './nftStake'; export * from './notification'; export * from './project'; export * from './proposal'; +export * from './soon_snap'; export * from './space'; export * from './stake'; export * from './stamp'; @@ -20,4 +21,3 @@ export * from './system.config'; export * from './ticker'; export * from './token'; export * from './transaction'; -export * from './soon_snap'; diff --git a/packages/interfaces/src/models/member.ts b/packages/interfaces/src/models/member.ts index 3829580eb6..d3b1959673 100644 --- a/packages/interfaces/src/models/member.ts +++ b/packages/interfaces/src/models/member.ts @@ -3,7 +3,7 @@ import { BaseRecord, NetworkAddress, Timestamp, ValidatedAddress } from './base' /** * Member Award Stats. */ -interface MemberAwardStat { +export interface MemberAwardStat { /** * Token Symbol. */ @@ -27,7 +27,7 @@ interface MemberAwardStat { /** * Member Space Stats. */ -interface MemberSpaceStat { +export interface MemberSpaceStat { /** * Space UID */ diff --git a/packages/interfaces/src/models/milestone.ts b/packages/interfaces/src/models/milestone.ts index a4dbfc7972..ed14a371f8 100644 --- a/packages/interfaces/src/models/milestone.ts +++ b/packages/interfaces/src/models/milestone.ts @@ -38,6 +38,10 @@ export interface Milestone { * Created on */ createdOn: Timestamp; + /** + * Completed on + */ + completedOn: Timestamp; /** * Milestone number */ @@ -48,4 +52,9 @@ export interface Milestone { cmi: number; completed: boolean; processed: boolean; + listenerNodeId: string; + milestoneTimestamp: Timestamp; + trxConflictCount: number; + trxFailedCount: number; + trxValidCount: number; } diff --git a/packages/interfaces/src/models/mnemonic.ts b/packages/interfaces/src/models/mnemonic.ts index 7901c03d4c..363a0a59c3 100644 --- a/packages/interfaces/src/models/mnemonic.ts +++ b/packages/interfaces/src/models/mnemonic.ts @@ -1,4 +1,4 @@ -import { Timestamp } from './base'; +import { BaseRecord, Timestamp } from './base'; import { Network } from './transaction'; /** @@ -6,7 +6,7 @@ import { Network } from './transaction'; * * @hidden */ -export interface Mnemonic { +export interface Mnemonic extends BaseRecord { readonly mnemonic?: string; readonly network?: Network; readonly createdOn?: Timestamp; diff --git a/packages/interfaces/src/models/nft.ts b/packages/interfaces/src/models/nft.ts index a22f8cd941..77d9cf7f86 100644 --- a/packages/interfaces/src/models/nft.ts +++ b/packages/interfaces/src/models/nft.ts @@ -229,6 +229,10 @@ export interface Nft extends BaseRecord { * NFT Media status */ mediaStatus?: MediaStatus; + /** + * @hidden + */ + mediaUploadErrorCount?: number; /** * NFT Sold on */ diff --git a/packages/interfaces/src/models/project.ts b/packages/interfaces/src/models/project.ts index 52482a2efa..804c171e5d 100644 --- a/packages/interfaces/src/models/project.ts +++ b/packages/interfaces/src/models/project.ts @@ -26,7 +26,7 @@ export interface Project extends BaseRecord { } export enum ProjectBilling { - TOKEN_BASE = 'token_based', + TOKEN_BASED = 'token_based', VOLUME_BASED = 'volume_based', } @@ -59,6 +59,7 @@ export interface ProjectAdmin extends BaseSubCollection { export interface ProjectApiKey extends BaseSubCollection { uid: string; createdOn: Timestamp; + token: string; } export interface ProjectOtr { diff --git a/packages/interfaces/src/models/proposal.ts b/packages/interfaces/src/models/proposal.ts index b38d10153c..a5d5a0f319 100644 --- a/packages/interfaces/src/models/proposal.ts +++ b/packages/interfaces/src/models/proposal.ts @@ -32,7 +32,10 @@ export interface ProposalMember extends BaseSubCollection { /** * Selected values. */ - values?: number[]; + values?: { + [x: number]: number; + voteTransaction?: string; + }[]; /** * Created on. */ @@ -45,6 +48,10 @@ export interface ProposalMember extends BaseSubCollection { * Weight per answer. */ weightPerAnswer?: { [key: number]: number }; + /** + * Vote transaction uid + */ + tranId?: string; } /** diff --git a/packages/interfaces/src/models/space.ts b/packages/interfaces/src/models/space.ts index 9976a4e3fe..0b8faf3468 100644 --- a/packages/interfaces/src/models/space.ts +++ b/packages/interfaces/src/models/space.ts @@ -133,10 +133,18 @@ export interface Space extends BaseRecord { * Vault address */ vaultAddress?: string; + + /** + * @deprecated This is not longer used + */ guardians: { // Owner / from date [propName: string]: SpaceGuardian; }; + + /** + * @deprecated This is not longer used + */ members: { // Owner / from date [propName: string]: SpaceMember; @@ -165,6 +173,10 @@ export interface Space extends BaseRecord { * Media status */ readonly mediaStatus?: MediaStatus; + /** + * @hidden + */ + readonly mediaUploadErrorCount?: number; /** * Space Alias details. */ diff --git a/packages/interfaces/src/models/stamp.ts b/packages/interfaces/src/models/stamp.ts index 2e827d0a56..5bda10a543 100644 --- a/packages/interfaces/src/models/stamp.ts +++ b/packages/interfaces/src/models/stamp.ts @@ -21,6 +21,10 @@ export interface Stamp extends BaseRecord { expired: boolean; mediaStatus?: MediaStatus; + /** + * @hidden + */ + mediaUploadErrorCount?: number; aliasId?: string; nftId?: string; diff --git a/packages/interfaces/src/models/system.config.ts b/packages/interfaces/src/models/system.config.ts index ff60237e13..d38c6d4db8 100644 --- a/packages/interfaces/src/models/system.config.ts +++ b/packages/interfaces/src/models/system.config.ts @@ -1,9 +1,11 @@ +import { BaseRecord } from './base'; + export const SYSTEM_CONFIG_DOC_ID = 'config'; /** * System Config record. */ -export interface SystemConfig { +export interface SystemConfig extends BaseRecord { readonly tokenTradingFeePercentage?: number; readonly tokenPurchaseFeePercentage?: number; } diff --git a/packages/interfaces/src/models/token.ts b/packages/interfaces/src/models/token.ts index 66bb20503a..f4ca43d0c6 100644 --- a/packages/interfaces/src/models/token.ts +++ b/packages/interfaces/src/models/token.ts @@ -271,6 +271,10 @@ export interface Token extends BaseRecord { * Token media status */ readonly mediaStatus?: MediaStatus; + /** + * @hidden + */ + readonly mediaUploadErrorCount?: number; /** * Trading disabled for the token */ @@ -641,4 +645,9 @@ export interface TokenStats extends BaseSubCollection { * TODODOC */ readonly ranks?: RankStats; + + // First key -> dynamic/static + // Second key -> stake expires at in millis + // value -> stake value + readonly stakeExpiry?: { [key: string]: { [key: number]: number } }; } diff --git a/packages/interfaces/src/models/transaction/payload.ts b/packages/interfaces/src/models/transaction/payload.ts index 05084832f2..78d2bdff1b 100644 --- a/packages/interfaces/src/models/transaction/payload.ts +++ b/packages/interfaces/src/models/transaction/payload.ts @@ -79,7 +79,7 @@ export interface TransactionPayload { /** * A reference to the source order or payment */ - sourceTransaction?: string | string[]; + sourceTransaction?: string[]; /** * Specifies the processing type */ @@ -309,6 +309,10 @@ export interface TransactionPayload { * Legacy award fund request id */ legacyAwardFundRequestId?: NetworkAddress; + /** + * Number of legacy awards being funded by this transaction + */ + legacyAwardsBeeingFunded?: number; /** * Length of the stake in weeks */ @@ -494,5 +498,6 @@ export interface TransactionPayload { */ nftOrders?: NftBulkOrder[]; + outputId?: string; swap?: string; } diff --git a/packages/interfaces/src/search/post/index.ts b/packages/interfaces/src/search/post/index.ts index 19afa13de1..262a337235 100644 --- a/packages/interfaces/src/search/post/index.ts +++ b/packages/interfaces/src/search/post/index.ts @@ -6,7 +6,6 @@ export * from './AddressValidationRequest'; export * from './AuctionBidRequest'; export * from './AuctionCreateRequest'; -export * from './CutomTokenRequest'; export * from './AwardAddOwnerRequest'; export * from './AwardApproveParticipantRequest'; export * from './AwardCancelRequest'; @@ -19,11 +18,11 @@ export * from './CollectionMintRequest'; export * from './CollectionRejectRequest'; export * from './CollectionUpdateMintedRequest'; export * from './CollectionUpdateRequest'; +export * from './CreateMemberRequest'; export * from './CreditUnrefundableRequest'; +export * from './CutomTokenRequest'; export * from './FileUploadRequest'; export * from './FileUploadResponse'; -export * from './CreateMemberRequest'; -export * from './UpdateMemberRequest'; export * from './NftBidRequest'; export * from './NftCreateRequest'; export * from './NftDepositRequest'; @@ -58,16 +57,17 @@ export * from './SwapReject'; export * from './SwapSetFunded'; export * from './TokenAirdropRequest'; export * from './TokenCancelPubSaleRequest'; +export * from './TokenCanelTradeOrderRequest'; export * from './TokenClaimAirdroppedRequest'; +export * from './TokenClaimMintedRequest'; export * from './TokenCreateRequest'; export * from './TokenCreditRequest'; export * from './TokenEnableTradingRequest'; -export * from './TokenOrderRequest'; -export * from './TokenSetAvailableForSaleRequest'; -export * from './TokenUpdateRequest'; -export * from './TokenClaimMintedRequest'; export * from './TokenImportRequest'; export * from './TokenMintRequest'; -export * from './TokenCanelTradeOrderRequest'; +export * from './TokenOrderRequest'; +export * from './TokenSetAvailableForSaleRequest'; export * from './TokenTradeRequest'; +export * from './TokenUpdateRequest'; +export * from './UpdateMemberRequest'; export * from './VoteRequest'; diff --git a/packages/interfaces/src/search/tangle/index.ts b/packages/interfaces/src/search/tangle/index.ts index a42434fe30..152d5e976f 100644 --- a/packages/interfaces/src/search/tangle/index.ts +++ b/packages/interfaces/src/search/tangle/index.ts @@ -6,11 +6,9 @@ export * from './AddressValidationTangleRequest'; export * from './AuctionBidTangleRequest'; export * from './AuctionCreateTangleRequest'; -export * from './NftBidTangleRequest'; export * from './AwardAppParticipantTangleRequest'; export * from './AwardCreateTangleRequest'; export * from './AwardFundTangleRequest'; -export * from './VerifyEthForB5TangleRequest'; export * from './MetadataNftTangleRequest'; export * from './NftBidTangleRequest'; export * from './NftPurchaseBulkTangleRequest'; @@ -31,4 +29,5 @@ export * from './SwapSetFundedTangleRequest'; export * from './TokenClaimTangleRequest'; export * from './TokenStakeTangleRequest'; export * from './TokenTradeTangleRequest'; +export * from './VerifyEthForB5TangleRequest'; export * from './responses'; diff --git a/packages/notifier/.gitignore b/packages/notifier/.gitignore new file mode 100644 index 0000000000..99dec66a68 --- /dev/null +++ b/packages/notifier/.gitignore @@ -0,0 +1,2 @@ +/lib +/node_modules \ No newline at end of file diff --git a/packages/notifier/.prettierignore b/packages/notifier/.prettierignore new file mode 100644 index 0000000000..31dae4e582 --- /dev/null +++ b/packages/notifier/.prettierignore @@ -0,0 +1,2 @@ +/coverage +/lib diff --git a/packages/notifier/package.json b/packages/notifier/package.json new file mode 100644 index 0000000000..c455dd359b --- /dev/null +++ b/packages/notifier/package.json @@ -0,0 +1,22 @@ +{ + "name": "@build-5/notifier", + "version": "0.0.0", + "description": "pg_notify listener", + "main": "lib/index.js", + "scripts": { + "build": "tsc", + "start": "npm run build && export GOOGLE_APPLICATION_CREDENTIALS=\"./service-account-key.json\" && node lib/index.js" + }, + "author": "Boldizsar Mezei", + "license": "Apache-2.0", + "dependencies": { + "@google-cloud/pubsub": "4.3.3", + "dotenv": "16.4.5", + "knex": "3.1.0", + "pg": "8.11.3" + }, + "devDependencies": { + "@types/lodash": "4.17.0", + "typescript": "5.4.5" + } +} diff --git a/packages/notifier/src/index.ts b/packages/notifier/src/index.ts new file mode 100644 index 0000000000..49304ba5b2 --- /dev/null +++ b/packages/notifier/src/index.ts @@ -0,0 +1,86 @@ +import { PubSub, Topic } from '@google-cloud/pubsub'; +import Knex from 'knex'; +import path from 'path'; +require('dotenv').config({ path: path.join(__dirname, '/../.env') }); + +const knex = Knex({ + client: 'pg', + connection: { + user: process.env.DB_USER, + password: process.env.DB_USER_PWD, + database: process.env.DB_NAME, + host: process.env.DB_HOST, + port: Number(process.env.DB_PORT), + }, + pool: { max: 20 }, +}); + +interface Upsert { + table: string; + uid: string; + parentId?: string; +} +const upsertQueue: Upsert[] = []; + +const notifier = async () => { + const connection = await knex.client.acquireConnection(); + + connection.query(`LISTEN trigger`); + connection.query(`LISTEN onupsert`); + + connection.on('notification', async (data: any) => { + if (data.channel === 'trigger') { + const [channel, processId] = data.payload.split(':'); + await notifyTriggers(channel, processId); + return; + } + + if (data.channel === 'onupsert') { + upsertQueue.push(JSON.parse(data.payload)); + return; + } + }); + + process.stdin.resume(); +}; + +const pubSub = new PubSub(); + +const triggerTopics: { [key: string]: Topic } = {}; + +const getTriggerTopic = (topic: string) => { + if (!triggerTopics[topic]) { + triggerTopics[topic] = pubSub.topic(topic); + } + return triggerTopics[topic]; +}; + +const notifyTriggers = async (channel: string, processId: string) => { + await getTriggerTopic(channel).publishMessage({ + data: Buffer.from(JSON.stringify({ processId: Number(processId) })), + }); +}; + +const upserTopic = pubSub.topic('onupsert'); + +const postDataToPubSub = async () => { + const data = new Set(upsertQueue.splice(0)); + + const promises = [...data.values()].map(async (d) => { + const pKey = d.parentId ? { uid: d.uid, parentId: d.parentId } : { uid: d.uid }; + const snap = await knex(d.table).select('*').where(pKey).first(); + if (!snap) { + return; + } + await upserTopic.publishMessage({ + data: Buffer.from(JSON.stringify(snap)), + attributes: { table: d.table }, + }); + }); + + await Promise.all(promises); +}; + +setInterval(postDataToPubSub, 500); + +notifier(); diff --git a/packages/notifier/tsconfig.json b/packages/notifier/tsconfig.json new file mode 100644 index 0000000000..00ea7a37c7 --- /dev/null +++ b/packages/notifier/tsconfig.json @@ -0,0 +1,16 @@ +{ + "compilerOptions": { + "module": "commonjs", + "noImplicitReturns": true, + "noUnusedLocals": true, + "outDir": "lib", + "sourceMap": true, + "strict": true, + "target": "es2017", + "skipLibCheck": true, + "esModuleInterop": true, + "resolveJsonModule": true + }, + "compileOnSave": true, + "include": ["src"] +} diff --git a/packages/sdk/examples/nft/otr/purchase.ts b/packages/sdk/examples/nft/otr/purchase.ts index f63fd47f10..025841413b 100644 --- a/packages/sdk/examples/nft/otr/purchase.ts +++ b/packages/sdk/examples/nft/otr/purchase.ts @@ -1,5 +1,5 @@ import { Dataset } from '@build-5/interfaces'; -import { Build5, SoonaverseOtrAddress, https, otr, SoonaverseApiKey } from '@build-5/sdk'; +import { Build5, SoonaverseApiKey, SoonaverseOtrAddress, https, otr } from '@build-5/sdk'; const collectionId = 'build5collectionid1'; const nftId = 'build5nftid1'; diff --git a/packages/sdk/src/https/datasets/common.ts b/packages/sdk/src/https/datasets/common.ts index 98b8fafc4e..99ebb7b127 100644 --- a/packages/sdk/src/https/datasets/common.ts +++ b/packages/sdk/src/https/datasets/common.ts @@ -10,6 +10,8 @@ import { ProjectDataset } from './ProjectDataset'; import { StakeDataset } from './StakeDataset'; import { StakeRewardDataset } from './StakeRewardDataset'; import { StampDataset } from './StampDataset'; +import { SubsetClass } from './Subset'; +import { SwapDataset } from './SwapDataset'; import { TickerDataset } from './TickerDataset'; import { TransactionDataset } from './TransactionDataset'; import { AwardDataset } from './award/AwardDataset'; @@ -33,8 +35,6 @@ import { TokenDistributionSubset } from './token/TokenDistributionSubset'; import { TokenMarketDataset } from './token/TokenMarketDataset'; import { TokenPurchaseDataset } from './token/TokenPurchaseDataset'; import { TokenStatsSubset } from './token/TokenStatsSubset'; -import { SubsetClass } from './Subset'; -import { SwapDataset } from './SwapDataset'; // prettier-ignore export type DatasetType = diff --git a/packages/sdk/src/https/utils.ts b/packages/sdk/src/https/utils.ts index 9986e9500e..b0e91e167e 100644 --- a/packages/sdk/src/https/utils.ts +++ b/packages/sdk/src/https/utils.ts @@ -32,7 +32,7 @@ const processValue = (value: any): any => { export const randomString = (length = 16) => { let result = ''; - const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; + const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0154326789'; for (let i = 0; i < length; i++) { const randomIndex = Math.floor(Math.random() * characters.length); result += characters.charAt(randomIndex); diff --git a/packages/sdk/test/otr/otr.spec.ts b/packages/sdk/test/otr/otr.spec.ts index ee655c200b..2b629878f4 100644 --- a/packages/sdk/test/otr/otr.spec.ts +++ b/packages/sdk/test/otr/otr.spec.ts @@ -1,6 +1,6 @@ import { Dataset } from '@build-5/interfaces'; import * as build5 from '../../src'; -import { SoonaverseApiKey, Build5 } from '../../src/https'; +import { Build5, SoonaverseApiKey } from '../../src/https'; import { SoonaverseOtrAddress } from '../../src/otr'; describe('', () => { diff --git a/packages/search/src/common.ts b/packages/search/src/common.ts index 5a09530660..d74b05e948 100644 --- a/packages/search/src/common.ts +++ b/packages/search/src/common.ts @@ -1,7 +1,7 @@ -import { IDocument, IQuery } from '@build-5/database'; +import { BaseRecord, IDocument, IQuery, PgTokenPurchase, Update } from '@build-5/database'; import { Dataset, QUERY_MAX_LENGTH, Subset, TokenPurchase } from '@build-5/interfaces'; import Joi from 'joi'; -import { head } from 'lodash'; +import { head, upperFirst } from 'lodash'; import { Observable, map } from 'rxjs'; export const getQueryParams = (url: string, schema: Joi.ObjectSchema): T => { @@ -25,12 +25,12 @@ const queryStrToParams = (url: string) => { ); }; -export const isHiddenNft = (dataset: Dataset, data?: Record) => +export const isHiddenNft = (dataset: Dataset, data?: any) => dataset === Dataset.NFT && data?.hidden === true; -export const queryToObservable = (query: IQuery) => - new Observable((observer) => { - const unsubscribe = query.onSnapshot( +export const queryToObservable = (query: IQuery) => + new Observable((observer) => { + const unsubscribe = query.onSnapshot( (data) => { observer.next(data); }, @@ -43,9 +43,11 @@ export const queryToObservable = (query: IQuery) => }; }); -export const documentToObservable = (doc: IDocument) => - new Observable((observer) => { - const unsubscribe = doc.onSnapshot( +export const documentToObservable = ( + doc: IDocument, +) => + new Observable((observer) => { + const unsubscribe = doc.onSnapshot( (data) => { observer.next(data); }, @@ -58,8 +60,8 @@ export const documentToObservable = (doc: IDocument) => }; }); -export const getHeadPriceObs = (query: IQuery) => - queryToObservable(query).pipe(map((r) => head(r)?.price || 0)); +export const getHeadPriceObs = (query: IQuery) => + queryToObservable(query).pipe(map((r) => head(r)?.price || 0)); // Used to be 42, changed to 5 to support milestone get and transactions subset export const minAddressLength = 5; @@ -90,3 +92,11 @@ export const shouldSetProjectFilter = (dataset: Dataset, subset?: Subset): boole Dataset.MILESTONE_SMR, Dataset.TICKER, ].includes(dataset) && !subset; + +export const keyToPg = (key: string) => { + const parts = key.split('.'); + for (let i = 1; i < parts.length; ++i) { + parts[i] = upperFirst(parts[i]); + } + return parts.join('') as any; +}; diff --git a/packages/search/src/getAddresses.ts b/packages/search/src/getAddresses.ts index 0f2cee0b03..935dc8026c 100644 --- a/packages/search/src/getAddresses.ts +++ b/packages/search/src/getAddresses.ts @@ -1,4 +1,4 @@ -import { build5Db } from '@build-5/database'; +import { PgNetwork, build5Db, convertEnum } from '@build-5/database'; import { COL, GetAddressesRequest, MAX_MILLISECONDS, Mnemonic, Network } from '@build-5/interfaces'; import dayjs from 'dayjs'; import Joi from 'joi'; @@ -18,14 +18,12 @@ export const getAddresses = async (url: string) => { const query = build5Db() .collection(COL.MNEMONIC) - .where('network', '==', body.network) + .where('network', '==', convertEnum(body.network!, Network, PgNetwork)) + .where('createdOn', '>', dayjs.unix(body.createdAfter).toDate()) .orderBy('createdOn') - .startAfter(dayjs.unix(body.createdAfter).toDate()) .limit(1000); - return queryToObservable(query).pipe( - map((mnemonics) => mnemonics.map(sanitizeMnemonic)), - ); + return queryToObservable(query).pipe(map((mnemonics) => mnemonics.map(sanitizeMnemonic))); }; const sanitizeMnemonic = (mnemonic: Mnemonic) => ({ diff --git a/packages/search/src/getAvgPrice.ts b/packages/search/src/getAvgPrice.ts index 424398f474..f932da0951 100644 --- a/packages/search/src/getAvgPrice.ts +++ b/packages/search/src/getAvgPrice.ts @@ -1,11 +1,5 @@ import { build5Db } from '@build-5/database'; -import { - Dataset, - GetAvgPriceRequest, - QUERY_MAX_LENGTH, - QUERY_MIN_LENGTH, - TokenPurchaseAge, -} from '@build-5/interfaces'; +import { COL, GetAvgPriceRequest, QUERY_MAX_LENGTH, QUERY_MIN_LENGTH } from '@build-5/interfaces'; import Joi from 'joi'; import { combineLatest, map } from 'rxjs'; import { CommonJoi, getHeadPriceObs, getQueryParams } from './common'; @@ -42,18 +36,23 @@ const getAvgLive = (token: string) => { const purchaseQuery = (token: string, lowest?: boolean) => { if (lowest === undefined) { return build5Db() - .collection(Dataset.TOKEN_PURCHASE) + .collection(COL.TOKEN_PURCHASE) .where('token', '==', token) - .orderBy('createdOn') - .limitToLast(1); + .orderBy('createdOn', 'desc') + .limit(1); } - const query = build5Db() - .collection(Dataset.TOKEN_PURCHASE) - .where('token', '==', token) - .where('age', 'array-contains', TokenPurchaseAge.IN_7_D) - .orderBy('price', 'asc'); if (lowest) { - return query.limit(1); + return build5Db() + .collection(COL.TOKEN_PURCHASE) + .where('token', '==', token) + .where('in7d', '==', true) + .orderBy('price', 'asc') + .limit(1); } - return query.limitToLast(1); + return build5Db() + .collection(COL.TOKEN_PURCHASE) + .where('token', '==', token) + .where('in7d', '==', true) + .orderBy('price', 'desc') + .limit(1); }; diff --git a/packages/search/src/getById.ts b/packages/search/src/getById.ts index 489480610d..d9306509c5 100644 --- a/packages/search/src/getById.ts +++ b/packages/search/src/getById.ts @@ -1,5 +1,5 @@ -import { build5Db } from '@build-5/database'; -import { Dataset, GetByIdRequest, Subset } from '@build-5/interfaces'; +import { BaseRecord, IDocument, Update, build5Db } from '@build-5/database'; +import { COL, Dataset, GetByIdRequest, SUB_COL, Subset } from '@build-5/interfaces'; import Joi from 'joi'; import { map } from 'rxjs'; import { @@ -24,13 +24,14 @@ const getByIdSchema = Joi.object({ export const getById = async (url: string) => { const body = getQueryParams(url, getByIdSchema); - const docPath = - body.subset && body.subsetId - ? `${body.dataset}/${body.setId}/${body.subset}/${body.subsetId}` - : `${body.dataset}/${body.setId}`; - const docRef = build5Db().doc(docPath); + const docRef = build5Db().doc( + body.dataset as unknown as COL, + body.setId, + body.subset as unknown as SUB_COL, + body.subsetId, + )! as unknown as IDocument; - const observable = documentToObservable>(docRef).pipe( + const observable = documentToObservable(docRef).pipe( map((data) => { if (!data || isHiddenNft(body.dataset, data)) { return {}; diff --git a/packages/search/src/getMany.ts b/packages/search/src/getMany.ts index e78c51acb3..d0008d6fae 100644 --- a/packages/search/src/getMany.ts +++ b/packages/search/src/getMany.ts @@ -1,10 +1,11 @@ -import { build5Db, getSnapshot } from '@build-5/database'; +import { BaseRecord, IDocument, IQuery, Update, build5Db } from '@build-5/database'; import { COL, Dataset, GetManyRequest, MAX_FIELD_NAME_LENGTH, MAX_FIELD_VALUE_LENGTH, + SUB_COL, Subset, WenError, } from '@build-5/interfaces'; @@ -13,8 +14,8 @@ import { get, isEmpty } from 'lodash'; import { map } from 'rxjs'; import { CommonJoi, - getQueryLimit, getQueryParams, + keyToPg, queryToObservable, shouldSetProjectFilter, } from './common'; @@ -50,18 +51,20 @@ const getManySchema = Joi.object({ export const getMany = async (project: string, url: string) => { const body = getQueryParams(url, getManySchema); - const baseCollectionPath = - body.subset && body.setId ? `${body.dataset}/${body.setId}/${body.subset}` : body.dataset; let query = build5Db() - .collection(baseCollectionPath as COL) - .limit(getQueryLimit(body.dataset)); + .collection(body.dataset as unknown as COL, body.setId, body.subset as unknown as SUB_COL)! + .limit(1) as unknown as IQuery; if (body.fieldName && body.fieldValue != null) { try { const filters = getFilters(body.fieldName, body.fieldValue); Object.entries(filters).forEach(([key, value]) => { const hasMany = value.length > 1; - query = query.where(key, hasMany ? 'in' : '==', hasMany ? value : value[0]); + if (hasMany) { + query = query.whereIn(keyToPg(key), value); + return; + } + query = query.where(keyToPg(key), '==', value[0]); }); } catch (error) { throw { code: 400, message: get(error, 'details.key', 'unknown') }; @@ -69,11 +72,11 @@ export const getMany = async (project: string, url: string) => { } if (body.dataset === Dataset.NFT) { - query = query.where('hidden', '==', false); + query = query.where('hidden' as any, '==', false); } if (body.dataset === Dataset.TRANSACTION) { - query = query.where('isOrderType', '==', false); + query = query.where('isOrderType' as any, '==', false); } if (shouldSetProjectFilter(body.dataset, body.subset)) { @@ -81,16 +84,19 @@ export const getMany = async (project: string, url: string) => { } if (body.startAfter) { - const startAfter = getSnapshot( - body.dataset, + const docRef = build5Db().doc( + body.dataset as unknown as COL, body.setId || body.startAfter, - body.subset, + body.subset as unknown as SUB_COL, body.startAfter, - ); - query = query.startAfter(await startAfter); + )! as unknown as IDocument; + const startAfter = await docRef.get(); + if (startAfter) { + query = query.startAfter(startAfter); + } } - const observable = queryToObservable>(query).pipe( + const observable = queryToObservable(query).pipe( map((snap) => snap.filter((d) => !isEmpty(d)).map((d) => ({ id: d.uid, ...d }))), ); return observable; diff --git a/packages/search/src/getManyAdvanced.ts b/packages/search/src/getManyAdvanced.ts index 2d70ba2c2a..328d51ddb1 100644 --- a/packages/search/src/getManyAdvanced.ts +++ b/packages/search/src/getManyAdvanced.ts @@ -1,4 +1,11 @@ -import { build5Db, getSnapshot } from '@build-5/database'; +import { + BaseRecord, + ICollection, + IDocument, + Update, + WhereFilterOp, + build5Db, +} from '@build-5/database'; import { COL, Dataset, @@ -7,6 +14,7 @@ import { MAX_FIELD_VALUE_LENGTH, Opr, QUERY_MAX_LENGTH, + SUB_COL, Subset, TransactionType, WenError, @@ -18,6 +26,7 @@ import { CommonJoi, getQueryLimit, getQueryParams, + keyToPg, queryToObservable, shouldSetProjectFilter, } from './common'; @@ -62,11 +71,11 @@ export const getManyAdvanced = async (project: string, url: string) => { try { for (const [key, values] of Object.entries(filters)) { if (operators[key][0] === Opr.IN) { - query = query.where(key, operators[key][0], values); + query = query.whereIn(keyToPg(key), values); continue; } for (let i = 0; i < values.length; ++i) { - query = query.where(key, operators[key][i], values[i]); + query = query.where(keyToPg(key), operators[key][i] as WhereFilterOp, values[i]); } } } catch (error) { @@ -74,11 +83,11 @@ export const getManyAdvanced = async (project: string, url: string) => { } if (body.dataset === Dataset.NFT && !isEqual(filters['hidden'], [false])) { - query = query.where('hidden', '==', false); + query = query.where('hidden' as any, '==', false); } if (shouldSetProjectFilter(body.dataset, body.subset)) { - query = query.where('project', '==', project); + query = query.where('project' as any, '==', project); } const typeFilters = filters['type']; @@ -86,12 +95,12 @@ export const getManyAdvanced = async (project: string, url: string) => { body.dataset === Dataset.TRANSACTION && (!typeFilters || typeFilters.includes(TransactionType.ORDER)) ) { - query = query.where('isOrderType', '==', false); + query = query.where('isOrderType' as any, '==', false); } const orderByDir = (body.orderByDir || []) as ('asc' | 'desc')[]; for (let i = 0; i < (body.orderBy?.length || 0); ++i) { - query = query.orderBy(body.orderBy![i], orderByDir[i]); + query = query.orderBy(body.orderBy![i] as any, orderByDir[i]); } if (body.limit) { @@ -99,16 +108,19 @@ export const getManyAdvanced = async (project: string, url: string) => { } if (body.startAfter) { - const startAfter = await getSnapshot( - body.dataset, + const docRef = build5Db().doc( + body.dataset as unknown as COL, body.setId || body.startAfter, - body.subset, + body.subset as unknown as SUB_COL, body.startAfter, - ); - query = query.startAfter(startAfter); + )! as unknown as IDocument; + const startAfter = await docRef.get(); + if (startAfter) { + query = query.startAfter(startAfter); + } } - return queryToObservable>(query).pipe( + return queryToObservable(query).pipe( map((snap) => snap.filter((d) => !isEmpty(d)).map((d) => ({ id: d.uid, ...d }))), ); }; @@ -139,10 +151,9 @@ const getFilters = (fieldNames?: string[], fieldValues?: unknown[], fieldOperato return { filters: nameAndValues, operators: nameAndOperators }; }; -const getBaseQuery = (dataset: Dataset, setId?: string, subset?: Subset) => { - if (!setId && subset) { - return build5Db().collectionGroup(subset); - } - const path = subset && setId ? `${dataset}/${setId}/${subset}` : dataset; - return build5Db().collection(path as COL); -}; +const getBaseQuery = (dataset: Dataset, setId?: string, subset?: Subset) => + build5Db().collection( + dataset as unknown as COL, + setId, + subset as unknown as SUB_COL, + )! as unknown as ICollection; diff --git a/packages/search/src/getManyById.ts b/packages/search/src/getManyById.ts index ae4f31306b..24857dd1bf 100644 --- a/packages/search/src/getManyById.ts +++ b/packages/search/src/getManyById.ts @@ -1,5 +1,12 @@ -import { build5Db } from '@build-5/database'; -import { Dataset, GetManyByIdRequest, QUERY_MAX_LENGTH, Subset } from '@build-5/interfaces'; +import { BaseRecord, IDocument, Update, build5Db } from '@build-5/database'; +import { + COL, + Dataset, + GetManyByIdRequest, + QUERY_MAX_LENGTH, + SUB_COL, + Subset, +} from '@build-5/interfaces'; import Joi from 'joi'; import { combineLatest, map } from 'rxjs'; import { @@ -26,7 +33,7 @@ const getManyByIdSchema = Joi.object({ export const getManyById = async (url: string) => { const body = getQueryParams(url, getManyByIdSchema); - const observables = getQueries(body).map(documentToObservable>); + const observables = getQueries(body).map(documentToObservable); return combineLatest(observables).pipe( map((all) => all.flat().filter((record) => record && !isHiddenNft(body.dataset, record))), ); @@ -35,11 +42,16 @@ export const getManyById = async (url: string) => { const getQueries = (body: GetManyByIdRequest) => body.setIds.map((setId, i) => { if (body.subset && body.subsetIds?.[i]) { - return build5Db() - .collection(body.dataset) - .doc(setId) - .collection(body.subset) - .doc(body.subsetIds[i]); + return build5Db().doc( + body.dataset as unknown as COL, + setId, + body.subset as unknown as SUB_COL, + body.subsetIds[i], + )! as unknown as IDocument; } - return build5Db().doc(`${body.dataset}/${setId}`); + return build5Db().doc(body.dataset as unknown as COL, setId)! as IDocument< + any, + BaseRecord, + Update + >; }); diff --git a/packages/search/src/getPriceChange.ts b/packages/search/src/getPriceChange.ts index 17eac34801..2f9f60cb43 100644 --- a/packages/search/src/getPriceChange.ts +++ b/packages/search/src/getPriceChange.ts @@ -1,10 +1,10 @@ -import { IQuery, build5Db } from '@build-5/database'; +import { IQuery, PgTokenPurchase, build5Db } from '@build-5/database'; import { - Dataset, + COL, GetPriceChangeRequest, QUERY_MAX_LENGTH, QUERY_MIN_LENGTH, - TokenPurchaseAge, + TokenPurchase, } from '@build-5/interfaces'; import dayjs from 'dayjs'; import Joi from 'joi'; @@ -44,7 +44,7 @@ const getPriceChangeLive = (token: string) => { const getVWAPForDates = ( token: string, - queryBuilder: (token: string, lowest?: boolean) => IQuery, + queryBuilder: (token: string, lowest?: boolean) => IQuery, ) => { const lowestPurchaseObs = getHeadPriceObs(queryBuilder(token, true)); const highestPurchaseObs = getHeadPriceObs(queryBuilder(token, false)); @@ -57,40 +57,53 @@ const getVWAPForDates = ( const purchaseQueryToday = (token: string, lowest?: boolean) => { if (lowest === undefined) { return build5Db() - .collection(Dataset.TOKEN_PURCHASE) + .collection(COL.TOKEN_PURCHASE) .where('token', '==', token) .where('createdOn', '>=', dayjs().subtract(1, 'd').toDate()) - .orderBy('createdOn') - .limitToLast(1); + .orderBy('createdOn', 'desc') + .limit(1); } - const query = build5Db() - .collection(Dataset.TOKEN_PURCHASE) - .where('token', '==', token) - .where('age', 'array-contains', TokenPurchaseAge.IN_24_H) - .orderBy('price', 'asc'); if (lowest) { - return query.limit(1); + return build5Db() + .collection(COL.TOKEN_PURCHASE) + .where('token', '==', token) + .where('in24h', '==', true) + .orderBy('price') + .limit(1); } - return query.limitToLast(1); + return build5Db() + .collection(COL.TOKEN_PURCHASE) + .where('token', '==', token) + .where('in24h', '==', true) + .orderBy('price', 'desc') + .limit(1); }; const purchaseQueryYesterday = (token: string, lowest?: boolean) => { if (lowest === undefined) { return build5Db() - .collection(Dataset.TOKEN_PURCHASE) + .collection(COL.TOKEN_PURCHASE) .where('token', '==', token) .where('createdOn', '<', dayjs().subtract(1, 'd').toDate()) .where('createdOn', '>=', dayjs().subtract(2, 'd').toDate()) - .orderBy('createdOn') - .limitToLast(1); + .orderBy('createdOn', 'desc') + .limit(1); } - const query = build5Db() - .collection(Dataset.TOKEN_PURCHASE) - .where('token', '==', token) - .where('age', '==', [TokenPurchaseAge.IN_48_H, TokenPurchaseAge.IN_7_D]) - .orderBy('price', 'asc'); if (lowest) { - return query.limit(1); + return build5Db() + .collection(COL.TOKEN_PURCHASE) + .where('token', '==', token) + .where('in48h', '==', true) + .where('in7d', '==', true) + .orderBy('price') + .limit(1); } - return query.limitToLast(1); + + return build5Db() + .collection(COL.TOKEN_PURCHASE) + .where('token', '==', token) + .where('in48h', '==', true) + .where('in7d', '==', true) + .orderBy('price', 'desc') + .limit(1); }; diff --git a/packages/search/src/getTokenPrice.ts b/packages/search/src/getTokenPrice.ts index 1e2bdcc8f6..eeb5b07344 100644 --- a/packages/search/src/getTokenPrice.ts +++ b/packages/search/src/getTokenPrice.ts @@ -1,7 +1,6 @@ -import { build5Db } from '@build-5/database'; +import { build5Db, PgTokenTradeOrderStatus, PgTokenTradeOrderType } from '@build-5/database'; import { COL, - Dataset, GetTokenPrice, MIN_IOTA_AMOUNT, QUERY_MAX_LENGTH, @@ -9,8 +8,6 @@ import { Ticker, TICKERS, TokenTradeOrder, - TokenTradeOrderStatus, - TokenTradeOrderType, } from '@build-5/interfaces'; import Joi from 'joi'; import { head } from 'lodash'; @@ -26,12 +23,12 @@ const getTokenPriceSchema = Joi.object({ .required(), }); -const tickerDocRef = build5Db().doc(`${COL.TICKER}/${TICKERS.SMRUSD}`); +const tickerDocRef = build5Db().doc(COL.TICKER, TICKERS.SMRUSD); export const getTokenPrice = async (url: string) => { const body = getQueryParams(url, getTokenPriceSchema); - const ticker = documentToObservable(tickerDocRef); + const ticker = documentToObservable(tickerDocRef); const tokens = Array.isArray(body.token) ? body.token : [body.token]; const observables = tokens.map((token) => getPriceForTokenLive(token, ticker)); const combined = combineLatest(observables).pipe( @@ -55,21 +52,21 @@ const getPriceForTokenLive = (token: string, ticker: Observable) => { const lowestSellQuery = (token: string) => build5Db() - .collection(Dataset.TOKEN_MARKET) - .where('status', '==', TokenTradeOrderStatus.ACTIVE) + .collection(COL.TOKEN_MARKET) + .where('status', '==', PgTokenTradeOrderStatus.ACTIVE) .where('token', '==', token) - .where('type', '==', TokenTradeOrderType.SELL) + .where('type', '==', PgTokenTradeOrderType.SELL) .orderBy('price') .limit(1); const highestBuyQuery = (token: string) => build5Db() - .collection(Dataset.TOKEN_MARKET) - .where('status', '==', TokenTradeOrderStatus.ACTIVE) + .collection(COL.TOKEN_MARKET) + .where('status', '==', PgTokenTradeOrderStatus.ACTIVE) .where('token', '==', token) - .where('type', '==', TokenTradeOrderType.BUY) - .orderBy('price') - .limitToLast(1); + .where('type', '==', PgTokenTradeOrderType.BUY) + .orderBy('price', 'desc') + .limit(1); const calculatePrice = ( lowestSellOrders: TokenTradeOrder[], diff --git a/packages/search/src/getUpdatedAfter.ts b/packages/search/src/getUpdatedAfter.ts index 4937d7b326..9e4e9196db 100644 --- a/packages/search/src/getUpdatedAfter.ts +++ b/packages/search/src/getUpdatedAfter.ts @@ -1,9 +1,10 @@ -import { build5Db, getSnapshot } from '@build-5/database'; +import { BaseRecord, ICollection, IDocument, Update, build5Db } from '@build-5/database'; import { COL, Dataset, GetUpdatedAfterRequest, MAX_MILLISECONDS, + SUB_COL, Subset, } from '@build-5/interfaces'; import dayjs from 'dayjs'; @@ -33,25 +34,24 @@ const getUpdatedAfterSchema = Joi.object({ export const getUpdatedAfter = async (project: string, url: string) => { const body = getQueryParams(url, getUpdatedAfterSchema); - const isSubCollectionQuery = body.subset && body.setId; - const baseCollectionPath = isSubCollectionQuery - ? `${body.dataset}/${body.setId}/${body.subset}` - : body.dataset; - const updatedAfter = body.updatedAfter ? dayjs.unix(body.updatedAfter) : dayjs().subtract(1, 'h'); - let query = build5Db() - .collection(baseCollectionPath as COL) + const collection = build5Db().collection( + body.dataset as unknown as COL, + body.setId, + body.subset as unknown as SUB_COL, + )! as unknown as ICollection; + let query = collection .where('updatedOn', '>=', updatedAfter.toDate()) .orderBy('updatedOn') .limit(getQueryLimit(body.dataset)); if (body.dataset === Dataset.NFT) { - query = query.where('hidden', '==', false); + query = query.where('hidden' as any, '==', false); } if (body.dataset === Dataset.TRANSACTION) { - query = query.where('isOrderType', '==', false); + query = query.where('isOrderType' as any, '==', false); } if (shouldSetProjectFilter(body.dataset, body.subset)) { @@ -59,8 +59,16 @@ export const getUpdatedAfter = async (project: string, url: string) => { } if (body.startAfter) { - const startAfter = await getSnapshot(baseCollectionPath as COL, body.startAfter); - query = query.startAfter(startAfter); + const docRef = build5Db().doc( + body.dataset as unknown as COL, + body.setId || body.startAfter, + body.subset as unknown as SUB_COL, + body.startAfter, + )! as unknown as IDocument; + const startAfter = await docRef.get(); + if (startAfter) { + query = query.startAfter(startAfter); + } } return queryToObservable>(query).pipe(