Peer-to-peer networking for TypeScript — connections, streams, blobs, and documents — powered by WASM.
Built on iroh v0.97 (Rust → WASM via wasm-pack). Works in Node.js ≥18 and modern browsers. Zero native dependencies.
Two nodes connect and exchange a message:
import { Endpoint } from "@salvatoret/iroh";
const ALPN = new TextEncoder().encode("my-app/1");
// --- Node A: accept a connection ---
const nodeA = await Endpoint.create();
await nodeA.online();
nodeA.setAlpns([ALPN]);
const addr = nodeA.endpointAddr();
// --- Node B: connect and send ---
const nodeB = await Endpoint.create();
await nodeB.online();
const conn = await nodeB.connect(addr, ALPN);
const stream = await conn.openBi();
await stream.send.writeAll(new TextEncoder().encode("hello from B"));
stream.send.finish();
// --- Node A: receive ---
const accepted = await nodeA.accept();
const incoming = await accepted.acceptBi();
const data = await incoming.recv.readToEnd(65536);
console.log(new TextDecoder().decode(data)); // "hello from B"
acceptBi() won't resolve until the opener writes to its SendStream. Always write before awaiting the accept side.
Peer-to-peer chat room. Create a room, share the link, and start messaging over iroh streams.
Multiplayer poker table with card rendering. Game state synced between players over iroh.
Diagnostic tool exercising every iroh API. Streams, datagrams, blobs, and docs — with full verbose logging.
The main entry point. Creates a QUIC endpoint with relay connectivity for NAT traversal.
| Method | Signature | Description |
|---|---|---|
| create | static create(): Promise<Endpoint> | Create endpoint with default n0 relay settings |
| endpointId | endpointId(): string | Hex-encoded Ed25519 public key (64 chars) |
| endpointAddr | endpointAddr(): EndpointAddr | Full address info (id + relay URL) |
| online | online(): Promise<void> | Wait until connected to a relay server |
| connect | connect(addr, alpn): Promise<Connection> | Connect to a remote peer |
| accept | accept(): Promise<Connection | undefined> | Accept an incoming connection |
| setAlpns | setAlpns(alpns: Uint8Array[]): void | Set accepted ALPN protocols |
| close | close(): Promise<void> | Gracefully shut down |
Address information for reaching an endpoint (ID + relay URL + direct addresses).
| Method | Signature | Description |
|---|---|---|
| fromEndpointId | static fromEndpointId(id: string): EndpointAddr | Create from hex endpoint ID |
| endpointId | endpointId(): string | Get the endpoint ID |
| relayUrl | relayUrl(): string | undefined | Get the relay URL, if any |
A QUIC connection to a remote peer. Supports bidirectional streams, unidirectional streams, and datagrams.
| Method | Signature | Description |
|---|---|---|
| openBi | openBi(): Promise<BiStream> | Open a bidirectional stream |
| acceptBi | acceptBi(): Promise<BiStream> | Accept incoming bidirectional stream |
| openUni | openUni(): Promise<SendStream> | Open a unidirectional send stream |
| acceptUni | acceptUni(): Promise<RecvStream> | Accept incoming unidirectional stream |
| sendDatagram | sendDatagram(data: Uint8Array): void | Send unreliable datagram |
| readDatagram | readDatagram(): Promise<Uint8Array> | Read unreliable datagram |
| remoteEndpointId | remoteEndpointId(): string | Remote peer's endpoint ID |
| close | close(error_code, reason): void | Close with error code |
| stableId | stableId(): number | Stable connection identifier |
| Property | Type | Description |
|---|---|---|
| send | SendStream | Send half |
| recv | RecvStream | Receive half |
| Method | Signature | Description |
|---|---|---|
| write | write(data: Uint8Array): Promise<number> | Write data, returns bytes written |
| writeAll | writeAll(data: Uint8Array): Promise<void> | Write all data |
| finish | finish(): void | Signal end of stream |
| Method | Signature | Description |
|---|---|---|
| readChunk | readChunk(max: number): Promise<Uint8Array | null> | Read a chunk incrementally |
| readToEnd | readToEnd(limit: number): Promise<Uint8Array> | Read all data up to limit |
| stop | stop(error_code: number): void | Stop reading with error code |
In-memory content-addressable storage using BLAKE3 hashing.
| Method | Signature | Description |
|---|---|---|
| constructor | new BlobStore() | Create in-memory store |
| addBytes | addBytes(data: Uint8Array): Promise<string> | Store data, returns BLAKE3 hash |
| getBytes | getBytes(hash: string): Promise<Uint8Array> | Retrieve by hash |
| has | has(hash: string): Promise<boolean> | Check existence |
| list | list(): Promise<string[]> | List all stored hashes |
CRDT-based replicated document engine. Creates its own Endpoint, gossip, and blob store internally.
| Method | Signature | Description |
|---|---|---|
| create | static create(): Promise<DocEngine> | Create engine with in-memory storage |
| createDoc | createDoc(): Promise<Doc> | Create a new document |
| authorDefault | authorDefault(): Promise<string> | Get/create default author ID |
| authorCreate | authorCreate(): Promise<string> | Create a new author |
| shutdown | shutdown(): Promise<void> | Shut down the engine |
A replicated key-value document.
| Method | Signature | Description |
|---|---|---|
| id | id(): string | Namespace ID (hex) |
| setBytes | setBytes(author, key, value): Promise<string> | Set entry, returns content hash |
| getExact | getExact(author, key): Promise<Uint8Array | undefined> | Get entry by author + key |
| del | del(author, prefix): Promise<number> | Delete by prefix, returns count |
| close | close(): Promise<void> | Close the document |
All WASM objects have a free() method and support Symbol.dispose. Call free() when done to release WASM memory:
const ep = await Endpoint.create();
// ... use it ...
await ep.close();
ep.free();