sdk_relay/docs/API.md

27 KiB

API Reference - sdk_relay

Vue d'Ensemble

sdk_relay expose deux interfaces principales :

  • WebSocket API (port 8090) : Communication temps réel bidirectionnelle
  • HTTP REST API (port 8091) : Interface REST pour les opérations CRUD

Base URLs

## WebSocket
ws://localhost:8090
wss://localhost:8090  # Sécurisé

## HTTP REST
http://localhost:8091
https://localhost:8091  # Sécurisé

WebSocket API - Flux de Messages

1. Connexion et Handshake

Flux de connexion :

Client → WebSocket Connection → sdk_relay
Client → Handshake Message → sdk_relay
sdk_relay → Handshake Response → Client

Message de Handshake (Client → sdk_relay) :

{
    "type": "handshake",
    "client_id": "my-client-123",
    "version": "1.0.0",
    "capabilities": ["sync", "notifications", "health"],
    "timestamp": 1703001600
}

Réponse de Handshake (sdk_relay → Client) :

{
    "type": "handshake_response",
    "status": "accepted",
    "relay_id": "relay-1",
    "version": "1.0.0",
    "capabilities": ["sync", "notifications", "health", "metrics"],
    "timestamp": 1703001600
}

2. Messages de Synchronisation

StateSync

Flux :

relay-1 → StateSync → relay-2
relay-2 → StateSync Response → relay-1

Message StateSync (relay-1 → relay-2) :

{
    "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,
            "known_relays": 3,
            "mesh_connections": 6
        }
    },
    "timestamp": 1703001600,
    "message_id": "msg-123"
}

Réponse StateSync (relay-2 → relay-1) :

{
    "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,
            "known_relays": 3,
            "mesh_connections": 6
        }
    },
    "timestamp": 1703001600,
    "message_id": "msg-124"
}

HealthSync

Flux :

relay-1 → HealthSync → relay-2
relay-2 → HealthSync Response → relay-1

Message HealthSync (relay-1 → relay-2) :

{
    "type": "sync",
    "sync_type": "HealthSync",
    "relay_id": "relay-1",
    "payload": {
        "health": {
            "status": "healthy",
            "memory_usage": "128MB",
            "cpu_usage": "5%",
            "disk_usage": "2GB",
            "network_latency": 45,
            "error_count": 0,
            "last_error": null
        }
    },
    "timestamp": 1703001600,
    "message_id": "msg-125"
}

Réponse HealthSync (relay-2 → relay-1) :

{
    "type": "sync_response",
    "sync_type": "HealthSync",
    "relay_id": "relay-2",
    "payload": {
        "health": {
            "status": "healthy",
            "memory_usage": "96MB",
            "cpu_usage": "3%",
            "disk_usage": "1.5GB",
            "network_latency": 32,
            "error_count": 0,
            "last_error": null
        }
    },
    "timestamp": 1703001600,
    "message_id": "msg-126"
}

MetricsSync

Flux :

relay-1 → MetricsSync → relay-2
relay-2 → MetricsSync Response → relay-1

Message MetricsSync (relay-1 → relay-2) :

{
    "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,
            "success_rate": 98.67,
            "messages_per_second": 2.5
        }
    },
    "timestamp": 1703001600,
    "message_id": "msg-127"
}

Réponse MetricsSync (relay-2 → relay-1) :

{
    "type": "sync_response",
    "sync_type": "MetricsSync",
    "relay_id": "relay-2",
    "payload": {
        "metrics": {
            "known_relays": 3,
            "mesh_connections": 6,
            "sync_requests": 120,
            "sync_responses": 120,
            "cache_hits": 95,
            "cache_misses": 25,
            "avg_latency": 38.5,
            "error_count": 0,
            "success_rate": 100.0,
            "messages_per_second": 2.0
        }
    },
    "timestamp": 1703001600,
    "message_id": "msg-128"
}

3. Messages de Notification

Payment Detected

Flux :

sdk_relay → Payment Notification → Client

Message Payment Detected (sdk_relay → Client) :

{
    "type": "notification",
    "notification_type": "payment_detected",
    "data": {
        "txid": "abc123def456789abcdef456789abcdef456789abc",
        "block_height": 12345,
        "block_hash": "def789abc123456def789abc123456def789abc123",
        "amount": "0.001",
        "address": "sp1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh",
        "confirmations": 1,
        "timestamp": 1703001600,
        "fee": "0.00001",
        "size": 250
    },
    "timestamp": 1703001600
}

Block Mined

Flux :

sdk_relay → Block Notification → Client

Message Block Mined (sdk_relay → Client) :

{
    "type": "notification",
    "notification_type": "block_mined",
    "data": {
        "block_height": 12346,
        "block_hash": "ghi012jkl345678ghi012jkl345678ghi012jkl345",
        "transactions": 150,
        "size": 1024000,
        "timestamp": 1703001600,
        "difficulty": 1.0,
        "merkle_root": "abc123def456789abcdef456789abcdef456789abc"
    },
    "timestamp": 1703001600
}

Relay Connected

Flux :

sdk_relay → Relay Notification → Client

Message Relay Connected (sdk_relay → Client) :

{
    "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,
        "connection_id": "conn-456"
    },
    "timestamp": 1703001600
}

4. Messages de Contrôle

Ping/Pong

Flux :

Client → Ping → sdk_relay
sdk_relay → Pong → Client

Message Ping (Client → sdk_relay) :

{
    "type": "ping",
    "client_id": "my-client-123",
    "timestamp": 1703001600
}

Message Pong (sdk_relay → Client) :

{
    "type": "pong",
    "relay_id": "relay-1",
    "timestamp": 1703001600
}

Subscribe/Unsubscribe

Flux :

Client → Subscribe → sdk_relay
sdk_relay → Subscribe Response → Client

Message Subscribe (Client → sdk_relay) :

{
    "type": "subscribe",
    "subscriptions": ["notifications", "health", "metrics"],
    "client_id": "my-client-123",
    "timestamp": 1703001600
}

Réponse Subscribe (sdk_relay → Client) :

{
    "type": "subscribe_response",
    "status": "subscribed",
    "subscriptions": ["notifications", "health", "metrics"],
    "relay_id": "relay-1",
    "timestamp": 1703001600
}

Message Unsubscribe (Client → sdk_relay) :

{
    "type": "unsubscribe",
    "subscriptions": ["metrics"],
    "client_id": "my-client-123",
    "timestamp": 1703001600
}

Réponse Unsubscribe (sdk_relay → Client) :

{
    "type": "unsubscribe_response",
    "status": "unsubscribed",
    "subscriptions": ["notifications", "health"],
    "relay_id": "relay-1",
    "timestamp": 1703001600
}

HTTP REST API - Flux de Requêtes

1. Health Check

Flux :

Client → GET /health → sdk_relay
sdk_relay → Health Response → Client

Requête :

GET /health HTTP/1.1
Host: localhost:8091
User-Agent: curl/7.68.0
Accept: application/json

Réponse :

{
    "status": "healthy",
    "uptime": 3600,
    "version": "1.0.0",
    "timestamp": 1703001600,
    "services": {
        "bitcoin_core": "connected",
        "blindbit": "connected",
        "websocket": "listening",
        "sync_manager": "active"
    },
    "checks": {
        "bitcoin_rpc": true,
        "blindbit_api": true,
        "websocket_server": true,
        "sync_manager": true
    }
}

2. Métriques

Flux :

Client → GET /metrics → sdk_relay
sdk_relay → Metrics Response → Client

Requête :

GET /metrics HTTP/1.1
Host: localhost:8091
User-Agent: curl/7.68.0
Accept: application/json

Réponse :

{
    "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,
        "success_rate": 98.67
    },
    "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
    },
    "timestamp": 1703001600
}

3. Configuration

Flux :

Client → GET /config → sdk_relay
sdk_relay → Config Response → Client

Requête :

GET /config HTTP/1.1
Host: localhost:8091
User-Agent: curl/7.68.0
Accept: application/json

Réponse :

{
    "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,
    "timestamp": 1703001600
}

4. Liste des Relais

Flux :

Client → GET /relays → sdk_relay
sdk_relay → Relays Response → Client

Requête :

GET /relays?status=healthy&limit=10 HTTP/1.1
Host: localhost:8091
User-Agent: curl/7.68.0
Accept: application/json

Réponse :

{
    "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,
            "metrics": {
                "sync_requests": 50,
                "sync_responses": 50,
                "avg_latency": 45.2
            }
        },
        {
            "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,
            "metrics": {
                "sync_requests": 30,
                "sync_responses": 30,
                "avg_latency": 38.5
            }
        }
    ],
    "total": 2,
    "healthy": 2,
    "warning": 0,
    "critical": 0,
    "timestamp": 1703001600
}

5. Détails d'un Relais

Flux :

Client → GET /relays/{relay_id} → sdk_relay
sdk_relay → Relay Details Response → Client

Requête :

GET /relays/relay-1 HTTP/1.1
Host: localhost:8091
User-Agent: curl/7.68.0
Accept: application/json

Réponse :

{
    "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,
        "error_count": 0,
        "success_rate": 100.0
    },
    "configuration": {
        "network": "signet",
        "dev_mode": true,
        "sync_interval": 30
    },
    "status": {
        "bitcoin_connected": true,
        "blindbit_connected": true,
        "websocket_listening": true,
        "sync_active": true
    },
    "timestamp": 1703001600
}

6. Statut de Synchronisation

Flux :

Client → GET /sync/status → sdk_relay
sdk_relay → Sync Status Response → Client

Requête :

GET /sync/status HTTP/1.1
Host: localhost:8091
User-Agent: curl/7.68.0
Accept: application/json

Réponse :

{
    "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,
        "avg_duration": 45.2
    },
    "active_syncs": [
        {
            "sync_type": "StateSync",
            "target_relay": "relay-2",
            "started": 1703001600,
            "status": "in_progress"
        }
    ],
    "timestamp": 1703001600
}

7. Forcer la Synchronisation

Flux :

Client → POST /sync/force → sdk_relay
sdk_relay → Force Sync Response → Client

Requête :

POST /sync/force HTTP/1.1
Host: localhost:8091
User-Agent: curl/7.68.0
Content-Type: application/json
Accept: application/json

{
    "sync_types": ["StateSync", "HealthSync"],
    "target_relays": ["relay-2", "relay-3"]
}

Réponse :

{
    "status": "sync_triggered",
    "sync_types": ["StateSync", "HealthSync"],
    "target_relays": ["relay-2", "relay-3"],
    "timestamp": 1703001600,
    "estimated_duration": "30s",
    "sync_id": "sync-789"
}

8. Historique des Synchronisations

Flux :

Client → GET /sync/history → sdk_relay
sdk_relay → Sync History Response → Client

Requête :

GET /sync/history?limit=10&since=1703000000&sync_type=StateSync HTTP/1.1
Host: localhost:8091
User-Agent: curl/7.68.0
Accept: application/json

Réponse :

{
    "history": [
        {
            "timestamp": 1703001600,
            "sync_type": "StateSync",
            "target_relay": "relay-2",
            "status": "success",
            "duration": 45,
            "message_id": "msg-123",
            "payload_size": 1024,
            "latency": 45.2
        },
        {
            "timestamp": 1703001570,
            "sync_type": "HealthSync",
            "target_relay": "relay-3",
            "status": "success",
            "duration": 32,
            "message_id": "msg-122",
            "payload_size": 512,
            "latency": 32.1
        }
    ],
    "total": 2,
    "successful": 2,
    "failed": 0,
    "filters": {
        "limit": 10,
        "since": 1703000000,
        "sync_type": "StateSync"
    },
    "timestamp": 1703001600
}

9. Informations Bitcoin

Flux :

Client → GET /bitcoin/info → sdk_relay
sdk_relay → Bitcoin Info Response → Client

Requête :

GET /bitcoin/info HTTP/1.1
Host: localhost:8091
User-Agent: curl/7.68.0
Accept: application/json

Réponse :

{
    "blockchain_info": {
        "chain": "signet",
        "blocks": 12345,
        "headers": 12345,
        "bestblockhash": "abc123def456789abcdef456789abcdef456789abc",
        "difficulty": 1.0,
        "verificationprogress": 0.9999,
        "initialblockdownload": false,
        "size_on_disk": 1073741824,
        "pruned": false
    },
    "network_info": {
        "connections": 8,
        "connections_in": 4,
        "connections_out": 4,
        "networkactive": true,
        "networks": [
            {
                "name": "ipv4",
                "limited": false,
                "reachable": true,
                "proxy": "tor:9050"
            }
        ]
    },
    "mempool_info": {
        "size": 150,
        "bytes": 1024000,
        "usage": 2048000,
        "maxmempool": 300000000,
        "mempoolminfee": 0.00001000
    },
    "timestamp": 1703001600
}

10. Bloc Spécifique

Flux :

Client → GET /bitcoin/blocks/{block_hash} → sdk_relay
sdk_relay → Block Details Response → Client

Requête :

GET /bitcoin/blocks/abc123def456789abcdef456789abcdef456789abc HTTP/1.1
Host: localhost:8091
User-Agent: curl/7.68.0
Accept: application/json

Réponse :

{
    "hash": "abc123def456789abcdef456789abcdef456789abc",
    "height": 12345,
    "version": 536870912,
    "merkleroot": "def456789abcdef456789abcdef456789abcdef456",
    "time": 1703001600,
    "mediantime": 1703001500,
    "nonce": 123456,
    "bits": "207fffff",
    "difficulty": 1.0,
    "size": 1024,
    "strippedsize": 512,
    "weight": 4096,
    "tx": [
        "txid1abc123def456789abcdef456789abcdef456789abc",
        "txid2def456789abcdef456789abcdef456789abcdef456"
    ],
    "confirmations": 1,
    "previousblockhash": "ghi789jkl012345ghi789jkl012345ghi789jkl012",
    "nextblockhash": "mno012pqr345678mno012pqr345678mno012pqr345",
    "timestamp": 1703001600
}

11. Logs

Flux :

Client → GET /logs → sdk_relay
sdk_relay → Logs Response → Client

Requête :

GET /logs?level=info&limit=50&search=sync HTTP/1.1
Host: localhost:8091
User-Agent: curl/7.68.0
Accept: application/json

Réponse :

{
    "logs": [
        {
            "timestamp": "2024-12-19T10:00:00Z",
            "level": "info",
            "message": "Relay started successfully",
            "relay_id": "relay-1",
            "module": "main",
            "line": 45
        },
        {
            "timestamp": "2024-12-19T10:00:30Z",
            "level": "info",
            "message": "Sync completed",
            "relay_id": "relay-1",
            "sync_type": "StateSync",
            "module": "sync",
            "line": 123
        }
    ],
    "total": 2,
    "levels": {
        "debug": 0,
        "info": 2,
        "warn": 0,
        "error": 0
    },
    "filters": {
        "level": "info",
        "limit": 50,
        "search": "sync"
    },
    "timestamp": 1703001600
}

12. Mettre à Jour la Configuration

Flux :

Client → PUT /config → sdk_relay
sdk_relay → Config Update Response → Client

Requête :

PUT /config HTTP/1.1
Host: localhost:8091
User-Agent: curl/7.68.0
Content-Type: application/json
Accept: application/json

{
    "sync": {
        "interval": 60,
        "health_interval": 120
    },
    "dev_mode": false
}

Réponse :

{
    "status": "updated",
    "changes": [
        "sync.interval: 30 -> 60",
        "sync.health_interval: 60 -> 120",
        "dev_mode: true -> false"
    ],
    "timestamp": 1703001600,
    "restart_required": false
}

13. Redémarrer le Service

Flux :

Client → POST /restart → sdk_relay
sdk_relay → Restart Response → Client

Requête :

POST /restart HTTP/1.1
Host: localhost:8091
User-Agent: curl/7.68.0
Accept: application/json

Réponse :

{
    "status": "restarting",
    "timestamp": 1703001600,
    "estimated_duration": "30s",
    "restart_id": "restart-456"
}

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

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

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

## 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

Cette documentation décrit tous les flux de données JSON entre les clients et sdk_relay. 🚀