NAME

Net::Nostr::Message - Nostr protocol message serialization and parsing

SYNOPSIS

use Net::Nostr::Message;

# Client-to-relay: publish an event
my $msg = Net::Nostr::Message->new(type => 'EVENT', event => $event);
my $json = $msg->serialize;  # '["EVENT",{...}]'

# Client-to-relay: subscribe
my $msg = Net::Nostr::Message->new(
    type            => 'REQ',
    subscription_id => 'feed',
    filters         => [$filter1, $filter2],
);

# Client-to-relay: close subscription
my $msg = Net::Nostr::Message->new(
    type            => 'CLOSE',
    subscription_id => 'feed',
);

# Parse a relay EVENT message
my $msg = Net::Nostr::Message->parse($json_string);
say $msg->type;             # 'EVENT'
say $msg->subscription_id;  # 'feed'
say $msg->event->content;   # event content

# Client-to-relay: NIP-42 authentication
my $msg = Net::Nostr::Message->new(type => 'AUTH', event => $auth_event);

# Relay-to-client: AUTH challenge
my $msg = Net::Nostr::Message->parse('["AUTH","challenge-string"]');
say $msg->challenge;  # 'challenge-string'

DESCRIPTION

Handles all NIP-01 message types for both client-to-relay and relay-to-client communication. Messages are constructed with new, serialized with serialize, and parsed from JSON with parse.

CONSTRUCTOR

new

my $msg = Net::Nostr::Message->new(type => $type, ...);

Creates a new message. type is required and must be one of: EVENT, REQ, CLOSE, OK, EOSE, NOTICE, CLOSED, AUTH.

Required fields by type:

EVENT  - event (Net::Nostr::Event), optional subscription_id
REQ    - subscription_id, filters (arrayref of Net::Nostr::Filter)
CLOSE  - subscription_id
OK     - event_id, accepted (bool), message (string)
EOSE   - subscription_id
NOTICE - message
CLOSED - subscription_id, message
AUTH   - challenge (relay-to-client) or event (client-to-relay)

subscription_id must be a non-empty string of at most 64 characters for REQ and CLOSE messages. Croaks on missing required fields, invalid subscription IDs, or unknown type.

METHODS

serialize

my $json = $msg->serialize;

Returns the JSON-encoded message string per the NIP-01 wire format.

my $msg = Net::Nostr::Message->new(type => 'CLOSE', subscription_id => 'x');
say $msg->serialize;  # '["CLOSE","x"]'

parse

my $msg = Net::Nostr::Message->parse($json_string);

Class method. Parses a JSON message string and returns a new Net::Nostr::Message object. Croaks on invalid JSON, unknown message types, or malformed messages.

my $msg = Net::Nostr::Message->parse('["NOTICE","hello"]');
say $msg->type;     # 'NOTICE'
say $msg->message;  # 'hello'

type

my $type = $msg->type;  # 'EVENT', 'OK', 'REQ', etc.

subscription_id

my $sub_id = $msg->subscription_id;

The subscription ID. Present on EVENT (relay-to-client), REQ, CLOSE, EOSE, and CLOSED messages.

event

my $event = $msg->event;  # Net::Nostr::Event

The event object. Present on EVENT and AUTH (client-to-relay) messages.

event_id

my $id = $msg->event_id;

The event ID string. Present on OK messages.

accepted

my $bool = $msg->accepted;  # 1 or 0

Whether the event was accepted. Present on OK messages.

message

my $text = $msg->message;

The message string. Present on OK, NOTICE, and CLOSED messages. For OK and CLOSED, may include a machine-readable prefix like "duplicate: already have this event".

prefix

my $prefix = $msg->prefix;  # 'duplicate', 'blocked', etc. or undef

The machine-readable prefix extracted from the message string. Standard prefixes: duplicate, pow, blocked, rate-limited, invalid, restricted, auth-required, mute, error.

my $msg = Net::Nostr::Message->parse(
    '["OK","aa...",false,"blocked: you are banned"]'
);
say $msg->prefix;  # 'blocked'

filters

my $filters = $msg->filters;  # arrayref of Net::Nostr::Filter

The filter objects. Present on REQ messages.

challenge

my $challenge = $msg->challenge;

The challenge string. Present on AUTH messages from relays.

my $msg = Net::Nostr::Message->parse('["AUTH","challenge123"]');
say $msg->challenge;  # 'challenge123'

SEE ALSO

Net::Nostr, Net::Nostr::Event, Net::Nostr::Filter