ODocumentation Index
Fetch the complete documentation index at: https://zapo.to/llms.txt
Use this file to discover all available pages before exploring further.
zapo é uma implementação independente e feita do zero do protocolo multi-dispositivo do WhatsApp. Esta página explica como o protocolo se parece na rede (on the wire) e aponta para os módulos onde o zapo cuida de cada camada. Você não precisa de nada disso para usar a biblioteca — está aqui para os curiosos e para contribuidores.
Os artefatos de definição do protocolo na pasta
spec/ (schemas protobuf, app-state e MEX) são gerados a partir do repositório aberto vinikjkkj/wa-spec, que acompanha as definições do protocolo do WhatsApp.As camadas
Do socket para cima:Transporte e o handshake Noise
O WhatsApp não fala WebSocket puro — cada byte após o connect é envolvido em uma sessão do protocolo Noise (um handshake estiloXX usando Curve25519, AES-GCM e SHA-256). O handshake autentica o servidor, negocia as chaves de sessão e, a partir daí, cada frame é criptografado com AES-GCM usando um nonce contador.
No zapo:
src/transport/WaComms.tsé dono do ciclo de vida do socket + Noise.src/transport/noise/implementa a máquina de estados do handshake (WaNoiseHandshake), o wrapper do socket criptografado e o client payload de login/registro (metadados do dispositivo, versão do app, locale).- O socket em si é plugável:
src/transport/WaWebSocket.tspara o WebSocket do navegador/Node (modo companion),src/transport/node/WaMobileTcpSocket.tspara o transporte TCP bruto (modo mobile).
Stanzas: o codec de binary node
Dentro do túnel Noise, o WhatsApp fala uma forma binária compacta de stanzas semelhantes a XMPP. Ozapo modela cada stanza como um BinaryNode:
s.whatsapp.net são bytes únicos), empacotamento em nibble/hex para JIDs e números, e compressão opcional. O codec do zapo fica em src/transport/binary/ (encoder.ts, decoder.ts, tokens.ts) e é escrito para zero-copy — o decoder retorna views subarray sobre os bytes recebidos em vez de copiá-los.
Requests e responses (IQ)
Muitas operações são stanzas IQ de request/response (<iq type="get|set"> → <iq type="result|error">), correlacionadas por um id de stanza. src/transport/node/WaNodeOrchestrator.ts atribui ids, rastreia queries em andamento em um map e resolve a response correspondente (ou expira por timeout). Os coordinators tipados são construídos sobre isso; você pode acessá-lo diretamente via client.lowlevel.query.
Criptografia ponta a ponta (Signal)
Os corpos das mensagens são criptografados ponta a ponta com o protocolo Signal. Ozapo o implementa em src/signal/ sobre as primitivas em src/crypto/:
- Identidade e prekeys — cada dispositivo tem uma chave de identidade de longo prazo e um conjunto de prekeys de uso único. Estabelecer uma sessão com um novo peer busca o prekey bundle dele.
- Chats 1:1 — uma sessão Double-Ratchet criptografa cada mensagem. Na rede, o envelope é
msg(uma sessão estabelecida) oupkmsg(uma prekey message que também inicializa a sessão). - Grupos — um esquema de sender-key (
skmsg): cada membro distribui uma sender key uma vez, e então criptografa as mensagens do grupo simetricamente (AES-CBC) com ela. As distribution messages acompanham para os membros que ainda não têm sua sender key.
'msg' | 'pkmsg' | 'skmsg') aparece em todo lugar como o tipo de mensagem criptografada.
Multi-dispositivo e fanout
O WhatsApp é multi-dispositivo: uma conta é um conjunto de dispositivos, e uma mensagem deve ser criptografada uma vez por dispositivo destinatário. Ozapo resolve a lista de dispositivos para cada destinatário, estabelece sessões Signal conforme necessário e faz o fanout do ciphertext em uma única stanza <message>. Os destinatários são endereçados pelo JID de número de telefone ou por LID, com o addressing_mode escolhido a partir da composição do grupo. Seus próprios outros dispositivos recebem uma cópia deviceSentMessage para que todos os seus dispositivos fiquem sincronizados.
Sincronização de app-state
Configurações que precisam parecer iguais em todos os dispositivos — silenciar, fixar, arquivar, estado de leitura, labels, contatos — não são mensagens. Elas sincronizam por um canal app-state separado: mutations criptografadas e com MAC, organizadas em coleções e reconciliadas com um LT-hash para que os dispositivos convirjam. Ozapo implementa isso em src/appstate/ (WaAppStateSyncClient + WaAppStateCrypto) e o expõe através de client.chat e do evento mutation.
Mídia
A mídia não é enviada inline. Os bytes são criptografados com uma media key por mensagem (AES-CBC + HMAC) e enviados a uma CDN do WhatsApp; a stanza carrega a URL, as chaves e os digests. O destinatário faz o download e descriptografa. Ozapo cuida do upload/download em src/media/ — veja o guia de mídia.
MEX (GraphQL)
Superfícies mais novas — newsletters, partes do business, algumas notificações — usam o MEX, uma camada de GraphQL-sobre-IQ. Ozapo envolve essas queries nos coordinators relevantes (por exemplo, client.newsletter); o peer opcional argo-codec decodifica certas respostas MEX.
Escolhas de design
Ozapo faz escolhas deliberadas e informadas pelo protocolo:
index-first— o comportamento é validado contra o WhatsApp Web antes de ser implementado.performance-first—Uint8Arrayem todo lugar, zero-copy nos caminhos quentes, estruturas em memória limitadas. A criptografia é síncrona exceto pelas operações de curva elíptica (que são assíncronas) — veja internals.- I/O
async-first— rede e I/O são assíncronos; os caminhos quentes de decode/encode evitam alocação desnecessária.
