Files
welshman/docs/relay/index.md
T
2025-10-20 14:19:44 -07:00

4.0 KiB

@welshman/relay

version

A few utilites for storing nostr events in memory.

What's Included

  • Event Store - A Repository class which stores events in memory
  • Relay Adapter - A LocalRelay class which adapts nostr messages to the repository
  • Event Tracker - A Tracker class for managing which events have been seen from which relays
  • Gift Wrap Manager - A WrapManager class for tracking and unwrapping NIP-59 gift wrapped events

Quick Example

import {Repository, LocalRelay} from "@welshman/relay"

// Create an in-memory event repository
const repository = Repository.get()

// Publish events directly to the repository
const textNote = {
  id: "event123",
  pubkey: "author-pubkey",
  created_at: Math.floor(Date.now() / 1000),
  kind: 1,
  tags: [],
  content: "Hello, world!",
  sig: "signature"
}

repository.publish(textNote)

// Query events using filters
const recentNotes = repository.query([{kinds: [1], limit: 10}])
console.log(`Found ${recentNotes.length} text notes`)

// Listen for repository updates
repository.on("update", ({added, removed}) => {
  console.log(`Added ${added.length} events, removed ${removed.size} events`)
})

// Create a local relay that adapts Nostr messages to the repository
const relay = new LocalRelay(repository)

// Listen for relay messages
relay.on("EVENT", (subId, event) => {
  console.log(`Received event ${event.id} for subscription ${subId}`)
})

relay.on("OK", (eventId, success, message) => {
  console.log(`Event ${eventId} ${success ? "accepted" : "rejected"}: ${message}`)
})

// Use relay protocol to publish and subscribe
relay.send("EVENT", {
  id: "event456",
  pubkey: "another-author",
  created_at: Math.floor(Date.now() / 1000),
  kind: 1,
  tags: [["t", "welshman"]],
  content: "Using LocalRelay!",
  sig: "signature"
})

// Subscribe to events with hashtag
relay.send("REQ", "tagged", {kinds: [1], "#t": ["welshman"]})

Tracking Events Across Relays

import {Tracker} from "@welshman/relay"

const tracker = new Tracker()

// Track events from different relays
const isDuplicate1 = tracker.track("event123", "wss://relay1.com") // false
const isDuplicate2 = tracker.track("event123", "wss://relay2.com") // false
const isDuplicate3 = tracker.track("event123", "wss://relay1.com") // true (duplicate)

// Check which relays have sent an event
const relays = tracker.getRelays("event123") // Set(["wss://relay1.com", "wss://relay2.com"])

// Copy relay tracking from one event to another (useful for wrapped events)
tracker.copy("wrap-event-id", "rumor-event-id")

Managing Gift Wrapped Events

The WrapManager handles NIP-59 gift wrapped events, automatically unwrapping incoming wrapped events and tracking the relationship between wraps and their inner rumors.

import {Repository, LocalRelay, Tracker, WrapManager} from "@welshman/relay"
import {ISigner} from "@welshman/signer"

const repository = Repository.get()
const relay = new LocalRelay(repository)
const tracker = new Tracker()

// Create a wrap manager with a function to get signers for different pubkeys
const wrapManager = new WrapManager({
  relay,
  tracker,
  getSigner: (pubkey: string) => {
    // Return the appropriate signer for this pubkey
    return mySignerMap.get(pubkey)
  }
})

// When you publish a wrapped event, track it
wrapManager.add({
  recipient: recipientPubkey,
  wrap: wrappedEvent,
  rumor: innerEvent
})

// When you receive a wrapped event, unwrap it
await wrapManager.unwrap(receivedWrapEvent)

// The rumor will be automatically published to the repository
// and relay tracking will be copied from the wrap to the rumor

// Remove wraps by various criteria
wrapManager.remove(wrapId)
wrapManager.removeByRumorId(rumorId)

// Listen for wrap manager events
wrapManager.on("add", (wrapItem) => {
  console.log("Wrap added:", wrapItem)
})

wrapManager.on("remove", (wrapItem) => {
  console.log("Wrap removed:", wrapItem)
})

Installation

npm install @welshman/relay