zapo pode conectar como um client mobile primário — falando o protocolo do app Android por um socket TCP bruto.
O suporte mobile é estável e funcional. A única coisa que o
zapo não fornece é uma API de registro — solicitar um código por SMS/voz, enviar um OTP ou aprovar um takeover. Registrar um número é complexo e requer um telefone físico, então está intencionalmente fora de escopo. Você conecta com um conjunto de credenciais já registrado, e esse caminho é sólido.Como difere do modo companion
Habilitando o modo mobile
O modo mobile é acionado pela opçãomobileTransport (um WaMobileTransportOptions). Sua presença — ou um deviceInfo persistido nas credenciais carregadas — muda o client do transporte WebSocket para o transporte TCP.
WaMobileTransportOptions
WaMobileTransportDeviceInfo
manufacturer, device, osVersion, osBuildNumber, appVersion são obrigatórios; mcc, mnc, localeLanguageIso6391, localeCountryIso31661Alpha2, phoneId, deviceBoard, deviceModelType são opcionais. Um fingerprint estável entre execuções importa — persista-o e reutilize os mesmos valores.
Credenciais
O modo mobile precisa de um conjunto de credenciais já registrado: umWaAuthCredentials com meJid preenchido, platform: 'android' e deviceInfo anexado. Você semeia isso na auth store antes de conectar (por exemplo, importado de um device bundle).
Uma vez que as credenciais com
deviceInfo são persistidas, reconexões posteriores rodam automaticamente em modo mobile-primary completo — transporte TCP, formatos de IQ / message id mobile, gating de app-state primary e withholding de placeholder-resend (veja abaixo) tudo deriva do deviceInfo carregado. Você não precisa re-passar mobileTransport em cada construção.Withholding de placeholder-resend
Quando um device companion falha em decifrar uma mensagem recebida, ele normalmente pede a um peer pareado o plaintext original via um placeholder-resend request. Um telefone primário não tem peer device segurando o plaintext, então uma sessão mobile-primary pula o placeholder request inteiro e cai para um retry receipt comum — o caminho padrão de re-encrypt que o sender já suporta. Isso evita o request expirar silenciosamente e a mensagem ser dropada.Eventos de registro
Enquanto sua sessão mobile está conectada, você é notificado quando alguém tenta registrar seu número em outro dispositivo — um sinal relevante para segurança, exposto como estes eventos:Esses eventos são informativos — o
zapo os expõe, mas intencionalmente não disponibiliza métodos para enviar um código ou responder a um takeover. O provisionamento de um número é feito em um telefone real; traga as credenciais resultantes para o zapo e conecte.Vínculo de email
Mobile-onlyclient.email (WaEmailCoordinator) vincula e verifica um endereço de email na conta — um fator de recuperação/login. É mobile-only: todo método lança erro em uma conexão Web/companion.
Hospedando dispositivos companheiros
Apenas mobile-primary Uma sessão companion vive do outro lado de um QR / código de pareamento, vinculada por um telefone real. Quando o zapo é o telefone, os papéis se invertem: esta sessão primary pode hospedar companions — vincular uma aba do WhatsApp Web, revogá-la, listar o que está conectado e reconciliar contra a lista de dispositivos do servidor. O coordinator fica emclient.mobile (WaMobileCoordinator).
client.mobile requer uma sessão mobile-primary. Ler o getter em uma conexão Web/companion retorna o coordinator, mas os métodos de link/revoke/publish lançam client.mobile requires a mobile-primary session (…) antes de tocar na rede. reconcileCompanions() vira um no-op em sessões não-primary.Métodos
Eventos
Atividade de companion-host aparece no client:Bootstrap gates cuidados por você
Todo companion que um telefone WhatsApp vincula hoje espera três sinais no pair-time. Ozapo os fornece para que o companion não se remova sozinho após o QR:
- Client-props de LID migration — um primary LID-native declara
isChatDbLidMigratedeisSyncdPureLidSessionno elemento<client-props>para que o companion rodesetIsLidMigratedno pair-time e não se remova sozinho por conta da sua blocklist endereçada por LID. - History-sync
INITIAL_BOOTSTRAP— o primary envia a notificação inicial de history-sync como uma peer message; sem ela, o companion se remove sozinho comHistorySyncTimeout. setting_pushNamesemeado — o nome de exibição do próprio primary é semeado na collectioncritical_blockdo app-state, uma vez por sessão, para o critical bootstrap do companion completar.
Persistência
O estado do epoch ADV (rawId, currentKeyIndex, companions rastreados) precisa persistir entre reinícios — reusar um índice de chave companion já emitido quebra dispositivos previamente vinculados. Wire um CompanionHostPersistence em WaClientOptions.companionHost.persistence e o zapo carrega/salva transparentemente.
Uma implementação file-backed vem embarcada com a lib:
Backend custom
O contrato é dois métodos sobreCompanionHostEpochState:
better-sqlite3:
save roda a cada mudança de estado por linkCompanion / revokeCompanion / reconcileCompanions, então envolva a escrita multi-statement numa transaction pra manter atomicidade. load é chamado uma vez durante o wire-up do coordinator.
Exemplo trabalhado
Funcionalidades padrão continuam valendo
Uma vez conectado no modo mobile, o resto da API permanece inalterado —client.message, client.group, eventos, stores, etc. funcionam todos da mesma forma. A única diferença é o transporte e o modelo de auth/identidade.