39 releases
new 0.2.2 | Dec 8, 2024 |
---|---|
0.1.35 | Dec 6, 2024 |
0.1.34 | Nov 30, 2024 |
0.1.25 | May 22, 2024 |
0.1.7 | Oct 25, 2023 |
#26 in WebSocket
1,129 downloads per month
Used in 2 crates
82KB
2K
SLoC
NostrO2
Simple yet powerful Rust tools for interacting with the Nostr ecosystem.
Built on top of serde
and tokio
for easy integration with other Rust libraries.
Supports WASM compilation for use in web applications.
Features
The library provides redy to use types for the main data structures of the Nostr protocol, as well as a simple interface for interacting with a relay, or a more complex interface for creating a relay pool.
NostrNote
s
The main data structures of Nostr, as defined by NIP-01.
NostrNote
s can be created using default helpers like this:
let note = NostrNote {
content: "Hello World".to_string(),
kind: 300,
public_key: "0x1234567890abcdef".to_string(),
..Default::default()
};
NostrKeypair
Can be created from a private key str
or a mnemonic phrase and will allow you to sign Nostr Notes.
let new_user = NostrKeypair::new("<64-bit hex string>").expect("Failed to create user keys");
let mut note = NostrNote {
content: "Hello World".to_string(),
kind: 300,
public_key: "0x1234567890abcdef".to_string(),
..Default::default()
};
note.add_tag(NostrTag::Custom("t", "myCustomTag"));
user_key_pair.sign_nostr_event(&mut unsigned_note); // -> Modifies the note in place
Subscriptions
Create a new NostrSubscription
using the default constructor and then add filters to it.
Filters correspond to the object described by NIP-01.
Using the relay_event() method, you can create a new event that can be sent to a relay.
let subscription =
NostrFilter {
kinds: vec![0, 1],
..Default::default()
vec![0, 1]
).relay_event();
println!("Subscribe to relay with id: {}", subscription.1);
NostrRelay
Ready-to-go connection to a relay. The NostrRelay
has two main parts, a reader
and a writer
.
The writer
is reference counted and can be cloned to send events to the relay across multiple threads.
The reader
is a single stream that can be used to receive events from the relay.
NostrRelay
also holds its url and connection state internally.
let mut relay = NostrRelay::new("wss://relay.illuminodes.com").await?;
let filter = NostrSubscription {
kinds: Some(vec![1]),
limit: Some(3),
..Default::default()
}
.relay_subscription();
let id = relay.writer.subscribe(filter).await?;
_debug("Subscribed with id");
let mut finished = String::new();
let mut ws_stream = relay.relay_event_stream()?;
while let Some(event) = ws_stream.next().await {
match event {
RelayEvent::EndOfSubscription(EndOfSubscriptionEvent(_, id)) => {
_debug(&format!("End of subscription: {}", id));
finished = id;
break;
}
_ => (),
}
}
Relay Pool
The NostrRelayPool
is a more complex interface for managing multiple relays. It's created with a list of relay urls
and will connect to all relays concurrently. The pool will then manage the connections and distribute events
to the relays in a round-robin fashion.
Unique NostrNotes
are kep in a library
and duplicate notes are filtered out.
The pool holds a RelayTable
that keeps the connection state of each relay.
let mut pool = NostrRelayPool::new(vec![
"wss://relay.arrakis.lat".to_string(),
"wss://relay.illuminodes.com".to_string(),
"wss://frens.nostr1.com".to_string(),
"wss://bitcoiner.social".to_string(),
"wss://bouncer.minibolt.info".to_string(),
"wss://freespeech.casa".to_string(),
"wss://junxingwang.org".to_string(),
"wss://nostr.0x7e.xyz".to_string(),
])
.await
.expect("Failed to create pool");
let filter = NostrSubscription {
kinds: Some(vec![1]),
limit: Some(10),
..Default::default()
}
.relay_subscription();
pool.subscribe(filter.clone())
.await
.expect("Failed to subscribe");
let mut events = vec![];
while let Some((_, event)) = pool.listener.recv().await {
if let RelayEvent::EndOfSubscription(EndOfSubscriptionEvent(_, ref subscription_id)) =
event
{
events.push(subscription_id.clone());
if events.len() == 5 {
break;
}
}
if let RelayEvent::NewNote(NoteEvent(_, _, _)) = event {}
}
Nostr Authentication
The NostrNotes
objects also provide a verification method for both content and signatures.
assert_eq!(signed_note.verify(), true);
Installation
Run cargo add nostro2
to get the latest version.
You can also add nostro2
to your Cargo.toml
dependencies:
[dependencies]
nostro2 = "0.2.0"
Dependencies
~10–24MB
~340K SLoC