refactor invoice required confirmations resolver to be more scalable for future confirmations based coins

This commit is contained in:
2026-09-03 11:45:30 +02:00
parent 932cbf64c1
commit 5c888551db
7 changed files with 89 additions and 21 deletions
@@ -0,0 +1,34 @@
import { PaymentMethod } from '../../modules/payment/types/PaymentMethod';
import { getConfirmationBasedInvoiceDetails } from './getConfirmationBasedInvoiceDetails';
describe('getConfirmationBasedInvoiceDetails', () => {
it('returns monero details for XMR invoices', () => {
const moneroDetails = { requiredConfirmations: 3 };
expect(
getConfirmationBasedInvoiceDetails({
paymentMethod: PaymentMethod.Xmr,
moneroDetails
})
).toBe(moneroDetails);
});
it('returns bitcoin details for BTC invoices', () => {
const btcDetails = { requiredConfirmations: 6 };
expect(
getConfirmationBasedInvoiceDetails({
paymentMethod: PaymentMethod.Btc,
btcDetails
})
).toBe(btcDetails);
});
it('returns undefined for unsupported payment methods', () => {
expect(
getConfirmationBasedInvoiceDetails({
paymentMethod: 'eth' as PaymentMethod
})
).toBeUndefined();
});
});
@@ -0,0 +1,16 @@
import { PaymentMethod } from '../../modules/payment/types/PaymentMethod';
import type { ConfirmationBasedInvoiceDetails } from './types/ConfirmationBasedInvoiceDetails';
import type { InvoiceStateInput } from './types/InvoiceStateInput';
export const getConfirmationBasedInvoiceDetails = (
invoice: Pick<InvoiceStateInput, 'paymentMethod' | 'moneroDetails' | 'btcDetails'>
): ConfirmationBasedInvoiceDetails | null | undefined => {
switch (invoice.paymentMethod) {
case PaymentMethod.Xmr:
return invoice.moneroDetails;
case PaymentMethod.Btc:
return invoice.btcDetails;
default:
return undefined;
}
};
@@ -17,14 +17,32 @@ describe('resolveInvoiceRequiredConfirmations', () => {
paymentMethod: PaymentMethod.Xmr, paymentMethod: PaymentMethod.Xmr,
moneroDetails: null moneroDetails: null
}) })
).toThrow('Invoice is missing Monero required confirmations'); ).toThrow('Invoice is missing xmr required confirmations');
});
it('returns required confirmations for BTC invoices', () => {
expect(
resolveInvoiceRequiredConfirmations({
paymentMethod: PaymentMethod.Btc,
btcDetails: { requiredConfirmations: 6 }
})
).toBe(6);
});
it('throws when bitcoin details are missing', () => {
expect(() =>
resolveInvoiceRequiredConfirmations({
paymentMethod: PaymentMethod.Btc,
btcDetails: null
})
).toThrow('Invoice is missing btc required confirmations');
}); });
it('throws for unsupported payment methods', () => { it('throws for unsupported payment methods', () => {
expect(() => expect(() =>
resolveInvoiceRequiredConfirmations({ resolveInvoiceRequiredConfirmations({
paymentMethod: 'btc' as PaymentMethod paymentMethod: 'eth' as PaymentMethod
}) })
).toThrow('Unsupported payment method: btc'); ).toThrow('Invoice is missing eth required confirmations');
}); });
}); });
@@ -1,18 +1,14 @@
import { PaymentMethod } from '../../modules/payment/types/PaymentMethod';
import type { InvoiceConfirmationsInput } from './types/InvoiceConfirmationsInput'; import type { InvoiceConfirmationsInput } from './types/InvoiceConfirmationsInput';
import { getConfirmationBasedInvoiceDetails } from './getConfirmationBasedInvoiceDetails';
export const resolveInvoiceRequiredConfirmations = (invoice: InvoiceConfirmationsInput): number => { export const resolveInvoiceRequiredConfirmations = (invoice: InvoiceConfirmationsInput): number => {
switch (invoice.paymentMethod) { const details = getConfirmationBasedInvoiceDetails(invoice);
case PaymentMethod.Xmr: {
const requiredConfirmations = invoice.moneroDetails?.requiredConfirmations; const requiredConfirmations = details?.requiredConfirmations;
if (requiredConfirmations === undefined) { if (requiredConfirmations === undefined) {
throw new Error('Invoice is missing Monero required confirmations'); throw new Error(`Invoice is missing ${invoice.paymentMethod} required confirmations`);
} }
return requiredConfirmations; return requiredConfirmations;
}
default:
throw new Error(`Unsupported payment method: ${String(invoice.paymentMethod)}`);
}
}; };
@@ -0,0 +1,3 @@
export type ConfirmationBasedInvoiceDetails = {
requiredConfirmations: number;
};
@@ -1,7 +1,6 @@
import type { PaymentMethod } from '../../../modules/payment/types/PaymentMethod'; import type { InvoiceStateInput } from './InvoiceStateInput';
export type InvoiceConfirmationsInput = { export type InvoiceConfirmationsInput = Pick<
paymentMethod: PaymentMethod; InvoiceStateInput,
payments?: { confirmations: number }[]; 'paymentMethod' | 'moneroDetails' | 'btcDetails' | 'payments'
moneroDetails?: { requiredConfirmations: number } | null; >;
};
@@ -1,9 +1,11 @@
import type { PaymentMethod } from '../../../modules/payment/types/PaymentMethod'; import type { PaymentMethod } from '../../../modules/payment/types/PaymentMethod';
import type { ConfirmationBasedInvoiceDetails } from './ConfirmationBasedInvoiceDetails';
export type InvoiceStateInput = { export type InvoiceStateInput = {
paymentMethod: PaymentMethod; paymentMethod: PaymentMethod;
expectedTotalAtomic: string; expectedTotalAtomic: string;
expiresAt: Date; expiresAt: Date;
payments?: { confirmations: number; amountAtomic: string }[]; payments?: { confirmations: number; amountAtomic: string }[];
moneroDetails?: { requiredConfirmations: number } | null; moneroDetails?: ConfirmationBasedInvoiceDetails | null;
btcDetails?: ConfirmationBasedInvoiceDetails | null;
}; };