WebSocket-Abonnements

Verbinden Sie sich mit den WebSocket-Endpunkten von BlockVectra für eth_subscribe newHeads und logs. Erfahren Sie mehr über Verbindungsmethoden, Filterregeln, Wiederverbindungs-Backoff und Wiederherstellung.

BlockVectra bietet sichere WebSocket-Verbindungen (wss://) zum Streamen von Ethereum-Ereignisabonnements in Echtzeit parallel zu standardmäßigen JSON-RPC-Anfragen.

Webhook, WebSocket oder Polling wählen

Verwenden Sie WebSocket für Live-newHeads und gefilterte logs, wenn Ihre Anwendung eine Verbindung aufrechterhalten kann. Verwenden Sie die Blockchain Webhook API, um Aktivitäten überwachter Wallets an einem HTTPS-Endpunkt zu empfangen, mit Raw-Body-Signaturverifizierung, Wiederholungen und Replay gespeicherter Treffer. Verwenden Sie HTTP-Polling für die geplante ERC-20-Zahlungsüberwachung und das historische Nachfüllen von Logs. Der Stablecoin-Leitfaden zeigt außerdem einen USDT- / USDC-Webhook-Empfänger. Einen architektonischen Vergleich hinsichtlich Chain-Unterstützung, Empfängeranforderungen und Wiederherstellungs-Kompromissen für Entwickler und KI-Agenten finden Sie im Leitfaden zur Auswahl zwischen Webhooks, WebSocket oder RPC-Polling.

Die WebSocket-Unterstützung ergibt sich aus ws und subscriptions in GET /v1/chains; Push-Unterstützung ergibt sich aus der authentifizierten Liste in GET /v1/push/chains. Eine Chain ohne WebSocket kann dennoch Adress-Webhooks nutzen, sofern sie dort aufgeführt ist.

WebSocket-Verbindungsabbrüche erfordern ein erneutes Abonnieren und Nachfüllen; sie geben nicht die Push-Steuerereignisse subscription.gap oder chain.reorg aus. Bei Webhooks erfordert eine Lücke einen Bereichsscan; eine Reorg-Benachrichtigung erfordert, dass ersetzte Ereignisse markiert oder verworfen werden, bevor automatisch erneut zugestellte kanonische Ereignisse beibehalten werden. Push-Replay sendet gespeicherte Treffer erneut, keine Daten von vor dem Hinzufügen einer Adresse oder Chain oder während das Abonnement offline war. Konsultieren Sie Abrechnungsregeln und die Fehlerreferenz bei der Implementierung der Wiederherstellung.

Verfügbare Chains

Sie können prüfen, ob WebSocket-Abonnements in einem Netzwerk aktiv sind, indem Sie ws (Boolean) und subscriptions (Array der unterstützten Typen) in GET /v1/chains auslesen.

Die folgende Tabelle zeigt Netzwerke, bei denen die WebSocket-Unterstützung aktiviert ist:

ChainWebSocket-Endpunkt (Schlüssel im Pfad)
Robinhood Chainwss://api.blockvectra.com/v1/robinhood_mainnet/{api_key}
Robinhood Chain Testnetwss://api.blockvectra.com/v1/robinhood_testnet/{api_key}

Verbindung und Authentifizierung

Clients stellen eine sichere TLS-WebSocket-Verbindung her (wss://). Der API-Schlüssel kann auf zwei Arten bereitgestellt werden:

  • Pfad-Schlüssel: wss://api.blockvectra.com/v1/{chain}/{api_key}
  • Header-Schlüssel: wss://api.blockvectra.com/v1/{chain} mit dem Header x-api-key: {api_key} oder Authorization: Bearer {api_key} während des HTTP-Upgrade-Handshakes.

Bei Verwendung eines Pfad-Schlüssels wird der Pfad-Schlüssel verwendet und beide Authentifizierungs-Header werden ignoriert. Ohne Pfad-Schlüssel hat ein nicht-leerer x-api-key-Header Vorrang vor Authorization: Bearer. Browser-WebSocket-APIs können diese Header nicht setzen; verwenden Sie in diesem Fall die Pfad-Schlüssel-URL.

Handshake-Zulassungsprüfungen

Der Handshake kann mit folgenden Fehlern fehlschlagen:

  • Authentifizierung: Ein fehlender API-Schlüssel gibt HTTP 401 zurück (missing_api_key); ein unbekannter, deaktivierter oder widerrufener API-Schlüssel gibt HTTP 401 zurück (invalid_api_key); wenn die Authentifizierung vorübergehend nicht verfügbar ist, lautet die Antwort HTTP 503 (auth_unavailable).
  • Kontoguthaben: Ein Konto mit einem Prepaid-Guthaben von null oder darunter gibt HTTP 402 zurück (balance_exhausted); wenn der Abrechnungsstatus nicht bestätigt werden kann, lautet die Antwort HTTP 503 (billing_unavailable).
  • Verbindungslimits: Das Überschreiten des Limits pro Schlüssel (20 Verbindungen) oder des Limits pro Konto (50 Verbindungen) gibt HTTP 429 zurück (ws_connection_limit).
  • Chain-Verfügbarkeit: Die Anforderung einer unbekannten oder nicht bedienten Chain gibt HTTP 404 zurück (unknown_chain).
  • Serverkapazität: Wenn der Server ausgelastet oder überlastet ist, gibt der Handshake HTTP 503 zurück (overloaded) mit einem Retry-After-Header.

Sobald die Verbindung hergestellt ist, können Clients Standard-JSON-RPC-2.0-Anfragen (wie eth_blockNumber oder eth_call) und Abonnement-Steuerungsmethoden im Format von UTF-8-Textframes senden.

Abrechnungsregeln

  • Das Herstellen einer Verbindung, das Offenhalten einer inaktiven Verbindung und Ping/Pong-Heartbeats werden nicht abgerechnet.
  • Erfolgreiche eth_subscribe- und eth_unsubscribe-Aufrufe werden abgerechnet, einschließlich eines Abmeldeaufrufs, der false zurückgibt; fehlgeschlagene Aufrufe werden nicht abgerechnet. Gewöhnliche JSON-RPC-Aufrufe folgen den JSON-RPC-Abrechnungsregeln.
  • newHeads-Benachrichtigungen zählen einmal pro Block-Hash pro Verbindung, unabhängig davon, wie viele newHeads-Abonnements die Verbindung besitzt.
  • logs-Benachrichtigungen zählen einmal pro Abonnement pro Block-Hash und Phase mit passenden Logs; Blöcke ohne Treffer werden nicht abgerechnet. Mehrere passende Logs im selben Block und in derselben Phase vervielfachen die Gebühr nicht. Getrennte Abonnements zählen separat, selbst wenn sich ihre Filter überschneiden. Reorganisations-Logs (removed: true) bilden eine separate Einheit; ein Ersatzblock auf derselben Höhe hat einen anderen Hash und stellt eine eigene Einheit dar.
  • Benachrichtigungen werden erst abgerechnet, nachdem sie erfolgreich in den Socket-Sendepuffer übertragen (flushed) wurden; in der Warteschlange befindliche oder verworfene Benachrichtigungen, die nicht übertragen wurden, werden nicht abgerechnet. Benachrichtigungen, die vor der Antwort auf ein eth_unsubscribe eingereiht wurden, zählen, wenn sie übertragen wurden. WebSocket-Nachrichten enthalten keine HTTP-Abrechnungsheader; konsultieren Sie die Kontonutzung für gemessene CU.

Abonnementmethoden

Die API implementiert die standardmäßige Ethereum-Pub/Sub-Schnittstelle: eth_subscribe und eth_unsubscribe.

newHeads

Gibt jedes Mal ein neues Block-Header-Objekt aus, wenn ein neuer Block an die Spitze der Chain angehängt wird.

  • Abonnier-Anfrage:
    {"jsonrpc":"2.0","id":1,"method":"eth_subscribe","params":["newHeads"]}
  • Abonnier-Antwort: Gibt eine opake hexadezimale Abonnement-Kennung zurück:
    {"jsonrpc":"2.0","id":1,"result":"0x1"}
  • Push-Benachrichtigungs-Frame:
    {"jsonrpc":"2.0","method":"eth_subscription","params":{"subscription":"0x1","result":{"number":"0x1b4","hash":"0x..."}}}

logs

Gibt Log-Ereignisse aus, die bestimmten Filterkriterien entsprechen.

  • Filteranforderung: Jeder Filter für ein logs-Abonnement muss eine address (eine Contract-Adresse oder ein Array von Adressen) oder ein topic0 (die erste Topic-Position, nicht null) angeben. Ein Filter, der keines von beiden angibt (wie {} oder {"topics":[null,"0x..."]}), wird mit dem Fehlercode -32602 (logs_filter_required) abgewiesen.

  • Filterlimits: Höchstens 100 Adressen; höchstens 4 Topic-Positionen mit höchstens 16 Kandidaten-Hashes pro Position.

  • Filterkapazität: Wenn aktive Log-Filter die Kapazitätsgrenze erreichen, gibt das Abonnement den Fehlercode -32022 zurück (ws_filter_capacity).

  • Chain-Reorganisationen: Wenn ein Block aufgrund einer Chain-Reorganisation entfernt wird, tragen Log-Benachrichtigungen für entfernte Logs "removed": true.

  • Abonnier-Anfrage:

    {"jsonrpc":"2.0","id":2,"method":"eth_subscribe","params":["logs",{"address":"0x1234567890123456789012345678901234567890"}]}

eth_unsubscribe

Beendet ein aktives Abonnement anhand seiner Abonnement-Kennung.

  • Abmelde-Anfrage:
    {"jsonrpc":"2.0","id":3,"method":"eth_unsubscribe","params":["0x1"]}
  • Abmelde-Antwort:
    {"jsonrpc":"2.0","id":3,"result":true}

Ausführbare Beispiele

Verbinden Sie sich mit viem v2 über createPublicClient und den webSocket-Transport. Ersetzen Sie {chain} durch die gewünschte Chain-Kennung und {api_key} durch Ihren API-Schlüssel:

import { createPublicClient, webSocket } from 'viem';

const apiKey = process.env.BLOCKVECTRA_API_KEY || '{api_key}';
const url = `wss://api.blockvectra.com/v1/robinhood_mainnet/${apiKey}`;

const client = createPublicClient({
  transport: webSocket(url),
});

// 1. Subscribe to new block headers (newHeads)
const unwatchBlocks = client.watchBlocks({
  onBlock: (block) => {
    console.log('New block header received:', block.number, block.hash);
  },
  onError: (error) => {
    console.error('watchBlocks error:', error);
  },
});

// 2. Subscribe to contract event logs (filter requires address or topic0)
const unwatchEvents = client.watchEvent({
  address: '0x1234567890123456789012345678901234567890',
  onLogs: (logs) => {
    console.log('Matching logs received:', logs);
  },
  onError: (error) => {
    console.error('watchEvent error:', error);
  },
});

Close-Codes und Client-Aktionen

Wenn der Server eine WebSocket-Sitzung beendet, sendet er einen Close-Frame mit einem bestimmten Close-Code und einer kurzen Begründung. Die folgende Tabelle listet die vom Server ausgegebenen Close-Codes und die empfohlenen Aktionen auf:

Close-CodeReason-ZeichenfolgeBeschreibungWiederholbarClient-Aktion
1001idleInaktive Verbindung ohne Abonnements oder Nachrichten für 3600 Sekunden (1 Stunde)JaBei Bedarf erneut verbinden.
1003binary frames are not acceptedBinärer WebSocket-Frame empfangen; nur UTF-8-TextframesNeinNicht automatisch erneut verbinden. Aktualisieren Sie den Client, um Textframes zu senden.
1009message too largeEingehende Payload hat 1 MiB überschrittenNeinNicht automatisch erneut verbinden. Große Anfragen aufteilen oder Payload-Größe reduzieren.
1012service restartServer startet neu oder Sitzung hat die maximale Lebensdauer erreicht (24 Stunden)JaVerbindung mit zufälligem Jitter-Backoff wiederherstellen, Abonnements neu einrichten und verpasste Daten nachfüllen.
1013chain unavailableChain nicht verfügbarJaVerbindung mit Full-Jitter exponentiellem Backoff wiederherstellen, Abonnements neu einrichten und verpasste Daten nachfüllen.
1013overloadedServer vorübergehend überlastetJaVerbindung mit Full-Jitter exponentiellem Backoff wiederherstellen, Abonnements neu einrichten und verpasste Daten nachfüllen.
4402insufficient balanceKontoguthaben erschöpftNeinNicht automatisch erneut verbinden. Guthaben aufladen und erneut verbinden.
4404invalid api keyAPI-Schlüssel ist unbekannt, deaktiviert oder widerrufenNeinNicht automatisch erneut verbinden. Überprüfen oder rotieren Sie den API-Schlüssel in der Konsole vor der erneuten Verbindung.
4408slow consumerDer Server schließt eine Sitzung, deren Push-Warteschlange 512 KiB überschreitet, und verwirft ausstehende Benachrichtigungen; Clients empfangen möglicherweise keinen Close-Frame (Browser meldet 1006)JaBehandeln Sie unerwartete Verbindungsabbrüche (kein Close-Frame empfangen, Browser meldet 1006) wie 4408: Verbindung mit Backoff wiederherstellen, Abonnements neu einrichten und verworfene Daten mit eth_getLogs nachfüllen; weniger abonnieren oder schneller lesen.
4429push rate exceededBenachrichtigungsrate hat 1.000 Pushes/Sekunde überschrittenJaAbonnements reduzieren oder Filter einengen; Verbindung mit Backoff wiederherstellen, erneut abonnieren und nachfüllen.
4503billing unavailableAbrechnung vorübergehend nicht verfügbarJaVorübergehender Zustand; Verbindung mit Full-Jitter exponentiellem Backoff wiederherstellen.

Wiederverbindung und exponentieller Backoff

Um synchronisierte Wiederverbindungsstürme bei Verbindungsabbrüchen zu verhindern, müssen Clients einen exponentiellen Backoff mit Full Jitter implementieren:

  • Backoff-Formel: Warten Sie vor dem n-ten Wiederverbindungsversuch (n = 0, 1, 2, ...) eine gleichmäßig zufällig gewählte Dauer:
    delay = random(0, min(20s, 0.5s * 2^n))
  • Zähler zurücksetzen: Setzen Sie den Wiederholungszähler n erst dann auf 0 zurück, nachdem eine ununterbrochene, stabile Verbindung für mindestens 60 Sekunden aufrechterhalten wurde.
  • Close-Code 1012: Führen Sie vor dem ersten Wiederverbindungsversuch eine zufällige Anfangsverzögerung ein, um synchronisierte Wiederverbindungsspitzen zu vermeiden.
  • Nicht wiederholbare Codes: Verbinden Sie sich bei 4402, 4404, 1003 oder 1009 nicht automatisch erneut.

Verpasste Daten nach der Wiederverbindung nachfüllen

WebSocket-Abonnements bleiben über Verbindungen hinweg nicht bestehen; Benachrichtigungen, die während eines Verbindungsabbruchs ausgegeben werden, werden nicht auf dem Server vorgehalten. Nach der Wiederverbindung sollten Clients eine Aufholstrategie ausführen:

  1. Logs mit eth_getLogs nachfüllen:
    • Speichern Sie die höchste erfolgreich verarbeitete Blocknummer dauerhaft (last_processed_block).
    • Rufen Sie bei der Wiederverbindung sofort eth_subscribe("logs", ...) auf, um Live-Ereignisse zu erfassen.
    • Fragen Sie verpasste Blöcke über eth_getLogs mit fromBlock: last_processed_block + 1 und toBlock: "latest" (oder dem ersten aus dem Live-Stream empfangenen Block) ab.
    • Wenn die Lücke des Verbindungsabbruchs das max_logs_block_range des Netzwerks (aus GET /v1/chains) überschreitet, unterteilen Sie die Abfragen in Abschnitte, die dieses Limit nicht überschreiten.
    • Deduplizieren Sie Log-Einträge über die Abfragegrenze hinweg anhand des eindeutigen Tupels (blockHash, transactionHash, logIndex).
  2. Block-Header mit eth_getBlockByNumber nachfüllen:
    • Notieren Sie die neueste Blocknummer und den Hash, die vor dem Abbruch empfangen wurden.
    • Abonnieren Sie erneut newHeads.
    • Fragen Sie eth_getBlockByNumber("latest", false) ab und rufen Sie fehlende Zwischenblöcke sequenziell ab. Überprüfen Sie die Kontinuität der parentHash-Kette, um Reorgs zu erkennen.

Limits

LimitWertErgebnis bei Überschreitung
Abonnements pro WebSocket-Verbindung100-32022 subscription_limit
newHeads-Abonnements pro WebSocket-Verbindung4-32022 subscription_limit
Filteranforderungen für logs-AbonnementsMuss eine address oder ein topic0 (erste Position in topics) angeben-32602 logs_filter_required

Nächste Schritte

Zuletzt aktualisiert:

Auf dieser Seite