UNPKG

nostr-relaypool

Version:

A Nostr RelayPool implementation in TypeScript using only nostr-tools library as a dependency.

68 lines (65 loc) 2.35 kB
import {type Event, type Filter, matchFilters} from "nostr-tools"; import {WebSocket, WebSocketServer} from "isomorphic-ws"; const _ = WebSocket; // Importing WebSocket is needed for WebSocketServer to work export class InMemoryRelayServer { events: (Event & {id: string})[] = []; auth?: string; wss: WebSocketServer; subs: Map<string, Filter[]> = new Map(); connections: Set<WebSocket> = new Set(); totalSubscriptions = 0; constructor(port = 8081, host = "localhost") { this.wss = new WebSocketServer({port, host}); this.wss.on("connection", (ws) => { this.connections.add(ws); // console.log('connected') ws.on("message", (message) => { const data = JSON.parse(message.toString()); // console.log('received: %s', JSON.stringify(data)) if (data && data[0] === "REQ") { const sub = data[1]; const filters = data.slice(2); this.totalSubscriptions++; this.subs.set(sub, filters); for (const event of this.events) { if (matchFilters(filters, event)) { // console.log('sending event to sub %s', sub, JSON.stringify(['EVENT', sub, event])) ws.send(JSON.stringify(["EVENT", sub, event])); } } // console.log('sending eose to sub %s', sub, JSON.stringify(['EOSE', sub])) ws.send(JSON.stringify(["EOSE", sub])); } else if (data && data[0] === "EVENT") { const event = data[1]; this.events.push(event); for (const [sub, filters] of this.subs) { if (matchFilters(filters, event)) { // console.log('sending event to sub %s', sub, JSON.stringify(['EVENT', sub, event])) ws.send(JSON.stringify(["EVENT", sub, event])); } } } else if (data && data[0] === "CLOSE") { const sub = data[1]; this.subs.delete(sub); } }); if (this.auth) { ws.send(JSON.stringify(["AUTH", this.auth])); } }); } async close(): Promise<void> { new Promise((resolve) => this.wss.close(resolve)); } clear() { this.events = []; this.subs = new Map(); this.totalSubscriptions = 0; this.auth = undefined; } disconnectAll() { for (const ws of this.connections) { ws.close(); } } }