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(