# TypeScript SDK The TypeScript SDK provides a browser-compatible client with WASM-based crypto. Location: `sdks/typescript/` ## Installation ```sh npm install quicprochat ``` ## Quick Start ```typescript import { QpqClient } from "quicprochat"; // Connect via WebSocket bridge const client = await QpqClient.connect({ addr: "ws://127.0.0.1:5002", }); const status = await client.health(); console.log("Server:", status); // Set session token (obtained via OPAQUE externally) client.setSessionToken(token); // Resolve user const peerKey = await client.resolveUser("bob"); // Create channel const { channelId, wasNew } = await client.createChannel(peerKey); // Send message const seq = await client.send(peerKey, new TextEncoder().encode("hello")); // Receive messages const messages = await client.receive(myKey); for (const msg of messages) { console.log(`[${msg.seq}] ${new TextDecoder().decode(msg.data)}`); } client.close(); ``` ## Offline Crypto The SDK includes WASM-compiled crypto primitives that work without a server: ```typescript const client = await QpqClient.offline(); // Ed25519 identity const { seed, publicKey } = client.generateIdentity(); const sig = client.sign(seed, message); const valid = client.verify(publicKey, message, sig); // Hybrid KEM (X25519 + ML-KEM-768) const kp = client.hybridGenerateKeypair(); const ciphertext = client.hybridEncrypt(kp.publicKey, plaintext); const decrypted = client.hybridDecrypt(kp.blob, ciphertext); // Safety numbers const safetyNumber = client.computeSafetyNumber(keyA, keyB); // Sealed sender const sealed = client.seal(seed, payload); const unsealed = client.unseal(sealed); // Message padding const padded = client.padMessage(data); const unpadded = client.unpadMessage(padded); ``` ## API ### RPC Methods | Method | Description | |---|---| | `QpqClient.connect(opts)` | Connect via WebSocket | | `QpqClient.offline()` | Crypto-only mode | | `client.health()` | Health check | | `client.resolveUser(username)` | Look up identity key | | `client.createChannel(peerKey)` | Create DM channel | | `client.send(recipientKey, payload)` | Send message | | `client.sendWithTTL(recipientKey, payload, ttl)` | Disappearing message | | `client.receive(recipientKey)` | Fetch messages | | `client.deleteAccount()` | Delete account | | `client.close()` | Disconnect | ### Crypto Methods | Method | Description | |---|---| | `client.generateIdentity()` | Generate Ed25519 keypair | | `client.identityPublicKey(seed)` | Derive public key | | `client.sign(seed, message)` | Ed25519 sign | | `client.verify(publicKey, message, sig)` | Ed25519 verify | | `client.hybridGenerateKeypair()` | Generate hybrid keypair | | `client.hybridEncrypt(pk, plaintext)` | Hybrid encrypt | | `client.hybridDecrypt(blob, ciphertext)` | Hybrid decrypt | | `client.computeSafetyNumber(keyA, keyB)` | Safety number | | `client.seal(seed, payload)` | Sealed sender | | `client.unseal(envelope)` | Unseal | | `client.padMessage(data)` | Pad message | | `client.unpadMessage(data)` | Unpad message | ## Architecture The TypeScript SDK uses a WebSocket bridge proxy because browsers cannot open raw QUIC connections. The bridge translates JSON-over-WebSocket to Cap'n Proto RPC: ``` Browser ─── WebSocket ───► Bridge Proxy ─── QUIC/capnp ───► Server ``` Crypto operations (Ed25519, hybrid KEM, sealed sender) run entirely in WASM, compiled from the Rust `quicprochat-core` crate. ## Structure | File | Purpose | |---|---| | `src/client.ts` | High-level client API | | `src/transport.ts` | WebSocket transport with auto-reconnect | | `src/crypto.ts` | WASM crypto bindings | | `src/types.ts` | TypeScript interfaces | | `wasm-crypto/` | Rust WASM crypto source |