diff --git a/backend/src/database/migrations/1784800000000-add-btc-invoice-details.ts b/backend/src/database/migrations/1784800000000-add-btc-invoice-details.ts new file mode 100644 index 0000000..0c46b14 --- /dev/null +++ b/backend/src/database/migrations/1784800000000-add-btc-invoice-details.ts @@ -0,0 +1,20 @@ +import { MigrationInterface, QueryRunner } from 'typeorm'; + +export class AddBtcInvoiceDetails1784800000000 implements MigrationInterface { + name = 'AddBtcInvoiceDetails1784800000000'; + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query(`ALTER TYPE "public"."invoices_paymentmethod_enum" ADD VALUE 'btc'`); + await queryRunner.query( + `CREATE TABLE "invoice_btc_details" ("id" uuid NOT NULL DEFAULT uuid_generate_v4(), "fiatPerBtcAtCreation" numeric(12,2) NOT NULL, "requiredConfirmations" integer NOT NULL, "invoiceId" uuid, CONSTRAINT "UQ_invoice_btc_details_invoice_id" UNIQUE ("invoiceId"), CONSTRAINT "PK_invoice_btc_details" PRIMARY KEY ("id"))` + ); + await queryRunner.query( + `ALTER TABLE "invoice_btc_details" ADD CONSTRAINT "FK_d307f6e0ecc770f47c0bc320d3d" FOREIGN KEY ("invoiceId") REFERENCES "invoices"("id") ON DELETE CASCADE ON UPDATE NO ACTION` + ); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(`ALTER TABLE "invoice_btc_details" DROP CONSTRAINT "FK_d307f6e0ecc770f47c0bc320d3d"`); + await queryRunner.query(`DROP TABLE "invoice_btc_details"`); + } +} diff --git a/backend/src/modules/payment/PaymentModule.ts b/backend/src/modules/payment/PaymentModule.ts index 55681cd..01f931f 100644 --- a/backend/src/modules/payment/PaymentModule.ts +++ b/backend/src/modules/payment/PaymentModule.ts @@ -3,6 +3,7 @@ import { TypeOrmModule } from '@nestjs/typeorm'; import { MoneroWalletModule } from '../moneroWallet/MoneroWalletModule'; import { ExchangeRateModule } from '../exchangeRate/ExchangeRateModule'; import { Invoice } from './entities/Invoice'; +import { InvoiceBtcDetails } from './entities/InvoiceBtcDetails'; import { InvoiceMoneroDetails } from './entities/InvoiceMoneroDetails'; import { InvoicePayment } from './entities/InvoicePayment'; import { InvoicePaymentService } from './services/InvoicePaymentService'; @@ -10,7 +11,7 @@ import { InvoiceService } from './services/InvoiceService'; @Module({ imports: [ - TypeOrmModule.forFeature([Invoice, InvoicePayment, InvoiceMoneroDetails]), + TypeOrmModule.forFeature([Invoice, InvoicePayment, InvoiceMoneroDetails, InvoiceBtcDetails]), MoneroWalletModule, ExchangeRateModule ], diff --git a/backend/src/modules/payment/entities/Invoice.ts b/backend/src/modules/payment/entities/Invoice.ts index f29eec4..117b61a 100644 --- a/backend/src/modules/payment/entities/Invoice.ts +++ b/backend/src/modules/payment/entities/Invoice.ts @@ -3,6 +3,7 @@ import { ColumnBigIntTransformer } from '../../../utils/ColumnBigIntTransformer' import { ColumnNumericTransformer } from '../../../utils/ColumnNumericTransformer'; import { PaymentMethod } from '../types/PaymentMethod'; import { InvoiceReason } from '../types/InvoiceReason'; +import { InvoiceBtcDetails } from './InvoiceBtcDetails'; import { InvoiceMoneroDetails } from './InvoiceMoneroDetails'; import { InvoicePayment } from './InvoicePayment'; @@ -43,6 +44,9 @@ export class Invoice { @OneToOne(() => InvoiceMoneroDetails, moneroDetails => moneroDetails.invoice, { cascade: true }) moneroDetails: InvoiceMoneroDetails | null; + @OneToOne(() => InvoiceBtcDetails, btcDetails => btcDetails.invoice, { cascade: true }) + btcDetails: InvoiceBtcDetails | null; + @CreateDateColumn() createdAt: Date; } diff --git a/backend/src/modules/payment/entities/InvoiceBtcDetails.ts b/backend/src/modules/payment/entities/InvoiceBtcDetails.ts new file mode 100644 index 0000000..86fd836 --- /dev/null +++ b/backend/src/modules/payment/entities/InvoiceBtcDetails.ts @@ -0,0 +1,24 @@ +import { Column, Entity, JoinColumn, OneToOne, PrimaryGeneratedColumn } from 'typeorm'; +import { ColumnNumericTransformer } from '../../../utils/ColumnNumericTransformer'; +import { Invoice } from './Invoice'; + +@Entity('invoice_btc_details') +export class InvoiceBtcDetails { + @PrimaryGeneratedColumn('uuid') + id: string; + + @OneToOne(() => Invoice, invoice => invoice.btcDetails, { onDelete: 'CASCADE' }) + @JoinColumn() + invoice: Invoice; + + @Column({ + type: 'numeric', + precision: 12, + scale: 2, + transformer: new ColumnNumericTransformer() + }) + fiatPerBtcAtCreation: number; + + @Column({ type: 'int' }) + requiredConfirmations: number; +} diff --git a/cms/src/types/payment/Invoice.ts b/cms/src/types/payment/Invoice.ts index 03c0f3c..ad95ba0 100644 --- a/cms/src/types/payment/Invoice.ts +++ b/cms/src/types/payment/Invoice.ts @@ -1,3 +1,4 @@ +import type { InvoiceBtcDetails } from './InvoiceBtcDetails'; import type { InvoiceMoneroDetails } from './InvoiceMoneroDetails'; import type { InvoicePayment } from './InvoicePayment'; import type { InvoiceReason } from './InvoiceReason'; @@ -14,5 +15,6 @@ export type Invoice = { expectedTotalAtomic: string; createdAt: string; moneroDetails?: InvoiceMoneroDetails | null; + btcDetails?: InvoiceBtcDetails | null; payments?: InvoicePayment[]; }; diff --git a/cms/src/types/payment/InvoiceBtcDetails.ts b/cms/src/types/payment/InvoiceBtcDetails.ts new file mode 100644 index 0000000..ea57713 --- /dev/null +++ b/cms/src/types/payment/InvoiceBtcDetails.ts @@ -0,0 +1,5 @@ +export type InvoiceBtcDetails = { + id: string; + fiatPerBtcAtCreation: number; + requiredConfirmations: number; +}; diff --git a/cms/src/types/payment/PaymentMethod.ts b/cms/src/types/payment/PaymentMethod.ts index ca816cc..d4b138b 100644 --- a/cms/src/types/payment/PaymentMethod.ts +++ b/cms/src/types/payment/PaymentMethod.ts @@ -1,7 +1,9 @@ export enum PaymentMethod { - Xmr = 'xmr' + Xmr = 'xmr', + Btc = 'btc' } export const paymentMethodCryptoCurrency: Record = { - [PaymentMethod.Xmr]: 'XMR' + [PaymentMethod.Xmr]: 'XMR', + [PaymentMethod.Btc]: 'BTC' };