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

# Filtragem de Contas em Grande Escala com Filtros Comprimidos

> Assine centenas de milhares de contas Solana em um único stream gRPC LaserStream usando filtros cuckoo comprimidos — solicitações de inscrição ~8x menores com verificação local exata.

## Visão Geral

O LaserStream suporta **filtragem de contas comprimidas via filtros cuckoo**. Em vez de enviar uma lista explícita de pubkey em sua solicitação de inscrição (32 bytes por conta), você envia um filtro probabilístico compacto que custa aproximadamente **3–4 bytes por conta** na rede.

Isso torna viável assinar **centenas de milhares de contas em um único stream** — sem fragmentação entre conexões, sem solicitações de inscrição grandes demais.

Por exemplo, um filtro que rastreia 500.000 contas serializa para cerca de 2,1 MB, em comparação com 16 MB como uma lista de pubkey bruta — aproximadamente **7,6x menor**. A economia exata depende de quão cheio está o filtro: quanto mais próximo da capacidade, menos bytes por conta.

### Disponibilidade

| Cliente                                                        | Versão mínima | Suporte a Cuckoo |
| -------------------------------------------------------------- | ------------- | ---------------- |
| LaserStream SDK — Rust (`helius-laserstream`)                  | 0.2.0         | ✅                |
| LaserStream SDK — JavaScript/TypeScript (`helius-laserstream`) | 0.4.0         | ✅                |
| LaserStream SDK — Go                                           | —             | ❌ Ainda não      |
| Yellowstone gRPC — Rust (`yellowstone-grpc-client`)            | 13.1.0        | ✅                |

## Quando usar filtros cuckoo

| Contas rastreadas | Abordagem recomendada                                             |
| ----------------- | ----------------------------------------------------------------- |
| Até \~10.000      | Listas explícitas de pubkey (`account: [...]`) — simples e exatas |
| \~10.000 e acima  | Filtro cuckoo via `CompressedAccountFilterSet`                    |

Casos de uso típicos: monitorar cada titular de um token, rastrear todas as posições em um protocolo de empréstimo ou observar grandes conjuntos de carteiras para um sistema de negociação ou análise.

## Como funciona

1. **Construa o filtro no lado do cliente.** Insira cada pubkey rastreada em um `CompressedAccountFilterSet`. A semente de hash é randomizada por filtro e serializada junto com ele, para que o servidor faça hash das contas recebidas com a mesma semente que seu cliente usou.
2. **Anexe-o à sua solicitação de inscrição.** `insert_into_subscribe_request()` coloca o filtro serializado no stream de contas de um `SubscribeRequest` padrão.
3. **O servidor faz a correspondência probabilística.** Como o filtro é probabilístico, o servidor pode entregar atualizações para contas que você não rastreou — falsos positivos são limitados a **menos de 1% sob carga total**. Nunca há falsos negativos: toda atualização para uma conta rastreada é entregue.
4. **Verifique novamente cada atualização localmente — este passo é necessário.** Chame `set.contains(pubkey)` em cada conta recebida antes de processá-la. Esta verificação é exata (suportada por um conjunto de hash interno), então após o filtro local você não vê falsos positivos.

## Início Rápido (Rust)

Adicione o SDK ao seu projeto:

```toml Cargo.toml theme={"system"}
[dependencies]
helius-laserstream = "0.2"
tokio = { version = "1", features = ["full"] }
futures = "0.3"
```

Construa um filtro, anexe-o a uma assinatura e elimine falsos positivos localmente:

```rust main.rs [expandable] theme={"system"}
use {
    futures::StreamExt,
    helius_laserstream::{
        cuckoo::{CompressedAccountFilterSet, Pubkey},
        grpc::{subscribe_update::UpdateOneof, SubscribeRequest},
        subscribe, LaserstreamConfig,
    },
    std::str::FromStr,
};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // The exact set of accounts you care about. In production this is
    // typically loaded from your database — hundreds of thousands of keys.
    let tracked: Vec<Pubkey> = [
        "So11111111111111111111111111111111111111112", // Wrapped SOL
        "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", // USDC
        "Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB", // USDT
    ]
    .iter()
    .map(|s| Pubkey::from_str(s).unwrap())
    .collect();

    // Build the cuckoo filter. Size it for your peak tracked-set size.
    let mut set = CompressedAccountFilterSet::with_capacity(500_000)?;
    for pk in &tracked {
        set.insert(*pk)?;
    }
    println!(
        "Tracking {} accounts via cuckoo filter ({} bytes on the wire)",
        set.len(),
        set.to_proto().data.len()
    );

    // Attach the compressed filter to the accounts stream.
    let mut request = SubscribeRequest::default();
    set.insert_into_subscribe_request(&mut request, "tracked_accounts");

    let config = LaserstreamConfig::new(
        "https://laserstream-mainnet-ewr.helius-rpc.com".to_string(), // Choose your closest region
        "YOUR_API_KEY".to_string(), // Replace with your key from https://dashboard.helius.dev/
    );

    let (stream, _handle) = subscribe(config, request);
    tokio::pin!(stream);
    while let Some(message) = stream.next().await {
        match message {
            Ok(update) => {
                if let Some(UpdateOneof::Account(account_update)) = update.update_oneof {
                    if let Some(info) = account_update.account {
                        let pk = Pubkey::try_from(info.pubkey.as_slice()).ok();
                        // Re-check locally: drop server-side false positives.
                        match pk {
                            Some(pk) if set.contains(pk) => {
                                println!(
                                    "tracked account update: {pk} (slot {})",
                                    account_update.slot
                                );
                            }
                            Some(pk) => {
                                println!("(false positive, ignored): {pk}");
                            }
                            None => {}
                        }
                    }
                }
            }
            Err(e) => eprintln!("stream error: {e}"),
        }
    }

    Ok(())
}
```

Uma versão completa executável acompanha o SDK: [`rust/examples/cuckoo_account_filter.rs`](https://github.com/helius-labs/laserstream-sdk/blob/main/rust/examples/cuckoo_account_filter.rs).

## Início Rápido (JavaScript/TypeScript)

Instale o SDK (suporte a cuckoo requer `helius-laserstream` 0.4.0+):

```bash theme={"system"}
npm install helius-laserstream
```

Construa o filtro, anexe e verifique novamente cada atualização localmente:

```typescript [expandable] theme={"system"}
import {
  subscribe,
  CommitmentLevel,
  CompressedAccountFilterSet,
  SubscribeUpdate,
  LaserstreamConfig,
} from 'helius-laserstream';

async function main() {
  const config: LaserstreamConfig = {
    apiKey: 'YOUR_API_KEY', // Replace with your key from https://dashboard.helius.dev/
    endpoint: 'https://laserstream-mainnet-ewr.helius-rpc.com', // Choose your closest region
  };

  // The accounts you want to track. In production this is typically loaded
  // from your database — hundreds of thousands of keys.
  const addresses = [
    'So11111111111111111111111111111111111111112', // Wrapped SOL
    'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v', // USDC
    'Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB', // USDT
  ];

  // Build a compact cuckoo filter instead of sending the full pubkey list.
  // Size capacity for your peak tracked-set size.
  const tracked = new CompressedAccountFilterSet(500_000);
  for (const address of addresses) {
    tracked.insert(address);
  }

  // Attach the filter to the request (no explicit account list needed).
  const request: any = { accounts: {}, commitment: CommitmentLevel.CONFIRMED };
  tracked.insertIntoSubscribeRequest(request, 'tracked-accounts');

  const stream = await subscribe(
    config,
    request,
    async (update: SubscribeUpdate) => {
      const pubkey = update.account?.account?.pubkey;
      if (!pubkey) return;
      // Re-check locally: drop server-side false positives. This is exact.
      if (tracked.contains(pubkey)) {
        console.log('tracked account update:', update.account);
      }
    },
    (error: Error) => {
      console.error('Stream error:', error);
    }
  );

  process.on('SIGINT', () => {
    stream.cancel();
    process.exit(0);
  });
}

main().catch(console.error);
```

Uma versão completa executável acompanha o SDK: [`javascript/examples/cuckoo-account-sub.ts`](https://github.com/helius-labs/laserstream-sdk/blob/main/javascript/examples/cuckoo-account-sub.ts).

## Referência de API

`CompressedAccountFilterSet` encapsula o filtro cuckoo bruto junto com um conjunto de hash exato, para que as mutações e verificações de associação sejam sempre seguras e exatas:

| Método                                                 | Comportamento                                                                                                                |
| ------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------- |
| `with_capacity(n)`                                     | Crie um filtro dimensionado para `n` contas rastreadas. Dimensione para o tamanho **máximo** do conjunto rastreado.          |
| `insert(pubkey)`                                       | Retorna `Ok(true)` se novo, `Ok(false)` se for um duplicado, `Err(TableFullError)` se o filtro estiver na capacidade máxima. |
| `remove(pubkey)`                                       | Remove a conta. Seguro e exato.                                                                                              |
| `contains(pubkey)`                                     | Verificação exata de associação — use isso para eliminar falsos positivos do lado do servidor.                               |
| `insert_into_subscribe_request(&mut request, "label")` | Anexe o filtro ao stream de contas de um `SubscribeRequest`.                                                                 |
| `to_account_filter()` / `to_proto()`                   | Conversões de nível inferior para montagem personalizada de solicitações.                                                    |
| `is_dirty()` / `take_dirty()`                          | Relate se o conjunto mudou desde que foi colocado em uma solicitação — útil para ciclos de reinscrição.                      |

Os nomes dos métodos acima usam convenções de Rust. O SDK JavaScript/TypeScript expõe a mesma superfície em camelCase — `new CompressedAccountFilterSet(capacity)` em vez de `with_capacity`, `insertIntoSubscribeRequest`, `isDirty`, `takeDirty`, `toProto`, e assim por diante. Em JavaScript `insert` retorna um booleano (`true` se recém-adicionado) e gera `TableFullError` quando o filtro está saturado. Uma pubkey pode ser passada como uma string base58, 32 bytes brutos ou qualquer objeto com um método `toBytes()`.

Sempre use `CompressedAccountFilterSet` em vez do `CuckooFilter` bruto que ele encapsula. O `remove()` do filtro bruto pode remover silenciosamente o item errado — um conhecido problema documentado dos filtros cuckoo. O wrapper emparelha o filtro com um conjunto de hash exato, para que inserir, remover e contém sejam sempre corretos.

## Dimensionamento de Capacidade

* Dimensione o filtro para o **número máximo** de contas que você espera rastrear via `with_capacity(n)`.
* Inserir além da capacidade falha graciosamente com um `TableFullError` — o filtro nunca é corrompido. Na prática, a tabela tolera um leve excesso antes de rejeitar inserções, mas não confie nesse espaço extra.
* O tamanho serializado é determinado pela capacidade, não pela quantidade de contas que você inseriu — então um filtro superdimensionado desperdiça bytes de rede. Escolha uma capacidade próxima ao seu pico real.

## Atualizando o conjunto rastreado

Quando seu conjunto rastreado muda (novas contas a seguir, antigas a serem removidas):

1. Chame `insert()` / `remove()` no `CompressedAccountFilterSet`.
2. Verifique `is_dirty()` (ou consuma o sinalizador com `take_dirty()`) para ver se o filtro mudou desde que foi enviado pela última vez.
3. Se estiver modificado, reconstrua a solicitação com `insert_into_subscribe_request()`. Em JavaScript, você pode reenvia-lo no mesmo stream com `stream.write(request)`; em Rust, reinscreva-se com a solicitação reconstruída.

## FAQ

<Accordion title="Posso perder atualizações para contas no meu filtro?">
  Não. Os filtros cuckoo produzem falsos positivos (atualizações extras para contas não rastreadas), mas **nunca falsos negativos**. Toda atualização para uma conta rastreada é entregue.
</Accordion>

<Accordion title="Quantas atualizações extras (falsos positivos) receberei?">
  Menos de 1% sob carga total, e geralmente menos quando o filtro está abaixo da capacidade. Uma chamada local `contains()` por atualização os filtra exatamente.
</Accordion>

<Accordion title="Quais clientes suportam filtros cuckoo?">
  O SDK Rust (`helius-laserstream` 0.2.0+), o SDK JavaScript/TypeScript (`helius-laserstream` 0.4.0+), e o cliente Yellowstone Rust (`yellowstone-grpc-client` 13.1.0+). O SDK Go ainda não suporta. Veja a [tabela de disponibilidade](#availability) acima.
</Accordion>

<Accordion title="Posso ainda usar listas explícitas de pubkey?">
  Sim. Os filtros padrão `account: [...]` funcionam inalterados e continuam sendo a escolha certa para conjuntos de contas pequenos (até cerca de 10.000 contas). Veja o [guia de assinatura de contas](/docs/pt-BR/laserstream/guides/account-subscription).
</Accordion>

## Relacionados

<CardGroup cols={2}>
  <Card title="Assinaturas de Contas" icon="user" href="/docs/pt-BR/laserstream/guides/account-subscription">
    Filtragem padrão de contas com filtros de proprietário, tamanho de dados e memcmp.
  </Card>

  <Card title="Clientes & SDKs" icon="code" href="/docs/pt-BR/laserstream/clients">
    SDKs TypeScript, Rust e Go com reprodução automática e reconexões.
  </Card>
</CardGroup>
