From 78fe3e1f9a8bfba213e3d58bc61514738a5ab46e Mon Sep 17 00:00:00 2001 From: David-patrick-chuks Date: Wed, 25 Mar 2026 04:27:05 +0100 Subject: [PATCH 1/2] feat(api): initialize prisma core schema --- apps/api/.env.example | 2 +- apps/api/package.json | 6 +- .../migration.sql | 66 ++++++ .../api/prisma/migrations/migration_lock.toml | 2 + apps/api/prisma/schema.prisma | 69 +++++++ apps/api/src/app.module.ts | 2 + apps/api/src/prisma/prisma.module.ts | 9 + apps/api/src/prisma/prisma.service.ts | 13 ++ pnpm-lock.yaml | 190 +++++++++++++++--- 9 files changed, 329 insertions(+), 30 deletions(-) create mode 100644 apps/api/prisma/migrations/20260325000000_init_core_schema/migration.sql create mode 100644 apps/api/prisma/migrations/migration_lock.toml create mode 100644 apps/api/prisma/schema.prisma create mode 100644 apps/api/src/prisma/prisma.module.ts create mode 100644 apps/api/src/prisma/prisma.service.ts diff --git a/apps/api/.env.example b/apps/api/.env.example index f10135c..3966e62 100644 --- a/apps/api/.env.example +++ b/apps/api/.env.example @@ -12,7 +12,7 @@ STELLAR_HORIZON_URL=https://horizon-testnet.stellar.org TREASURY_WALLET_ADDRESS=GDTREASURYADDRESSXXXXXX SUPPORTED_ASSETS=USDC,ARS -# Database (for when implemented) +# Database DATABASE_URL=postgresql://user:password@localhost:5432/stellar_pay # Redis (for when implemented) diff --git a/apps/api/package.json b/apps/api/package.json index 9605cb5..c3fa7d1 100644 --- a/apps/api/package.json +++ b/apps/api/package.json @@ -17,7 +17,9 @@ "test:watch": "jest --watch", "test:cov": "jest --coverage", "test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand", - "test:e2e": "jest --config ./test/jest-e2e.json" + "test:e2e": "jest --config ./test/jest-e2e.json", + "prisma:generate": "prisma generate", + "prisma:migrate": "prisma migrate deploy" }, "dependencies": { "@nestjs/common": "^11.0.1", @@ -26,6 +28,7 @@ "@nestjs/platform-express": "^11.0.1", "@nestjs/terminus": "^11.1.1", "@nestjs/throttler": "^6.5.0", + "@prisma/client": "^6.7.0", "@stellar/stellar-sdk": "^14.6.1", "passport": "^0.7.0", "passport-jwt": "^4.0.1", @@ -49,6 +52,7 @@ "globals": "^16.0.0", "jest": "^30.0.0", "prettier": "^3.4.2", + "prisma": "^6.7.0", "source-map-support": "^0.5.21", "supertest": "^7.0.0", "ts-jest": "^29.2.5", diff --git a/apps/api/prisma/migrations/20260325000000_init_core_schema/migration.sql b/apps/api/prisma/migrations/20260325000000_init_core_schema/migration.sql new file mode 100644 index 0000000..6683463 --- /dev/null +++ b/apps/api/prisma/migrations/20260325000000_init_core_schema/migration.sql @@ -0,0 +1,66 @@ +-- CreateEnum +CREATE TYPE "KycStatus" AS ENUM ('pending', 'approved', 'rejected'); + +-- CreateEnum +CREATE TYPE "PaymentIntentStatus" AS ENUM ('pending', 'detected', 'confirmed', 'failed'); + +-- CreateTable +CREATE TABLE "merchants" ( + "id" UUID NOT NULL, + "email" TEXT NOT NULL, + "password_hash" TEXT NOT NULL, + "kyc_status" "KycStatus" NOT NULL DEFAULT 'pending', + "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updated_at" TIMESTAMP(3) NOT NULL, + + CONSTRAINT "merchants_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "payment_intents" ( + "id" UUID NOT NULL, + "merchant_id" UUID NOT NULL, + "amount" DECIMAL(20,2) NOT NULL, + "currency" VARCHAR(3) NOT NULL, + "status" "PaymentIntentStatus" NOT NULL DEFAULT 'pending', + "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updated_at" TIMESTAMP(3) NOT NULL, + + CONSTRAINT "payment_intents_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "treasury_assets" ( + "symbol" VARCHAR(16) NOT NULL, + "total_minted" DECIMAL(30,7) NOT NULL DEFAULT 0, + "total_reserved" DECIMAL(30,7) NOT NULL DEFAULT 0, + + CONSTRAINT "treasury_assets_pkey" PRIMARY KEY ("symbol") +); + +-- CreateTable +CREATE TABLE "webhook_endpoints" ( + "id" UUID NOT NULL, + "merchant_id" UUID NOT NULL, + "url" TEXT NOT NULL, + "secret" TEXT NOT NULL, + "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updated_at" TIMESTAMP(3) NOT NULL, + + CONSTRAINT "webhook_endpoints_pkey" PRIMARY KEY ("id") +); + +-- CreateIndex +CREATE UNIQUE INDEX "merchants_email_key" ON "merchants"("email"); + +-- CreateIndex +CREATE INDEX "payment_intents_merchant_id_idx" ON "payment_intents"("merchant_id"); + +-- CreateIndex +CREATE INDEX "webhook_endpoints_merchant_id_idx" ON "webhook_endpoints"("merchant_id"); + +-- AddForeignKey +ALTER TABLE "payment_intents" ADD CONSTRAINT "payment_intents_merchant_id_fkey" FOREIGN KEY ("merchant_id") REFERENCES "merchants"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "webhook_endpoints" ADD CONSTRAINT "webhook_endpoints_merchant_id_fkey" FOREIGN KEY ("merchant_id") REFERENCES "merchants"("id") ON DELETE CASCADE ON UPDATE CASCADE; diff --git a/apps/api/prisma/migrations/migration_lock.toml b/apps/api/prisma/migrations/migration_lock.toml new file mode 100644 index 0000000..1eed3a5 --- /dev/null +++ b/apps/api/prisma/migrations/migration_lock.toml @@ -0,0 +1,2 @@ +# Please do not edit this file manually +provider = "postgresql" diff --git a/apps/api/prisma/schema.prisma b/apps/api/prisma/schema.prisma new file mode 100644 index 0000000..7a0a1a9 --- /dev/null +++ b/apps/api/prisma/schema.prisma @@ -0,0 +1,69 @@ +generator client { + provider = "prisma-client-js" +} + +datasource db { + provider = "postgresql" + url = env("DATABASE_URL") +} + +enum KycStatus { + PENDING @map("pending") + APPROVED @map("approved") + REJECTED @map("rejected") +} + +enum PaymentIntentStatus { + PENDING @map("pending") + DETECTED @map("detected") + CONFIRMED @map("confirmed") + FAILED @map("failed") +} + +model Merchant { + id String @id @default(uuid()) @db.Uuid + email String @unique + passwordHash String @map("password_hash") + kycStatus KycStatus @default(PENDING) @map("kyc_status") + paymentIntents PaymentIntent[] + webhookEndpoints WebhookEndpoint[] + createdAt DateTime @default(now()) @map("created_at") + updatedAt DateTime @updatedAt @map("updated_at") + + @@map("merchants") +} + +model PaymentIntent { + id String @id @default(uuid()) @db.Uuid + merchantId String @map("merchant_id") @db.Uuid + merchant Merchant @relation(fields: [merchantId], references: [id], onDelete: Cascade) + amount Decimal @db.Decimal(20, 2) + currency String @db.VarChar(3) + status PaymentIntentStatus @default(PENDING) + createdAt DateTime @default(now()) @map("created_at") + updatedAt DateTime @updatedAt @map("updated_at") + + @@index([merchantId]) + @@map("payment_intents") +} + +model TreasuryAsset { + symbol String @id @db.VarChar(16) + totalMinted Decimal @default(0) @map("total_minted") @db.Decimal(30, 7) + totalReserved Decimal @default(0) @map("total_reserved") @db.Decimal(30, 7) + + @@map("treasury_assets") +} + +model WebhookEndpoint { + id String @id @default(uuid()) @db.Uuid + merchantId String @map("merchant_id") @db.Uuid + merchant Merchant @relation(fields: [merchantId], references: [id], onDelete: Cascade) + url String + secret String + createdAt DateTime @default(now()) @map("created_at") + updatedAt DateTime @updatedAt @map("updated_at") + + @@index([merchantId]) + @@map("webhook_endpoints") +} diff --git a/apps/api/src/app.module.ts b/apps/api/src/app.module.ts index 72888f2..4d9fe1f 100644 --- a/apps/api/src/app.module.ts +++ b/apps/api/src/app.module.ts @@ -3,6 +3,7 @@ import { APP_GUARD } from '@nestjs/core'; import { ThrottlerModule } from '@nestjs/throttler'; import { AppController } from './app.controller'; import { AppService } from './app.service'; +import { PrismaModule } from './prisma/prisma.module'; import { HealthModule } from './health/health.module'; import { TreasuryModule } from './treasury/treasury.module'; import { AuthModule } from './auth/auth.module'; @@ -11,6 +12,7 @@ import { ThrottlerRedisGuard } from './rate-limiter/guards/throttler-redis.guard @Module({ imports: [ + PrismaModule, HealthModule, TreasuryModule, AuthModule, diff --git a/apps/api/src/prisma/prisma.module.ts b/apps/api/src/prisma/prisma.module.ts new file mode 100644 index 0000000..7207426 --- /dev/null +++ b/apps/api/src/prisma/prisma.module.ts @@ -0,0 +1,9 @@ +import { Global, Module } from '@nestjs/common'; +import { PrismaService } from './prisma.service'; + +@Global() +@Module({ + providers: [PrismaService], + exports: [PrismaService], +}) +export class PrismaModule {} diff --git a/apps/api/src/prisma/prisma.service.ts b/apps/api/src/prisma/prisma.service.ts new file mode 100644 index 0000000..623d5e0 --- /dev/null +++ b/apps/api/src/prisma/prisma.service.ts @@ -0,0 +1,13 @@ +import { Injectable, OnModuleDestroy, OnModuleInit } from '@nestjs/common'; +import { PrismaClient } from '@prisma/client'; + +@Injectable() +export class PrismaService extends PrismaClient implements OnModuleInit, OnModuleDestroy { + async onModuleInit() { + await this.$connect(); + } + + async onModuleDestroy() { + await this.$disconnect(); + } +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index de8c444..14b6d14 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -97,10 +97,13 @@ importers: version: 11.1.14(@nestjs/common@11.1.14(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.14) '@nestjs/terminus': specifier: ^11.1.1 - version: 11.1.1(@nestjs/common@11.1.14(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.14)(reflect-metadata@0.2.2)(rxjs@7.8.2) + version: 11.1.1(@nestjs/common@11.1.14(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.14)(@prisma/client@6.7.0(prisma@6.7.0(typescript@5.9.3))(typescript@5.9.3))(reflect-metadata@0.2.2)(rxjs@7.8.2) '@nestjs/throttler': specifier: ^6.5.0 version: 6.5.0(@nestjs/common@11.1.14(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.14)(reflect-metadata@0.2.2) + '@prisma/client': + specifier: ^6.7.0 + version: 6.7.0(prisma@6.7.0(typescript@5.9.3))(typescript@5.9.3) '@stellar/stellar-sdk': specifier: ^14.6.1 version: 14.6.1 @@ -125,7 +128,7 @@ importers: version: 9.39.3 '@nestjs/cli': specifier: ^11.0.0 - version: 11.0.16(@types/node@22.19.13) + version: 11.0.16(@types/node@22.19.13)(esbuild@0.27.3) '@nestjs/schematics': specifier: ^11.0.0 version: 11.0.9(chokidar@4.0.3)(typescript@5.9.3) @@ -161,10 +164,13 @@ importers: version: 16.5.0 jest: specifier: ^30.0.0 - version: 30.2.0(@types/node@22.19.13)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@22.19.13)(typescript@5.9.3)) + version: 30.2.0(@types/node@22.19.13)(babel-plugin-macros@3.1.0)(esbuild-register@3.6.0(esbuild@0.27.3))(ts-node@10.9.2(@types/node@22.19.13)(typescript@5.9.3)) prettier: specifier: ^3.4.2 version: 3.8.1 + prisma: + specifier: ^6.7.0 + version: 6.7.0(typescript@5.9.3) source-map-support: specifier: ^0.5.21 version: 0.5.21 @@ -173,10 +179,10 @@ importers: version: 7.2.2 ts-jest: specifier: ^29.2.5 - version: 29.4.6(@babel/core@7.29.0)(@jest/transform@30.2.0)(@jest/types@30.2.0)(babel-jest@30.2.0(@babel/core@7.29.0))(jest-util@30.2.0)(jest@30.2.0(@types/node@22.19.13)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@22.19.13)(typescript@5.9.3)))(typescript@5.9.3) + version: 29.4.6(@babel/core@7.29.0)(@jest/transform@30.2.0)(@jest/types@30.2.0)(babel-jest@30.2.0(@babel/core@7.29.0))(esbuild@0.27.3)(jest-util@30.2.0)(jest@30.2.0(@types/node@22.19.13)(babel-plugin-macros@3.1.0)(esbuild-register@3.6.0(esbuild@0.27.3))(ts-node@10.9.2(@types/node@22.19.13)(typescript@5.9.3)))(typescript@5.9.3) ts-loader: specifier: ^9.5.2 - version: 9.5.4(typescript@5.9.3)(webpack@5.104.1) + version: 9.5.4(typescript@5.9.3)(webpack@5.104.1(esbuild@0.27.3)) ts-node: specifier: ^10.9.2 version: 10.9.2(@types/node@22.19.13)(typescript@5.9.3) @@ -2513,6 +2519,57 @@ packages: integrity: sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==, } + '@prisma/client@6.7.0': + resolution: + { + integrity: sha512-+k61zZn1XHjbZul8q6TdQLpuI/cvyfil87zqK2zpreNIXyXtpUv3+H/oM69hcsFcZXaokHJIzPAt5Z8C8eK2QA==, + } + engines: { node: '>=18.18' } + peerDependencies: + prisma: '*' + typescript: '>=5.1.0' + peerDependenciesMeta: + prisma: + optional: true + typescript: + optional: true + + '@prisma/config@6.7.0': + resolution: + { + integrity: sha512-di8QDdvSz7DLUi3OOcCHSwxRNeW7jtGRUD2+Z3SdNE3A+pPiNT8WgUJoUyOwJmUr5t+JA2W15P78C/N+8RXrOA==, + } + + '@prisma/debug@6.7.0': + resolution: + { + integrity: sha512-RabHn9emKoYFsv99RLxvfG2GHzWk2ZI1BuVzqYtmMSIcuGboHY5uFt3Q3boOREM9de6z5s3bQoyKeWnq8Fz22w==, + } + + '@prisma/engines-version@6.7.0-36.3cff47a7f5d65c3ea74883f1d736e41d68ce91ed': + resolution: + { + integrity: sha512-EvpOFEWf1KkJpDsBCrih0kg3HdHuaCnXmMn7XFPObpFTzagK1N0Q0FMnYPsEhvARfANP5Ok11QyoTIRA2hgJTA==, + } + + '@prisma/engines@6.7.0': + resolution: + { + integrity: sha512-3wDMesnOxPrOsq++e5oKV9LmIiEazFTRFZrlULDQ8fxdub5w4NgRBoxtWbvXmj2nJVCnzuz6eFix3OhIqsZ1jw==, + } + + '@prisma/fetch-engine@6.7.0': + resolution: + { + integrity: sha512-zLlAGnrkmioPKJR4Yf7NfW3hftcvqeNNEHleMZK9yX7RZSkhmxacAYyfGsCcqRt47jiZ7RKdgE0Wh2fWnm7WsQ==, + } + + '@prisma/get-platform@6.7.0': + resolution: + { + integrity: sha512-i9IH5lO4fQwnMLvQLYNdgVh9TK3PuWBfQd7QLk/YurnAIg+VeADcZDbmhAi4XBBDD+hDif9hrKyASu0hbjwabw==, + } + '@radix-ui/number@1.1.0': resolution: { @@ -6786,6 +6843,14 @@ packages: } engines: { node: '>= 0.4' } + esbuild-register@3.6.0: + resolution: + { + integrity: sha512-H2/S7Pm8a9CL1uhp9OvjwrBh5Pvx0H8qVOxNu8Wed9Y7qv56MPtq+GGM8RJpq6glYJn9Wspr8uw7l55uyinNeg==, + } + peerDependencies: + esbuild: '>=0.12 <1' + esbuild@0.27.3: resolution: { @@ -9829,6 +9894,19 @@ packages: } engines: { node: '>=18' } + prisma@6.7.0: + resolution: + { + integrity: sha512-vArg+4UqnQ13CVhc2WUosemwh6hr6cr6FY2uzDvCIFwH8pu8BXVv38PktoMLVjtX7sbYThxbnZF5YiR8sN2clw==, + } + engines: { node: '>=18.18' } + hasBin: true + peerDependencies: + typescript: '>=5.1.0' + peerDependenciesMeta: + typescript: + optional: true + prompts@2.4.2: resolution: { @@ -12693,7 +12771,7 @@ snapshots: jest-util: 30.2.0 slash: 3.0.0 - '@jest/core@30.2.0(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@22.19.13)(typescript@5.9.3))': + '@jest/core@30.2.0(babel-plugin-macros@3.1.0)(esbuild-register@3.6.0(esbuild@0.27.3))(ts-node@10.9.2(@types/node@22.19.13)(typescript@5.9.3))': dependencies: '@jest/console': 30.2.0 '@jest/pattern': 30.0.1 @@ -12708,7 +12786,7 @@ snapshots: exit-x: 0.2.2 graceful-fs: 4.2.11 jest-changed-files: 30.2.0 - jest-config: 30.2.0(@types/node@22.19.13)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@22.19.13)(typescript@5.9.3)) + jest-config: 30.2.0(@types/node@22.19.13)(babel-plugin-macros@3.1.0)(esbuild-register@3.6.0(esbuild@0.27.3))(ts-node@10.9.2(@types/node@22.19.13)(typescript@5.9.3)) jest-haste-map: 30.2.0 jest-message-util: 30.2.0 jest-regex-util: 30.0.1 @@ -13019,7 +13097,7 @@ snapshots: '@tybys/wasm-util': 0.10.1 optional: true - '@nestjs/cli@11.0.16(@types/node@22.19.13)': + '@nestjs/cli@11.0.16(@types/node@22.19.13)(esbuild@0.27.3)': dependencies: '@angular-devkit/core': 19.2.19(chokidar@4.0.3) '@angular-devkit/schematics': 19.2.19(chokidar@4.0.3) @@ -13030,14 +13108,14 @@ snapshots: chokidar: 4.0.3 cli-table3: 0.6.5 commander: 4.1.1 - fork-ts-checker-webpack-plugin: 9.1.0(typescript@5.9.3)(webpack@5.104.1) + fork-ts-checker-webpack-plugin: 9.1.0(typescript@5.9.3)(webpack@5.104.1(esbuild@0.27.3)) glob: 13.0.0 node-emoji: 1.11.0 ora: 5.4.1 tsconfig-paths: 4.2.0 tsconfig-paths-webpack-plugin: 4.2.0 typescript: 5.9.3 - webpack: 5.104.1 + webpack: 5.104.1(esbuild@0.27.3) webpack-node-externals: 3.0.0 transitivePeerDependencies: - '@types/node' @@ -13099,7 +13177,7 @@ snapshots: transitivePeerDependencies: - chokidar - '@nestjs/terminus@11.1.1(@nestjs/common@11.1.14(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.14)(reflect-metadata@0.2.2)(rxjs@7.8.2)': + '@nestjs/terminus@11.1.1(@nestjs/common@11.1.14(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.14)(@prisma/client@6.7.0(prisma@6.7.0(typescript@5.9.3))(typescript@5.9.3))(reflect-metadata@0.2.2)(rxjs@7.8.2)': dependencies: '@nestjs/common': 11.1.14(reflect-metadata@0.2.2)(rxjs@7.8.2) '@nestjs/core': 11.1.14(@nestjs/common@11.1.14(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/platform-express@11.1.14)(reflect-metadata@0.2.2)(rxjs@7.8.2) @@ -13107,6 +13185,8 @@ snapshots: check-disk-space: 3.4.0 reflect-metadata: 0.2.2 rxjs: 7.8.2 + optionalDependencies: + '@prisma/client': 6.7.0(prisma@6.7.0(typescript@5.9.3))(typescript@5.9.3) '@nestjs/testing@11.1.14(@nestjs/common@11.1.14(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.14)(@nestjs/platform-express@11.1.14)': dependencies: @@ -13198,6 +13278,39 @@ snapshots: '@popperjs/core@2.11.8': {} + '@prisma/client@6.7.0(prisma@6.7.0(typescript@5.9.3))(typescript@5.9.3)': + optionalDependencies: + prisma: 6.7.0(typescript@5.9.3) + typescript: 5.9.3 + + '@prisma/config@6.7.0': + dependencies: + esbuild: 0.27.3 + esbuild-register: 3.6.0(esbuild@0.27.3) + transitivePeerDependencies: + - supports-color + + '@prisma/debug@6.7.0': {} + + '@prisma/engines-version@6.7.0-36.3cff47a7f5d65c3ea74883f1d736e41d68ce91ed': {} + + '@prisma/engines@6.7.0': + dependencies: + '@prisma/debug': 6.7.0 + '@prisma/engines-version': 6.7.0-36.3cff47a7f5d65c3ea74883f1d736e41d68ce91ed + '@prisma/fetch-engine': 6.7.0 + '@prisma/get-platform': 6.7.0 + + '@prisma/fetch-engine@6.7.0': + dependencies: + '@prisma/debug': 6.7.0 + '@prisma/engines-version': 6.7.0-36.3cff47a7f5d65c3ea74883f1d736e41d68ce91ed + '@prisma/get-platform': 6.7.0 + + '@prisma/get-platform@6.7.0': + dependencies: + '@prisma/debug': 6.7.0 + '@radix-ui/number@1.1.0': {} '@radix-ui/number@1.1.1': {} @@ -16128,6 +16241,13 @@ snapshots: is-date-object: 1.1.0 is-symbol: 1.1.1 + esbuild-register@3.6.0(esbuild@0.27.3): + dependencies: + debug: 4.4.3 + esbuild: 0.27.3 + transitivePeerDependencies: + - supports-color + esbuild@0.27.3: optionalDependencies: '@esbuild/aix-ppc64': 0.27.3 @@ -16604,7 +16724,7 @@ snapshots: cross-spawn: 7.0.6 signal-exit: 4.1.0 - fork-ts-checker-webpack-plugin@9.1.0(typescript@5.9.3)(webpack@5.104.1): + fork-ts-checker-webpack-plugin@9.1.0(typescript@5.9.3)(webpack@5.104.1(esbuild@0.27.3)): dependencies: '@babel/code-frame': 7.29.0 chalk: 4.1.2 @@ -16619,7 +16739,7 @@ snapshots: semver: 7.7.4 tapable: 2.3.0 typescript: 5.9.3 - webpack: 5.104.1 + webpack: 5.104.1(esbuild@0.27.3) form-data@4.0.5: dependencies: @@ -17149,15 +17269,15 @@ snapshots: - babel-plugin-macros - supports-color - jest-cli@30.2.0(@types/node@22.19.13)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@22.19.13)(typescript@5.9.3)): + jest-cli@30.2.0(@types/node@22.19.13)(babel-plugin-macros@3.1.0)(esbuild-register@3.6.0(esbuild@0.27.3))(ts-node@10.9.2(@types/node@22.19.13)(typescript@5.9.3)): dependencies: - '@jest/core': 30.2.0(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@22.19.13)(typescript@5.9.3)) + '@jest/core': 30.2.0(babel-plugin-macros@3.1.0)(esbuild-register@3.6.0(esbuild@0.27.3))(ts-node@10.9.2(@types/node@22.19.13)(typescript@5.9.3)) '@jest/test-result': 30.2.0 '@jest/types': 30.2.0 chalk: 4.1.2 exit-x: 0.2.2 import-local: 3.2.0 - jest-config: 30.2.0(@types/node@22.19.13)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@22.19.13)(typescript@5.9.3)) + jest-config: 30.2.0(@types/node@22.19.13)(babel-plugin-macros@3.1.0)(esbuild-register@3.6.0(esbuild@0.27.3))(ts-node@10.9.2(@types/node@22.19.13)(typescript@5.9.3)) jest-util: 30.2.0 jest-validate: 30.2.0 yargs: 17.7.2 @@ -17168,7 +17288,7 @@ snapshots: - supports-color - ts-node - jest-config@30.2.0(@types/node@22.19.13)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@22.19.13)(typescript@5.9.3)): + jest-config@30.2.0(@types/node@22.19.13)(babel-plugin-macros@3.1.0)(esbuild-register@3.6.0(esbuild@0.27.3))(ts-node@10.9.2(@types/node@22.19.13)(typescript@5.9.3)): dependencies: '@babel/core': 7.29.0 '@jest/get-type': 30.1.0 @@ -17196,6 +17316,7 @@ snapshots: strip-json-comments: 3.1.1 optionalDependencies: '@types/node': 22.19.13 + esbuild-register: 3.6.0(esbuild@0.27.3) ts-node: 10.9.2(@types/node@22.19.13)(typescript@5.9.3) transitivePeerDependencies: - babel-plugin-macros @@ -17422,12 +17543,12 @@ snapshots: merge-stream: 2.0.0 supports-color: 8.1.1 - jest@30.2.0(@types/node@22.19.13)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@22.19.13)(typescript@5.9.3)): + jest@30.2.0(@types/node@22.19.13)(babel-plugin-macros@3.1.0)(esbuild-register@3.6.0(esbuild@0.27.3))(ts-node@10.9.2(@types/node@22.19.13)(typescript@5.9.3)): dependencies: - '@jest/core': 30.2.0(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@22.19.13)(typescript@5.9.3)) + '@jest/core': 30.2.0(babel-plugin-macros@3.1.0)(esbuild-register@3.6.0(esbuild@0.27.3))(ts-node@10.9.2(@types/node@22.19.13)(typescript@5.9.3)) '@jest/types': 30.2.0 import-local: 3.2.0 - jest-cli: 30.2.0(@types/node@22.19.13)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@22.19.13)(typescript@5.9.3)) + jest-cli: 30.2.0(@types/node@22.19.13)(babel-plugin-macros@3.1.0)(esbuild-register@3.6.0(esbuild@0.27.3))(ts-node@10.9.2(@types/node@22.19.13)(typescript@5.9.3)) transitivePeerDependencies: - '@types/node' - babel-plugin-macros @@ -18166,6 +18287,16 @@ snapshots: dependencies: parse-ms: 4.0.0 + prisma@6.7.0(typescript@5.9.3): + dependencies: + '@prisma/config': 6.7.0 + '@prisma/engines': 6.7.0 + optionalDependencies: + fsevents: 2.3.3 + typescript: 5.9.3 + transitivePeerDependencies: + - supports-color + prompts@2.4.2: dependencies: kleur: 3.0.3 @@ -19003,14 +19134,16 @@ snapshots: tapable@2.3.0: {} - terser-webpack-plugin@5.3.16(webpack@5.104.1): + terser-webpack-plugin@5.3.16(esbuild@0.27.3)(webpack@5.104.1(esbuild@0.27.3)): dependencies: '@jridgewell/trace-mapping': 0.3.31 jest-worker: 27.5.1 schema-utils: 4.3.3 serialize-javascript: 6.0.2 terser: 5.46.0 - webpack: 5.104.1 + webpack: 5.104.1(esbuild@0.27.3) + optionalDependencies: + esbuild: 0.27.3 terser@5.46.0: dependencies: @@ -19084,12 +19217,12 @@ snapshots: ts-interface-checker@0.1.13: {} - ts-jest@29.4.6(@babel/core@7.29.0)(@jest/transform@30.2.0)(@jest/types@30.2.0)(babel-jest@30.2.0(@babel/core@7.29.0))(jest-util@30.2.0)(jest@30.2.0(@types/node@22.19.13)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@22.19.13)(typescript@5.9.3)))(typescript@5.9.3): + ts-jest@29.4.6(@babel/core@7.29.0)(@jest/transform@30.2.0)(@jest/types@30.2.0)(babel-jest@30.2.0(@babel/core@7.29.0))(esbuild@0.27.3)(jest-util@30.2.0)(jest@30.2.0(@types/node@22.19.13)(babel-plugin-macros@3.1.0)(esbuild-register@3.6.0(esbuild@0.27.3))(ts-node@10.9.2(@types/node@22.19.13)(typescript@5.9.3)))(typescript@5.9.3): dependencies: bs-logger: 0.2.6 fast-json-stable-stringify: 2.1.0 handlebars: 4.7.8 - jest: 30.2.0(@types/node@22.19.13)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@22.19.13)(typescript@5.9.3)) + jest: 30.2.0(@types/node@22.19.13)(babel-plugin-macros@3.1.0)(esbuild-register@3.6.0(esbuild@0.27.3))(ts-node@10.9.2(@types/node@22.19.13)(typescript@5.9.3)) json5: 2.2.3 lodash.memoize: 4.1.2 make-error: 1.3.6 @@ -19102,9 +19235,10 @@ snapshots: '@jest/transform': 30.2.0 '@jest/types': 30.2.0 babel-jest: 30.2.0(@babel/core@7.29.0) + esbuild: 0.27.3 jest-util: 30.2.0 - ts-loader@9.5.4(typescript@5.9.3)(webpack@5.104.1): + ts-loader@9.5.4(typescript@5.9.3)(webpack@5.104.1(esbuild@0.27.3)): dependencies: chalk: 4.1.2 enhanced-resolve: 5.20.0 @@ -19112,7 +19246,7 @@ snapshots: semver: 7.7.4 source-map: 0.7.6 typescript: 5.9.3 - webpack: 5.104.1 + webpack: 5.104.1(esbuild@0.27.3) ts-morph@26.0.0: dependencies: @@ -19439,7 +19573,7 @@ snapshots: webpack-sources@3.3.4: {} - webpack@5.104.1: + webpack@5.104.1(esbuild@0.27.3): dependencies: '@types/eslint-scope': 3.7.7 '@types/estree': 1.0.8 @@ -19463,7 +19597,7 @@ snapshots: neo-async: 2.6.2 schema-utils: 4.3.3 tapable: 2.3.0 - terser-webpack-plugin: 5.3.16(webpack@5.104.1) + terser-webpack-plugin: 5.3.16(esbuild@0.27.3)(webpack@5.104.1(esbuild@0.27.3)) watchpack: 2.5.1 webpack-sources: 3.3.4 transitivePeerDependencies: From e570ca248c4923a067dd9b1b534fe69f182b6f7a Mon Sep 17 00:00:00 2001 From: David-patrick-chuks Date: Mon, 27 Apr 2026 12:41:55 +0100 Subject: [PATCH 2/2] fix(frontend): resolve lint failures Made-with: Cursor --- apps/frontend/src/app/checkout/page.tsx | 4 +- apps/frontend/src/app/dashboard/page.tsx | 150 +++++++++--------- .../src/app/dashboard/subscriptions/page.tsx | 60 +++++-- .../src/app/dashboard/treasury/page.tsx | 82 +++++----- .../src/app/dashboard/webhooks/page.tsx | 62 ++++++-- 5 files changed, 208 insertions(+), 150 deletions(-) diff --git a/apps/frontend/src/app/checkout/page.tsx b/apps/frontend/src/app/checkout/page.tsx index 98dbd5b..95cb110 100644 --- a/apps/frontend/src/app/checkout/page.tsx +++ b/apps/frontend/src/app/checkout/page.tsx @@ -511,7 +511,7 @@ export default function PaymentCheckout() { onClick={handleBankPayment} className="w-full bg-white hover:bg-zinc-100 text-black h-14 rounded-xl mt-6 text-base transition-all duration-200 shadow-lg shadow-white/10" > - I've Completed the Transfer + I've Completed the Transfer

@@ -611,7 +611,7 @@ export default function PaymentCheckout() { onClick={handleCryptoDetection} className="w-full bg-white hover:bg-zinc-100 text-black h-14 rounded-xl mt-6 text-base transition-all duration-200 shadow-lg shadow-white/10" > - I've Sent the Payment + I've Sent the Payment

diff --git a/apps/frontend/src/app/dashboard/page.tsx b/apps/frontend/src/app/dashboard/page.tsx index 68a7042..6ce48d5 100644 --- a/apps/frontend/src/app/dashboard/page.tsx +++ b/apps/frontend/src/app/dashboard/page.tsx @@ -1,6 +1,6 @@ 'use client'; -import { motion } from "motion/react"; +import { motion } from 'motion/react'; import { TrendingUp, TrendingDown, @@ -10,90 +10,90 @@ import { Clock, CheckCircle2, AlertCircle, -} from "lucide-react"; +} from 'lucide-react'; const stats = [ { - label: "Total Volume (30d)", - value: "$12,847,392.45", - change: "+18.2%", - trend: "up", + label: 'Total Volume (30d)', + value: '$12,847,392.45', + change: '+18.2%', + trend: 'up', icon: DollarSign, }, { - label: "Settlement Balance", - value: "$2,103,482.12", - change: "+5.4%", - trend: "up", + label: 'Settlement Balance', + value: '$2,103,482.12', + change: '+5.4%', + trend: 'up', icon: Activity, }, { - label: "Pending Settlements", - value: "47", - change: "-12.3%", - trend: "down", + label: 'Pending Settlements', + value: '47', + change: '-12.3%', + trend: 'down', icon: Clock, }, { - label: "Reserve Ratio", - value: "127.3%", - change: "+2.1%", - trend: "up", + label: 'Reserve Ratio', + value: '127.3%', + change: '+2.1%', + trend: 'up', icon: CheckCircle2, }, ]; const assets = [ - { symbol: "sUSDC", balance: "1,245,382.45", usd: "1,245,382.45", change: "+2.3%" }, - { symbol: "sBTC", balance: "12.4583", usd: "625,847.92", change: "+5.1%" }, - { symbol: "sETH", balance: "145.2341", usd: "232,251.75", change: "-1.2%" }, + { symbol: 'sUSDC', balance: '1,245,382.45', usd: '1,245,382.45', change: '+2.3%' }, + { symbol: 'sBTC', balance: '12.4583', usd: '625,847.92', change: '+5.1%' }, + { symbol: 'sETH', balance: '145.2341', usd: '232,251.75', change: '-1.2%' }, ]; const transactions = [ { - id: "pay_9k2j3n4k5j6h", - type: "Payment", - asset: "sUSDC", - amount: "+12,450.00", - status: "completed", - time: "2m ago", - hash: "0x7a8f9b2c...4e5d6f1a", + id: 'pay_9k2j3n4k5j6h', + type: 'Payment', + asset: 'sUSDC', + amount: '+12,450.00', + status: 'completed', + time: '2m ago', + hash: '0x7a8f9b2c...4e5d6f1a', }, { - id: "pay_8h1j2k3l4m5n", - type: "Redemption", - asset: "sBTC", - amount: "-0.2341", - status: "completed", - time: "5m ago", - hash: "0x3c4d5e6f...7a8b9c0d", + id: 'pay_8h1j2k3l4m5n', + type: 'Redemption', + asset: 'sBTC', + amount: '-0.2341', + status: 'completed', + time: '5m ago', + hash: '0x3c4d5e6f...7a8b9c0d', }, { - id: "pay_7g8h9i0j1k2l", - type: "Payment", - asset: "sETH", - amount: "+5.4321", - status: "pending", - time: "8m ago", - hash: "0x1a2b3c4d...5e6f7g8h", + id: 'pay_7g8h9i0j1k2l', + type: 'Payment', + asset: 'sETH', + amount: '+5.4321', + status: 'pending', + time: '8m ago', + hash: '0x1a2b3c4d...5e6f7g8h', }, { - id: "pay_6f7g8h9i0j1k", - type: "Settlement", - asset: "sUSDC", - amount: "-8,230.50", - status: "completed", - time: "12m ago", - hash: "0x9h8g7f6e...5d4c3b2a", + id: 'pay_6f7g8h9i0j1k', + type: 'Settlement', + asset: 'sUSDC', + amount: '-8,230.50', + status: 'completed', + time: '12m ago', + hash: '0x9h8g7f6e...5d4c3b2a', }, { - id: "pay_5e6f7g8h9i0j", - type: "Payment", - asset: "sBTC", - amount: "+0.1234", - status: "completed", - time: "15m ago", - hash: "0x2b3c4d5e...6f7g8h9i", + id: 'pay_5e6f7g8h9i0j', + type: 'Payment', + asset: 'sBTC', + amount: '+0.1234', + status: 'completed', + time: '15m ago', + hash: '0x2b3c4d5e...6f7g8h9i', }, ]; @@ -109,9 +109,7 @@ export default function OverviewPage() { > Overview -

- Real-time metrics and settlement status -

+

Real-time metrics and settlement status

{/* Stats Grid */} @@ -136,17 +134,17 @@ export default function OverviewPage() { repeatDelay: 2, }} /> - +
- {stat.trend === "up" ? ( + {stat.trend === 'up' ? ( ) : ( @@ -154,7 +152,7 @@ export default function OverviewPage() { {stat.change}
- +
{stat.value}
{stat.label}
@@ -200,7 +198,9 @@ export default function OverviewPage() {
${asset.usd}
-
+
{asset.change}
@@ -211,7 +211,7 @@ export default function OverviewPage() {
@@ -228,7 +228,7 @@ export default function OverviewPage() { transition={{ delay: 0.3 }} >

Reserve Health

- +
{/* Background circle */} @@ -249,9 +249,9 @@ export default function OverviewPage() { stroke="rgba(255,255,255,0.3)" strokeWidth="12" strokeLinecap="round" - initial={{ strokeDasharray: "0 440" }} - animate={{ strokeDasharray: "350 440" }} - transition={{ duration: 1.5, ease: "easeOut" }} + initial={{ strokeDasharray: '0 440' }} + animate={{ strokeDasharray: '350 440' }} + transition={{ duration: 1.5, ease: 'easeOut' }} />
@@ -336,18 +336,20 @@ export default function OverviewPage() { {tx.asset} - + {tx.amount} - {tx.status === "completed" ? ( + {tx.status === 'completed' ? ( ) : ( diff --git a/apps/frontend/src/app/dashboard/subscriptions/page.tsx b/apps/frontend/src/app/dashboard/subscriptions/page.tsx index cf1fb17..6c658f7 100644 --- a/apps/frontend/src/app/dashboard/subscriptions/page.tsx +++ b/apps/frontend/src/app/dashboard/subscriptions/page.tsx @@ -1,12 +1,36 @@ 'use client'; -import { motion } from "motion/react"; -import { Plus, RefreshCw, CheckCircle2, AlertCircle } from "lucide-react"; +import { motion } from 'motion/react'; +import { Plus, CheckCircle2, AlertCircle } from 'lucide-react'; const subscriptions = [ - { id: "sub_1a2b3c4d", customer: "Acme Corp", plan: "Enterprise", amount: "999.00", interval: "Monthly", status: "active", nextBilling: "2026-04-03" }, - { id: "sub_5e6f7g8h", customer: "TechStart Inc", plan: "Pro", amount: "299.00", interval: "Monthly", status: "active", nextBilling: "2026-04-15" }, - { id: "sub_9i0j1k2l", customer: "BuildCo", plan: "Starter", amount: "99.00", interval: "Monthly", status: "past_due", nextBilling: "2026-03-01" }, + { + id: 'sub_1a2b3c4d', + customer: 'Acme Corp', + plan: 'Enterprise', + amount: '999.00', + interval: 'Monthly', + status: 'active', + nextBilling: '2026-04-03', + }, + { + id: 'sub_5e6f7g8h', + customer: 'TechStart Inc', + plan: 'Pro', + amount: '299.00', + interval: 'Monthly', + status: 'active', + nextBilling: '2026-04-15', + }, + { + id: 'sub_9i0j1k2l', + customer: 'BuildCo', + plan: 'Starter', + amount: '99.00', + interval: 'Monthly', + status: 'past_due', + nextBilling: '2026-03-01', + }, ]; export default function SubscriptionsPage() { @@ -25,9 +49,9 @@ export default function SubscriptionsPage() {
{[ - { label: "Active Subscriptions", value: "2" }, - { label: "Monthly Recurring Revenue", value: "$1,298.00" }, - { label: "Past Due", value: "1" }, + { label: 'Active Subscriptions', value: '2' }, + { label: 'Monthly Recurring Revenue', value: '$1,298.00' }, + { label: 'Past Due', value: '1' }, ].map((stat, index) => ( - +