Self-Hosting the Relay
The relay is a stateless WebSocket router. It validates connection metadata, emits join events, and forwards application frames unchanged. It does not create channels with a separate command, decrypt payloads, store messages, or require a WebSocket subprotocol header.
Build from source
bash
cd walletpair-relay
cargo build --release
./target/release/walletpair-relayConnection
text
ws(s)://<relay-host>/v1?ch=<channel-id>&name=<name>&url=<url>&icon=<icon-url>&pubkey=<x25519-public-key>| Field | Validation |
|---|---|
ch | Exactly 64 lowercase hexadecimal characters. |
name | 1–128 UTF-8 bytes; no control characters. |
url | Absolute http: or https: URL, at most 2048 UTF-8 bytes. |
icon | Absolute https: URL, at most 2048 UTF-8 bytes. |
pubkey | Canonical unpadded base64url, 32 decoded bytes, not all zero. |
Join event and routing
After a client joins, the relay sends this JSON text frame to every active connection in that channel, including the new connection. A client waits for its own event before sending application frames.
json
{
"type": "channel_joined",
"ch": "<channel-id>",
"name": "Example Wallet",
"url": "https://wallet.example",
"icon": "https://wallet.example/icon.png",
"pubkey": "<base64url-x25519-public-key>"
}- Text and binary application frames are forwarded unchanged to every other active connection in the same channel.
- The sender does not receive its own application frame.
- There is no cross-channel forwarding and no replay for later joiners.
Deployment note
Each in-memory channel must remain on one relay instance. Use TLS for public traffic and configure load balancing for channel affinity if you run multiple instances.