Files
easy-nostr/README.md
2025-12-19 20:25:39 +01:00

3.8 KiB

EasyNostr

A simple and functional Rust crate for building Nostr applications. This library handles the complexity of keys, relays, and protocol details (NIPs), giving you easy-to-use functions for a social media app.

Features

  • Identity: Easy management of keys (nsec/npub).
  • Social Feed: View timeline of friends or global random posts.
  • Posting: Publish text notes (Kind 1).
  • Contacts: Follow users and retrieve your contact list.
  • Direct Messages: Send and receive encrypted private messages (NIP-17 & NIP-04).

Getting Started

1. Initialize the Client

First, you need to create an instance of EasyNostr using your secret key (nsec).

use easy_nostr::EasyNostr;
use anyhow::Result;

#[tokio::main]
async fn main() -> Result<()> {
    // Your secret key (nsec)
    let my_secret_key = "nsec1..."; 

    // Initialize client
    let client = EasyNostr::new(my_secret_key).await?;

    // Connect to Relays
    client.add_relays(vec![
        "wss://relay.damus.io",
        "wss://nos.lol",
        "wss://relay.primal.net"
    ]).await?;

    println!("Connected and ready!");
    Ok(())
}

Capabilities & Usage

📝 Publishing Posts

Post a simple text message to the network.

let event_id = client.post_text("Hello Nostr world!").await?;
println!("Posted! ID: {}", event_id.to_bech32()?);

📰 Reading Feeds

You can read posts from people you follow (Timeline) or random posts from the network.

Get Timeline (Followed Users):

// List of public keys (npubs) you want to see posts from
let following = vec!["npub1...", "npub1..."];

let posts = client.get_timeline(following).await?;

for post in posts {
    println!("@{} wrote: {}", post.author.to_bech32()?, post.content);
}

Get Global Feed (Random/Recent):

let random_posts = client.get_random_posts().await?;

for post in random_posts {
    println!("New Post: {}", post.content);
}

The Post Structure: When you get posts, you receive a Post struct:

  • post.id: The unique Event ID.
  • post.author: The PublicKey of the author.
  • post.content: The text content.
  • post.created_at: The timestamp.

👥 Managing Contacts (Followers)

Manage who you follow.

Follow a User:

let jack_dorsey = "npub1sg6plzptd64u62a878hep2kd8856nmmhd0x479jp6bir725uqqks698teq";
// Context: (NPub, Optional Nickname)
client.create_contact(jack_dorsey, Some("Jack".to_string())).await?;

Get Your Contact List:

let my_contacts = client.get_contacts().await?;

for contact in my_contacts {
    println!("Following: {:?}", contact.public_key.to_bech32()?);
    if let Some(alias) = &contact.alias {
        println!(" - Alias: {}", alias);
    }
}

🔒 Direct Messages (DMs)

Send and receive encrypted private chats. Supports modern GiftWraps (NIP-17).

Send a DM:

let friend_npub = "npub1...";
client.send_private_message(friend_npub, "Hey, this is secret!").await?;

Read DMs:

let friend_npub = "npub1...";
let messages = client.get_private_messages(friend_npub).await?;

for msg in messages {
    let direction = if msg.is_incoming { "Received" } else { "Sent" };
    println!("[{}] {}", direction, msg.content);
}

The Message Structure:

  • msg.sender: PublicKey of the sender.
  • msg.content: Decrypted text.
  • msg.is_incoming: true if you received it, false if you sent it.
  • msg.created_at: Use msg.created_at.as_secs() to get the unix timestamp.

Dependencies

Ensure you have the following in your Cargo.toml. easy-nostr re-exports most things you need, but you might need anyhow and tokio.

[dependencies]
nostr-sdk = { version = "0.44.1", features = ["all-nips", "nip44"] }
tokio = { version = "1.48.0", features = ["full"] }
anyhow = "1.0.100"