# WebSocket-Abonnements

> Source: https://docs.blockvectra.com/de/guides/websocket-subscriptions/

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](https://docs.blockvectra.com/de/guides/webhook-push/), um Aktivitäten überwachter Wallets an einem HTTPS-Endpunkt zu empfangen, mit [Raw-Body-Signaturverifizierung](https://docs.blockvectra.com/de/guides/webhook-push/#verify-signatures), Wiederholungen und Replay gespeicherter Treffer. Verwenden Sie [HTTP-Polling](https://docs.blockvectra.com/de/guides/stablecoin-payments/) 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](https://docs.blockvectra.com/de/guides/stablecoin-payments/#receive-payments-with-webhooks). 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](https://docs.blockvectra.com/de/guides/webhook-vs-websocket/).

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](https://docs.blockvectra.com/de/guides/webhook-push/#delivery-retries-and-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](https://docs.blockvectra.com/de/guides/billing-rules/) und die [Fehlerreferenz](https://docs.blockvectra.com/de/errors/) 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:

| Chain | WebSocket-Endpunkt (Schlüssel im Pfad) |
| --- | --- |
| Robinhood Chain | `wss://api.blockvectra.com/v1/robinhood_mainnet/{api_key}` |
| Robinhood Chain Testnet | `wss://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`](https://docs.blockvectra.com/de/errors/#missing_api_key)); ein unbekannter, deaktivierter oder widerrufener API-Schlüssel gibt HTTP 401 zurück ([`invalid_api_key`](https://docs.blockvectra.com/de/errors/#invalid_api_key)); wenn die Authentifizierung vorübergehend nicht verfügbar ist, lautet die Antwort HTTP 503 ([`auth_unavailable`](https://docs.blockvectra.com/de/errors/#auth_unavailable)).
* **Kontoguthaben**: Ein Konto mit einem Prepaid-Guthaben von null oder darunter gibt HTTP 402 zurück ([`balance_exhausted`](https://docs.blockvectra.com/de/errors/#balance_exhausted)); wenn der Abrechnungsstatus nicht bestätigt werden kann, lautet die Antwort HTTP 503 ([`billing_unavailable`](https://docs.blockvectra.com/de/errors/#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`](https://docs.blockvectra.com/de/errors/#ws_connection_limit)).
* **Chain-Verfügbarkeit**: Die Anforderung einer unbekannten oder nicht bedienten Chain gibt HTTP 404 zurück ([`unknown_chain`](https://docs.blockvectra.com/de/errors/#unknown_chain)).
* **Serverkapazität**: Wenn der Server ausgelastet oder überlastet ist, gibt der Handshake HTTP 503 zurück ([`overloaded`](https://docs.blockvectra.com/de/errors/#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](https://docs.blockvectra.com/de/guides/billing-rules/).
* `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**:
  ```json
  {"jsonrpc":"2.0","id":1,"method":"eth_subscribe","params":["newHeads"]}
  ```
* **Abonnier-Antwort**: Gibt eine opake hexadezimale Abonnement-Kennung zurück:
  ```json
  {"jsonrpc":"2.0","id":1,"result":"0x1"}
  ```
* **Push-Benachrichtigungs-Frame**:
  ```json
  {"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`](https://docs.blockvectra.com/de/errors/#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`](https://docs.blockvectra.com/de/errors/#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**:
  ```json
  {"jsonrpc":"2.0","id":2,"method":"eth_subscribe","params":["logs",{"address":"0x1234567890123456789012345678901234567890"}]}
  ```

### `eth_unsubscribe`

Beendet ein aktives Abonnement anhand seiner Abonnement-Kennung.

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

## Ausführbare Beispiele

**viem v2 (TypeScript)**

Verbinden Sie sich mit [viem](https://viem.sh) v2 über `createPublicClient` und den `webSocket`-Transport. Ersetzen Sie `{chain}` durch die gewünschte Chain-Kennung und `{api_key}` durch Ihren API-Schlüssel:

```ts
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);
  },
});
```


  **Command line (websocat / wscat)**

Verbinden Sie sich mit Befehlszeilen-Tools wie `websocat` oder `wscat` und senden Sie rohe JSON-RPC-Frames:

```bash
# Connect with path-based API key using websocat
websocat "wss://api.blockvectra.com/v1/{chain}/{api_key}"

# Alternatively, pass the key via request header
websocat -H="x-api-key: {api_key}" "wss://api.blockvectra.com/v1/{chain}"

# Or connect using wscat
wscat -c "wss://api.blockvectra.com/v1/{chain}/{api_key}"
```

Senden Sie Abonnement-Befehle in die interaktive Sitzung:

```json
{"jsonrpc":"2.0","id":1,"method":"eth_subscribe","params":["newHeads"]}
{"jsonrpc":"2.0","id":2,"method":"eth_subscribe","params":["logs",{"address":"0x1234567890123456789012345678901234567890"}]}
{"jsonrpc":"2.0","id":3,"method":"eth_unsubscribe","params":["0x1"]}
```


## 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-Code | Reason-Zeichenfolge              | Beschreibung                                                                                                                                                                                             | Wiederholbar | Client-Aktion                                                                                                                                                                                                                                                             |
| -----------------------: | -------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :----------: | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [1001](https://docs.blockvectra.com/de/errors/#1001) | `idle`                           | Inaktive Verbindung ohne Abonnements oder Nachrichten für 3600 Sekunden (1 Stunde)                                                                                                                       |      Ja      | Bei Bedarf erneut verbinden.                                                                                                                                                                                                                                              |
| [1003](https://docs.blockvectra.com/de/errors/#1003) | `binary frames are not accepted` | Binärer WebSocket-Frame empfangen; nur UTF-8-Textframes                                                                                                                                                  |     Nein     | Nicht automatisch erneut verbinden. Aktualisieren Sie den Client, um Textframes zu senden.                                                                                                                                                                                |
| [1009](https://docs.blockvectra.com/de/errors/#1009) | `message too large`              | Eingehende Payload hat 1 MiB überschritten                                                                                                                                                               |     Nein     | Nicht automatisch erneut verbinden. Große Anfragen aufteilen oder Payload-Größe reduzieren.                                                                                                                                                                               |
| [1012](https://docs.blockvectra.com/de/errors/#1012) | `service restart`                | Server startet neu oder Sitzung hat die maximale Lebensdauer erreicht (24 Stunden)                                                                                                                       |      Ja      | Verbindung mit zufälligem Jitter-Backoff wiederherstellen, Abonnements neu einrichten und verpasste Daten nachfüllen.                                                                                                                                                     |
| [1013](https://docs.blockvectra.com/de/errors/#1013) | `chain unavailable`              | Chain nicht verfügbar                                                                                                                                                                                    |      Ja      | Verbindung mit Full-Jitter exponentiellem Backoff wiederherstellen, Abonnements neu einrichten und verpasste Daten nachfüllen.                                                                                                                                            |
| [1013](https://docs.blockvectra.com/de/errors/#1013) | `overloaded`                     | Server vorübergehend überlastet                                                                                                                                                                          |      Ja      | Verbindung mit Full-Jitter exponentiellem Backoff wiederherstellen, Abonnements neu einrichten und verpasste Daten nachfüllen.                                                                                                                                            |
| [4402](https://docs.blockvectra.com/de/errors/#4402) | `insufficient balance`           | Kontoguthaben erschöpft                                                                                                                                                                                  |     Nein     | Nicht automatisch erneut verbinden. [Guthaben aufladen und erneut verbinden](https://docs.blockvectra.com/de/guides/billing-rules/).                                                                                                                                                                  |
| [4404](https://docs.blockvectra.com/de/errors/#4404) | `invalid api key`                | API-Schlüssel ist unbekannt, deaktiviert oder widerrufen                                                                                                                                                 |     Nein     | Nicht automatisch erneut verbinden. Überprüfen oder rotieren Sie den API-Schlüssel in der Konsole vor der erneuten Verbindung.                                                                                                                                            |
| [4408](https://docs.blockvectra.com/de/errors/#4408) | `slow consumer`                  | Der 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) |      Ja      | Behandeln 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. |
| [4429](https://docs.blockvectra.com/de/errors/#4429) | `push rate exceeded`             | Benachrichtigungsrate hat 1.000 Pushes/Sekunde überschritten                                                                                                                                             |      Ja      | Abonnements reduzieren oder Filter einengen; Verbindung mit Backoff wiederherstellen, erneut abonnieren und nachfüllen.                                                                                                                                                   |
| [4503](https://docs.blockvectra.com/de/errors/#4503) | `billing unavailable`            | Abrechnung vorübergehend nicht verfügbar                                                                                                                                                                 |      Ja      | Vorü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](https://docs.blockvectra.com/de/errors/#4402), [4404](https://docs.blockvectra.com/de/errors/#4404), [1003](https://docs.blockvectra.com/de/errors/#1003) oder [1009](https://docs.blockvectra.com/de/errors/#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

| Limit                                           | Wert                                                                       | Ergebnis bei Überschreitung                                         |
| ----------------------------------------------- | -------------------------------------------------------------------------- | ------------------------------------------------------------------- |
| Abonnements pro WebSocket-Verbindung            | 100                                                                        | `-32022` [`subscription_limit`](https://docs.blockvectra.com/de/errors/#subscription_limit)     |
| `newHeads`-Abonnements pro WebSocket-Verbindung | 4                                                                          | `-32022` [`subscription_limit`](https://docs.blockvectra.com/de/errors/#subscription_limit)     |
| Filteranforderungen für `logs`-Abonnements      | Muss eine `address` oder ein `topic0` (erste Position in `topics`) angeben | `-32602` [`logs_filter_required`](https://docs.blockvectra.com/de/errors/#logs_filter_required) |

## Nächste Schritte

* [Datensatzverzeichnis durchsuchen](https://blockvectra.com/de/data/), um alle von BlockVectra indexierten Datensätze zu sehen.
* [Kostenlosen Tarif und Preise ansehen](https://blockvectra.com/de/pricing/#free), um zu prüfen, was Ihr Konto beinhaltet.
* [In der Konsole anmelden](https://console.blockvectra.com/login/?next=%2Fkeys%2F), um einen API-Schlüssel zu erstellen.
