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

@xdevplatform/chat-xdk

v0.4.3

Published

X Chat SDK - encryption for X Direct Messages

Downloads

9,803

Readme

chat-xdk JavaScript/WASM bindings

JavaScript/WASM bindings for the X Chat SDK — encryption for X Direct Messages.

Architecture

JavaScript (chat-xdk) → wasm-bindgen → Rust WASM (chat_xdk_wasm) → chat-xdk-core

The Rust WASM layer is a pure crypto engine; Juicebox key-storage lifecycle is orchestrated in the JS wrapper (index.js).

Prerequisites

  • Node.js 18+

Install

npm install @xdevplatform/chat-xdk

The compiled WASM engine ships inside the package (pkg/) — no build step.

Juicebox PIN-based key storage is an optional peer dependency:

npm install juicebox-sdk   # only needed for setup()/unlock()/changePin()

Developing in this repo

Working from a chat-xdk checkout (instead of the npm package) requires staging the WASM build that index.js resolves at ./pkg/:

make wasm   # from the repo root; builds --target web and stages js/pkg/

Quick Start

import { createChat } from "@xdevplatform/chat-xdk";

const chat = await createChat({
  juiceboxConfig: configJson,
  getAuthToken: async (realmId) => await myBackend.getToken(realmId),
});
await chat.unlock("2580");

// Set the session once: your user id + registered signing-key version,
// the participants' signing keys, and the opt-in conversation-key cache.
chat.setIdentity("111", "v1");
chat.setCacheKeys(true);
// Each signing-key entry carries all five fields from the X API
// public keys response.
chat.setSigningKeys([
  {
    userId: "111",
    publicKeyVersion: "v1",
    publicKey: "BASE64...",
    identityPublicKey: "BASE64...",
    identityPublicKeySignature: "BASE64...",
  },
  {
    userId: "222",
    publicKeyVersion: "v1",
    publicKey: "BASE64...",
    identityPublicKey: "BASE64...",
    identityPublicKeySignature: "BASE64...",
  },
]);

// Initial load — batch decrypt with automatic key extraction. Signing keys
// come from the store; the verified conversation keys populate the cache.
const result = chat.decryptEvents(rawEvents);

for (const dm of result.messages) {
  if (dm.event.type === "message") {
    console.log(dm.event.senderId, dm.event.content.text);
  }
}

// Individual events after the initial load: conversation keys resolve from
// the cache and signing keys from the store (pass either explicitly to
// override).
const event = chat.decryptEvent(webhookEventB64);

// Sending resolves the identity and conversation key from the session too.
const payload = chat.encryptMessage({ conversationId: event.conversationId, text: "hi!" });
// Reply / react by handing back the raw event being answered.
const reply = chat.encryptReply({
  conversationId: event.conversationId,
  text: "pong",
  replyToEvent: webhookEventB64,
});
const reaction = chat.encryptAddReaction({ emoji: "👍", targetEvent: webhookEventB64 });

API

See the JS column of the unified tables in docs/API.md for the full method list, parameters, and return types.

Security limitations

The underlying protocol provides no forward secrecy and no post-compromise security: compromise of an identity private key exposes all conversation keys ever encrypted to that public key — and therefore all past and future messages in those conversations. Key rotation does not retroactively protect messages encrypted under a previous key. See docs/CRYPTO.md — Known Limitations.

Key export is not exposed in the browser build

Raw private-key export and import are not part of this binding's public API. exportKeys() would return unencrypted private key material to page JavaScript, where any script that can reach the chat instance — including code injected via XSS or a compromised dependency — could exfiltrate the identity permanently. Keys are managed inside the Juicebox layer (setup/unlock) instead, so raw key bytes never cross into application JavaScript.

License

MIT — see LICENSE. Third-party notices: THIRD_PARTY_NOTICES.md.