# API Reference - sdk_relay ## Vue d'Ensemble `sdk_relay` expose deux interfaces principales pour l'intégration avec les clients : - **WebSocket API** (port 8090) : Communication temps réel bidirectionnelle - **HTTP REST API** (port 8091) : Interface REST pour les opérations CRUD ## Base URLs ```bash # WebSocket ws://localhost:8090 wss://localhost:8090 # Sécurisé # HTTP REST http://localhost:8091 https://localhost:8091 # Sécurisé ``` --- ## WebSocket API ### Connexion ```javascript const ws = new WebSocket('ws://localhost:8090'); ws.onopen = () => { console.log('Connecté à sdk_relay'); // Envoyer le handshake initial sendHandshake(); }; ws.onmessage = (event) => { const message = JSON.parse(event.data); handleMessage(message); }; ws.onerror = (error) => { console.error('Erreur WebSocket:', error); }; ws.onclose = (event) => { console.log('Connexion fermée:', event.code, event.reason); }; ``` ### Handshake Initial **Endpoint :** `ws://localhost:8090` **Message de Handshake :** ```json { "type": "handshake", "client_id": "my-client-123", "version": "1.0.0", "capabilities": ["sync", "notifications", "health"], "timestamp": 1703001600 } ``` **Réponse de Handshake :** ```json { "type": "handshake_response", "status": "accepted", "relay_id": "relay-1", "version": "1.0.0", "capabilities": ["sync", "notifications", "health", "metrics"], "timestamp": 1703001600 } ``` ### Messages de Synchronisation #### 1. StateSync **Envoi :** ```json { "type": "sync", "sync_type": "StateSync", "relay_id": "relay-1", "payload": { "state": { "uptime": "3600", "version": "1.0.0", "network": "signet", "status": "healthy", "last_block": "12345", "connections": 5 } }, "timestamp": 1703001600, "message_id": "msg-123" } ``` **Réception :** ```json { "type": "sync_response", "sync_type": "StateSync", "relay_id": "relay-2", "payload": { "state": { "uptime": "1800", "version": "1.0.0", "network": "signet", "status": "healthy", "last_block": "12345", "connections": 3 } }, "timestamp": 1703001600, "message_id": "msg-124" } ``` #### 2. HealthSync **Envoi :** ```json { "type": "sync", "sync_type": "HealthSync", "relay_id": "relay-1", "payload": { "health": { "status": "healthy", "memory_usage": "128MB", "cpu_usage": "5%", "disk_usage": "2GB", "network_latency": "45ms" } }, "timestamp": 1703001600, "message_id": "msg-125" } ``` #### 3. MetricsSync **Envoi :** ```json { "type": "sync", "sync_type": "MetricsSync", "relay_id": "relay-1", "payload": { "metrics": { "known_relays": 3, "mesh_connections": 6, "sync_requests": 150, "sync_responses": 150, "cache_hits": 120, "cache_misses": 30, "avg_latency": 45.2, "error_count": 0 } }, "timestamp": 1703001600, "message_id": "msg-126" } ``` ### Messages de Notification #### 1. Payment Detected ```json { "type": "notification", "notification_type": "payment_detected", "data": { "txid": "abc123def456789...", "block_height": 12345, "block_hash": "def789abc123456...", "amount": "0.001", "address": "sp1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh", "confirmations": 1, "timestamp": 1703001600 }, "timestamp": 1703001600 } ``` #### 2. Block Mined ```json { "type": "notification", "notification_type": "block_mined", "data": { "block_height": 12346, "block_hash": "ghi012jkl345678...", "transactions": 150, "size": "1024000", "timestamp": 1703001600 }, "timestamp": 1703001600 } ``` #### 3. Relay Connected ```json { "type": "notification", "notification_type": "relay_connected", "data": { "relay_id": "relay-4", "address": "relay-4.example.com:8090", "version": "1.0.0", "capabilities": ["sync", "notifications"], "timestamp": 1703001600 }, "timestamp": 1703001600 } ``` ### Messages de Contrôle #### 1. Ping/Pong **Ping :** ```json { "type": "ping", "client_id": "my-client-123", "timestamp": 1703001600 } ``` **Pong :** ```json { "type": "pong", "relay_id": "relay-1", "timestamp": 1703001600 } ``` #### 2. Subscribe/Unsubscribe **Subscribe :** ```json { "type": "subscribe", "subscriptions": ["notifications", "health", "metrics"], "client_id": "my-client-123", "timestamp": 1703001600 } ``` **Unsubscribe :** ```json { "type": "unsubscribe", "subscriptions": ["metrics"], "client_id": "my-client-123", "timestamp": 1703001600 } ``` --- ## HTTP REST API ### Endpoints de Base #### 1. Health Check **GET** `/health` **Description :** Vérifier l'état de santé du service **Réponse :** ```json { "status": "healthy", "uptime": 3600, "version": "1.0.0", "timestamp": 1703001600, "services": { "bitcoin_core": "connected", "blindbit": "connected", "websocket": "listening", "sync_manager": "active" } } ``` **Codes de réponse :** - `200` : Service en bonne santé - `503` : Service indisponible #### 2. Métriques **GET** `/metrics` **Description :** Obtenir les métriques de performance **Réponse :** ```json { "sync_metrics": { "known_relays": 3, "mesh_connections": 6, "sync_requests": 150, "sync_responses": 150, "cache_hits": 120, "cache_misses": 30, "avg_latency": 45.2, "error_count": 0 }, "system_metrics": { "memory_usage": "128MB", "cpu_usage": "5%", "active_connections": 10, "total_requests": 1000, "uptime": 3600 }, "bitcoin_metrics": { "block_height": 12345, "connections": 8, "mempool_size": 150, "verification_progress": 0.9999 } } ``` #### 3. Configuration **GET** `/config` **Description :** Obtenir la configuration actuelle **Réponse :** ```json { "relay_id": "relay-1", "network": "signet", "ws_url": "0.0.0.0:8090", "http_url": "0.0.0.0:8091", "bitcoin_core": { "url": "http://bitcoin:18443", "wallet": "relay_wallet", "zmq_url": "tcp://bitcoin:29000" }, "blindbit": { "url": "http://blindbit:8000" }, "sync": { "interval": 30, "health_interval": 60, "metrics_interval": 120 }, "dev_mode": true, "standalone": false } ``` ### Endpoints de Gestion des Relais #### 4. Liste des Relais **GET** `/relays` **Description :** Obtenir la liste des relais connus **Paramètres de requête :** - `status` : Filtrer par statut (healthy, warning, critical) - `limit` : Limiter le nombre de résultats (défaut: 100) **Réponse :** ```json { "relays": [ { "relay_id": "relay-1", "address": "sdk_relay_1:8090", "version": "1.0.0", "uptime": 3600, "health": "healthy", "last_seen": 1703001600, "capabilities": ["sync", "notifications", "health"], "connections": 5 }, { "relay_id": "relay-2", "address": "sdk_relay_2:8090", "version": "1.0.0", "uptime": 1800, "health": "healthy", "last_seen": 1703001600, "capabilities": ["sync", "notifications"], "connections": 3 } ], "total": 2, "healthy": 2, "warning": 0, "critical": 0 } ``` #### 5. Détails d'un Relais **GET** `/relays/{relay_id}` **Description :** Obtenir les détails d'un relais spécifique **Réponse :** ```json { "relay_id": "relay-1", "address": "sdk_relay_1:8090", "version": "1.0.0", "uptime": 3600, "health": "healthy", "last_seen": 1703001600, "capabilities": ["sync", "notifications", "health"], "connections": 5, "metrics": { "sync_requests": 50, "sync_responses": 50, "avg_latency": 45.2 }, "configuration": { "network": "signet", "dev_mode": true } } ``` **Codes de réponse :** - `200` : Relais trouvé - `404` : Relais non trouvé ### Endpoints de Synchronisation #### 6. Statut de Synchronisation **GET** `/sync/status` **Description :** Obtenir le statut de la synchronisation **Réponse :** ```json { "status": "syncing", "last_sync": 1703001600, "next_sync": 1703001630, "sync_types": [ "StateSync", "HealthSync", "MetricsSync" ], "errors": [], "statistics": { "total_syncs": 150, "successful_syncs": 148, "failed_syncs": 2, "success_rate": 98.67 } } ``` #### 7. Forcer la Synchronisation **POST** `/sync/force` **Description :** Forcer une synchronisation immédiate **Corps de la requête :** ```json { "sync_types": ["StateSync", "HealthSync"], "target_relays": ["relay-2", "relay-3"] } ``` **Réponse :** ```json { "status": "sync_triggered", "sync_types": ["StateSync", "HealthSync"], "target_relays": ["relay-2", "relay-3"], "timestamp": 1703001600, "estimated_duration": "30s" } ``` #### 8. Historique des Synchronisations **GET** `/sync/history` **Description :** Obtenir l'historique des synchronisations **Paramètres de requête :** - `limit` : Nombre d'entrées (défaut: 50) - `since` : Timestamp de début - `until` : Timestamp de fin - `sync_type` : Filtrer par type de synchronisation **Réponse :** ```json { "history": [ { "timestamp": 1703001600, "sync_type": "StateSync", "target_relay": "relay-2", "status": "success", "duration": 45, "message_id": "msg-123" }, { "timestamp": 1703001570, "sync_type": "HealthSync", "target_relay": "relay-3", "status": "success", "duration": 32, "message_id": "msg-122" } ], "total": 2, "successful": 2, "failed": 0 } ``` ### Endpoints de Bitcoin Core #### 9. Informations Bitcoin **GET** `/bitcoin/info` **Description :** Obtenir les informations Bitcoin Core **Réponse :** ```json { "blockchain_info": { "chain": "signet", "blocks": 12345, "headers": 12345, "bestblockhash": "abc123...", "difficulty": 1.0, "verificationprogress": 0.9999, "initialblockdownload": false }, "network_info": { "connections": 8, "connections_in": 4, "connections_out": 4 }, "mempool_info": { "size": 150, "bytes": 1024000, "usage": 2048000 } } ``` #### 10. Bloc Spécifique **GET** `/bitcoin/blocks/{block_hash}` **Description :** Obtenir les détails d'un bloc **Réponse :** ```json { "hash": "abc123...", "height": 12345, "version": 536870912, "merkleroot": "def456...", "time": 1703001600, "mediantime": 1703001500, "nonce": 123456, "bits": "207fffff", "difficulty": 1.0, "size": 1024, "strippedsize": 512, "weight": 4096, "tx": [ "txid1...", "txid2..." ] } ``` ### Endpoints de Logs #### 11. Logs **GET** `/logs` **Description :** Obtenir les logs du service **Paramètres de requête :** - `level` : Niveau de log (debug, info, warn, error) - `limit` : Nombre de lignes (défaut: 100) - `since` : Timestamp de début - `search` : Recherche dans les logs **Réponse :** ```json { "logs": [ { "timestamp": "2024-12-19T10:00:00Z", "level": "info", "message": "Relay started successfully", "relay_id": "relay-1" }, { "timestamp": "2024-12-19T10:00:30Z", "level": "info", "message": "Sync completed", "relay_id": "relay-1", "sync_type": "StateSync" } ], "total": 2, "levels": { "debug": 0, "info": 2, "warn": 0, "error": 0 } } ``` ### Endpoints de Configuration #### 12. Mettre à Jour la Configuration **PUT** `/config` **Description :** Mettre à jour la configuration **Corps de la requête :** ```json { "sync": { "interval": 60, "health_interval": 120 }, "dev_mode": false } ``` **Réponse :** ```json { "status": "updated", "changes": [ "sync.interval: 30 -> 60", "sync.health_interval: 60 -> 120", "dev_mode: true -> false" ], "timestamp": 1703001600 } ``` #### 13. Redémarrer le Service **POST** `/restart` **Description :** Redémarrer le service **Réponse :** ```json { "status": "restarting", "timestamp": 1703001600, "estimated_duration": "30s" } ``` --- ## Codes d'Erreur ### WebSocket - `1000` : Fermeture normale - `1001` : Client part - `1002` : Erreur de protocole - `1003` : Type de données non supporté - `1006` : Connexion fermée anormalement - `1011` : Erreur serveur ### HTTP - `200` : Succès - `400` : Requête invalide - `401` : Non autorisé - `404` : Endpoint non trouvé - `422` : Données invalides - `429` : Trop de requêtes - `500` : Erreur serveur interne - `503` : Service indisponible --- ## Exemples d'Utilisation ### Client JavaScript Complet ```javascript class SdkRelayClient { constructor(wsUrl, httpUrl) { this.wsUrl = wsUrl; this.httpUrl = httpUrl; this.ws = null; this.clientId = `client-${Date.now()}`; } async connect() { return new Promise((resolve, reject) => { this.ws = new WebSocket(this.wsUrl); this.ws.onopen = () => { console.log('Connecté à sdk_relay'); this.sendHandshake(); resolve(); }; this.ws.onmessage = (event) => { const message = JSON.parse(event.data); this.handleMessage(message); }; this.ws.onerror = (error) => { console.error('Erreur WebSocket:', error); reject(error); }; }); } sendHandshake() { const handshake = { type: 'handshake', client_id: this.clientId, version: '1.0.0', capabilities: ['sync', 'notifications', 'health'] }; this.ws.send(JSON.stringify(handshake)); } handleMessage(message) { switch(message.type) { case 'handshake_response': console.log('Handshake accepté'); break; case 'notification': this.handleNotification(message); break; case 'sync': this.handleSync(message); break; case 'pong': console.log('Pong reçu'); break; } } handleNotification(message) { console.log('Notification:', message.notification_type, message.data); } handleSync(message) { console.log('Sync:', message.sync_type, message.payload); } // Méthodes HTTP async getHealth() { const response = await fetch(`${this.httpUrl}/health`); return response.json(); } async getMetrics() { const response = await fetch(`${this.httpUrl}/metrics`); return response.json(); } async getRelays() { const response = await fetch(`${this.httpUrl}/relays`); return response.json(); } async forceSync(syncTypes = ['StateSync']) { const response = await fetch(`${this.httpUrl}/sync/force`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ sync_types: syncTypes }) }); return response.json(); } disconnect() { if (this.ws) { this.ws.close(); } } } // Utilisation const client = new SdkRelayClient('ws://localhost:8090', 'http://localhost:8091'); async function main() { await client.connect(); // Obtenir les métriques const metrics = await client.getMetrics(); console.log('Métriques:', metrics); // Forcer une synchronisation await client.forceSync(['HealthSync']); } main().catch(console.error); ``` ### Client Python Complet ```python import asyncio import aiohttp import json import websockets from datetime import datetime class SdkRelayClient: def __init__(self, ws_url, http_url): self.ws_url = ws_url self.http_url = http_url self.websocket = None self.client_id = f"python-client-{int(datetime.now().timestamp())}" async def connect(self): self.websocket = await websockets.connect(self.ws_url) await self.send_handshake() async def send_handshake(self): handshake = { "type": "handshake", "client_id": self.client_id, "version": "1.0.0", "capabilities": ["sync", "notifications", "health"] } await self.websocket.send(json.dumps(handshake)) async def listen(self): async for message in self.websocket: data = json.loads(message) await self.handle_message(data) async def handle_message(self, message): if message['type'] == 'handshake_response': print(f"Handshake accepté par {message['relay_id']}") elif message['type'] == 'notification': await self.handle_notification(message) elif message['type'] == 'sync': await self.handle_sync(message) async def handle_notification(self, message): print(f"Notification {message['notification_type']}: {message['data']}") async def handle_sync(self, message): print(f"Sync {message['sync_type']}: {message['payload']}") # Méthodes HTTP async def get_health(self): async with aiohttp.ClientSession() as session: async with session.get(f"{self.http_url}/health") as response: return await response.json() async def get_metrics(self): async with aiohttp.ClientSession() as session: async with session.get(f"{self.http_url}/metrics") as response: return await response.json() async def get_relays(self): async with aiohttp.ClientSession() as session: async with session.get(f"{self.http_url}/relays") as response: return await response.json() async def force_sync(self, sync_types=None): if sync_types is None: sync_types = ['StateSync'] async with aiohttp.ClientSession() as session: async with session.post( f"{self.http_url}/sync/force", json={"sync_types": sync_types} ) as response: return await response.json() async def close(self): if self.websocket: await self.websocket.close() async def main(): client = SdkRelayClient('ws://localhost:8090', 'http://localhost:8091') try: await client.connect() # Obtenir les métriques metrics = await client.get_metrics() print("Métriques:", metrics) # Écouter les messages await client.listen() except Exception as e: print(f"Erreur: {e}") finally: await client.close() if __name__ == "__main__": asyncio.run(main()) ``` ### Client cURL ```bash # Vérifier la santé curl -X GET http://localhost:8091/health # Obtenir les métriques curl -X GET http://localhost:8091/metrics # Obtenir la liste des relais curl -X GET http://localhost:8091/relays # Obtenir les détails d'un relais curl -X GET http://localhost:8091/relays/relay-1 # Forcer une synchronisation curl -X POST http://localhost:8091/sync/force \ -H "Content-Type: application/json" \ -d '{"sync_types": ["StateSync", "HealthSync"]}' # Obtenir l'historique des synchronisations curl -X GET "http://localhost:8091/sync/history?limit=10" # Obtenir les logs curl -X GET "http://localhost:8091/logs?level=info&limit=50" # Obtenir les informations Bitcoin curl -X GET http://localhost:8091/bitcoin/info # Obtenir un bloc spécifique curl -X GET http://localhost:8091/bitcoin/blocks/abc123... # Mettre à jour la configuration curl -X PUT http://localhost:8091/config \ -H "Content-Type: application/json" \ -d '{"sync": {"interval": 60}}' # Redémarrer le service curl -X POST http://localhost:8091/restart ``` --- ## Limites et Quotas ### WebSocket - **Connexions simultanées** : 1000 par relais - **Taille des messages** : 1MB maximum - **Heartbeat** : 30 secondes - **Timeout de connexion** : 60 secondes - **Rate limiting** : 1000 messages/minute par client ### HTTP REST - **Taux limite** : 1000 requêtes/minute par IP - **Taille des requêtes** : 10MB maximum - **Timeout** : 30 secondes - **Connexions simultanées** : 100 par IP - **Rate limiting** : 100 requêtes/minute par endpoint --- ## Sécurité ### Authentification - **WebSocket** : Authentification optionnelle via handshake - **HTTP** : Authentification basique (à configurer) - **Rate limiting** : Protection contre les abus ### Validation - Validation JSON des messages - Validation des types de données - Protection contre les injections - Validation des URLs et paramètres ### Chiffrement - **WebSocket** : WSS (WebSocket Secure) recommandé - **HTTP** : HTTPS recommandé - **Certificats** : Certificats SSL/TLS valides --- ## Monitoring ### Métriques Clés - **Latence** : Temps de réponse des APIs - **Débit** : Messages/requêtes par seconde - **Erreurs** : Taux d'erreur par endpoint - **Connexions** : Nombre de connexions actives - **Synchronisation** : Taux de succès des syncs ### Alertes - Service indisponible - Latence élevée (> 1s) - Taux d'erreur élevé (> 5%) - Mémoire/CPU élevés - Échecs de synchronisation --- **Cette API permet une intégration complète et professionnelle avec sdk_relay pour tous types de clients.** 🚀