#nostr #relay #notes #interop #structures #nip-01 #user-keys

nostro2

Nostro2 is a simple toolset for interacting with the Nostr protocol

31 releases

0.1.30 Oct 24, 2024
0.1.27 Sep 25, 2024
0.1.25 May 22, 2024
0.1.16 Mar 28, 2024
0.1.7 Oct 25, 2023

#257 in Cryptography

Download history 2/week @ 2024-08-26 103/week @ 2024-09-09 32/week @ 2024-09-16 238/week @ 2024-09-23 25/week @ 2024-09-30 295/week @ 2024-10-07 37/week @ 2024-10-14 144/week @ 2024-10-21 31/week @ 2024-10-28 98/week @ 2024-11-04

318 downloads per month
Used in ignis-nostr

MIT license

80KB
2K SLoC

NostrO2

This crate is our first approach at building simple Rust tools for interacting with the Nostr ecosystem.

Features

The library provides class-based functionality through 3 basic types: UserKeys, Notes, and Relays.

Notes

The main data structures of Nostr, as defined by NIP-01. Implementations are split between Notes and SignedNotes, to allow for easy interoperability with external applications like NIP-07. Both structures have full serde serialization features and provide ready-to-send outputs for relay messages.

UserKeys

Can be created from a private key str and will allow you to sign Nostr Notes.

    let new_user = UserKeys::new("<64-bit hex string>").expect("Failed to create user keys");
    let mut unsigned_note = Note::new(
        &user_key_pair.get_public_key(),
        1,
        "Hello World"
    );
    unsigned_note.tag_note("t", "test");
    let signed_note = user_key_pair.sign_nostr_event(unsigned_note); // -> SignedNote

Subscriptions

Create a new NostrFilter using the default constructor and then add filters to it. Filters correspond to the object described by NIP-01. Using the subscribe() method, you can create a new NostrSubscription that can be sent to a relay.

let subscription = 
    NostrFilter::default().new_kinds(
        vec![0, 1]
    )
    .subscribe();

println!("Subscribe to relay with id: {}", subscription.id());

NostrRelay

Ready-to-go connection to a relay. The NostrRelay object can be cloned across thread safely. The relay_event_reader() method returns a Receiver<RelayEvent> that can be used to listen to relay events. THis can also be cloned across threads. RelayEvents provide easy pattern-matching for relay/client communication and error-handling.

let relay = NostrRelay::new("wss://relay.illuminodes.com").await.expect("Failed to create relay");

let subscription = 
    NostrFilter::default().new_kinds(
        vec![0, 1, 4]
    )
    .subscribe();
relay.subscribe(&subscription).await.expect("Failed to subscribe to relay");
while let Ok(event) = reader_relay.relay_event_reader().recv().await {
    match event {
        RelayEvent::EVENT(sub_id, signed_note) => {
            println!("Received note: {:?}", signed_note);
        },
        RelayEvent::EOSE(sub_id) => {
            println!("End of events for subscription: {:?}", sub_id);
        },
        _ => {
            println!("Other Relay events {:?}", event);
        }
    }
}

Nostr Authentication

The SignedNotes 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.1.27"

Dependencies

~11–24MB
~347K SLoC