# @suaveplan/network-discovery-trystero - Browser-tier Trystero DiscoveryStrategy: serverless WebRTC peer discovery via four interchangeable transports (BitTorrent / Nostr / MQTT / IPFS) behind a single TrysteroTransportAdapter contract. Insecure-default rejection: every transport requires explicit relay / tracker / broker lists. AbortSignal + EventBusLike + ServiceRegistry + OTel + Zod boundaries. ## Summary Browser-tier `DiscoveryStrategy` for `@suaveplan/network-bootstrap`. Serverless WebRTC peer discovery via [Trystero](https://github.com/dmotz/trystero), with four interchangeable transports — BitTorrent trackers, Nostr relays, MQTT brokers, and IPFS libp2p pubsub — all sitting behind a single `TrysteroTransportAdapter` contract. Construction-time transport selection; zero runtime branching on transport-id strings. Optional inter-transport fallback chain using `@suaveplan/retry`'s exponential backoff. **Insecure-default rejection.** Every transport requires an explicit non-empty relay / tracker / broker / bootstrap list. The constructor throws `INVALID_OPTIONS` if any list is empty or missing. No implicit public defaults survive anywhere in the code. ## Documentation tree - [ipfs-transport](./src/core/ipfs-transport/ipfs-transport.md) — _(no submodules)_ - [ipfs-transport](./src/core/ipfs-transport/ipfs-transport.md) — _(no submodules)_ - [mqtt-transport](./src/core/mqtt-transport/mqtt-transport.md) — _(no submodules)_ - [mqtt-transport](./src/core/mqtt-transport/mqtt-transport.md) — _(no submodules)_ - [nostr-transport](./src/core/nostr-transport/nostr-transport.md) — _(no submodules)_ - [nostr-transport](./src/core/nostr-transport/nostr-transport.md) — _(no submodules)_ - [torrent-transport](./src/core/torrent-transport/torrent-transport.md) — _(no submodules)_ - [torrent-transport](./src/core/torrent-transport/torrent-transport.md) — _(no submodules)_ - [trystero-discovery](./src/core/trystero-discovery/trystero-discovery.md) — _(no submodules)_ - [trystero-discovery](./src/core/trystero-discovery/trystero-discovery.md) — _(no submodules)_ - [trystero-fallback](./src/core/trystero-fallback/trystero-fallback.md) — _(no submodules)_ - [trystero-fallback](./src/core/trystero-fallback/trystero-fallback.md) — _(no submodules)_ - [trystero-intervals](./src/core/trystero-intervals/trystero-intervals.md) — _(no submodules)_ - [trystero-intervals](./src/core/trystero-intervals/trystero-intervals.md) — _(no submodules)_ - [trystero-message-handlers](./src/core/trystero-message-handlers/trystero-message-handlers.md) — _(no submodules)_ - [trystero-message-handlers](./src/core/trystero-message-handlers/trystero-message-handlers.md) — _(no submodules)_ - [trystero-peer-manager](./src/core/trystero-peer-manager/trystero-peer-manager.md) — _(no submodules)_ - [trystero-peer-manager](./src/core/trystero-peer-manager/trystero-peer-manager.md) — _(no submodules)_ - [errors](./src/errors/errors.md) — _(no submodules)_ - [errors](./src/errors/errors.md) — _(no submodules)_ - [otel](./src/otel/otel.md) — _(no submodules)_ - [otel](./src/otel/otel.md) — _(no submodules)_ - [plugin](./src/plugin/plugin.md) — _(no submodules)_ - [plugin](./src/plugin/plugin.md) — _(no submodules)_ - [transport](./src/transport/transport.md) — _(no submodules)_ - [transport](./src/transport/transport.md) — _(no submodules)_ - [types](./src/types/types.md) — _(no submodules)_ - [types](./src/types/types.md) — _(no submodules)_ - [ipfs-transport](./src/core/ipfs-transport/ipfs-transport.md) — _(no submodules)_- [mqtt-transport](./src/core/mqtt-transport/mqtt-transport.md) — _(no submodules)_- [mqtt-transport](./src/core/mqtt-transport/mqtt-transport.md) — _(no submodules)_- [nostr-transport](./src/core/nostr-transport/nostr-transport.md) — _(no submodules)_- [nostr-transport](./src/core/nostr-transport/nostr-transport.md) — _(no submodules)_- [torrent-transport](./src/core/torrent-transport/torrent-transport.md) — _(no submodules)_- [torrent-transport](./src/core/torrent-transport/torrent-transport.md) — _(no submodules)_- [trystero-discovery](./src/core/trystero-discovery/trystero-discovery.md) — _(no submodules)_- [trystero-discovery](./src/core/trystero-discovery/trystero-discovery.md) — _(no submodules)_- [trystero-fallback](./src/core/trystero-fallback/trystero-fallback.md) — _(no submodules)_- [trystero-fallback](./src/core/trystero-fallback/trystero-fallback.md) — _(no submodules)_- [trystero-intervals](./src/core/trystero-intervals/trystero-intervals.md) — _(no submodules)_- [trystero-intervals](./src/core/trystero-intervals/trystero-intervals.md) — _(no submodules)_- [trystero-message-handlers](./src/core/trystero-message-handlers/trystero-message-handlers.md) — _(no submodules)_- [trystero-message-handlers](./src/core/trystero-message-handlers/trystero-message-handlers.md) — _(no submodules)_- [trystero-peer-manager](./src/core/trystero-peer-manager/trystero-peer-manager.md) — _(no submodules)_- [trystero-peer-manager](./src/core/trystero-peer-manager/trystero-peer-manager.md) — _(no submodules)_- [errors](./src/errors/errors.md) — _(no submodules)_- [errors](./src/errors/errors.md) — _(no submodules)_- [otel](./src/otel/otel.md) — _(no submodules)_- [otel](./src/otel/otel.md) — _(no submodules)_- [plugin](./src/plugin/plugin.md) — _(no submodules)_- [plugin](./src/plugin/plugin.md) — _(no submodules)_- [transport](./src/transport/transport.md) — _(no submodules)_- [transport](./src/transport/transport.md) — _(no submodules)_- [types](./src/types/types.md) — _(no submodules)_- [types](./src/types/types.md) — _(no submodules)_- [ipfs-transport](./src/core/ipfs-transport/ipfs-transport.md) — _(no submodules)_- [mqtt-transport](./src/core/mqtt-transport/mqtt-transport.md) — _(no submodules)_- [mqtt-transport](./src/core/mqtt-transport/mqtt-transport.md) — _(no submodules)_- [nostr-transport](./src/core/nostr-transport/nostr-transport.md) — _(no submodules)_- [nostr-transport](./src/core/nostr-transport/nostr-transport.md) — _(no submodules)_- [torrent-transport](./src/core/torrent-transport/torrent-transport.md) — _(no submodules)_- [torrent-transport](./src/core/torrent-transport/torrent-transport.md) — _(no submodules)_- [trystero-discovery](./src/core/trystero-discovery/trystero-discovery.md) — _(no submodules)_- [trystero-discovery](./src/core/trystero-discovery/trystero-discovery.md) — _(no submodules)_- [trystero-fallback](./src/core/trystero-fallback/trystero-fallback.md) — _(no submodules)_- [trystero-fallback](./src/core/trystero-fallback/trystero-fallback.md) — _(no submodules)_- [trystero-intervals](./src/core/trystero-intervals/trystero-intervals.md) — _(no submodules)_- [trystero-intervals](./src/core/trystero-intervals/trystero-intervals.md) — _(no submodules)_- [trystero-message-handlers](./src/core/trystero-message-handlers/trystero-message-handlers.md) — _(no submodules)_- [trystero-message-handlers](./src/core/trystero-message-handlers/trystero-message-handlers.md) — _(no submodules)_- [trystero-peer-manager](./src/core/trystero-peer-manager/trystero-peer-manager.md) — _(no submodules)_- [trystero-peer-manager](./src/core/trystero-peer-manager/trystero-peer-manager.md) — _(no submodules)_- [errors](./src/errors/errors.md) — _(no submodules)_- [errors](./src/errors/errors.md) — _(no submodules)_- [otel](./src/otel/otel.md) — _(no submodules)_- [otel](./src/otel/otel.md) — _(no submodules)_- [plugin](./src/plugin/plugin.md) — _(no submodules)_- [plugin](./src/plugin/plugin.md) — _(no submodules)_- [transport](./src/transport/transport.md) — _(no submodules)_- [transport](./src/transport/transport.md) — _(no submodules)_- [types](./src/types/types.md) — _(no submodules)_- [types](./src/types/types.md) — _(no submodules)_- [ipfs-transport](./src/core/ipfs-transport/ipfs-transport.md) — _(no submodules)_- [mqtt-transport](./src/core/mqtt-transport/mqtt-transport.md) — _(no submodules)_- [mqtt-transport](./src/core/mqtt-transport/mqtt-transport.md) — _(no submodules)_- [nostr-transport](./src/core/nostr-transport/nostr-transport.md) — _(no submodules)_- [nostr-transport](./src/core/nostr-transport/nostr-transport.md) — _(no submodules)_- [torrent-transport](./src/core/torrent-transport/torrent-transport.md) — _(no submodules)_- [torrent-transport](./src/core/torrent-transport/torrent-transport.md) — _(no submodules)_- [trystero-discovery](./src/core/trystero-discovery/trystero-discovery.md) — _(no submodules)_- [trystero-discovery](./src/core/trystero-discovery/trystero-discovery.md) — _(no submodules)_- [trystero-fallback](./src/core/trystero-fallback/trystero-fallback.md) — _(no submodules)_- [trystero-fallback](./src/core/trystero-fallback/trystero-fallback.md) — _(no submodules)_- [trystero-intervals](./src/core/trystero-intervals/trystero-intervals.md) — _(no submodules)_- [trystero-intervals](./src/core/trystero-intervals/trystero-intervals.md) — _(no submodules)_- [trystero-message-handlers](./src/core/trystero-message-handlers/trystero-message-handlers.md) — _(no submodules)_- [trystero-message-handlers](./src/core/trystero-message-handlers/trystero-message-handlers.md) — _(no submodules)_- [trystero-peer-manager](./src/core/trystero-peer-manager/trystero-peer-manager.md) — _(no submodules)_- [trystero-peer-manager](./src/core/trystero-peer-manager/trystero-peer-manager.md) — _(no submodules)_- [errors](./src/errors/errors.md) — _(no submodules)_- [errors](./src/errors/errors.md) — _(no submodules)_- [otel](./src/otel/otel.md) — _(no submodules)_- [otel](./src/otel/otel.md) — _(no submodules)_- [plugin](./src/plugin/plugin.md) — _(no submodules)_- [plugin](./src/plugin/plugin.md) — _(no submodules)_- [transport](./src/transport/transport.md) — _(no submodules)_- [transport](./src/transport/transport.md) — _(no submodules)_- [types](./src/types/types.md) — _(no submodules)_- [types](./src/types/types.md) — _(no submodules)_- [ipfs-transport](./src/core/ipfs-transport/ipfs-transport.md) — _(no submodules)_- [mqtt-transport](./src/core/mqtt-transport/mqtt-transport.md) — _(no submodules)_ - [mqtt-transport](./src/core/mqtt-transport/mqtt-transport.md) — _(no submodules)_- [nostr-transport](./src/core/nostr-transport/nostr-transport.md) — _(no submodules)_ - [nostr-transport](./src/core/nostr-transport/nostr-transport.md) — _(no submodules)_- [torrent-transport](./src/core/torrent-transport/torrent-transport.md) — _(no submodules)_ - [torrent-transport](./src/core/torrent-transport/torrent-transport.md) — _(no submodules)_- [trystero-discovery](./src/core/trystero-discovery/trystero-discovery.md) — _(no submodules)_ - [trystero-discovery](./src/core/trystero-discovery/trystero-discovery.md) — _(no submodules)_- [trystero-fallback](./src/core/trystero-fallback/trystero-fallback.md) — _(no submodules)_ - [trystero-fallback](./src/core/trystero-fallback/trystero-fallback.md) — _(no submodules)_- [trystero-intervals](./src/core/trystero-intervals/trystero-intervals.md) — _(no submodules)_ - [trystero-intervals](./src/core/trystero-intervals/trystero-intervals.md) — _(no submodules)_- [trystero-message-handlers](./src/core/trystero-message-handlers/trystero-message-handlers.md) — _(no submodules)_ - [trystero-message-handlers](./src/core/trystero-message-handlers/trystero-message-handlers.md) — _(no submodules)_- [trystero-peer-manager](./src/core/trystero-peer-manager/trystero-peer-manager.md) — _(no submodules)_ - [trystero-peer-manager](./src/core/trystero-peer-manager/trystero-peer-manager.md) — _(no submodules)_- [errors](./src/errors/errors.md) — _(no submodules)_ - [errors](./src/errors/errors.md) — _(no submodules)_- [otel](./src/otel/otel.md) — _(no submodules)_ - [otel](./src/otel/otel.md) — _(no submodules)_- [plugin](./src/plugin/plugin.md) — _(no submodules)_ - [plugin](./src/plugin/plugin.md) — _(no submodules)_- [transport](./src/transport/transport.md) — _(no submodules)_ - [transport](./src/transport/transport.md) — _(no submodules)_- [types](./src/types/types.md) — _(no submodules)_ - [types](./src/types/types.md) — _(no submodules)_ ## Install ```bash bun add @suaveplan/network-discovery-trystero # plus the trystero peer dep if you want the real transports bun add trystero ``` ## Basic example ```ts import { TrysteroDiscovery } from "@suaveplan/network-discovery-trystero"; const strategy = new TrysteroDiscovery({ appId: "my-app", transport: "nostr", nostr: { relays: ["wss://relay.example"] }, nostrRoomFactory: async (appId, config) => { const { joinRoom } = await import("trystero/nostr"); return joinRoom({ relayUrls: config.relays }, appId); }, }); await strategy.start(); const peers = await strategy.discover(5000); console.log(peers); await strategy.stop(); ``` ## Advanced example — fallback chain + ServiceRegistry + EventBus ```ts import { EventBus } from "@suaveplan/events"; import { ServiceRegistry } from "@suaveplan/service-discovery"; import { TrysteroDiscovery, type TrysteroEventMap, } from "@suaveplan/network-discovery-trystero"; const bus = new EventBus(); const registry = new ServiceRegistry(); bus.on("trystero:fallback", (e) => console.log(`fell back ${e.from} -> ${e.to}`), ); bus.on("trystero:transport-failed", (e) => console.warn(`transport ${e.transport} failed: ${e.reason}`), ); const strategy = new TrysteroDiscovery({ appId: "my-app", transport: "nostr", nostr: { relays: ["wss://nostr.example"] }, mqtt: { brokers: ["wss://broker.example:1883"] }, torrent: { trackers: ["wss://tracker.example"] }, fallbackTransports: ["mqtt", "torrent"], nostrRoomFactory: realNostrJoin, mqttRoomFactory: realMqttJoin, torrentRoomFactory: realTorrentJoin, bus, registry, }); await strategy.start(); ``` ## Documentation Every implementation file has a sibling `.md` with full API reference, basic + advanced examples, and implementation notes: - `src/core/trystero-discovery/trystero-discovery.md` — orchestrator - `src/core/trystero-peer-manager/trystero-peer-manager.md` - `src/core/trystero-intervals/trystero-intervals.md` - `src/core/trystero-fallback/trystero-fallback.md` - `src/core/trystero-message-handlers/trystero-message-handlers.md` - `src/core/torrent-transport/torrent-transport.md` - `src/core/nostr-transport/nostr-transport.md` - `src/core/mqtt-transport/mqtt-transport.md` - `src/core/ipfs-transport/ipfs-transport.md` - `src/errors/errors.md` - `src/otel/otel.md` - `src/types/types.md` ## License MIT