RelayPool struct manages connections to multiple Nostr relays, handles subscriptions, and provides automatic reconnection with keepalive functionality.
Struct fields
Map of relay URLs to their corresponding Relay connection objects
Map of subscription IDs to Subscription objects tracking active Nostr filters
Methods
new()
Creates a newRelayPool instance with no connections.
A new RelayPool instance with empty relay and subscription maps
add_url()
Adds a new relay connection to the pool.WebSocket URL of the relay (e.g., “wss://relay.damus.io”)
Callback function to trigger UI updates when events are received
Ok(()) if successful, or an error if the connection fails
remove_url()
Removes a relay connection from the pool.URL of the relay to remove
The removed Relay object if it existed, or None
add_subscription()
Adds a new Nostr subscription to all connected relays.Subscription object containing an ID and Nostr filters to apply
Ok(()) if the subscription was sent successfully, or an error
Behavior
- Stores the subscription in the pool’s subscription map
- Serializes the subscription as a Nostr REQ message
- Sends the subscription to all connected relays
- Automatically resends subscriptions when relays reconnect
send()
Sends a WebSocket message to all connected relays.WebSocket message to broadcast (typically Text containing JSON)
Ok(()) if sent to all connected relays successfully
Only sends to relays with status
RelayStatus::Connected. Disconnected relays are skipped.try_recv()
Attempts to receive pending messages from all relays.A tuple of (relay_url, message_text) if a message is available, or None
Behavior
- Polls all relays for pending WebSocket events
- Returns the first available message
- Automatically handles connection events (Opened) by resubscribing
- Responds to Ping messages with Pong automatically
keepalive()
Performs periodic maintenance: reconnects disconnected relays and sends keepalive pings.Callback function to wake up the UI thread when events occur
Behavior
This method should be called regularly (e.g., in the UI update loop):- Reconnection (every 5 seconds): Attempts to reconnect any disconnected relays
- Keepalive pings (every 30 seconds): Sends ping messages to all connected relays to keep connections alive
The reconnection interval is defined by the
RELAY_RECONNECT_SECONDS constant (5 seconds).send_auth()
Sends an authentication event (NIP-42) to a specific relay.URL of the relay to authenticate with
Signed authentication event (kind 22242)
Ok(()) if the AUTH message was sent successfully
get_challenge()
Retrieves the authentication challenge string from a relay.URL of the relay to get the challenge from
The challenge string if the relay has sent one, or None
is_key_authenticated()
Checks if a public key has been authenticated with a specific relay.URL of the relay to check
Public key (hex string) to check authentication status for
true if the key is authenticated with this relay, false otherwise
send_subscription_to_relay()
Sends a specific subscription to a specific relay.URL of the relay to send the subscription to
ID of the subscription to send
Ok(()) if successful, or an error if the relay or subscription doesn’t exist
Example usage
Authentication flow (NIP-42)
For relays requiring authentication:Constants
Interval in seconds between reconnection attempts:
5Related
- MailMessage - For creating messages to send through relays
- AccountManager - For authentication and key management
- Database - For storing received events