NAME
Net::Nostr::Relay - Nostr WebSocket relay server
SYNOPSIS
use Net::Nostr::Relay;
# Standalone relay (blocks until stop is called)
my $relay = Net::Nostr::Relay->new;
$relay->run('127.0.0.1', 8080);
# Non-blocking: run a relay and client together
use Net::Nostr::Key;
use Net::Nostr::Client;
my $relay = Net::Nostr::Relay->new;
$relay->start('127.0.0.1', 8080);
my $key = Net::Nostr::Key->new;
my $client = Net::Nostr::Client->new;
$client->connect('ws://127.0.0.1:8080');
my $event = $key->create_event(kind => 1, content => 'hello', tags => []);
$client->publish($event);
DESCRIPTION
An in-process Nostr relay. Accepts WebSocket connections, stores events in memory, manages subscriptions, and broadcasts new events to matching subscribers. Events do not persist across restarts.
Implements:
NIP-01 - Basic protocol flow
NIP-09 - Event deletion requests
NIP-42 - Authentication of clients to relays
Supports all NIP-01 event semantics:
Regular events - stored and broadcast
Replaceable events (kinds 0, 3, 10000-19999) - only latest per pubkey+kind
Ephemeral events (kinds 20000-29999) - broadcast but never stored
Addressable events (kinds 30000-39999) - only latest per pubkey+kind+d_tag
CONSTRUCTOR
new
my $relay = Net::Nostr::Relay->new;
my $relay = Net::Nostr::Relay->new(verify_signatures => 0);
my $relay = Net::Nostr::Relay->new(max_connections_per_ip => 10);
my $relay = Net::Nostr::Relay->new(relay_url => 'wss://relay.example.com/');
Creates a new relay instance. Options:
verify_signatures- Enable Schnorr signature verification (default: true). Pass0to disable (useful for testing with synthetic events).max_connections_per_ip- Maximum simultaneous WebSocket connections allowed from a single IP address. Connections beyond this limit are rejected at the TCP level. Default:undef(unlimited).relay_url- The relay's own WebSocket URL (e.g.wss://relay.example.com/). When set, NIP-42 AUTH events are validated to ensure therelaytag matches this URL (domain comparison, case-insensitive). Default:undef(relay tag not validated).
METHODS
run
$relay->run('127.0.0.1', 8080);
Starts the relay and blocks until stop is called. Equivalent to calling start followed by a blocking event loop.
start
$relay->start('127.0.0.1', 8080);
Starts listening for WebSocket connections on the given host and port. Returns immediately without blocking. Use this when you want to embed the relay in a larger application, run a client and relay in the same process, or compose with other AnyEvent watchers.
# Run a relay and client together
my $relay = Net::Nostr::Relay->new;
$relay->start('127.0.0.1', 8080);
my $client = Net::Nostr::Client->new;
$client->connect('ws://127.0.0.1:8080');
stop
$relay->stop;
Stops the relay, closes all connections, and clears all subscriptions. If the relay was started with run, also unblocks it. Safe to call on an unstarted relay.
broadcast
$relay->broadcast($event);
Sends the event to all connected clients whose subscriptions match. Normally called internally when a new event is accepted, but can be called directly for testing or custom event injection.
connections
my $conns = $relay->connections; # hashref
Returns the hashref of active connections.
subscriptions
my $subs = $relay->subscriptions; # hashref
Returns the hashref of active subscriptions, keyed by connection ID then subscription ID.
events
my $events = $relay->events; # arrayref of Net::Nostr::Event
Returns the arrayref of stored events. This list is kept in memory only and reflects replaceable/addressable semantics (only the latest version of each replaceable or addressable event is retained). Ephemeral events are never stored here.
verify_signatures
my $bool = $relay->verify_signatures;
Returns whether Schnorr signature verification is enabled (default: true).
max_connections_per_ip
my $limit = $relay->max_connections_per_ip;
Returns the maximum number of simultaneous connections allowed per IP address, or undef if unlimited (the default).
my $relay = Net::Nostr::Relay->new(max_connections_per_ip => 10);
$relay->start('0.0.0.0', 8080);
relay_url
my $url = $relay->relay_url;
Returns the relay's own WebSocket URL, or undef if not set. Used for NIP-42 relay tag validation.
my $relay = Net::Nostr::Relay->new(relay_url => 'wss://relay.example.com/');
$relay->start('0.0.0.0', 8080);
authenticated_pubkeys
my $auth = $relay->authenticated_pubkeys;
Returns a hashref of authenticated pubkeys per connection (NIP-42). Keys are connection IDs, values are hashrefs of pubkey hex strings.
my $auth = $relay->authenticated_pubkeys;
for my $conn_id (keys %$auth) {
for my $pubkey (keys %{$auth->{$conn_id}}) {
say "Connection $conn_id authenticated as $pubkey";
}
}