refactor confirmation tiers to shared crypto-agnostic types and validation

This commit is contained in:
2026-09-03 00:28:17 +02:00
parent 5db64ea905
commit a7282a1888
11 changed files with 27 additions and 31 deletions
@@ -1,13 +1,13 @@
import { validateSync } from 'class-validator';
import { IsMoneroConfirmationTiers } from './isMoneroConfirmationTiers';
import { IsConfirmationTiers } from './isConfirmationTiers';
class TestDto {
@IsMoneroConfirmationTiers()
MONERO_CONFIRMATION_TIERS: string;
@IsConfirmationTiers()
CONFIRMATION_TIERS: string;
}
const validateTiers = (value: string) => {
const dto = Object.assign(new TestDto(), { MONERO_CONFIRMATION_TIERS: value });
const dto = Object.assign(new TestDto(), { CONFIRMATION_TIERS: value });
return validateSync(dto);
};
@@ -15,7 +15,7 @@ const validateTiers = (value: string) => {
const validTiers =
'[{"upToTotalFiat":"25","minConfirmations":0},{"upToTotalFiat":"250","minConfirmations":5},{"minConfirmations":10}]';
describe('IsMoneroConfirmationTiers', () => {
describe('IsConfirmationTiers', () => {
it('accepts valid default tiers', () => {
expect(validateTiers(validTiers)).toHaveLength(0);
});
@@ -1,5 +1,5 @@
import { Validate, ValidatorConstraint, type ValidatorConstraintInterface } from 'class-validator';
import type { MoneroConfirmationTier } from '../../types/MoneroConfirmationTier';
import type { ConfirmationTier } from '../../types/ConfirmationTier';
const isPositiveDecimalString = (value: string): boolean => {
const trimmed = value.trim();
@@ -16,12 +16,12 @@ const isPositiveDecimalString = (value: string): boolean => {
const isMinConfirmations = (value: unknown): boolean =>
typeof value === 'number' && Number.isInteger(value) && value >= 0;
const isMoneroConfirmationTier = (value: unknown): value is MoneroConfirmationTier => {
const isConfirmationTier = (value: unknown): value is ConfirmationTier => {
if (typeof value !== 'object' || value === null) {
return false;
}
const tier = value as MoneroConfirmationTier;
const tier = value as ConfirmationTier;
if (!isMinConfirmations(tier.minConfirmations)) {
return false;
@@ -34,7 +34,7 @@ const isMoneroConfirmationTier = (value: unknown): value is MoneroConfirmationTi
return typeof tier.upToTotalFiat === 'string' && isPositiveDecimalString(tier.upToTotalFiat);
};
const isValidMoneroConfirmationTiersJson = (raw: string): boolean => {
const isValidConfirmationTiersJson = (raw: string): boolean => {
let parsed: unknown;
try {
@@ -43,7 +43,7 @@ const isValidMoneroConfirmationTiersJson = (raw: string): boolean => {
return false;
}
if (!Array.isArray(parsed) || parsed.length === 0 || !parsed.every(isMoneroConfirmationTier)) {
if (!Array.isArray(parsed) || parsed.length === 0 || !parsed.every(isConfirmationTier)) {
return false;
}
@@ -75,19 +75,19 @@ const isValidMoneroConfirmationTiersJson = (raw: string): boolean => {
return true;
};
@ValidatorConstraint({ name: 'isMoneroConfirmationTiers' })
class IsMoneroConfirmationTiersConstraint implements ValidatorConstraintInterface {
@ValidatorConstraint({ name: 'isConfirmationTiers' })
class IsConfirmationTiersConstraint implements ValidatorConstraintInterface {
validate(value: unknown): boolean {
if (typeof value !== 'string' || !value) {
return false;
}
return isValidMoneroConfirmationTiersJson(value);
return isValidConfirmationTiersJson(value);
}
defaultMessage(): string {
return '$property must be a non-empty JSON array of Monero confirmation tiers; minConfirmations must be 0 (tx-detected) or an integer >= 1, 0 may appear only once and not on the catch-all tier, non-final tiers need a positive upToTotalFiat in shop fiat currency, and the last tier must be a catch-all without upToTotalFiat';
return '$property must be a non-empty JSON array of confirmation tiers; minConfirmations must be 0 (tx-detected) or an integer >= 1, 0 may appear only once and not on the catch-all tier, non-final tiers need a positive upToTotalFiat in shop fiat currency, and the last tier must be a catch-all without upToTotalFiat';
}
}
export const IsMoneroConfirmationTiers = () => Validate(IsMoneroConfirmationTiersConstraint);
export const IsConfirmationTiers = () => Validate(IsConfirmationTiersConstraint);