nostro2-relay
WebSocket relay client and connection pool for the Nostr protocol.
Features
- Single Relay Connection - Connect to individual Nostr relays
- Connection Pool - Manage multiple relay connections with automatic aggregation
- Automatic Reconnection - Exponential backoff reconnection when connections drop
- Event Deduplication - Built-in LRU cache to prevent duplicate events across relays
- Configurable Crypto Backend - Choose between Ring or AWS-LC for TLS/crypto operations
- Async/Await - Built on Tokio for efficient async I/O
- Zero-Copy Message Passing - Optimized internal architecture using channels
Installation
Add to your Cargo.toml:
[]
= "0.3"
Choosing a Crypto Backend
By default, nostro2-relay uses the Ring crypto library. You can switch to AWS-LC-RS:
[]
# Use Ring (default)
= "0.3"
# Or use AWS-LC
= { = "0.3", = false, = ["rustls-aws-lc"] }
Why choose one over the other?
- Ring (default): Pure Rust, well-audited, works everywhere including WASM
- AWS-LC: AWS's cryptographic library, potentially faster on some platforms, FIPS-validated builds available
Usage
Single Relay Connection
Connect to a single relay and subscribe to events:
use NostrRelay;
use NostrSubscription;
async
Connection Pool with Multiple Relays
Manage multiple relays with automatic event deduplication:
use NostrPool;
use NostrSubscription;
async
Custom Cache Configuration
Configure the deduplication cache size for the pool:
use NostrPool;
// Default cache: 10,000 events
let pool = new;
// Custom cache: 50,000 events (higher memory, fewer duplicates)
let pool = with_cache_size;
The cache uses an LRU (Least Recently Used) eviction strategy. When the cache is full, the oldest events are automatically evicted to make room for new ones. This prevents unbounded memory growth in long-running applications.
Cache sizing guidelines:
- 10,000 events (~640 KB): Good for most applications
- 50,000 events (~3.2 MB): Better for high-traffic pools with many relays
- 100,000 events (~6.4 MB): Enterprise applications with extensive relay networks
Automatic Reconnection
By default, relays automatically reconnect with exponential backoff when connections drop. This makes your application resilient to network issues.
use ;
use Duration;
// Default: infinite retries with exponential backoff
let relay = new.await?;
// Custom reconnection settings
let config = ReconnectConfig ;
let relay = with_reconnect.await?;
// Disable reconnection entirely
let config = disabled;
let relay = with_reconnect.await?;
Reconnection behavior:
- Connection drops or encounters an error
- Wait
initial_delaybefore first retry - Each subsequent retry doubles the delay (exponential backoff)
- Delay is capped at
max_delay - Stops after
max_retriesattempts (0 = never stop) - Successfully reconnected connections reset the retry counter
Configure reconnection for pools:
use ;
use Duration;
let config = ReconnectConfig ;
let pool = with_config;
Publishing Events
use NostrNote;
// Create and sign a note (requires nostro2-signer)
let mut note = text_note;
// ... sign the note with nostro2-signer ...
// Publish to a single relay
relay.send?;
// Or publish to all relays in a pool
pool.send?;
Architecture
NostrRelay
- Single WebSocket connection to one relay
- Separate reader/writer tasks for concurrent I/O
- Unbounded channels for message passing
- Automatic reconnection with exponential backoff
NostrPool
- Manages multiple
NostrRelayinstances - Broadcast channel for sending to all relays
- Aggregated receiver for all relay events
- Built-in event deduplication using
nostro2-cache - Each relay runs in its own task
Performance Considerations
- Zero-copy message passing using Arc and channels
- LRU cache with O(1) insert/lookup for deduplication
- Parallel relay connections spawn independent tasks
- Efficient serialization with pre-serialized JSON in writer tasks
Error Handling
use NostrRelayError;
match relay.send
Compatibility
- Rust: 1.75+ (2021 edition)
- Tokio: Requires async runtime
- Platform: Linux, macOS, Windows
- WASM: Not yet supported (coming soon)
Examples
See the examples/ directory for more usage patterns:
Related Crates
nostro2- Core Nostr protocol types and utilitiesnostro2-signer- Key management and event signingnostro2-cache- Standalone LRU deduplication cachenostro2-nips- Extended protocol implementations (NIPs)
Contributing
Contributions are welcome! Please see the main repository for guidelines.
License
MIT License - see LICENSE for details.