# Assinaturas via WebSocket

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

A BlockVectra fornece conexões WebSocket seguras (`wss://`) para streaming de assinaturas de eventos Ethereum em tempo real juntamente com requisições JSON-RPC padrão.

## Escolher WebSocket, Webhook ou polling

Use WebSocket para `newHeads` em tempo real e `logs` filtrados quando sua aplicação puder manter uma conexão. Use a [API de Webhooks de Blockchain](https://docs.blockvectra.com/en/guides/webhook-push/) para receber a atividade de carteiras monitoradas em um endpoint HTTPS, com [verificação de assinatura no corpo bruto](https://docs.blockvectra.com/en/guides/webhook-push/#verify-signatures), novas tentativas e replay de correspondências retidas. Use [polling via HTTP](https://docs.blockvectra.com/en/guides/stablecoin-payments/) para monitoramento agendado de pagamentos ERC-20 e recuperação de logs históricos. O guia de stablecoins também apresenta um [receptor de Webhooks para USDT / USDC](https://docs.blockvectra.com/en/guides/stablecoin-payments/#receive-payments-with-webhooks). Para uma comparação arquitetural abrangendo suporte a redes, requisitos de receptor e trade-offs de recuperação para desenvolvedores e agentes de IA, consulte o [guia de escolha entre Webhooks, WebSocket ou polling de RPC](https://docs.blockvectra.com/en/guides/webhook-vs-websocket/).

O suporte a WebSocket vem de `ws` e `subscriptions` em `GET /v1/chains`; o suporte a Push vem da lista autenticada `GET /v1/push/chains`. Uma rede sem suporte a WebSocket ainda pode usar Webhooks de endereços se estiver listada ali.

Desconexões de WebSocket exigem nova assinatura e preenchimento de histórico; elas não emitem os eventos de controle de Push `subscription.gap` ou `chain.reorg`. Para Webhooks, uma lacuna requer varredura de intervalo; uma notificação de reorg requer que eventos substituídos sejam marcados ou descartados antes de manter os eventos canônicos reenviados automaticamente. O [replay de Push](https://docs.blockvectra.com/en/guides/webhook-push/#delivery-retries-and-replay) reenvia correspondências retidas, e não dados anteriores à inclusão de um endereço ou rede, ou enquanto a assinatura estava offline. Revise as [regras de cobrança](https://docs.blockvectra.com/en/guides/billing-rules/) e a [referência de erros](https://docs.blockvectra.com/en/errors/) ao implementar a recuperação.

## Redes disponíveis

Você pode verificar se assinaturas via WebSocket estão ativas em uma rede lendo `ws` (booleano) e `subscriptions` (array de tipos suportados) em `GET /v1/chains`.

A tabela abaixo reflete as redes onde o suporte a WebSocket está habilitado:

| Rede | Endpoint WebSocket (chave no caminho) |
| --- | --- |
| Robinhood Chain | `wss://api.blockvectra.com/v1/robinhood_mainnet/{api_key}` |
| Robinhood Chain Testnet | `wss://api.blockvectra.com/v1/robinhood_testnet/{api_key}` |

## Conexão e autenticação

Os clientes estabelecem uma conexão WebSocket TLS segura (`wss://`). A API key pode ser fornecida de duas maneiras:

* **Chave no caminho**: `wss://api.blockvectra.com/v1/{chain}/{api_key}`
* **Chave no cabeçalho**: `wss://api.blockvectra.com/v1/{chain}` com o cabeçalho `x-api-key: {api_key}` ou `Authorization: Bearer {api_key}` durante o handshake HTTP Upgrade.

Com uma chave no caminho, a chave do caminho é usada e ambos os cabeçalhos de autenticação são ignorados. Sem uma chave no caminho, um `x-api-key` não vazio tem precedência sobre `Authorization: Bearer`. APIs de WebSocket em navegadores não podem definir esses cabeçalhos; utilize a URL com a chave no caminho.

### Verificações de admissão no handshake

O handshake pode falhar com:

* **Autenticação**: Uma API key ausente retorna HTTP 401 ([`missing_api_key`](https://docs.blockvectra.com/en/errors/#missing_api_key)); uma API key desconhecida, desativada ou revogada retorna HTTP 401 ([`invalid_api_key`](https://docs.blockvectra.com/en/errors/#invalid_api_key)); se a autenticação estiver temporariamente indisponível, a resposta será HTTP 503 ([`auth_unavailable`](https://docs.blockvectra.com/en/errors/#auth_unavailable)).
* **Saldo da conta**: Uma conta com saldo pré-pago zero ou negativo retorna HTTP 402 ([`balance_exhausted`](https://docs.blockvectra.com/en/errors/#balance_exhausted)); se o estado de cobrança não puder ser confirmado, a resposta será HTTP 503 ([`billing_unavailable`](https://docs.blockvectra.com/en/errors/#billing_unavailable)).
* **Limites de conexão**: Ultrapassar o limite por chave (20 conexões) ou o limite por conta (50 conexões) retorna HTTP 429 ([`ws_connection_limit`](https://docs.blockvectra.com/en/errors/#ws_connection_limit)).
* **Disponibilidade da rede**: Requisitar uma rede desconhecida ou não atendida retorna HTTP 404 ([`unknown_chain`](https://docs.blockvectra.com/en/errors/#unknown_chain)).
* **Capacidade do servidor**: Quando o servidor estiver ocupado ou sobrecarregado, o handshake retornará HTTP 503 ([`overloaded`](https://docs.blockvectra.com/en/errors/#overloaded)) com um cabeçalho `Retry-After`.

Uma vez conectados, os clientes podem enviar requisições JSON-RPC 2.0 padrão (como `eth_blockNumber` ou `eth_call`) e métodos de controle de assinatura formatados como quadros de texto UTF-8.

## Regras de cobrança

* Estabelecer uma conexão, manter uma conexão ociosa aberta e batimentos de coração ping/pong não são cobrados.
* Chamadas bem-sucedidas a `eth_subscribe` e `eth_unsubscribe` são cobradas, incluindo um cancelamento de assinatura que retorne `false`; chamadas com falha não são cobradas. Chamadas JSON-RPC comuns seguem as [regras de cobrança de JSON-RPC](https://docs.blockvectra.com/en/guides/billing-rules/).
* Notificações de `newHeads` contam uma vez por hash de bloco por conexão, independentemente de quantas assinaturas `newHeads` a conexão tiver.
* Notificações de `logs` contam uma vez por assinatura por hash de bloco e fase com logs correspondentes; blocos sem correspondências não são cobrados. Vários logs correspondentes no mesmo bloco e fase não multiplicam a cobrança. Assinaturas separadas contam separadamente, mesmo quando seus filtros se sobrepõem. Logs de reorganização (`removed: true`) formam uma unidade separada; um bloco de substituição na mesma altura tem um hash diferente e é uma unidade diferente.
* Notificações são cobradas apenas após serem descarregadas com sucesso no buffer de envio do socket; notificações enfileiradas ou descartadas que não foram descarregadas não são cobradas. Notificações enfileiradas antes da resposta de um `eth_unsubscribe` contam se forem descarregadas. Mensagens WebSocket não carregam cabeçalhos HTTP de cobrança; consulte o consumo da conta para ver as CU medidas.

## Métodos de assinatura

A API implementa a interface pub/sub padrão do Ethereum: `eth_subscribe` e `eth_unsubscribe`.

### `newHeads`

Emite um novo objeto de cabeçalho de bloco sempre que um novo bloco for anexado ao topo da cadeia.

* **Requisição de assinatura**:
  ```json
  {"jsonrpc":"2.0","id":1,"method":"eth_subscribe","params":["newHeads"]}
  ```
* **Resposta da assinatura**: Retorna um identificador de assinatura hexadecimal opaco:
  ```json
  {"jsonrpc":"2.0","id":1,"result":"0x1"}
  ```
* **Quadro de notificação push**:
  ```json
  {"jsonrpc":"2.0","method":"eth_subscription","params":{"subscription":"0x1","result":{"number":"0x1b4","hash":"0x..."}}}
  ```

### `logs`

Emite eventos de log que correspondem aos critérios de filtro especificados.

* **Exigência de filtro**: Todo filtro de assinatura de `logs` **deve** especificar um `address` (um endereço de contrato ou array de endereços) ou um `topic0` (a primeira posição de tópico, não nula). Um filtro que não especifique nenhum dos dois (como `{}` ou `{"topics":[null,"0x..."]}`) é rejeitado com o código de erro `-32602` ([`logs_filter_required`](https://docs.blockvectra.com/en/errors/#logs_filter_required)).

* **Limites de filtros**: No máximo 100 endereços; no máximo 4 posições de tópicos com no máximo 16 hashes candidatos por posição.

* **Capacidade de filtros**: Se os filtros de log ativos atingirem a capacidade máxima, a assinatura retornará o código de erro `-32022` ([`ws_filter_capacity`](https://docs.blockvectra.com/en/errors/#ws_filter_capacity)).

* **Reorganizações de cadeia**: Se um bloco for removido devido a uma reorg de cadeia, as notificações de log para os logs removidos trarão `"removed": true`.

* **Requisição de assinatura**:
  ```json
  {"jsonrpc":"2.0","id":2,"method":"eth_subscribe","params":["logs",{"address":"0x1234567890123456789012345678901234567890"}]}
  ```

### `eth_unsubscribe`

Encerra uma assinatura ativa usando o identificador da assinatura.

* **Requisição de cancelamento de assinatura**:
  ```json
  {"jsonrpc":"2.0","id":3,"method":"eth_unsubscribe","params":["0x1"]}
  ```
* **Resposta do cancelamento de assinatura**:
  ```json
  {"jsonrpc":"2.0","id":3,"result":true}
  ```

## Exemplos executáveis

**viem v2 (TypeScript)**

Conecte-se usando o [viem](https://viem.sh) v2 via `createPublicClient` e o transporte `webSocket`. Substitua `{chain}` pelo identificador da rede de destino e `{api_key}` pela sua API key:

```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)**

Conecte-se usando ferramentas de linha de comando como `websocat` ou `wscat` e envie quadros JSON-RPC brutos:

```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}"
```

Envie comandos de assinatura para a sessão interativa:

```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"]}
```


## Códigos de encerramento e ações do cliente

Quando o servidor encerra uma sessão WebSocket, ele envia um quadro Close com um código de encerramento específico e um motivo curto. A tabela abaixo lista os códigos de encerramento emitidos pelo servidor e as ações recomendadas:

|   Código de encerramento | String de motivo                 | Descrição                                                                                                                                                                            | Repetível | Ação do cliente                                                                                                                                                                                                                             |
| -----------------------: | -------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | :-------: | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [1001](https://docs.blockvectra.com/en/errors/#1001) | `idle`                           | Conexão inativa sem assinaturas ou mensagens por 3600 segundos (1 hora)                                                                                                              |    Sim    | Reconecte conforme necessário.                                                                                                                                                                                                              |
| [1003](https://docs.blockvectra.com/en/errors/#1003) | `binary frames are not accepted` | Quadro WebSocket binário recebido; apenas quadros de texto UTF-8 são aceitos                                                                                                         |    Não    | Não reconecte automaticamente. Atualize o cliente para enviar quadros de texto.                                                                                                                                                             |
| [1009](https://docs.blockvectra.com/en/errors/#1009) | `message too large`              | Carga útil recebida excedeu 1 MiB                                                                                                                                                    |    Não    | Não reconecte automaticamente. Divida requisições grandes ou reduza o tamanho da carga útil.                                                                                                                                                |
| [1012](https://docs.blockvectra.com/en/errors/#1012) | `service restart`                | Servidor reiniciando ou a sessão atingiu o tempo de vida máximo (24 horas)                                                                                                           |    Sim    | Reconecte usando recuo com jitter aleatório, restabeleça as assinaturas e recupere dados perdidos.                                                                                                                                          |
| [1013](https://docs.blockvectra.com/en/errors/#1013) | `chain unavailable`              | Rede indisponível                                                                                                                                                                    |    Sim    | Reconecte usando recuo exponencial com full jitter, restabeleça as assinaturas e recupere dados perdidos.                                                                                                                                   |
| [1013](https://docs.blockvectra.com/en/errors/#1013) | `overloaded`                     | Servidor temporariamente sobrecarregado                                                                                                                                              |    Sim    | Reconecte usando recuo exponencial com full jitter, restabeleça as assinaturas e recupere dados perdidos.                                                                                                                                   |
| [4402](https://docs.blockvectra.com/en/errors/#4402) | `insufficient balance`           | Saldo da conta esgotado                                                                                                                                                              |    Não    | Não reconecte automaticamente. [Recarregue seu saldo e reconecte](https://docs.blockvectra.com/en/guides/billing-rules/).                                                                                                                                               |
| [4404](https://docs.blockvectra.com/en/errors/#4404) | `invalid api key`                | A API key é desconhecida, está desativada ou foi revogada                                                                                                                            |    Não    | Não reconecte automaticamente. Verifique ou rotacione a API key no console antes de reconectar.                                                                                                                                             |
| [4408](https://docs.blockvectra.com/en/errors/#4408) | `slow consumer`                  | O servidor fecha uma sessão cuja fila de envio ultrapassa 512 KiB e descarta notificações pendentes; clientes podem não receber um quadro de encerramento (o navegador reporta 1006) |    Sim    | Trate desconexões inesperadas (nenhum quadro de encerramento recebido, navegador reporta 1006) como 4408: reconecte com recuo, restabeleça as assinaturas e preencha dados descartados com `eth_getLogs`; assine menos ou leia mais rápido. |
| [4429](https://docs.blockvectra.com/en/errors/#4429) | `push rate exceeded`             | Taxa de notificação excedeu 1.000 envios/segundo                                                                                                                                     |    Sim    | Reduza as assinaturas ou restrinja os filtros; reconecte com recuo, assine novamente e recupere dados.                                                                                                                                      |
| [4503](https://docs.blockvectra.com/en/errors/#4503) | `billing unavailable`            | Cobrança temporariamente indisponível                                                                                                                                                |    Sim    | Estado transitório; reconecte usando recuo exponencial com full jitter.                                                                                                                                                                     |

## Reconexão e recuo exponencial

Para evitar tempestades de reconexão sincronizadas quando conexões caem, os clientes devem implementar recuo exponencial com full jitter:

* **Fórmula de recuo**: Antes da n-ésima tentativa de reconexão (n = 0, 1, 2, ...), aguarde por uma duração escolhida uniformemente ao acaso:
  ```
  delay = random(0, min(20s, 0.5s * 2^n))
  ```
* **Redefinição do contador**: Redefina o contador de tentativas n para 0 somente após manter uma conexão ininterrupta e estável por pelo menos `60 segundos`.
* **Código de encerramento 1012**: Introduza um atraso inicial aleatório antes da primeira tentativa de reconexão para evitar picos sincronizados de reconexão.
* **Códigos não repetíveis**: Não reconecte automaticamente em [4402](https://docs.blockvectra.com/en/errors/#4402), [4404](https://docs.blockvectra.com/en/errors/#4404), [1003](https://docs.blockvectra.com/en/errors/#1003) ou [1009](https://docs.blockvectra.com/en/errors/#1009).

### Recuperação de dados perdidos após a reconexão

Assinaturas via WebSocket não persistem entre conexões; notificações emitidas durante uma desconexão não são retidas no servidor. Após a reconexão, os clientes devem executar uma estratégia de sincronização:

1. **Recuperar logs com `eth_getLogs`**:
   * Persista o número de bloco mais alto processado com sucesso (`last_processed_block`).
   * Chame imediatamente `eth_subscribe("logs", ...)` na reconexão para capturar eventos em tempo real.
   * Consulte os blocos perdidos via `eth_getLogs` com `fromBlock: last_processed_block + 1` e `toBlock: "latest"` (ou o primeiro bloco recebido do fluxo em tempo real).
   * Se a lacuna da desconexão exceder o `max_logs_block_range` da rede (obtido em `GET /v1/chains`), divida as consultas em partes que não excedam esse limite.
   * Deduplique entradas de log no limite da consulta usando a tupla exclusiva `(blockHash, transactionHash, logIndex)`.
2. **Recuperar cabeçalhos de blocos com `eth_getBlockByNumber`**:
   * Registre o número e o hash do bloco mais recente recebido antes da desconexão.
   * Assine novamente `newHeads`.
   * Consulte `eth_getBlockByNumber("latest", false)` e busque os blocos intermediários ausentes sequencialmente. Verifique a continuidade da cadeia via `parentHash` para detectar reorgs.

## Limites

| Limite                                       | Valor                                                                       | Resultado ao exceder                                                |
| -------------------------------------------- | --------------------------------------------------------------------------- | ------------------------------------------------------------------- |
| Assinaturas por conexão WebSocket            | 100                                                                         | `-32022` [`subscription_limit`](https://docs.blockvectra.com/en/errors/#subscription_limit)     |
| Assinaturas `newHeads` por conexão WebSocket | 4                                                                           | `-32022` [`subscription_limit`](https://docs.blockvectra.com/en/errors/#subscription_limit)     |
| Requisitos de filtro da assinatura de `logs` | Deve especificar um `address` ou um `topic0` (primeira posição em `topics`) | `-32602` [`logs_filter_required`](https://docs.blockvectra.com/en/errors/#logs_filter_required) |

## Próximos passos

* [Explore o diretório de conjuntos de dados](https://blockvectra.com/en/data/) para ver todos os conjuntos de dados indexados pela BlockVectra.
* [Consulte o plano gratuito e os preços](https://blockvectra.com/en/pricing/#free) para verificar o que sua conta inclui.
* [Entre no console](https://console.blockvectra.com/login/?next=%2Fkeys%2F) para criar uma API key.
