NAME

Net::Nostr::RelayList - NIP-65 relay list metadata

SYNOPSIS

use Net::Nostr::RelayList;

# Build a relay list
my $rl = Net::Nostr::RelayList->new;
$rl->add('wss://alicerelay.example.com');
$rl->add('wss://expensive-relay.example2.com', marker => 'write');
$rl->add('wss://nostr-relay.example.com', marker => 'read');

# Query relay categories
my @write = $rl->write_relays;  # unmarked + write-marked
my @read  = $rl->read_relays;   # unmarked + read-marked

# Convert to a kind 10002 event for publishing
my $event = $rl->to_event(pubkey => $key->pubkey_hex);
$key->sign_event($event);
$client->publish($event);

# Parse from a received kind 10002 event
my $rl = Net::Nostr::RelayList->from_event($event);
for my $r ($rl->relays) {
    say "$r->{url} ($r->{marker})";
}

DESCRIPTION

Implements NIP-65 relay list metadata. A relay list is a kind 10002 replaceable event containing r tags, one per relay. Each tag carries a relay URL and an optional read or write marker. If the marker is omitted, the relay is used for both reading and writing.

Clients SHOULD use an author's write relays when downloading events from that user, and read relays when downloading events about that user (where the user was tagged). Clients SHOULD guide users to keep lists small (2-4 relays per category).

CONSTRUCTOR

new

my $rl = Net::Nostr::RelayList->new;

Creates an empty relay list. Croaks on unknown arguments.

from_event

my $rl = Net::Nostr::RelayList->from_event($event);

Parses a kind 10002 event into a RelayList. Extracts all r tags and ignores other tag types. Croaks if the event is not kind 10002.

my $event = Net::Nostr::Event->new(
    pubkey => 'a' x 64, kind => 10002, content => '',
    tags => [['r', 'wss://relay.example.com', 'write']],
);
my $rl = Net::Nostr::RelayList->from_event($event);
say $rl->count;  # 1

METHODS

add

$rl->add($url);
$rl->add($url, marker => 'write');
$rl->add($url, marker => 'read');

Adds a relay entry. marker must be 'read', 'write', or omitted (meaning both). If the URL already exists, the entry is updated in place. Returns $self for chaining.

$rl->add('wss://relay1.com')
   ->add('wss://relay2.com', marker => 'write');

remove

$rl->remove($url);

Removes the entry for the given URL. No-op if not present. Returns $self for chaining.

contains

my $bool = $rl->contains($url);

Returns true if the given relay URL is in the list.

$rl->add('wss://relay.com');
say $rl->contains('wss://relay.com');   # 1
say $rl->contains('wss://other.com');   # 0

count

my $n = $rl->count;

Returns the total number of relays in the list.

relays

my @relays = $rl->relays;

Returns the list of relay entries as hashrefs, each with keys url and marker. Entries appear in the order they were added.

for my $r ($rl->relays) {
    say "$r->{url}: $r->{marker}";
}

write_relays

my @urls = $rl->write_relays;

Returns the URLs of relays the user writes to: those with marker 'write' or no marker (both). Use these when downloading events from the user.

$rl->add('wss://both.example.com');
$rl->add('wss://w.example.com', marker => 'write');
$rl->add('wss://r.example.com', marker => 'read');
my @write = $rl->write_relays;
# ('wss://both.example.com', 'wss://w.example.com')

read_relays

my @urls = $rl->read_relays;

Returns the URLs of relays the user reads from: those with marker 'read' or no marker (both). Use these when downloading events about the user (where the user was tagged).

$rl->add('wss://both.example.com');
$rl->add('wss://w.example.com', marker => 'write');
$rl->add('wss://r.example.com', marker => 'read');
my @read = $rl->read_relays;
# ('wss://both.example.com', 'wss://r.example.com')

to_tags

my $tags = $rl->to_tags;
# [['r', 'wss://relay.com'], ['r', 'wss://w.com', 'write'], ...]

Returns the relay list as an arrayref of tag arrays, suitable for passing to "new" in Net::Nostr::Event. The marker is omitted for relays with no marker.

to_event

my $event = $rl->to_event(pubkey => $pubkey_hex);
my $event = $rl->to_event(pubkey => $pubkey_hex, created_at => time());

Creates a kind 10002 Net::Nostr::Event from the relay list. All extra arguments are passed through to Net::Nostr::Event->new. The kind, content, and tags fields are set automatically.

my $event = $rl->to_event(pubkey => $key->pubkey_hex);
$key->sign_event($event);

SEE ALSO

NIP-65, Net::Nostr, Net::Nostr::Event