npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@johnlester-0369/fb-messenger-e2ee

v0.1.4

Published

E2EE-only TypeScript/Bun toolkit for Facebook Messenger Noise, Signal Protocol, WA-binary, media, and DGW flows

Readme

FME - FB Messenger E2EE

TypeScript Bun License: MIT

FME - FB Messenger E2EE is a TypeScript/Bun toolkit focused on Facebook Messenger E2EE flows built on Noise, WA-binary, protobuf, and the Signal Protocol. Plaintext/non-E2EE messaging is intentionally left to fca-unofficial directly.


Key Features

  • Native E2EE path: Signal Protocol sessions, prekeys, sender keys, Noise socket frames, and WA-binary nodes for encrypted Messenger chats.
  • Group sender-key support: group skmsg decrypt/encrypt plus participant fanout of sender-key distribution messages (skdm).
  • Device persistence: JSON-backed DeviceStore keeps Noise keys, Signal identity, sessions, prekeys, signed prekeys, and sender keys across restarts.
  • Automatic prekey maintenance: replenishes server-side one-time prekeys without deleting or re-registering the E2EE device.
  • Typed E2EE events: catch-all and typed event subscriptions for E2EE messages, receipts, reactions, errors, and raw frames.
  • DGW support: optional Direct Gateway / LightSpeed socket helpers.

Tech Stack

  • Runtime: Bun / Node-compatible APIs
  • Language: TypeScript
  • Encryption: @signalapp/libsignal-client
  • Protocol: ProtobufJS + manual WA-binary/protobuf encoders
  • Auth bootstrap bridge: fca-unofficial is used internally only for appState login/CAT bootstrap; use it directly for non-E2EE messaging.

Getting Started

1. Installation

bun install

2. Basic Usage

import { FBClient } from "fb-messenger-e2ee";

const client = new FBClient({
  appStatePath: "./appstate.json",
  sessionStorePath: "./session.json",
  platform: "facebook",
});

const { userId } = await client.connect();

// Keep this file. It is the registered E2EE device identity and Signal state.
await client.connectE2EE("./device-store.json", userId);

client.onEvent((event) => {
  if (event.type === "e2ee_connected") {
    console.log("E2EE stream is ready");
  }

  if (event.type === "e2ee_message") {
    console.log(`[E2EE] ${event.data.threadId} ${event.data.senderJid}: ${event.data.text}`);
  }

  if (event.type === "error") {
    console.error("Client error:", event.data.message);
  }
});

await client.sendMessage({
  threadId: "1234567890", // user ID, *.@msgr JID, or group JID
  text: "Hello from the secure side!",
});

Device Store & Key Maintenance

connectE2EE(deviceStorePath, userId) loads or creates a persistent device store. Do not delete it as a normal recovery step:

  • Deleting it generates a new Noise key, Signal identity, registration ID, facebook_uuid, and device registration.
  • Keeping it lets the same registered E2EE device continue using existing sessions and sender keys.
  • The client now refreshes one-time prekeys automatically and does not need a new device registration for normal prekey exhaustion.

Configurable environment variables:

| Env | Default | Purpose | |---|---:|---| | FB_E2EE_PREKEY_SYNC_INTERVAL_MS | 1800000 | Periodic prekey check interval. Set 0 to disable. | | FB_E2EE_PREKEY_MIN_COUNT | 5 | Upload more prekeys when server count falls below this. | | FB_E2EE_PREKEY_UPLOAD_COUNT | 50 | Number of fresh one-time prekeys to upload per refill. |

Group decrypt note: if local sender_keys for a group/sender are truly missing, the client cannot derive that key locally. On retryable decrypt failures it sends an E2EE retry receipt to request a resend/SKDM from the sender/server. The send path also keeps a short in-memory retry cache so incoming receipt type="retry" requests for recently-sent messages can be re-encrypted directly to the requesting device. This is different from prekey exhaustion.

E2EE event identity model:

  • threadId: stable conversation ID. For DMs this is the bare Facebook user ID; for groups it is the group JID.
  • chatJid: canonical E2EE chat JID. For DMs this is user.0@msgr; for groups it is [email protected].
  • senderJid: device-specific sender JID such as user.160@msgr.
  • senderDeviceId: numeric Messenger E2EE device ID when available.
  • kind: normalized content kind (text, image, reaction, edit, etc.). Empty optional fields are omitted from the event payload.

Project Structure

src/
├── controllers/    # Thin orchestration + receive handlers
├── core/           # Public FBClient facade
├── e2ee/
│   ├── application/ # E2EEClient, retry/prekey/cache/fanout runtime helpers
│   ├── store/       # DeviceStore + JSON migration/repository
│   ├── transport/   # Noise, WA-binary, DGW sockets
│   ├── signal/      # Signal sessions, prekeys, sender keys
│   ├── message/     # Protobuf writer/builders/codecs/schemas
│   ├── media/       # Media crypto/upload
│   └── facebook/    # FB-specific SKMSG/SKDM/ICDC helpers
├── models/         # TypeScript interfaces & domain models
├── services/       # Auth/CAT bridge, ICDC, E2EE facade, media helpers
├── repositories/   # Session persistence
└── utils/          # Logger and conversion helpers

Testing

npm run typecheck
npm test -- --runInBand

Manual echo script:

bun run tests/script/echo-e2ee.ts

Documentation

For the API reference and operational notes, see DOCS.md.


Acknowledgements

Special thanks to the fca-unofficial team for the foundational bridge work.


License

MIT © VangBanLaNhat