Skip to main content

Quickstart

This page takes you from nothing to two peers exchanging a message. The first version runs in a single script with an in-memory network, so you can see the whole flow without a relay or a second device. The second version is the same code over real WebRTC.

1. Install​

npm install @vaultys/peer-sdk @vaultys/id
# for real connections in the browser:
npm install peerjs
Pre-release

v2 isn't on npm yet (npm install @vaultys/peer-sdk still gives you v1). Until it's published, build it from source and link it, for example pnpm add link:../peer-sdk.

2. Two peers in one script​

hello.ts
import { createPeer, memoryNetwork } from "@vaultys/peer-sdk";
import { VaultysId } from "@vaultys/id";

const network = memoryNetwork(); // an in-process network, for trying things out

const alice = await createPeer({
identity: await VaultysId.generatePerson(),
transport: network.transport(),
});
const bob = await createPeer({
identity: await VaultysId.generatePerson(),
transport: network.transport(),
});

// By default a peer only accepts connections from its contacts.
await bob.contacts.add(alice.did, { name: "Alice" });

bob.on("message", ({ from, body }) => {
console.log(`${from} says`, body); // `from` is Alice's proven DID
});
alice.on("delivered", ({ id }) => console.log("delivered", id));

await alice.send(bob.did, { text: "Hello, Bob" });

Run it and you'll see Bob receive the message, then Alice get the delivery receipt. Between those two lines, the peers:

  1. Opened a link through the transport.
  2. Ran a mutual VaultysID handshake. Bob checked that Alice is a contact before accepting.
  3. Derived a session key only they can compute.
  4. Sent the message encrypted, and Bob acknowledged it.

3. Real connections between browsers​

Swap the in-memory network for the PeerJS transport. Peers find each other through a PeerJS relay, then talk over a direct WebRTC data channel.

chat.ts
import { createPeer, indexedDBStore } from "@vaultys/peer-sdk";
import { peerjsTransport } from "@vaultys/peer-sdk/peerjs";
import { VaultysId } from "@vaultys/id";

// Keep the identity across reloads: the SDK never stores secrets for you.
const saved = localStorage.getItem("my-identity");
const identity = saved ? VaultysId.fromSecret(saved) : await VaultysId.generatePerson();
if (!saved) localStorage.setItem("my-identity", identity.getSecret());

const peer = await createPeer({
identity,
transport: peerjsTransport(), // the public PeerJS relay; see "Relays" to run your own
store: indexedDBStore(), // contacts and undelivered messages survive reloads
});

console.log("Share this DID:", peer.did);

Open the page in two browsers, add each other's DID as a contact, and send:

await peer.contacts.add(friendDid, { name: "Friend" });
await peer.send(friendDid, { text: "Hi!" });

If your friend is offline, the message waits in the store and goes out when you next reach each other.

Where to keep the identity

localStorage is fine for a demo. In a real app, the identity secret deserves storage your platform protects. See Identity and trust and Security model.

Next steps​