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
@@ -0,0 +1,85 @@
import { validateSync } from 'class-validator';
import { IsConfirmationTiers } from './isConfirmationTiers';
class TestDto {
@IsConfirmationTiers()
CONFIRMATION_TIERS: string;
}
const validateTiers = (value: string) => {
const dto = Object.assign(new TestDto(), { CONFIRMATION_TIERS: value });
return validateSync(dto);
};
const validTiers =
'[{"upToTotalFiat":"25","minConfirmations":0},{"upToTotalFiat":"250","minConfirmations":5},{"minConfirmations":10}]';
describe('IsConfirmationTiers', () => {
it('accepts valid default tiers', () => {
expect(validateTiers(validTiers)).toHaveLength(0);
});
it('accepts numeric-only tiers without tx-detected (0)', () => {
const tiers =
'[{"upToTotalFiat":"25","minConfirmations":1},{"upToTotalFiat":"250","minConfirmations":5},{"minConfirmations":10}]';
expect(validateTiers(tiers)).toHaveLength(0);
});
it('rejects empty string', () => {
expect(validateTiers('').length).toBeGreaterThan(0);
});
it('rejects invalid JSON', () => {
expect(validateTiers('not-json').length).toBeGreaterThan(0);
});
it('rejects empty array', () => {
expect(validateTiers('[]').length).toBeGreaterThan(0);
});
it('rejects tx-detected (0) more than once', () => {
const tiers =
'[{"upToTotalFiat":"25","minConfirmations":0},{"upToTotalFiat":"250","minConfirmations":0},{"minConfirmations":10}]';
expect(validateTiers(tiers).length).toBeGreaterThan(0);
});
it('rejects tx-detected (0) on catch-all tier', () => {
const tiers = '[{"upToTotalFiat":"25","minConfirmations":1},{"minConfirmations":0}]';
expect(validateTiers(tiers).length).toBeGreaterThan(0);
});
it('rejects legacy tx-detected string', () => {
const tiers =
'[{"upToTotalFiat":"25","minConfirmations":"tx-detected"},{"upToTotalFiat":"250","minConfirmations":5},{"minConfirmations":10}]';
expect(validateTiers(tiers).length).toBeGreaterThan(0);
});
it('rejects missing upToTotalFiat on non-final tier', () => {
const tiers = '[{"minConfirmations":1},{"upToTotalFiat":"250","minConfirmations":5},{"minConfirmations":10}]';
expect(validateTiers(tiers).length).toBeGreaterThan(0);
});
it('rejects non-positive upToTotalFiat on non-final tier', () => {
const tiers = '[{"upToTotalFiat":"0","minConfirmations":1},{"minConfirmations":10}]';
expect(validateTiers(tiers).length).toBeGreaterThan(0);
});
it('rejects negative minConfirmations', () => {
const tiers = '[{"upToTotalFiat":"25","minConfirmations":-1},{"minConfirmations":10}]';
expect(validateTiers(tiers).length).toBeGreaterThan(0);
});
it('rejects catch-all tier with upToTotalFiat', () => {
const tiers = '[{"upToTotalFiat":"25","minConfirmations":1},{"upToTotalFiat":"999","minConfirmations":10}]';
expect(validateTiers(tiers).length).toBeGreaterThan(0);
});
});