From 0bec1eca83c97ba9581bf7431336d5c2d85ca1ab Mon Sep 17 00:00:00 2001 From: Boki Date: Wed, 18 Jun 2025 09:29:20 -0400 Subject: [PATCH] fixed exchange mappings and added visible column --- .../src/services/sync-manager.ts | 5 +-- apps/web-api/src/routes/exchange.routes.ts | 29 ++++++++++++--- .../exchanges/components/ExchangesTable.tsx | 2 +- .../src/features/exchanges/types/index.ts | 2 ++ .../postgres/init/05-add-visible-column.sql | 35 +++++++++++++++++++ 5 files changed, 66 insertions(+), 7 deletions(-) create mode 100644 database/postgres/init/05-add-visible-column.sql diff --git a/apps/data-sync-service/src/services/sync-manager.ts b/apps/data-sync-service/src/services/sync-manager.ts index f1d774c..3f9c7d5 100644 --- a/apps/data-sync-service/src/services/sync-manager.ts +++ b/apps/data-sync-service/src/services/sync-manager.ts @@ -259,8 +259,8 @@ export class SyncManager { private async createExchange(qmExchange: any): Promise { const query = ` - INSERT INTO exchanges (code, name, country, currency) - VALUES ($1, $2, $3, $4) + INSERT INTO exchanges (code, name, country, currency, visible) + VALUES ($1, $2, $3, $4, $5) ON CONFLICT (code) DO NOTHING `; @@ -269,6 +269,7 @@ export class SyncManager { qmExchange.exchangeShortName || qmExchange.name, qmExchange.countryCode || 'US', 'USD', // Default currency, can be improved + true, // New exchanges are visible by default ]); } diff --git a/apps/web-api/src/routes/exchange.routes.ts b/apps/web-api/src/routes/exchange.routes.ts index 9c9ec0a..76def4d 100644 --- a/apps/web-api/src/routes/exchange.routes.ts +++ b/apps/web-api/src/routes/exchange.routes.ts @@ -14,7 +14,7 @@ exchangeRoutes.get('/', async c => { try { const postgresClient = getPostgreSQLClient(); - // First get all exchanges with counts + // First get all exchanges with counts (only visible ones) const exchangesQuery = ` SELECT e.id, @@ -23,6 +23,7 @@ exchangeRoutes.get('/', async c => { e.country, e.currency, e.active, + e.visible, e.created_at, e.updated_at, COUNT(pem.id) as provider_mapping_count, @@ -31,7 +32,8 @@ exchangeRoutes.get('/', async c => { STRING_AGG(DISTINCT pem.provider, ', ') as providers FROM exchanges e LEFT JOIN provider_exchange_mappings pem ON e.id = pem.master_exchange_id - GROUP BY e.id, e.code, e.name, e.country, e.currency, e.active, e.created_at, e.updated_at + WHERE e.visible = true + GROUP BY e.id, e.code, e.name, e.country, e.currency, e.active, e.visible, e.created_at, e.updated_at ORDER BY e.code `; @@ -97,8 +99,8 @@ exchangeRoutes.get('/:id', async c => { const exchangeId = c.req.param('id'); const postgresClient = getPostgreSQLClient(); - // Get exchange details - const exchangeQuery = 'SELECT * FROM exchanges WHERE id = $1'; + // Get exchange details (only if visible) + const exchangeQuery = 'SELECT * FROM exchanges WHERE id = $1 AND visible = true'; const exchangeResult = await postgresClient.query(exchangeQuery, [exchangeId]); if (exchangeResult.rows.length === 0) { @@ -169,6 +171,11 @@ exchangeRoutes.patch('/:id', async c => { values.push(body.currency); } + if (body.visible !== undefined) { + updateFields.push(`visible = $${paramIndex++}`); + values.push(body.visible); + } + if (updateFields.length === 0) { return c.json({ success: false, error: 'No valid fields to update' }, 400); } @@ -189,6 +196,20 @@ exchangeRoutes.patch('/:id', async c => { return c.json({ success: false, error: 'Exchange not found' }, 404); } + // If hiding an exchange (visible=false), delete its provider mappings to make them available for remapping + if (body.visible === false) { + const deleteMappingsQuery = ` + DELETE FROM provider_exchange_mappings + WHERE master_exchange_id = $1 + `; + const mappingsResult = await postgresClient.query(deleteMappingsQuery, [exchangeId]); + + logger.info('Deleted provider mappings for hidden exchange', { + exchangeId, + deletedMappings: mappingsResult.rowCount + }); + } + logger.info('Exchange updated', { exchangeId, updates: body }); return c.json({ diff --git a/apps/web-app/src/features/exchanges/components/ExchangesTable.tsx b/apps/web-app/src/features/exchanges/components/ExchangesTable.tsx index 7a1aec4..cc8558e 100644 --- a/apps/web-app/src/features/exchanges/components/ExchangesTable.tsx +++ b/apps/web-app/src/features/exchanges/components/ExchangesTable.tsx @@ -49,7 +49,7 @@ export function ExchangesTable() { const handleDeleteExchange = useCallback(async (exchangeId: string, exchangeName: string) => { if (confirm(`Are you sure you want to delete "${exchangeName}"? This will hide the exchange and make all its provider mappings available for remapping.`)) { - const success = await updateExchange(exchangeId, { active: false }); + const success = await updateExchange(exchangeId, { visible: false }); if (success) { // Optionally refresh the list or show a success message refetch(); diff --git a/apps/web-app/src/features/exchanges/types/index.ts b/apps/web-app/src/features/exchanges/types/index.ts index 3c4904d..4350a3c 100644 --- a/apps/web-app/src/features/exchanges/types/index.ts +++ b/apps/web-app/src/features/exchanges/types/index.ts @@ -24,6 +24,7 @@ export interface Exchange { country: string; currency: string; active: boolean; + visible: boolean; created_at: string; updated_at: string; provider_mapping_count: string; @@ -47,6 +48,7 @@ export interface ExchangesApiResponse { export interface UpdateExchangeRequest { name?: string; active?: boolean; + visible?: boolean; country?: string; currency?: string; } diff --git a/database/postgres/init/05-add-visible-column.sql b/database/postgres/init/05-add-visible-column.sql new file mode 100644 index 0000000..53e1b7b --- /dev/null +++ b/database/postgres/init/05-add-visible-column.sql @@ -0,0 +1,35 @@ +-- Add visible column to exchanges table +-- Connect to trading_bot database +\c trading_bot; + +-- Add visible column to exchanges table with default true +ALTER TABLE exchanges +ADD COLUMN IF NOT EXISTS visible BOOLEAN DEFAULT true; + +-- Update existing records to be visible by default +UPDATE exchanges SET visible = true WHERE visible IS NULL; + +-- Create index for visibility filtering +CREATE INDEX IF NOT EXISTS idx_exchanges_visible ON exchanges(visible); + +-- Update the exchange_provider_summary view to include visibility +CREATE OR REPLACE VIEW exchange_provider_summary AS +SELECT + e.code as master_code, + e.name as master_name, + e.country, + e.currency, + e.active as master_active, + e.visible as master_visible, + COUNT(pem.id) as provider_mappings, + COUNT(CASE WHEN pem.active = true THEN 1 END) as active_mappings, + COUNT(CASE WHEN pem.verified = true THEN 1 END) as verified_mappings, + STRING_AGG(DISTINCT pem.provider, ', ') as providers +FROM exchanges e +LEFT JOIN provider_exchange_mappings pem ON e.id = pem.master_exchange_id +WHERE e.visible = true -- Only show visible exchanges in summary +GROUP BY e.id, e.code, e.name, e.country, e.currency, e.active, e.visible +ORDER BY e.code; + +-- Show what we created +SELECT 'Added visible column to exchanges table' as status; \ No newline at end of file