> ## Documentation Index
> Fetch the complete documentation index at: https://www.helius.dev/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Início Rápido de Streams Analisados

> Conecte-se aos Streams Analisados, envie seu primeiro filtro e leia uma notificação decodificada. Além da referência completa do protocolo JSON-RPC 2.0.

<Tip>
  Novo em Streams Analisados? Leia [o modelo mental](/docs/pt-BR/parsed-streams#the-mental-model) primeiro — ele explica por que os filtros são como são.
</Tip>

## Início Rápido

<Steps>
  <Step title="Obter Acesso">
    Streams Analisados está em beta fechado. A equipe Helius coloca seu ID de projeto na lista branca e compartilha o endpoint de conexão com você. Para participar do beta fechado, [inscreva-se aqui](https://form.typeform.com/to/BlFWKbC9).

    Autentique-se com a chave de API do seu projeto, passada como o parâmetro de consulta `api-key` (ou o cabeçalho `x-api-key`).
  </Step>

  <Step title="Conectar">
    ```bash wscat theme={"system"}
    wscat -c "wss://<ENDPOINT>/?api-key=YOUR_API_KEY"
    ```

    Uma chave ausente, inválida ou não incluída na lista branca é rejeitada com HTTP 401. Um projeto no limite de conexão recebe HTTP 429.
  </Step>

  <Step title="Assine com um Filtro">
    Envie `parsedTransactionSubscribe` com um filtro e opções opcionais:

    ```json theme={"system"}
    {"jsonrpc":"2.0","id":1,"method":"parsedTransactionSubscribe","params":[{"programs":["JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4"]}]}
    ```

    A resposta `result` é um inteiro **id de assinatura**:

    ```json theme={"system"}
    { "jsonrpc": "2.0", "id": 1, "result": 23 }
    ```
  </Step>

  <Step title="Leia uma Notificação">
    Cada transação correspondente chega como um `parsedTransactionNotification`, já decodificado, com `matchedIndexes` apontando para as instruções que seu filtro atingiu. Veja [Notificações](#notifications) para o formato completo.
  </Step>

  <Step title="Cancelar Assinatura">
    ```json theme={"system"}
    { "jsonrpc": "2.0", "id": 2, "method": "parsedTransactionUnsubscribe", "params": [23] }
    ```

    Ou simplesmente feche a conexão — isso remove todas as suas assinaturas.
  </Step>
</Steps>

## Guias

<CardGroup cols={2}>
  <Card title="Acompanhe Trocas Jupiter" icon="arrow-right-arrow-left" href="/docs/pt-BR/parsed-streams/guides/track-jupiter-swaps">
    Use `describeProgram` para construir um filtro confiável antes de assinar.
  </Card>

  <Card title="Acompanhe Mints do Pump.fun" icon="rocket" href="/docs/pt-BR/parsed-streams/guides/track-pumpfun-mints">
    Um ouvinte seguro para reconexões que registra cada novo deploy de token Pump.fun.
  </Card>

  <Card title="Lidando com Reconexões" icon="rotate" href="/docs/pt-BR/parsed-streams/guides/handling-reconnects">
    Sobreviva a timeouts de inatividade e implantações, depois recupere exatamente o que perdeu.
  </Card>
</CardGroup>

## Referência do Protocolo

Streams Analisados usa **JSON-RPC 2.0** sobre uma única conexão WebSocket. Cada solicitação recebe uma resposta com o mesmo `id`. Uma assinatura então envia mensagens `parsedTransactionNotification` até você cancelar a assinatura ou desconectar.

| Método                         | Finalidade                                                 |
| ------------------------------ | ---------------------------------------------------------- |
| `parsedTransactionSubscribe`   | Iniciar uma assinatura com um filtro                       |
| `parsedTransactionUnsubscribe` | Parar uma assinatura                                       |
| `ping`                         | Verificação de atividade; retorna o slot atual             |
| `describeProgram`              | Liste instruções, eventos e papéis de conta de um programa |

### Inscrever-se

Envie `parsedTransactionSubscribe` com um filtro e opções opcionais. A resposta `result` é um inteiro **id de assinatura**.

```json Request theme={"system"}
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "parsedTransactionSubscribe",
  "params": [
    {
      "programs": ["JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4"],
      "instructionNames": ["route", "shared_accounts_route"],
      "accounts": {
        "include": ["So11111111111111111111111111111111111111112"],
        "roles": { "user_transfer_authority": "9xQeWvG816bUx9EPjHmaT23yvVM2ZWbrrpZb9PusVFin" }
      },
      "includeFailed": false,
      "includeCpi": true
    },
    { "commitment": "confirmed", "details": "full" }
  ]
}
```

```json Response theme={"system"}
{ "jsonrpc": "2.0", "id": 1, "result": 23 }
```

#### Campos de Filtro

Pelo menos um de `programs` ou `accounts.include` é necessário. Os campos que você define se combinam com **E**: uma instrução deve satisfazer todos eles para corresponder.

<ParamField body="programs" type="string[]">
  IDs dos Programas para corresponder (endereços base58, não nomes). Uma instrução corresponde se seu programa estiver nesta lista. OU dentro da lista.
</ParamField>

<ParamField body="instructionNames" type="string[]">
  Nomes de instruções decodificadas, como `route`. Correspondido exatamente primeiro, depois com uma diferença insensível a maiúsculas e separadores, então `sharedAccountsRoute` também corresponde ao nome da rede `shared_accounts_route`. OU dentro da lista. Apenas instruções cujo nome o catálogo pôde identificar podem corresponder, então pegue nomes de `describeProgram`.
</ParamField>

<ParamField body="accounts.include" type="string[]">
  Endereços de contas. Uma instrução corresponde se algum destes aparecer em sua lista de contas. OU dentro da lista. Funciona para todas as instruções, decodificadas ou não. O ID do programa em si não conta como uma conta aqui.
</ParamField>

<ParamField body="accounts.roles" type="object">
  Um mapa do nome do papel da conta decodificado para o endereço, como `{ "user_transfer_authority": "<pubkey>" }`. Cada entrada deve ser válida (E entre entradas), e a instrução deve estar decodificada para que isso se aplique. Nomes de papéis correspondem **exatamente**, sem distinção de maiúsculas, então copie-os de `describeProgram` em vez de adivinhar.
</ParamField>

<ParamField body="includeFailed" type="boolean" default="false">
  Incluir instruções de transações falhadas.
</ParamField>

<ParamField body="includeCpi" type="boolean" default="true">
  Instruções internas (CPI) são elegíveis para corresponder. Defina `false` para corresponder apenas a instruções de nível superior.
</ParamField>

Campos desconhecidos em qualquer lugar no filtro ou opções são rejeitados com `-32602` em vez de ignorados silenciosamente, então erros de digitação falham ruidosamente em vez de não corresponder a nada.

#### Opções

O segundo parâmetro é opcional.

<ParamField body="commitment" type="string" default="confirmed">
  Apenas `confirmed` é suportado.
</ParamField>

<ParamField body="details" type="string" default="full">
  O que cada notificação carrega. `full`: a transação inteira, cada instrução, além de `matchedIndexes` apontando para os acertos do filtro. `matched`: apenas as instruções que corresponderam, sem lista de índice. `raw`: apenas instruções correspondidas, cada uma reduzida à sua posição, `programId`, e blob base58 `data`, sem campos decodificados e sem matriz `accountKeys`. Use `matched` quando a largura de banda for mais importante que o contexto (cargas completas são, em média, aproximadamente três vezes o tamanho), e `raw` quando você decodificar dados de instrução por conta própria e só precisar dos bytes.
</ParamField>

Um projeto pode ter até **100 conexões simultâneas**, compartilhadas entre todas as suas chaves de API.

### Notificações

Uma notificação por transação correspondente por assinatura. Com o padrão `details: "full"`:

```json theme={"system"}
{
  "jsonrpc": "2.0",
  "method": "parsedTransactionNotification",
  "params": {
    "subscription": 23,
    "result": {
      "context": { "slot": 430172053 },
      "value": {
        "transaction": {
          "signature": "3riSYL4HTRxgQjLayt6L2JPaDR3oaEQg1H4v3fnjUxNU...",
          "slot": 430172053,
          "blockTime": null,
          "feePayer": "6jduWNCTQzG91JGBchfGGxd55Vi5FxJCCJEV18RkXzJX",
          "fee": 5000,
          "accountKeys": ["6jduWNCT...", "..."],
          "status": "ok",
          "error": null,
          "summary": {
            "type": "swap",
            "description": "6jduWNCTQzG91JGBchfGGxd55Vi5FxJCCJEV18RkXzJX swapped 0.001 SOL for 0.183985 EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v via Jupiter",
            "parsedData": {
              "type": "swap",
              "protocol": "jupiter",
              "kind": "swap",
              "in_amount": "1000000",
              "actual_out_amount": "183985",
              "input_mint": "So11111111111111111111111111111111111111112",
              "output_mint": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"
            }
          },
          "nativeTransfers": [
            { "fromUserAccount": "6jduWNCT...", "toUserAccount": "DfXygSm4...", "amount": 1000000 }
          ],
          "tokenTransfers": [
            {
              "fromUserAccount": "6jduWNCT...",
              "toUserAccount": "AeUfFU6L...",
              "fromTokenAccount": "HLaEoW1s...",
              "toTokenAccount": "G13P9kSY...",
              "rawTokenAmount": 183985,
              "decimals": 6,
              "tokenStandard": "Fungible",
              "mint": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"
            }
          ]
        },
        "instructions": [
          {
            "topIndex": 4,
            "innerIndex": null,
            "stackHeight": 1,
            "programId": "JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4",
            "programName": "jupiter",
            "instructionName": "route",
            "summary": {
              "type": "swap",
              "description": "6jduWNCTQzG91JGBchfGGxd55Vi5FxJCCJEV18RkXzJX swapped 0.001 SOL for 0.183985 EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v via Jupiter",
              "parsedData": {
                "type": "swap",
                "protocol": "jupiter",
                "kind": "swap",
                "in_amount": "1000000",
                "actual_out_amount": "183985",
                "input_mint": "So11111111111111111111111111111111111111112",
                "output_mint": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"
              }
            },
            "decoded": {
              "args": { "in_amount": "1000000", "slippage_bps": 50 },
              "accounts": [
                { "name": "user_transfer_authority", "pubkey": "9xQe...", "isSigner": true, "isWritable": false }
              ]
            }
          }
        ],
        "matchedIndexes": [8, 13]
      }
    }
  }
}
```

Lendo-o:

* **`transaction`** é o contexto completo. `fee` está em lamports. `accountKeys` é a lista completa de chaves, incluindo chaves carregadas de tabelas de pesquisa de endereço, na mesma ordem em que a rede as relata. `feePayer` é sempre `accountKeys[0]`. `error` carrega o erro da transação como JSON estruturado, por exemplo `{"InstructionError": [2, {"Custom": 6001}]}`, quando `status` é `"error"`.
* **`summary`** tem uma forma em todo lugar que aparece: um `type` (como `swap` ou `transfer`), um `description` legível por humanos e uma carga `parsedData` estruturada quando o analisador reconhece a ação — para uma troca: o protocolo, valores e mints. `transaction.summary` rotula a ação principal da transação; cada instrução reconhecida carrega seu próprio `summary` com a mesma forma. Para coletar toda troca em uma transação, percorra `instructions` e leia `summary.parsedData` onde `summary.type` é `"swap"`.
* **`nativeTransfers`** e **`tokenTransfers`** listam os movimentos de SOL e tokens que o analisador extraiu de toda a transação, na mesma forma que a API de Eventos Analisados retorna, para que consumidores de stream e API possam compartilhar código de processamento. Ambos estão sempre presentes, possivelmente vazios.
* **`instructions`** é cada instrução da transação em ordem de execução: cada instrução de nível superior seguida por suas instruções internas. Cada entrada carrega sua própria posição: `topIndex` é a qual instrução de nível superior pertence (começando em 0), `innerIndex` é sua posição entre as chamadas internas daquela instrução (`null` significa que é a própria instrução de nível superior), e `stackHeight` é a profundidade da chamada (1 para nível superior). Use esses, não a posição do array.
* **`matchedIndexes`** são índices em `instructions` dizendo quais seu filtro realmente atingiu. O resto está lá para contexto. Com `details: "matched"` o array contém apenas os acertos e `matchedIndexes` está ausente.
* **Nomes `decoded` são snake\_case** (`in_amount`, `user_transfer_authority`), conforme publicado no IDL do programa. Argumentos inteiros são comumente strings (`"1000000"`) porque valores u64 não cabem em números JavaScript.
* **`blockTime`** está atualmente sempre `null`. Não construa em cima disso.
* Espere uma **mistura de instruções decodificadas e não decodificadas** dentro de uma transação: uma troca totalmente decodificada pode estar ao lado de um memo não reconhecido. Divida em `decoded`: quando é `null`, a instrução carrega `rawData` (bytes base58) e `rawAccounts` (lista de pubkey simples) em vez disso, então você sempre terá algo com que trabalhar.

Com `details: "raw"` o `value` reduz-se a meta da transação e blobs. `accountKeys`, `nativeTransfers`, `tokenTransfers`, `matchedIndexes`, e todos os campos decodificados estão ausentes (a transação `summary` ainda está incluída); cada instrução correspondida é sua posição, seu programa e seus bytes `data` em base58, exatamente como aparecem na cadeia (presentes mesmo para instruções que o catálogo poderia ter decodificado):

```json theme={"system"}
"value": {
  "transaction": {
    "signature": "3riSYL4HTRxgQjLayt6L2JPaDR3oaEQg1H4v3fnjUxNU...",
    "slot": 430172053,
    "blockTime": null,
    "feePayer": "6jduWNCTQzG91JGBchfGGxd55Vi5FxJCCJEV18RkXzJX",
    "fee": 5000,
    "status": "ok",
    "error": null,
    "summary": {
      "type": "swap",
      "description": "6jduWNCTQzG91JGBchfGGxd55Vi5FxJCCJEV18RkXzJX swapped 0.001 SOL for 0.183985 EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v via Jupiter",
      "parsedData": {
        "type": "swap",
        "protocol": "jupiter",
        "kind": "swap",
        "in_amount": "1000000",
        "actual_out_amount": "183985",
        "input_mint": "So11111111111111111111111111111111111111112",
        "output_mint": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"
      }
    }
  },
  "instructions": [
    { "topIndex": 4, "innerIndex": null, "stackHeight": 1, "programId": "JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4", "data": "3Bxs4h24hBtQy9rw" }
  ]
}
```

### Cancelar Assinatura

```json theme={"system"}
{ "jsonrpc": "2.0", "id": 2, "method": "parsedTransactionUnsubscribe", "params": [23] }
```

Retorna `true` se a assinatura existia e era sua. As notificações param imediatamente. Fechar a conexão remove todas as suas assinaturas.

### Descoberta

O erro mais comum com esse tipo de API é um filtro que é válido mas não corresponde a nada, geralmente um nome de instrução ou papel adivinhado. `describeProgram` previne isso retornando os nomes exatos que o comparador verifica:

```json Request theme={"system"}
{ "jsonrpc": "2.0", "id": 1, "method": "describeProgram", "params": [{ "program": "JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4" }] }
```

```json Response theme={"system"}
{
  "jsonrpc": "2.0", "id": 1,
  "result": {
    "id": "JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4",
    "name": "jupiter",
    "instructions": ["route", "shared_accounts_route", "exact_out_route"],
    "events": ["SwapEvent"],
    "roles": ["user_transfer_authority", "destination_token_account"]
  }
}
```

Você pode passar um endereço de programa ou um nome de catálogo, mas **prefira o endereço**: nomes podem ser ambíguos entre versões de programas (mais de uma entrada de catálogo é nomeada `jupiter`, e uma busca por nome pode resolver para a mais antiga). Se você fizer a busca por nome, verifique se `result.id` é o programa que você pretende assinar.

Fluxo recomendado: `describeProgram` para obter os nomes exatos de instrução e papel, construa o filtro com esses nomes, depois assine. O guia [Acompanhe Trocas Jupiter](/docs/pt-BR/parsed-streams/guides/track-jupiter-swaps) percorre isso do início ao fim.

### Limites

| Limite                           | Valor                                        |
| -------------------------------- | -------------------------------------------- |
| Conexões simultâneas por projeto | 100                                          |
| Assinaturas por conexão          | 25                                           |
| Mensagens do cliente             | 10 por segundo, pico de 20                   |
| Tamanho da mensagem do cliente   | 64 KiB                                       |
| `programs` por filtro            | 10                                           |
| `instructionNames` por filtro    | 50, cada um até 64 caracteres                |
| `accounts.include` por filtro    | 100                                          |
| `accounts.roles` por filtro      | 20, cada nome até 64 caracteres              |
| Buffer de saída por conexão      | 2048 notificações, então a conexão é fechada |

### Erros

Erros seguem JSON-RPC 2.0: `{ "error": { "code": <int>, "message": "<text>" }, "id": <id> }`. Mensagens dizem exatamente o que estava errado e onde.

| Código   | Significado                                                                                                  |
| -------- | ------------------------------------------------------------------------------------------------------------ |
| `-32700` | Erro de parse (JSON inválido)                                                                                |
| `-32600` | Solicitação inválida                                                                                         |
| `-32601` | Método não encontrado                                                                                        |
| `-32602` | Parâmetros inválidos: chave pública ruim, campo desconhecido, valor de compromisso ou detalhes não suportado |
| `-32000` | Limite de filtro excedido                                                                                    |
| `-32001` | Servidor não pronto; tente novamente com backoff                                                             |
| `-32002` | Limitado por taxa (10 mensagens por segundo)                                                                 |
| `-32006` | Muitas assinaturas (25 por conexão)                                                                          |

Conexões também podem fechar com um código de fechamento WebSocket — veja [Lidando com Reconexões](/docs/pt-BR/parsed-streams/guides/handling-reconnects) para o que cada um significa e como se recuperar.

## Exemplos de Cliente

<CodeGroup>
  ```bash wscat theme={"system"}
  wscat -c "wss://<ENDPOINT>/?api-key=<API_KEY>"
  # then send:
  {"jsonrpc":"2.0","id":1,"method":"parsedTransactionSubscribe","params":[{"programs":["JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4"]}]}
  ```

  ```typescript TypeScript theme={"system"}
  import WebSocket from "ws";

  const ws = new WebSocket("wss://<ENDPOINT>/?api-key=<API_KEY>");

  ws.on("open", () => {
    ws.send(JSON.stringify({
      jsonrpc: "2.0",
      id: 1,
      method: "parsedTransactionSubscribe",
      params: [{ programs: ["JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4"] }],
    }));
  });

  ws.on("message", (data) => {
    const msg = JSON.parse(data.toString());
    if (msg.method === "parsedTransactionNotification") {
      const { transaction, instructions, matchedIndexes } = msg.params.result.value;
      for (const i of matchedIndexes ?? instructions.keys()) {
        const ix = instructions[i];
        console.log(transaction.signature, ix.programName, ix.instructionName, ix.decoded?.args);
      }
    }
  });
  ```

  ```python Python theme={"system"}
  import asyncio, json, websockets

  URL = "wss://<ENDPOINT>/?api-key=<API_KEY>"

  async def main():
      async with websockets.connect(URL) as ws:
          await ws.send(json.dumps({
              "jsonrpc": "2.0", "id": 1, "method": "parsedTransactionSubscribe",
              "params": [{"programs": ["JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4"]}],
          }))
          async for raw in ws:
              msg = json.loads(raw)
              if msg.get("method") == "parsedTransactionNotification":
                  value = msg["params"]["result"]["value"]
                  for i in value.get("matchedIndexes") or range(len(value["instructions"])):
                      ix = value["instructions"][i]
                      print(ix.get("programName"), ix.get("instructionName"), (ix.get("decoded") or {}).get("args"))

  asyncio.run(main())
  ```
</CodeGroup>
