Skip to content

refactor: Nettoyage complet code obsolète - Suppression fallbacks RE…#7

Merged
chpeu merged 1 commit into
claude2from
cursor
Nov 10, 2025
Merged

refactor: Nettoyage complet code obsolète - Suppression fallbacks RE…#7
chpeu merged 1 commit into
claude2from
cursor

Conversation

@chpeu

@chpeu chpeu commented Nov 10, 2025

Copy link
Copy Markdown
Owner

User description

…ST, marquage endpoints deprecated, WebSocket natif uniquement


PR Type

Enhancement, Refactoring


Description

  • Mark REST API endpoints as deprecated with WebSocket alternatives

  • Remove REST API fallbacks from frontend components

  • Enforce WebSocket-only communication throughout application

  • Simplify error handling by eliminating dual-path code logic


Diagram Walkthrough

flowchart LR
  A["REST API Endpoints"] -->|"Mark Deprecated"| B["Deprecation Warnings"]
  C["Frontend Components"] -->|"Remove Fallbacks"| D["WebSocket Only"]
  E["Error Handling"] -->|"Simplify"| F["Direct Error Messages"]
  D --> G["Cleaner Codebase"]
  B --> G
  F --> G
Loading

File Walkthrough

Relevant files
Deprecation, documentation
main.py
Mark REST endpoints deprecated, WebSocket native only       

main.py

  • Added deprecation warnings to 7 REST endpoints (/api/state,
    /api/start, /api/stop, /api/scanner/start, /api/position/close,
    /api/log/config, /api/config/update)
  • Updated docstrings to recommend WebSocket alternatives for each
    deprecated endpoint
  • Modified add_log() function to use WebSocket native only instead of
    dual SocketIO + WebSocket support
  • Maintained backward compatibility while clearly marking endpoints as
    deprecated
+35/-8   
Refactoring, error handling
BotControls.svelte
Remove REST fallbacks, enforce WebSocket commands               

frontend/src/lib/components/BotControls.svelte

  • Removed REST API fallback logic from startBot() and stopBot()
    functions
  • Replaced dual-path code with WebSocket-only implementation using
    sendCommandViaWS()
  • Changed error handling to throw exceptions when WebSocket is
    unavailable instead of silently falling back
  • Added user-facing error alerts for better feedback
+14/-31 
PositionCard.svelte
Simplify position closing to WebSocket only                           

frontend/src/lib/components/PositionCard.svelte

  • Removed extensive REST API fallback code from closePosition() function
  • Simplified to WebSocket-only implementation with sendCommandViaWS()
  • Eliminated nested try-catch blocks for fallback REST calls
  • Replaced complex error recovery logic with simple error alert
+2/-44   
SettingsPanel.svelte
Remove REST fallbacks from settings synchronization           

frontend/src/lib/components/SettingsPanel.svelte

  • Removed REST API fallback from config loading in loadConfig() function
  • Removed REST fallback from updateSetting() function
  • Changed error handling to display WebSocket-specific error messages
  • Eliminated dual-path code for configuration synchronization
+2/-31   
VariablesPanel.svelte
Migrate variables panel to WebSocket-only communication   

frontend/src/lib/components/VariablesPanel.svelte

  • Replaced REST API call with WebSocket sendRequestViaWS() in
    loadConfig() function
  • Removed REST fallback from saveConfig() function
  • Removed REST fallback from logConfigChange() function
  • Simplified error handling to use WebSocket-only approach
+31/-59 
+page.svelte
Enforce WebSocket-only state management in main page         

frontend/src/routes/+page.svelte

  • Removed REST API fallback from changeTpSlMode() function
  • Removed REST API fallback from loadInitialState() function
  • Changed to throw errors when WebSocket is unavailable instead of
    falling back to REST
  • Simplified state loading logic by removing dual-path code
+21/-52 

…ST, marquage endpoints deprecated, WebSocket natif uniquement
@chpeu chpeu merged commit b3e1f97 into claude2 Nov 10, 2025
@qodo-code-review

Copy link
Copy Markdown

PR Compliance Guide 🔍

Below is a summary of compliance checks for this PR:

Security Compliance
🟢
No security concerns identified No security vulnerabilities detected by AI analysis. Human verification advised for critical code.
Ticket Compliance
🎫 No ticket provided
  • Create ticket/issue
Codebase Duplication Compliance
Codebase context is not defined

Follow the guide to enable codebase context checks.

Custom Compliance
🟢
Generic: Meaningful Naming and Self-Documenting Code

Objective: Ensure all identifiers clearly express their purpose and intent, making code
self-documenting

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Secure Logging Practices

Objective: To ensure logs are useful for debugging and auditing without exposing sensitive
information like PII, PHI, or cardholder data.

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Comprehensive Audit Trails

Objective: To create a detailed and reliable record of critical system actions for security analysis
and compliance.

Status:
Missing context: Newly added deprecation docstrings and frontend WebSocket-only flows perform critical
actions (start/stop scanner, close position, update config) without clearly adding audit
logs including user identity and outcome in the new paths.

Referred Code
"""
⚠️ DEPRECATED: Utiliser WebSocket command 'start_scanner' à la place
Conservé pour compatibilité uniquement
Démarrer le scanner et le scheduler
"""
init_instances()

# 🔥 JOUR 3: Si pas de top_pairs, faire un scan initial
if not app_state['top_pairs']:
    await add_log('INFO', 'Scanner démarré', 'Scan initial des top pairs...')
    if scanner:
        top_pairs = await scanner.scan_top_pairs(20)
        app_state['top_pairs'] = top_pairs
        await ws_manager.emit('top_pairs_update', {'pairs': top_pairs})

        # Démarrer WebSocket pour les top pairs
        if price_provider and top_pairs:
            symbols = [p.get('symbol', '') for p in top_pairs[:30] if p.get('symbol')]
            if symbols:
                try:
                    await price_provider.start_websocket(symbols)


 ... (clipped 25 lines)

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Robust Error Handling and Edge Case Management

Objective: Ensure comprehensive error handling that provides meaningful context and graceful
degradation

Status:
User error handling: New WebSocket-only flows throw on disconnected sockets and alert generic messages without
retry/backoff or alternative path, which may degrade UX and lacks recovery handling for
edge cases like transient disconnections.

Referred Code
async function startBot() {
	try {
		loading = true;
		const { getWebSocket, sendCommandViaWS } = await import('$lib/utils/websocket');
		const ws = getWebSocket();

		if (!ws || !ws.connected) {
			throw new Error('WebSocket non connecté. Veuillez attendre la connexion.');
		}

		await sendCommandViaWS('start_scanner', {});
		console.log('✅ Bot started via WebSocket');
	} catch (err) {
		console.error('❌ Error starting bot:', err);
		alert(`❌ Erreur: ${err.message || 'Impossible de démarrer le scanner'}`);
	} finally {
		loading = false;
	}
}

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Secure Error Handling

Objective: To prevent the leakage of sensitive system information through error messages while
providing sufficient detail for internal debugging.

Status:
Error exposure: New code continues to return JSON with 'error': str(e) to clients which may
expose internal details; verify that these endpoints are not user-facing or that errors
are sanitized.

Referred Code
    'error': str(e)
}, status_code=200)  # Retourner 200 avec stats vides

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Security-First Input Validation and Data Handling

Objective: Ensure all data inputs are validated, sanitized, and handled securely to prevent
vulnerabilities

Status:
Input validation: Newly added endpoints still parse JSON bodies and act on commands (e.g., config updates)
without visible validation or authorization checks in the added lines, risking improper
input handling.

Referred Code
@app.post("/api/config/update")  # ⚠️ DEPRECATED: Utiliser WebSocket command 'update_config' à la place
async def api_update_config(request: Request):
    """
    ⚠️ DEPRECATED: Utiliser WebSocket command 'update_config' à la place
    Conservé pour compatibilité uniquement
    Modifier la configuration à la volée (tous les paramètres)
    """
    from config import TRADING_CONFIG

    try:
        data = await request.json() if hasattr(request, 'json') else {}
        data = data if isinstance(data, dict) else {}

Learn more about managing compliance generic rules or creating your own custom rules

Compliance status legend 🟢 - Fully Compliant
🟡 - Partial Compliant
🔴 - Not Compliant
⚪ - Requires Further Human Verification
🏷️ - Compliance label

@qodo-code-review

Copy link
Copy Markdown

PR Compliance Guide 🔍

Below is a summary of compliance checks for this PR:

Security Compliance
WebSocket auth/CSRF

Description: The code calls initWebSocket() and ws.sendCommand() but other updated components use
getWebSocket()/sendCommandViaWS; if initWebSocket auto-connects without origin checks or
CSRF protections for WS upgrade, it could allow unauthorized command invocation—verify WS
authentication/authorization and origin checks.
+page.svelte [41-44]

Referred Code
// 🔥 MIGRATION COMPLÈTE: Utiliser WebSocket natif au lieu de REST
const ws = initWebSocket();
const result = await ws.sendCommand('update_config', { tp_sl_mode: tpSlMode });
Insecure legacy endpoints

Description: Deprecated REST endpoints like /api/state, /api/start, /api/stop, /api/position/close, and
/api/config/update remain enabled and can trigger sensitive operations; ensure they
require proper authentication/authorization or are rate-limited to prevent abuse.
main.py [1249-1253]

Referred Code
"""
⚠️ DEPRECATED: Utiliser WebSocket request 'state' à la place
Conservé pour compatibilité uniquement
"""
"""🔥 NOUVEAU: État complet de l'application (config + UI + position + stats + etc.)"""
Ticket Compliance
🎫 No ticket provided
  • Create ticket/issue
Codebase Duplication Compliance
Codebase context is not defined

Follow the guide to enable codebase context checks.

Custom Compliance
🟢
Generic: Meaningful Naming and Self-Documenting Code

Objective: Ensure all identifiers clearly express their purpose and intent, making code
self-documenting

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Comprehensive Audit Trails

Objective: To create a detailed and reliable record of critical system actions for security analysis
and compliance.

Status:
Missing Audit Context: New deprecation updates and control endpoints (e.g., start/stop, config update,
close_position) do not add explicit audit logs tying actions to a user identity or
outcome, which may leave critical actions insufficiently auditable.

Referred Code
"""
⚠️ DEPRECATED: Utiliser WebSocket command 'start_scanner' à la place
Conservé pour compatibilité uniquement
Démarrer le scanner et le scheduler
"""
init_instances()

# 🔥 JOUR 3: Si pas de top_pairs, faire un scan initial
if not app_state['top_pairs']:
    await add_log('INFO', 'Scanner démarré', 'Scan initial des top pairs...')
    if scanner:
        top_pairs = await scanner.scan_top_pairs(20)
        app_state['top_pairs'] = top_pairs
        await ws_manager.emit('top_pairs_update', {'pairs': top_pairs})

        # Démarrer WebSocket pour les top pairs
        if price_provider and top_pairs:
            symbols = [p.get('symbol', '') for p in top_pairs[:30] if p.get('symbol')]
            if symbols:
                try:
                    await price_provider.start_websocket(symbols)


 ... (clipped 1148 lines)

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Robust Error Handling and Edge Case Management

Objective: Ensure comprehensive error handling that provides meaningful context and graceful
degradation

Status:
No Fallback Path: New WebSocket-only flows throw on disconnected sockets without a functional fallback or
retry strategy, which may degrade robustness when the WS is temporarily unavailable.

Referred Code
	const { getWebSocket, sendCommandViaWS } = await import('$lib/utils/websocket');
	const ws = getWebSocket();

	if (!ws || !ws.connected) {
		throw new Error('WebSocket non connecté. Veuillez attendre la connexion.');
	}

	await sendCommandViaWS('start_scanner', {});
	console.log('✅ Bot started via WebSocket');
} catch (err) {
	console.error('❌ Error starting bot:', err);
	alert(`❌ Erreur: ${err.message || 'Impossible de démarrer le scanner'}`);
} finally {

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Secure Error Handling

Objective: To prevent the leakage of sensitive system information through error messages while
providing sufficient detail for internal debugging.

Status:
Verbose Alerts: The UI surfaces raw error messages from exceptions directly to users via alert strings,
which may expose internal details if upstream errors contain sensitive info.

Referred Code
	// 🔥 MIGRATION COMPLÈTE: Utiliser WebSocket natif au lieu de REST
	const result = await sendCommandViaWS('update_config', { [backendKey]: value });

	if (result && result.updated) {
		console.log(`✅ ${key} synchronisé avec backend via WebSocket: ${backendKey} = ${value}`);
	} else {
		console.log(`✅ ${key} synchronisé avec backend via WebSocket: ${backendKey} = ${value}`);
	}
} catch (err) {
	console.error(`❌ Erreur synchronisation ${key} via WebSocket:`, err);
	alert(`❌ Erreur: Impossible de synchroniser ${key}. Vérifiez la connexion WebSocket.`);
}

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Secure Logging Practices

Objective: To ensure logs are useful for debugging and auditing without exposing sensitive
information like PII, PHI, or cardholder data.

Status:
Logs May Leak: New error handlers log full exceptions (e.g., f-strings of Exception) and return str(e) to
clients, which risks leaking sensitive info in logs or responses depending on exception
contents.

Referred Code
        logger.error(f"Erreur check position: {e}")
        return JSONResponse({'error': str(e)}, status_code=500)


@app.post("/api/position/close")
async def api_close_position():
    """
    ⚠️ DEPRECATED: Utiliser WebSocket command 'close_position' à la place
    Conservé pour compatibilité uniquement
    Clôturer position manuellement
    """
    init_instances()

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Security-First Input Validation and Data Handling

Objective: Ensure all data inputs are validated, sanitized, and handled securely to prevent
vulnerabilities

Status:
Input Validation: Endpoints like api_update_config and api_log_config accept JSON bodies and pass values to
configuration/logging without visible validation or sanitization in the diff, which may
permit unsafe inputs.

Referred Code
    try:
        data = await request.json() if hasattr(request, 'json') else {}
        data = data if isinstance(data, dict) else {}

        # Logger le changement de config
        config_key = data.get('key', 'unknown')
        config_value = data.get('value', 'unknown')
        await add_log('INFO', f'Config modifiée: {config_key}', str(config_value))

        return JSONResponse({'status': 'logged', 'key': config_key, 'value': config_value})
    except Exception as e:
        logger.error(f"Erreur log config: {e}")
        return JSONResponse({'error': str(e)}, status_code=500)

@app.post("/api/config")
@app.post("/api/config/update")  # ⚠️ DEPRECATED: Utiliser WebSocket command 'update_config' à la place
async def api_update_config(request: Request):
    """
    ⚠️ DEPRECATED: Utiliser WebSocket command 'update_config' à la place
    Conservé pour compatibilité uniquement
    Modifier la configuration à la volée (tous les paramètres)


 ... (clipped 6 lines)

Learn more about managing compliance generic rules or creating your own custom rules

Compliance status legend 🟢 - Fully Compliant
🟡 - Partial Compliant
🔴 - Not Compliant
⚪ - Requires Further Human Verification
🏷️ - Compliance label

@qodo-code-review

Copy link
Copy Markdown

PR Code Suggestions ✨

Explore these optional code suggestions:

CategorySuggestion                                                                                                                                    Impact
High-level
Reconsider removing REST fallbacks entirely

The PR removes REST API fallbacks, making WebSockets the sole communication
method. This introduces a single point of failure; a better approach would be a
centralized service that implements a "WebSocket-first, REST-fallback" strategy
for improved resilience.

Examples:

frontend/src/lib/components/BotControls.svelte [6-24]
	async function startBot() {
		try {
			loading = true;
			const { getWebSocket, sendCommandViaWS } = await import('$lib/utils/websocket');
			const ws = getWebSocket();

			if (!ws || !ws.connected) {
				throw new Error('WebSocket non connecté. Veuillez attendre la connexion.');
			}


 ... (clipped 9 lines)
frontend/src/lib/components/PositionCard.svelte [7-31]
	async function closePosition() {
		if (!confirm('Êtes-vous sûr de vouloir clôturer cette position manuellement ?')) {
			return;
		}

		// 🔥 FIX: Mise à jour optimiste immédiate pour feedback instantané
		clearPosition();

		try {
			// 🔥 MIGRATION COMPLÈTE: Utiliser WebSocket natif uniquement

 ... (clipped 15 lines)

Solution Walkthrough:

Before:

// In a component like BotControls.svelte
async function startBot() {
  try {
    const { getWebSocket, sendCommandViaWS } = await import('$lib/utils/websocket');
    const ws = getWebSocket();

    if (!ws || !ws.connected) {
      throw new Error('WebSocket not connected.');
    }

    await sendCommandViaWS('start_scanner', {});
    console.log('Bot started via WebSocket');
  } catch (err) {
    console.error('Error starting bot:', err);
    alert(`Error: ${err.message}`);
  }
}

After:

// In a new central communication service, e.g., 'lib/api.js'
import { sendCommandViaWS, getWebSocket } from '$lib/utils/websocket';
import { sendCommandViaREST } from '$lib/utils/rest'; // Hypothetical REST utility

export async function sendCommand(command, params) {
  const ws = getWebSocket();
  if (ws && ws.connected) {
    try {
      return await sendCommandViaWS(command, params);
    } catch (wsError) {
      console.warn('WebSocket command failed, falling back to REST:', wsError);
      return await sendCommandViaREST(command, params);
    }
  }
  return await sendCommandViaREST(command, params);
}

// In a component like BotControls.svelte
import { sendCommand } from '$lib/api';
async function startBot() {
  try {
    await sendCommand('start_scanner', {});
  } catch (err) {
    alert(`Error: ${err.message}`);
  }
}
Suggestion importance[1-10]: 9

__

Why: The suggestion correctly identifies a critical architectural flaw introduced by the PR: removing REST fallbacks makes the application brittle and degrades user experience upon WebSocket failure, which is a significant regression in robustness.

High
Possible issue
Revert optimistic UI on failure

In closePosition, revert the optimistic UI update by re-fetching the state if
the WebSocket call to close the position fails, preventing UI/backend state
inconsistency.

frontend/src/lib/components/PositionCard.svelte [12-30]

 		// 🔥 FIX: Mise à jour optimiste immédiate pour feedback instantané
 		clearPosition();
 
 		try {
 			// 🔥 MIGRATION COMPLÈTE: Utiliser WebSocket natif uniquement
 			const result = await sendCommandViaWS('close_position', {
 				reason: 'MANUAL',
 				exit_price: $activePosition.current_price
 			});
 			
 			if (result && result.status === 'closed') {
 				console.log('✅ Position fermée via WebSocket:', result.result);
 			} else {
 				console.log('✅ Position fermée via WebSocket');
 			}
 		} catch (err) {
 			console.error('❌ Error closing position via WebSocket:', err);
 			alert(`❌ Erreur: ${err.message || 'Impossible de clôturer la position. Vérifiez la connexion WebSocket.'}`);
+			// Revert optimistic update on failure
+			try {
+				const { sendRequestViaWS } = await import('$lib/utils/websocket');
+				const response = await sendRequestViaWS('state', {});
+				const stateData = response?.data || response;
+				if (stateData && stateData.active_position) {
+					updatePosition(stateData.active_position);
+				}
+			} catch (revertErr) {
+				console.error('❌ Failed to revert optimistic UI update:', revertErr);
+			}
 		}

[To ensure code accuracy, apply this suggestion manually]

Suggestion importance[1-10]: 9

__

Why: The suggestion correctly identifies a UI state inconsistency bug introduced by the PR, where a failed operation leaves the UI in a misleading state, and proposes a fix that was present in the pre-refactor code.

High
  • More

chpeu pushed a commit that referenced this pull request Nov 12, 2025
🐛 BUGS CORRIGÉS:

**Bug #1 - Double fees TP partiel** ⚠️ MOYENNE
Fichier: core/position/pnl_calculator.py:131-137
Problème: Fees calculés sur size totale même avec TP partiel
- Fees entrée partie vendue payés 2× (TP partiel + clôture)
- Fees sur-estimés, PnL net sous-estimé
Fix: Calcul fees uniquement sur size_remaining si partial_tp_sold
Impact: PnL net plus précis pour positions avec TP partiel

**Bug #3 - Race condition config_updated** 🟡 MOYENNE
Fichier: frontend/src/lib/components/VariablesPanel.svelte:534-540
Problème: Modifications user écrasées par backend pendant debounce
- User édite → timer 2.5s démarre
- Backend émet config_updated → timer annulé, valeurs écrasées
- User perd ses modifications non sauvegardées
Fix: Ignorer config_updated si hasUnsavedChanges && debounceTimer
Impact: Modifications utilisateur protégées

**Bug #5 - Comparaisons float == 0** 🟢 FAIBLE
Fichier: core/callbacks/scanner_loop.py:257, 265, 287
Problème: Comparaisons exactes (== 0) sur floats peu robustes
- Floats peuvent être 0.0000001 au lieu de exactement 0.0
- Spread/depth invalides non détectés
Fix: Remplacé == 0 par <= 0 (plus robuste)
Impact: Meilleure détection valeurs invalides

**Bug #6 - Format durée > 24h** 🟢 FAIBLE
Fichier: frontend/src/lib/components/PositionCard.svelte:34-47
Problème: Positions > 24h affichées "25h 30m 15s" (illisible)
Fix: Ajout support jours → "1j 1h 30m"
Impact: Meilleure lisibilité positions longues

**Bug #7 - NaN formatters** ✅ DÉJÀ CORRIGÉ
Fichier: frontend/src/lib/utils/format.js
Statut: formatPercent/formatUSDT gèrent déjà isNaN()
Aucune modification nécessaire

📊 RÉSUMÉ:
- 4 bugs corrigés
- 1 bug déjà géré
- 4 fichiers modifiés
- 0 régression introduite

✅ Tests recommandés:
- Position avec TP partiel → vérifier fees corrects
- Éditer variable pendant que backend update → vérifier pas écrasé
- Position ouverte > 24h → vérifier format "Xj Yh Zm"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant