import { CreateExchangeRequest, CreateProviderMappingRequest } from '../types/exchange.types'; export class ValidationError extends Error { constructor(message: string, public field?: string) { super(message); this.name = 'ValidationError'; } } export function validateCreateExchange(data: any): CreateExchangeRequest { const { code, name, country, currency, active = true } = data; if (!code || typeof code !== 'string') { throw new ValidationError('Exchange code is required', 'code'); } if (!name || typeof name !== 'string') { throw new ValidationError('Exchange name is required', 'name'); } if (!country || typeof country !== 'string') { throw new ValidationError('Country is required', 'country'); } if (!currency || typeof currency !== 'string') { throw new ValidationError('Currency is required', 'currency'); } if (code.length > 10) { throw new ValidationError('Exchange code must be 10 characters or less', 'code'); } if (country.length !== 2) { throw new ValidationError('Country must be exactly 2 characters (e.g., US, CA, GB)', 'country'); } if (currency.length !== 3) { throw new ValidationError('Currency must be exactly 3 characters (e.g., USD, EUR, CAD)', 'currency'); } return { code: code.toUpperCase().trim(), name: name.trim(), country: country.toUpperCase().trim(), currency: currency.toUpperCase().trim(), active: Boolean(active), }; } export function validateCreateProviderMapping(data: any): CreateProviderMappingRequest { const { provider, provider_exchange_code, provider_exchange_name, master_exchange_id, country_code, currency, confidence = 1.0, active = false, verified = false, } = data; if (!provider || typeof provider !== 'string') { throw new ValidationError('Provider is required', 'provider'); } if (!provider_exchange_code || typeof provider_exchange_code !== 'string') { throw new ValidationError('Provider exchange code is required', 'provider_exchange_code'); } if (!master_exchange_id || typeof master_exchange_id !== 'string') { throw new ValidationError('Master exchange ID is required', 'master_exchange_id'); } // Validate currency is 3 characters or null const cleanCurrency = currency && currency.length <= 3 ? currency : null; return { provider: provider.trim(), provider_exchange_code: provider_exchange_code.trim(), provider_exchange_name: provider_exchange_name?.trim(), master_exchange_id: master_exchange_id.trim(), country_code: country_code?.trim() || null, currency: cleanCurrency, confidence: Number(confidence), active: Boolean(active), verified: Boolean(verified), }; } export function validateUpdateExchange(data: any): any { const updates: any = {}; if (data.name !== undefined) { if (typeof data.name !== 'string') { throw new ValidationError('Name must be a string', 'name'); } updates.name = data.name.trim(); } if (data.active !== undefined) { updates.active = Boolean(data.active); } if (data.visible !== undefined) { updates.visible = Boolean(data.visible); } if (data.country !== undefined) { if (typeof data.country !== 'string' || data.country.length !== 2) { throw new ValidationError('Country must be exactly 2 characters', 'country'); } updates.country = data.country.toUpperCase().trim(); } if (data.currency !== undefined) { if (typeof data.currency !== 'string' || data.currency.length !== 3) { throw new ValidationError('Currency must be exactly 3 characters', 'currency'); } updates.currency = data.currency.toUpperCase().trim(); } if (Object.keys(updates).length === 0) { throw new ValidationError('No valid fields to update'); } return updates; } export function validateUpdateProviderMapping(data: any): any { const updates: any = {}; if (data.active !== undefined) { updates.active = Boolean(data.active); } if (data.verified !== undefined) { updates.verified = Boolean(data.verified); } if (data.confidence !== undefined) { const confidence = Number(data.confidence); if (isNaN(confidence) || confidence < 0 || confidence > 1) { throw new ValidationError('Confidence must be a number between 0 and 1', 'confidence'); } updates.confidence = confidence; } if (data.master_exchange_id !== undefined) { if (typeof data.master_exchange_id !== 'string') { throw new ValidationError('Master exchange ID must be a string', 'master_exchange_id'); } updates.master_exchange_id = data.master_exchange_id.trim(); } if (Object.keys(updates).length === 0) { throw new ValidationError('No valid fields to update'); } return updates; }