/** * Exchange management routes - Refactored */ import { Hono } from 'hono'; import { getLogger } from '@stock-bot/logger'; import { exchangeService } from '../services/exchange.service'; import { validateCreateExchange, validateUpdateExchange, validateCreateProviderMapping, validateUpdateProviderMapping, } from '../utils/validation'; import { handleError, createSuccessResponse } from '../utils/error-handler'; const logger = getLogger('exchange-routes'); export const exchangeRoutes = new Hono(); // Get all exchanges with provider mapping counts and mappings exchangeRoutes.get('/', async c => { logger.debug('Getting all exchanges'); try { const exchanges = await exchangeService.getAllExchanges(); logger.info('Successfully retrieved exchanges', { count: exchanges.length }); return c.json(createSuccessResponse(exchanges, undefined, exchanges.length)); } catch (error) { logger.error('Failed to get exchanges', { error }); return handleError(c, error, 'to get exchanges'); } }); // Get exchange by ID with detailed provider mappings exchangeRoutes.get('/:id', async c => { const exchangeId = c.req.param('id'); logger.debug('Getting exchange by ID', { exchangeId }); try { const result = await exchangeService.getExchangeById(exchangeId); if (!result) { logger.warn('Exchange not found', { exchangeId }); return c.json(createSuccessResponse(null, 'Exchange not found'), 404); } logger.info('Successfully retrieved exchange details', { exchangeId, exchangeCode: result.exchange.code, mappingCount: result.provider_mappings.length }); return c.json(createSuccessResponse(result)); } catch (error) { logger.error('Failed to get exchange details', { error, exchangeId }); return handleError(c, error, 'to get exchange details'); } }); // Create new exchange exchangeRoutes.post('/', async c => { logger.debug('Creating new exchange'); try { const body = await c.req.json(); logger.debug('Received exchange creation request', { requestBody: body }); const validatedData = validateCreateExchange(body); logger.debug('Exchange data validated successfully', { validatedData }); const exchange = await exchangeService.createExchange(validatedData); logger.info('Exchange created successfully', { exchangeId: exchange.id, code: exchange.code, name: exchange.name }); return c.json( createSuccessResponse(exchange, 'Exchange created successfully'), 201 ); } catch (error) { logger.error('Failed to create exchange', { error }); return handleError(c, error, 'to create exchange'); } }); // Update exchange (activate/deactivate, rename, etc.) exchangeRoutes.patch('/:id', async c => { const exchangeId = c.req.param('id'); logger.debug('Updating exchange', { exchangeId }); try { const body = await c.req.json(); logger.debug('Received exchange update request', { exchangeId, updates: body }); const validatedUpdates = validateUpdateExchange(body); logger.debug('Exchange update data validated', { exchangeId, validatedUpdates }); const exchange = await exchangeService.updateExchange(exchangeId, validatedUpdates); if (!exchange) { logger.warn('Exchange not found for update', { exchangeId }); return c.json(createSuccessResponse(null, 'Exchange not found'), 404); } logger.info('Exchange updated successfully', { exchangeId, code: exchange.code, updates: validatedUpdates }); // Log special actions if (validatedUpdates.visible === false) { logger.warn('Exchange marked as hidden - provider mappings will be deleted', { exchangeId, code: exchange.code }); } return c.json(createSuccessResponse(exchange, 'Exchange updated successfully')); } catch (error) { logger.error('Failed to update exchange', { error, exchangeId }); return handleError(c, error, 'to update exchange'); } }); // Get all provider mappings exchangeRoutes.get('/provider-mappings/all', async c => { logger.debug('Getting all provider mappings'); try { const mappings = await exchangeService.getAllProviderMappings(); logger.info('Successfully retrieved all provider mappings', { count: mappings.length }); return c.json(createSuccessResponse(mappings, undefined, mappings.length)); } catch (error) { logger.error('Failed to get provider mappings', { error }); return handleError(c, error, 'to get provider mappings'); } }); // Get provider mappings by provider exchangeRoutes.get('/provider-mappings/:provider', async c => { const provider = c.req.param('provider'); logger.debug('Getting provider mappings by provider', { provider }); try { const mappings = await exchangeService.getProviderMappingsByProvider(provider); logger.info('Successfully retrieved provider mappings', { provider, count: mappings.length }); return c.json( createSuccessResponse( mappings, undefined, mappings.length ) ); } catch (error) { logger.error('Failed to get provider mappings', { error, provider }); return handleError(c, error, 'to get provider mappings'); } }); // Update provider mapping (activate/deactivate, verify, change confidence) exchangeRoutes.patch('/provider-mappings/:id', async c => { const mappingId = c.req.param('id'); logger.debug('Updating provider mapping', { mappingId }); try { const body = await c.req.json(); logger.debug('Received provider mapping update request', { mappingId, updates: body }); const validatedUpdates = validateUpdateProviderMapping(body); logger.debug('Provider mapping update data validated', { mappingId, validatedUpdates }); const mapping = await exchangeService.updateProviderMapping(mappingId, validatedUpdates); if (!mapping) { logger.warn('Provider mapping not found for update', { mappingId }); return c.json(createSuccessResponse(null, 'Provider mapping not found'), 404); } logger.info('Provider mapping updated successfully', { mappingId, provider: mapping.provider, providerExchangeCode: mapping.provider_exchange_code, updates: validatedUpdates }); return c.json(createSuccessResponse(mapping, 'Provider mapping updated successfully')); } catch (error) { logger.error('Failed to update provider mapping', { error, mappingId }); return handleError(c, error, 'to update provider mapping'); } }); // Create new provider mapping exchangeRoutes.post('/provider-mappings', async c => { logger.debug('Creating new provider mapping'); try { const body = await c.req.json(); logger.debug('Received provider mapping creation request', { requestBody: body }); const validatedData = validateCreateProviderMapping(body); logger.debug('Provider mapping data validated successfully', { validatedData }); const mapping = await exchangeService.createProviderMapping(validatedData); logger.info('Provider mapping created successfully', { mappingId: mapping.id, provider: mapping.provider, providerExchangeCode: mapping.provider_exchange_code, masterExchangeId: mapping.master_exchange_id }); return c.json( createSuccessResponse(mapping, 'Provider mapping created successfully'), 201 ); } catch (error) { logger.error('Failed to create provider mapping', { error }); return handleError(c, error, 'to create provider mapping'); } }); // Get all available providers exchangeRoutes.get('/providers/list', async c => { logger.debug('Getting providers list'); try { const providers = await exchangeService.getProviders(); logger.info('Successfully retrieved providers list', { count: providers.length, providers }); return c.json(createSuccessResponse(providers)); } catch (error) { logger.error('Failed to get providers list', { error }); return handleError(c, error, 'to get providers list'); } }); // Get unmapped provider exchanges by provider exchangeRoutes.get('/provider-exchanges/unmapped/:provider', async c => { const provider = c.req.param('provider'); logger.debug('Getting unmapped provider exchanges', { provider }); try { const exchanges = await exchangeService.getUnmappedProviderExchanges(provider); logger.info('Successfully retrieved unmapped provider exchanges', { provider, count: exchanges.length }); return c.json( createSuccessResponse( exchanges, undefined, exchanges.length ) ); } catch (error) { logger.error('Failed to get unmapped provider exchanges', { error, provider }); return handleError(c, error, 'to get unmapped provider exchanges'); } }); // Get exchange statistics exchangeRoutes.get('/stats/summary', async c => { logger.debug('Getting exchange statistics'); try { const stats = await exchangeService.getExchangeStats(); logger.info('Successfully retrieved exchange statistics', { stats }); return c.json(createSuccessResponse(stats)); } catch (error) { logger.error('Failed to get exchange statistics', { error }); return handleError(c, error, 'to get exchange statistics'); } });