2026-08-13 12:42:40 -04:00
2026-08-13 12:42:40 -04:00

NOSTR Core Library — Rust

A Rust implementation of the NOSTR protocol library, ported from the C nostr_core_lib project.

Version License Build Status

📋 NIP Implementation Status

Core Protocol NIPs

  • NIP-01 — Basic protocol flow — event creation, signing, and validation
  • NIP-02 — Contact List and Petnames
  • NIP-03 — OpenTimestamps Attestations for Events
  • NIP-04 — Encrypted Direct Messages (legacy)
  • NIP-05 — Mapping Nostr keys to DNS-based internet identifiers
  • NIP-06 — Basic key derivation from mnemonic seed phrase
  • NIP-07 — window.nostr capability for web browsers
  • NIP-08 — Handling Mentions
  • NIP-09 — Event Deletion
  • NIP-10 — Conventions for clients' use of e and p tags in text events
  • NIP-11 — Relay Information Document
  • NIP-12 — Generic Tag Queries
  • NIP-13 — Proof of Work
  • NIP-14 — Subject tag in text events
  • NIP-15 — Nostr Marketplace
  • NIP-16 — Event Treatment
  • NIP-17 — Private Direct Messages
  • NIP-18 — Reposts
  • NIP-19 — bech32-encoded entities
  • NIP-20 — Command Results
  • NIP-21 — nostr: URI scheme
  • NIP-22 — Event created_at Limits
  • NIP-23 — Long-form Content
  • NIP-24 — Extra metadata fields and tags
  • NIP-25 — Reactions
  • NIP-26 — Delegated Event Signing
  • NIP-27 — Text Note References
  • NIP-28 — Public Chat
  • NIP-29 — Relay-based Groups
  • NIP-30 — Custom Emoji
  • NIP-31 — Dealing with Unknown Events
  • NIP-32 — Labeling
  • NIP-33 — Parameterized Replaceable Events
  • NIP-34 — git stuff
  • NIP-35 — Torrents
  • NIP-36 — Sensitive Content
  • NIP-37 — Draft Events
  • NIP-38 — User Statuses
  • NIP-39 — External Identities in Profiles
  • NIP-40 — Expiration Timestamp
  • NIP-42 — Authentication of clients to relays
  • NIP-44 — Versioned Encryption
  • NIP-45 — Counting results
  • NIP-46 — Nostr Remote Signing
  • NIP-47 — Wallet Connect
  • NIP-48 — Proxy Tags
  • NIP-49 — Private Key Encryption
  • NIP-50 — Search Capability
  • NIP-51 — Lists (kind:10000 Mute List)
  • NIP-52 — Calendar Events
  • NIP-53 — Live Activities
  • NIP-54 — Wiki
  • NIP-55 — Android Signer Application
  • NIP-56 — Reporting
  • NIP-57 — Lightning Zaps
  • NIP-58 — Badges
  • NIP-59 — Gift Wrap
  • NIP-60 — Cashu Wallet
  • NIP-61 — Nutzaps
  • NIP-62 — Log events
  • NIP-64 — Chess (PGN)
  • NIP-65 — Relay List Metadata
  • NIP-66 — Relay Monitor
  • NIP-68 — Web badges
  • NIP-69 — Peer-to-peer Order events
  • NIP-70 — Protected Events
  • NIP-71 — Video Events
  • NIP-72 — Moderated Communities
  • NIP-73 — External Content IDs
  • NIP-75 — Zap Goals
  • NIP-77 — Arbitrary custom app data
  • NIP-78 — Application-specific data
  • NIP-84 — Highlights
  • NIP-86 — Relay Management API
  • NIP-87 — Relay List Recommendations
  • NIP-88 — Stella: A Stellar Relay
  • NIP-89 — Recommended Application Handlers
  • NIP-90 — Data Vending Machines
  • NIP-92 — Media Attachments
  • NIP-94 — File Metadata
  • NIP-96 — HTTP File Storage Integration
  • NIP-98 — HTTP Auth
  • NIP-99 — Classified Listings

Legend: ✅ Implemented | ❌ Not Implemented

Implementation Summary: 18 of 96+ NIPs implemented (18.8%)

Workspace Structure

nostr_core_lib_rust/
├── core/              # Core types, errors, crypto, utilities
├── relay/             # WebSocket, HTTP, relay pool
├── nips/              # All NIP implementations
├── signer/            # Signer trait, local + signer remote
├── services/          # Request validator, Blossom, Cashu
├── nostr-core/        # Umbrella re-export crate
├── examples/          # Example programs
│   ├── keypair_generator/  # Generate Nostr keypairs
│   └── event_signer/       # Create and sign events
└── tests/             # Integration tests (ported from C)

Building

# Build all crates
cargo build

# Build release binaries
cargo build --release

# Run all tests (300 total)
cargo test --workspace

Usage

Generate a keypair

cargo run -p keypair-generator

Sign a text note

cargo run -p event-signer -- nsec1... "Hello, Nostr!"

Use as a library dependency

Add to your Cargo.toml:

[dependencies]
nostr-core = { git = "ssh://git@laantungir.net:2222/laantungir/nostr_core_lib_rust.git" }

Relay pool

RelayPool keeps a set of relay connections alive in the background: it reconnects with exponential backoff (1 s → 60 s, ×2, ±20% jitter), replays open REQ subscriptions after every reconnect, and publishes a status snapshot through a tokio::sync::watch channel.

use nostr_relay::pool::{RelayPool, ReconnectConfig};
use std::sync::Arc;

// Persistent pool: unlimited reconnect attempts, 1 s → 60 s backoff,
// 10 s per-attempt connect timeout.
let pool = Arc::new(RelayPool::new(Some(ReconnectConfig::persistent())));
for url in ["wss://relay.damus.io", "wss://nos.lol"] {
    pool.add_relay(url).await?;
}

// Drive the pool in the background (non-blocking; pass a small tick).
tokio::spawn(Arc::clone(&pool).run(50));

// Watch connection status changes (RelayStatusInfo: status, attempt,
// next_retry_in, last_error, connected_for, enabled).
let mut rx = pool.status_watch();
while rx.changed().await.is_ok() {
    for s in rx.borrow().iter() {
        println!("{}: {:?}", s.url, s.status);
    }
}

// Per-relay manual control: a disabled relay is never connected by the
// pool (run(), subscribe, publish_async, connect_all*) until re-enabled.
pool.disable_relay("wss://relay.damus.io").await?;   // disconnect + stay down
pool.enable_relay("wss://relay.damus.io").await?;    // reconnect right away
pool.reconnect_relay("wss://relay.damus.io").await?; // force drop + retry now
pool.add_relay_disabled("wss://backup.lol").await?;  // add parked (disabled)

Fetch a user's NIP-65 relay list through the bootstrap relays:

let relay_list = nostr_relay::nip65::fetch_relay_list(
    &pubkey_hex,
    &nostr_relay::nip65::default_bootstrap_relays(),
    8_000,
).await?;

Test Summary

Crate Tests Description
nostr-core 62 Types, errors, crypto, utilities
nostr-nips 97 All 18 NIP implementations
nostr-relay 46 WebSocket, HTTP, relay pool (35 unit + 11 pool_live integration)
nostr-signer 29 Signer trait, local + signer
nostr-services 31 Validator, Blossom, Cashu
integration-tests 35 Ported from C test suite
Total 300

Versioning

This project uses Semantic Versioning with a single source of truth in the VERSION file. The workspace version in Cargo.toml and the badge in README.md are kept in sync by the increment_and_push.sh script.

Releasing a new version

# Patch bump (bug fixes): 0.2.0 → 0.2.1
./increment_and_push.sh patch

# Minor bump (new features): 0.2.0 → 0.3.0
./increment_and_push.sh minor

# Major bump (breaking changes): 0.2.0 → 1.0.0
./increment_and_push.sh major

# Prerelease bump: 0.2.0 → 0.2.0-pre.1
./increment_and_push.sh prerelease

# Set an explicit version
./increment_and_push.sh 1.2.3

# Preview without modifying files or git
./increment_and_push.sh minor --dry-run

# Bump without pushing to origin
./increment_and_push.sh patch no-push

The script:

  1. Reads the current version from VERSION.
  2. Computes the next version per the requested bump type.
  3. Updates VERSION, the workspace version in Cargo.toml, and the badge in README.md.
  4. Moves the [Unreleased] section in CHANGELOG.md to the new version with today's date.
  5. Verifies the workspace still builds with cargo build --workspace.
  6. Creates a [release] vX.Y.Z commit and an annotated vX.Y.Z git tag.
  7. Pushes the branch and tag to origin (unless no-push).

Changelog

See CHANGELOG.md for a record of notable changes per release. Follow the Keep a Changelog format when adding entries under [Unreleased].

License

MIT

S
Description
No description provided
Readme
627 MiB
Languages
Rust 98.4%
Shell 1.6%