diff --git a/crates/nostr-database/examples/helper.rs b/crates/nostr-database/examples/helper.rs index e3fef25ff..dbecc29f9 100644 --- a/crates/nostr-database/examples/helper.rs +++ b/crates/nostr-database/examples/helper.rs @@ -24,27 +24,29 @@ async fn main() { .unwrap(); let keys_b = Keys::new(secret_key); - let index = DatabaseHelper::unbounded(); + let helper = DatabaseHelper::unbounded(); for i in 0..100_000 { let event = EventBuilder::text_note(format!("Event #{i}"), []) - .to_event(&keys_a) + .sign_with_keys(&keys_a) .unwrap(); - index.index_event(&event).await; + helper.index_event(&event).await; let event = EventBuilder::text_note( format!("Reply to event #{i}"), [Tag::event(event.id), Tag::public_key(event.pubkey)], ) - .to_event(&keys_b) + .sign_with_keys(&keys_b) .unwrap(); - index.index_event(&event).await; + helper.index_event(&event).await; } for i in 0..1000 { let metadata = Metadata::new().name(format!("Name #{i}")); - let event = EventBuilder::metadata(&metadata).to_event(&keys_a).unwrap(); - index.index_event(&event).await; + let event = EventBuilder::metadata(&metadata) + .sign_with_keys(&keys_a) + .unwrap(); + helper.index_event(&event).await; } for i in 0..500_000 { @@ -53,12 +55,12 @@ async fn main() { "Custom with d tag", [Tag::identifier(format!("myid{i}"))], ) - .to_event(&keys_a) + .sign_with_keys(&keys_a) .unwrap(); - index.index_event(&event).await; + helper.index_event(&event).await; } - let ids = index + let events = helper .query(vec![Filter::new() .kinds(vec![Kind::Metadata, Kind::Custom(123), Kind::TextNote]) .limit(20) @@ -66,7 +68,7 @@ async fn main() { //.identifier("myid5000") .author(keys_a.public_key())]) .await; - println!("Got {} ids", ids.len()); + println!("Got {} events", events.len()); loop { tokio::time::sleep(Duration::from_secs(60)).await; diff --git a/crates/nostr-database/examples/memory.rs b/crates/nostr-database/examples/memory.rs index 3ddf6b9fa..0ff69287d 100644 --- a/crates/nostr-database/examples/memory.rs +++ b/crates/nostr-database/examples/memory.rs @@ -34,7 +34,7 @@ async fn main() { for i in 0..100_000 { let event = EventBuilder::text_note(format!("Event #{i}"), []) - .to_event(&keys_a) + .sign_with_keys(&keys_a) .unwrap(); database.save_event(&event).await.unwrap(); @@ -42,14 +42,16 @@ async fn main() { format!("Reply to event #{i}"), [Tag::event(event.id), Tag::public_key(event.pubkey)], ) - .to_event(&keys_b) + .sign_with_keys(&keys_b) .unwrap(); database.save_event(&event).await.unwrap(); } for i in 0..10 { let metadata = Metadata::new().name(format!("Name #{i}")); - let event = EventBuilder::metadata(&metadata).to_event(&keys_a).unwrap(); + let event = EventBuilder::metadata(&metadata) + .sign_with_keys(&keys_a) + .unwrap(); database.save_event(&event).await.unwrap(); } @@ -59,7 +61,7 @@ async fn main() { "Custom with d tag", [Tag::identifier(format!("myid{i}"))], ) - .to_event(&keys_a) + .sign_with_keys(&keys_a) .unwrap(); database.save_event(&event).await.unwrap(); } diff --git a/crates/nostr-lmdb/src/lib.rs b/crates/nostr-lmdb/src/lib.rs index 60dc5e850..fb62ec445 100644 --- a/crates/nostr-lmdb/src/lib.rs +++ b/crates/nostr-lmdb/src/lib.rs @@ -212,12 +212,12 @@ mod tests { // Add some text notes events.push( EventBuilder::text_note("Text Note A", []) - .to_event(&keys_a) + .sign_with_keys(&keys_a) .unwrap(), ); events.push( EventBuilder::text_note("Text Note B", []) - .to_event(&keys_b) + .sign_with_keys(&keys_b) .unwrap(), ); @@ -226,14 +226,14 @@ mod tests { EventBuilder::metadata( &Metadata::new().name("account-a").display_name("Account A"), ) - .to_event(&keys_a) + .sign_with_keys(&keys_a) .unwrap(), ); events.push( EventBuilder::metadata( &Metadata::new().name("account-b").display_name("Account B"), ) - .to_event(&keys_b) + .sign_with_keys(&keys_b) .unwrap(), ); @@ -244,7 +244,7 @@ mod tests { "", [Tag::identifier("my-id-a")], ) - .to_event(&keys_a) + .sign_with_keys(&keys_a) .unwrap(), ); events.push( @@ -253,7 +253,7 @@ mod tests { "", [Tag::identifier("my-id-b")], ) - .to_event(&keys_b) + .sign_with_keys(&keys_b) .unwrap(), ); @@ -267,13 +267,13 @@ mod tests { async fn add_event(&self, builder: EventBuilder) -> (Keys, Event) { let keys = Keys::generate(); - let event = builder.to_event(&keys).unwrap(); + let event = builder.sign_with_keys(&keys).unwrap(); self.db.save_event(&event).await.unwrap(); (keys, event) } async fn add_event_with_keys(&self, builder: EventBuilder, keys: &Keys) -> (Event, bool) { - let event = builder.to_event(&keys).unwrap(); + let event = builder.sign_with_keys(&keys).unwrap(); let stored = self.db.save_event(&event).await.unwrap(); (event, stored) } diff --git a/crates/nostr-sdk/README.md b/crates/nostr-sdk/README.md index 6271162ea..55ad79766 100644 --- a/crates/nostr-sdk/README.md +++ b/crates/nostr-sdk/README.md @@ -26,13 +26,13 @@ use nostr_sdk::prelude::*; #[tokio::main] async fn main() -> Result<()> { // Generate new random keys - let my_keys = Keys::generate(); + let keys = Keys::generate(); // Or use your already existing (from hex or bech32) - let my_keys = Keys::parse("hex-or-bech32-secret-key")?; + let keys = Keys::parse("hex-or-bech32-secret-key")?; // Show bech32 public key - let bech32_pubkey: String = my_keys.public_key().to_bech32()?; + let bech32_pubkey: String = keys.public_key().to_bech32()?; println!("Bech32 PubKey: {}", bech32_pubkey); // Configure client to use proxy for `.onion` relays @@ -45,7 +45,7 @@ async fn main() -> Result<()> { // Create new client with custom options. // Use `Client::new(signer)` to construct the client with a custom signer and default options // or `Client::default()` to create one without signer and with default options. - let client = Client::with_opts(&my_keys, opts); + let client = Client::with_opts(keys.clone(), opts); // Add relays client.add_relay("wss://relay.damus.io").await?; @@ -74,7 +74,7 @@ async fn main() -> Result<()> { client.publish_text_note("My first text note from rust-nostr!", []).await?; // Create a POW text note - let event: Event = EventBuilder::text_note("POW text note from nostr-sdk", []).pow(20).to_event(&my_keys)?; + let event: Event = EventBuilder::text_note("POW text note from nostr-sdk", []).pow(20).sign(&keys).await?; client.send_event(event).await?; // Send to all relays // client.send_event_to(["wss://relay.damus.io"], event).await?; // Send to specific relay @@ -141,7 +141,6 @@ The following crate feature flags are available: | `nip07` | Yes | Enable NIP-07: `window.nostr` capability for web browsers (**available only for `wasm32`!**) | | `nip11` | Yes | Enable NIP-11: Relay Information Document | | `nip44` | Yes | Enable NIP-44: Encrypted Payloads (Versioned) | -| `nip46` | Yes | Enable NIP-46: Nostr Connect | | `nip47` | Yes | Enable NIP-47: Nostr Wallet Connect | | `nip49` | Yes | Enable NIP-49: Private Key Encryption | | `nip57` | Yes | Enable NIP-57: Zaps | diff --git a/crates/nostr-sdk/examples/bot.rs b/crates/nostr-sdk/examples/bot.rs index 3a4448e3f..37c88f516 100644 --- a/crates/nostr-sdk/examples/bot.rs +++ b/crates/nostr-sdk/examples/bot.rs @@ -6,19 +6,16 @@ use std::time::Duration; use nostr_sdk::prelude::*; -const BECH32_SK: &str = "nsec12kcgs78l06p30jz7z7h3n2x2cy99nw2z6zspjdp7qc206887mwvs95lnkx"; - #[tokio::main] async fn main() -> Result<()> { tracing_subscriber::fmt::init(); - let secret_key = SecretKey::from_bech32(BECH32_SK)?; - let keys = Keys::new(secret_key); + let keys = Keys::parse("nsec12kcgs78l06p30jz7z7h3n2x2cy99nw2z6zspjdp7qc206887mwvs95lnkx")?; let opts = Options::new() .skip_disconnected_relays(true) .connection_timeout(Some(Duration::from_secs(10))) .send_timeout(Some(Duration::from_secs(5))); - let client = Client::with_opts(&keys, opts); + let client = Client::with_opts(keys.clone(), opts); println!("Bot public key: {}", keys.public_key().to_bech32()?); diff --git a/crates/nostr-sdk/examples/client-with-opts.rs b/crates/nostr-sdk/examples/client-with-opts.rs index e3afda4b4..cbe60d019 100644 --- a/crates/nostr-sdk/examples/client-with-opts.rs +++ b/crates/nostr-sdk/examples/client-with-opts.rs @@ -6,14 +6,12 @@ use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4}; use nostr_sdk::prelude::*; -const BECH32_SK: &str = "nsec1ufnus6pju578ste3v90xd5m2decpuzpql2295m3sknqcjzyys9ls0qlc85"; - #[tokio::main] async fn main() -> Result<()> { tracing_subscriber::fmt::init(); // Parse keys - let my_keys = Keys::parse(BECH32_SK)?; + let keys = Keys::parse("nsec1ufnus6pju578ste3v90xd5m2decpuzpql2295m3sknqcjzyys9ls0qlc85")?; // Configure client to use proxy for `.onion` relays let addr = SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::LOCALHOST, 9050)); @@ -21,7 +19,7 @@ async fn main() -> Result<()> { .proxy(addr) .target(ConnectionTarget::Onion); let opts = Options::new().connection(connection); - let client = Client::with_opts(&my_keys, opts); + let client = Client::with_opts(keys.clone(), opts); // Add relays client.add_relay("wss://relay.damus.io").await?; @@ -37,7 +35,7 @@ async fn main() -> Result<()> { client.connect().await; - let subscription = Filter::new().pubkey(my_keys.public_key()).limit(0); + let subscription = Filter::new().pubkey(keys.public_key()).limit(0); client.subscribe(vec![subscription], None).await?; diff --git a/crates/nostr-sdk/examples/client.rs b/crates/nostr-sdk/examples/client.rs index 7e8f07445..db62fa5dd 100644 --- a/crates/nostr-sdk/examples/client.rs +++ b/crates/nostr-sdk/examples/client.rs @@ -4,16 +4,13 @@ use nostr_sdk::prelude::*; -const BECH32_SK: &str = "nsec1ufnus6pju578ste3v90xd5m2decpuzpql2295m3sknqcjzyys9ls0qlc85"; - #[tokio::main] async fn main() -> Result<()> { tracing_subscriber::fmt::init(); - let secret_key = SecretKey::from_bech32(BECH32_SK)?; - let my_keys = Keys::new(secret_key); + let keys = Keys::parse("nsec1ufnus6pju578ste3v90xd5m2decpuzpql2295m3sknqcjzyys9ls0qlc85")?; + let client = Client::new(keys); - let client = Client::new(&my_keys); client.add_relay("wss://relay.damus.io").await?; client.add_relay("wss://nostr.wine").await?; client.add_relay("wss://relay.rip").await?; @@ -26,26 +23,14 @@ async fn main() -> Result<()> { println!("Sent to: {:?}", output.success); println!("Not sent to: {:?}", output.failed); - // Create a text note POW event and broadcast to all connected relays - let event: Event = EventBuilder::text_note("POW text note from rust-nostr", []) - .pow(20) - .to_event(&my_keys)?; - client.send_event(event).await?; - - // Send multiple events at once (to all relays) - let mut events: Vec = Vec::new(); - for i in 0..10 { - events.push(EventBuilder::text_note(format!("Event #{i}"), []).to_event(&my_keys)?); - } - let opts = RelaySendOptions::default(); - client.batch_event(events, opts).await?; + // Create a text note POW event and broadcast to relays + let builder = EventBuilder::text_note("POW text note from rust-nostr", []).pow(20); + client.send_event_builder(builder).await?; // Send event to specific relays - let event: Event = EventBuilder::text_note("POW text note from rust-nostr 16", []) - .pow(16) - .to_event(&my_keys)?; + let builder = EventBuilder::text_note("POW text note from rust-nostr 16", []).pow(16); client - .send_event_to(["wss://relay.damus.io", "wss://relay.rip"], event) + .send_event_builder_to(["wss://relay.damus.io", "wss://relay.rip"], builder) .await?; Ok(()) diff --git a/crates/nostr-sdk/examples/gossip.rs b/crates/nostr-sdk/examples/gossip.rs index c132e31db..a1d65e95c 100644 --- a/crates/nostr-sdk/examples/gossip.rs +++ b/crates/nostr-sdk/examples/gossip.rs @@ -15,7 +15,7 @@ async fn main() -> Result<()> { let my_keys = Keys::parse(BECH32_SK)?; let opts = Options::new().gossip(true); - let client = Client::with_opts(&my_keys, opts); + let client = Client::with_opts(my_keys, opts); client.add_discovery_relay("wss://relay.damus.io").await?; client.add_discovery_relay("wss://purplepag.es").await?; diff --git a/crates/nostr-sdk/examples/lmdb.rs b/crates/nostr-sdk/examples/lmdb.rs index ae6c13f06..1583acbec 100644 --- a/crates/nostr-sdk/examples/lmdb.rs +++ b/crates/nostr-sdk/examples/lmdb.rs @@ -8,11 +8,11 @@ use nostr_sdk::prelude::*; async fn main() -> Result<()> { tracing_subscriber::fmt::init(); - let my_keys = Keys::parse("nsec1ufnus6pju578ste3v90xd5m2decpuzpql2295m3sknqcjzyys9ls0qlc85")?; + let keys = Keys::parse("nsec1ufnus6pju578ste3v90xd5m2decpuzpql2295m3sknqcjzyys9ls0qlc85")?; let database = NostrLMDB::open("./db/nostr-lmdb")?; let client: Client = ClientBuilder::default() - .signer(&my_keys) + .signer(keys.clone()) .database(database) .build(); @@ -26,7 +26,7 @@ async fn main() -> Result<()> { client.publish_text_note("Hello world", []).await?; // Negentropy reconcile - let filter = Filter::new().author(my_keys.public_key()); + let filter = Filter::new().author(keys.public_key()); let output = client .reconcile( filter, @@ -47,7 +47,7 @@ async fn main() -> Result<()> { } // Query events from database - let filter = Filter::new().author(my_keys.public_key()).limit(10); + let filter = Filter::new().author(keys.public_key()).limit(10); let events = client.database().query(vec![filter]).await?; println!("Events: {events:?}"); diff --git a/crates/nostr-sdk/examples/nostrdb.rs b/crates/nostr-sdk/examples/nostrdb.rs index 3e2e6fc79..0f5001b17 100644 --- a/crates/nostr-sdk/examples/nostrdb.rs +++ b/crates/nostr-sdk/examples/nostrdb.rs @@ -10,11 +10,11 @@ const BECH32_SK: &str = "nsec1ufnus6pju578ste3v90xd5m2decpuzpql2295m3sknqcjzyys9 async fn main() -> Result<()> { tracing_subscriber::fmt::init(); - let my_keys = Keys::parse(BECH32_SK)?; + let keys = Keys::parse(BECH32_SK)?; let database = NdbDatabase::open("./db/ndb")?; let client: Client = Client::builder() - .signer(&my_keys) + .signer(keys.clone()) .database(database) .build(); @@ -26,13 +26,13 @@ async fn main() -> Result<()> { client.publish_text_note("Hello world", []).await?; // Negentropy reconcile - let filter = Filter::new().author(my_keys.public_key()); + let filter = Filter::new().author(keys.public_key()); client .reconcile(filter, NegentropyOptions::default()) .await?; // Query events from database - let filter = Filter::new().author(my_keys.public_key()).limit(10); + let filter = Filter::new().author(keys.public_key()).limit(10); let events = client.database().query(vec![filter]).await?; println!("Events: {events:?}"); diff --git a/crates/nostr-sdk/examples/shutdown-on-drop.rs b/crates/nostr-sdk/examples/shutdown-on-drop.rs index a0c2353ee..4471863ab 100644 --- a/crates/nostr-sdk/examples/shutdown-on-drop.rs +++ b/crates/nostr-sdk/examples/shutdown-on-drop.rs @@ -12,17 +12,17 @@ async fn main() -> Result<()> { tracing_subscriber::fmt::init(); let keys = Keys::generate(); - let client = Client::new(keys); // Ref countert set to 1 + let client = Client::new(keys); // Counter set to 1 client.add_relay("wss://relay.rip").await?; client.add_relay("wss://relay.damus.io").await?; client.connect().await; - let c = client.clone(); // Clone, ref counter set to 2 + let c = client.clone(); // Clone, counter set to 2 let _ = thread::spawn(async move { thread::sleep(Duration::from_secs(3)).await; c.relays().await; - // First drop, decrease ref counter to 1... + // First drop, decrease counter to 1... }); thread::sleep(Duration::from_secs(5)).await; @@ -34,4 +34,4 @@ async fn main() -> Result<()> { Ok(()) } -// Client dropped, ref counter set to 0: auto shutdown relay pool. +// Client dropped, counter set to 0: auto shutdown relay pool. diff --git a/crates/nostr-sdk/examples/subscriptions.rs b/crates/nostr-sdk/examples/subscriptions.rs index 0d6b8d37d..7c3a2a79c 100644 --- a/crates/nostr-sdk/examples/subscriptions.rs +++ b/crates/nostr-sdk/examples/subscriptions.rs @@ -4,14 +4,11 @@ use nostr_sdk::prelude::*; -const BECH32_SK: &str = "nsec1ufnus6pju578ste3v90xd5m2decpuzpql2295m3sknqcjzyys9ls0qlc85"; - #[tokio::main] async fn main() -> Result<()> { tracing_subscriber::fmt::init(); - let secret_key = SecretKey::from_bech32(BECH32_SK)?; - let keys = Keys::new(secret_key); + let keys = Keys::parse("nsec1ufnus6pju578ste3v90xd5m2decpuzpql2295m3sknqcjzyys9ls0qlc85")?; let public_key = keys.public_key(); let opts = Options::new().wait_for_send(false); diff --git a/crates/nostr-sdk/examples/tor.rs b/crates/nostr-sdk/examples/tor.rs index 3102171e3..a5e401591 100644 --- a/crates/nostr-sdk/examples/tor.rs +++ b/crates/nostr-sdk/examples/tor.rs @@ -4,21 +4,19 @@ use nostr_sdk::prelude::*; -const BECH32_SK: &str = "nsec1ufnus6pju578ste3v90xd5m2decpuzpql2295m3sknqcjzyys9ls0qlc85"; - #[tokio::main] async fn main() -> Result<()> { tracing_subscriber::fmt::init(); // Parse keys - let my_keys = Keys::parse(BECH32_SK)?; + let keys = Keys::parse("nsec1ufnus6pju578ste3v90xd5m2decpuzpql2295m3sknqcjzyys9ls0qlc85")?; // Configure client to use embedded tor for `.onion` relays let connection: Connection = Connection::new() .embedded_tor() .target(ConnectionTarget::Onion); let opts = Options::new().connection(connection); - let client = Client::with_opts(&my_keys, opts); + let client = Client::with_opts(keys.clone(), opts); // Add relays client.add_relay("wss://relay.damus.io").await?; @@ -31,7 +29,7 @@ async fn main() -> Result<()> { client.connect().await; - let filter: Filter = Filter::new().pubkey(my_keys.public_key()).limit(0); + let filter: Filter = Filter::new().pubkey(keys.public_key()).limit(0); client.subscribe(vec![filter], None).await?; // Handle subscription notifications with `handle_notifications` method diff --git a/crates/nostr-sdk/examples/zapper.rs b/crates/nostr-sdk/examples/zapper.rs index 674632b65..ea6a80d9c 100644 --- a/crates/nostr-sdk/examples/zapper.rs +++ b/crates/nostr-sdk/examples/zapper.rs @@ -22,9 +22,7 @@ async fn main() -> Result<()> { let nwc = NWC::new(uri); // Compose client - let secret_key = - SecretKey::from_bech32("nsec1ufnus6pju578ste3v90xd5m2decpuzpql2295m3sknqcjzyys9ls0qlc85")?; - let keys = Keys::new(secret_key); + let keys = Keys::parse("nsec1ufnus6pju578ste3v90xd5m2decpuzpql2295m3sknqcjzyys9ls0qlc85")?; let client = Client::builder().signer(keys).zapper(nwc).build(); client.add_relay("wss://relay.nostr.band").await?; @@ -35,7 +33,7 @@ async fn main() -> Result<()> { PublicKey::from_bech32("npub1drvpzev3syqt0kjrls50050uzf25gehpz9vgdw08hvex7e0vgfeq0eseet") .unwrap(); - // Send sats without zap event + // Send SAT without zap event client.zap(public_key, 1000, None).await?; // Zap profile diff --git a/crates/nostr-sdk/src/client/builder.rs b/crates/nostr-sdk/src/client/builder.rs index f013d8fb9..3e9b43c9f 100644 --- a/crates/nostr-sdk/src/client/builder.rs +++ b/crates/nostr-sdk/src/client/builder.rs @@ -6,9 +6,9 @@ use std::sync::Arc; +use nostr::signer::{IntoNostrSigner, NostrSigner}; use nostr_database::memory::MemoryDatabase; use nostr_database::{DynNostrDatabase, IntoNostrDatabase}; -use nostr_signer::NostrSigner; #[cfg(feature = "nip57")] use nostr_zapper::{DynNostrZapper, IntoNostrZapper}; @@ -18,7 +18,7 @@ use crate::{Client, Options}; #[derive(Debug, Clone)] pub struct ClientBuilder { /// Nostr Signer - pub signer: Option, + pub signer: Option>, /// Nostr Zapper #[cfg(feature = "nip57")] pub zapper: Option>, @@ -58,11 +58,11 @@ impl ClientBuilder { /// let client = ClientBuilder::new().signer(keys).build(); /// ``` #[inline] - pub fn signer(mut self, signer: S) -> Self + pub fn signer(mut self, signer: T) -> Self where - S: Into, + T: IntoNostrSigner, { - self.signer = Some(signer.into()); + self.signer = Some(signer.into_nostr_signer()); self } diff --git a/crates/nostr-sdk/src/client/mod.rs b/crates/nostr-sdk/src/client/mod.rs index dcca5004b..19f706abc 100644 --- a/crates/nostr-sdk/src/client/mod.rs +++ b/crates/nostr-sdk/src/client/mod.rs @@ -14,7 +14,6 @@ use atomic_destructor::StealthClone; use nostr::prelude::*; use nostr_database::DynNostrDatabase; use nostr_relay_pool::prelude::*; -use nostr_signer::prelude::*; #[cfg(feature = "nip57")] use nostr_zapper::{DynNostrZapper, IntoNostrZapper, ZapperError}; use thiserror::Error; @@ -48,7 +47,7 @@ pub enum Error { Database(#[from] DatabaseError), /// Signer error #[error(transparent)] - Signer(#[from] nostr_signer::Error), + Signer(#[from] SignerError), /// Zapper error #[cfg(feature = "nip57")] #[error(transparent)] @@ -74,6 +73,10 @@ pub enum Error { #[cfg(feature = "nip57")] #[error(transparent)] LnUrlPay(#[from] lnurl_pay::Error), + /// NIP59 + #[cfg(feature = "nip59")] + #[error(transparent)] + NIP59(#[from] nip59::Error), /// Event not found #[error("event not found: {0}")] EventNotFound(EventId), @@ -89,7 +92,7 @@ pub enum Error { #[derive(Debug, Clone)] pub struct Client { pool: RelayPool, - signer: Arc>>, + signer: Arc>>>, #[cfg(feature = "nip57")] zapper: Arc>>>, gossip_graph: GossipGraph, @@ -117,46 +120,46 @@ impl StealthClone for Client { } impl Client { - /// Create a new [`Client`] with signer + /// Construct client with signer /// - /// To create a [`Client`] without any signer use `Client::default()`. + /// To construct one without signer use [`Client::default()`]. /// /// # Example /// ```rust,no_run /// use nostr_sdk::prelude::*; /// - /// let my_keys = Keys::generate(); - /// let client = Client::new(&my_keys); + /// let keys = Keys::generate(); + /// let client = Client::new(keys); /// ``` #[inline] - pub fn new(signer: S) -> Self + pub fn new(signer: T) -> Self where - S: Into, + T: IntoNostrSigner, { Self::builder().signer(signer).build() } - /// Create a new [`Client`] with [`Options`] + /// Construct client with signer and options /// - /// To create a [`Client`] with custom [`Options`] and without any signer use `Client::builder().opts(opts).build()`. + /// Check [`ClientBuilder`] to construct more customized clients (i.e. with persistent database). /// /// # Example /// ```rust,no_run /// use nostr_sdk::prelude::*; /// - /// let my_keys = Keys::generate(); + /// let keys = Keys::generate(); /// let opts = Options::new().wait_for_send(true); - /// let client = Client::with_opts(&my_keys, opts); + /// let client = Client::with_opts(keys, opts); /// ``` #[inline] - pub fn with_opts(signer: S, opts: Options) -> Self + pub fn with_opts(signer: T, opts: Options) -> Self where - S: Into, + T: IntoNostrSigner, { Self::builder().signer(signer).opts(opts).build() } - /// Construct [ClientBuilder] + /// Construct client builder /// /// # Example /// ```rust,no_run @@ -214,15 +217,24 @@ impl Client { /// Get current nostr signer /// /// Rise error if it not set. - pub async fn signer(&self) -> Result { + pub async fn signer(&self) -> Result, Error> { let signer = self.signer.read().await; signer.clone().ok_or(Error::SignerNotConfigured) } /// Set nostr signer - pub async fn set_signer(&self, signer: Option) { + pub async fn set_signer(&self, signer: T) + where + T: IntoNostrSigner, + { let mut s = self.signer.write().await; - *s = signer; + *s = Some(signer.into_nostr_signer()); + } + + /// Unset nostr signer + pub async fn unset_signer(&self) { + let mut s = self.signer.write().await; + *s = None; } /// Check if `zapper` is configured @@ -404,21 +416,6 @@ impl Client { /// To use custom [`RelayOptions`] use [`RelayPool::add_relay`]. /// /// Connection is **NOT** automatically started with relay, remember to call `client.connect()`! - /// - /// # Example - /// ```rust,no_run - /// use nostr_sdk::prelude::*; - /// - /// # #[tokio::main] - /// # async fn main() { - /// # let my_keys = Keys::generate(); - /// # let client = Client::new(&my_keys); - /// client.add_relay("wss://relay.nostr.info").await.unwrap(); - /// client.add_relay("wss://relay.damus.io").await.unwrap(); - /// - /// client.connect().await; - /// # } - /// ``` #[inline] pub async fn add_relay(&self, url: U) -> Result where @@ -545,21 +542,6 @@ impl Client { } /// Connect to a previously added relay - /// - /// # Example - /// ```rust,no_run - /// use nostr_sdk::prelude::*; - /// - /// # #[tokio::main] - /// # async fn main() { - /// # let my_keys = Keys::generate(); - /// # let client = Client::new(&my_keys); - /// client - /// .connect_relay("wss://relay.nostr.info") - /// .await - /// .unwrap(); - /// # } - /// ``` #[inline] pub async fn connect_relay(&self, url: U) -> Result<(), Error> where @@ -573,21 +555,6 @@ impl Client { } /// Disconnect relay - /// - /// # Example - /// ```rust,no_run - /// use nostr_sdk::prelude::*; - /// - /// # #[tokio::main] - /// # async fn main() { - /// # let my_keys = Keys::generate(); - /// # let client = Client::new(&my_keys); - /// client - /// .disconnect_relay("wss://relay.nostr.info") - /// .await - /// .unwrap(); - /// # } - /// ``` #[inline] pub async fn disconnect_relay(&self, url: U) -> Result<(), Error> where @@ -598,18 +565,6 @@ impl Client { } /// Connect to all added relays - /// - /// # Example - /// ```rust,no_run - /// use nostr_sdk::prelude::*; - /// - /// # #[tokio::main] - /// # async fn main() { - /// # let my_keys = Keys::generate(); - /// # let client = Client::new(&my_keys); - /// client.connect().await; - /// # } - /// ``` #[inline] pub async fn connect(&self) { self.pool.connect(self.opts.connection_timeout).await; @@ -625,18 +580,6 @@ impl Client { } /// Disconnect from all relays - /// - /// # Example - /// ```rust,no_run - /// use nostr_sdk::prelude::*; - /// - /// # #[tokio::main] - /// # async fn main() { - /// # let my_keys = Keys::generate(); - /// # let client = Client::new(&my_keys); - /// client.disconnect().await.unwrap(); - /// # } - /// ``` #[inline] pub async fn disconnect(&self) -> Result<(), Error> { Ok(self.pool.disconnect().await?) @@ -671,14 +614,14 @@ impl Client { /// /// # Example /// ```rust,no_run - /// use nostr_sdk::prelude::*; - /// + /// # use nostr_sdk::prelude::*; /// # #[tokio::main] /// # async fn main() -> Result<()> { - /// # let my_keys = Keys::generate(); - /// # let client = Client::new(&my_keys); + /// # let keys = Keys::generate(); + /// # let client = Client::new(keys.clone()); + /// // Compose filter /// let subscription = Filter::new() - /// .pubkeys(vec![my_keys.public_key()]) + /// .pubkeys(vec![keys.public_key()]) /// .since(Timestamp::now()); /// /// // Subscribe @@ -830,16 +773,14 @@ impl Client { /// /// # Example /// ```rust,no_run - /// use std::time::Duration; - /// - /// use nostr_sdk::prelude::*; - /// + /// # use std::time::Duration; + /// # use nostr_sdk::prelude::*; /// # #[tokio::main] /// # async fn main() { - /// # let my_keys = Keys::generate(); - /// # let client = Client::new(&my_keys); + /// # let keys = Keys::generate(); + /// # let client = Client::new(keys.clone()); /// let subscription = Filter::new() - /// .pubkeys(vec![my_keys.public_key()]) + /// .pubkeys(vec![keys.public_key()]) /// .since(Timestamp::now()); /// /// let _events = client @@ -1125,7 +1066,7 @@ impl Client { let public_key: PublicKey = signer.public_key().await?; let difficulty: u8 = self.opts.get_difficulty(); - let unsigned: UnsignedEvent = builder.pow(difficulty).to_unsigned_event(public_key); + let unsigned: UnsignedEvent = builder.pow(difficulty).build(public_key); Ok(signer.sign_event(unsigned).await?) } @@ -1189,12 +1130,11 @@ impl Client { /// /// # Example /// ```rust,no_run - /// use nostr_sdk::prelude::*; - /// + /// # use nostr_sdk::prelude::*; /// # #[tokio::main] /// # async fn main() { - /// # let my_keys = Keys::generate(); - /// # let client = Client::new(&my_keys); + /// # let keys = Keys::generate(); + /// # let client = Client::new(keys); /// let metadata = Metadata::new() /// .name("username") /// .display_name("My Username") @@ -1226,21 +1166,6 @@ impl Client { /// Publish text note /// /// - /// - /// # Example - /// ```rust,no_run - /// use nostr_sdk::prelude::*; - /// - /// # #[tokio::main] - /// # async fn main() { - /// # let my_keys = Keys::generate(); - /// # let client = Client::new(&my_keys); - /// client - /// .publish_text_note("My first text note from rust-nostr!", []) - /// .await - /// .unwrap(); - /// # } - /// ``` #[inline] pub async fn publish_text_note( &self, @@ -1280,21 +1205,6 @@ impl Client { /// Get contact list from relays. /// /// - /// - /// # Example - /// ```rust,no_run - /// use std::time::Duration; - /// - /// use nostr_sdk::prelude::*; - /// - /// # #[tokio::main] - /// # async fn main() { - /// # let my_keys = Keys::generate(); - /// # let client = Client::new(&my_keys); - /// let timeout = Duration::from_secs(10); - /// let _list = client.get_contact_list(Some(timeout)).await.unwrap(); - /// # } - /// ``` pub async fn get_contact_list(&self, timeout: Option) -> Result, Error> { let mut contact_list: Vec = Vec::new(); let filters: Vec = self.get_contact_list_filters().await?; @@ -1434,24 +1344,6 @@ impl Client { /// Like event /// /// - /// - /// # Example - /// ```rust,no_run - /// use std::str::FromStr; - /// - /// use nostr_sdk::prelude::*; - /// - /// # #[tokio::main] - /// # async fn main() { - /// # let my_keys = Keys::generate(); - /// # let client = Client::new(&my_keys); - /// let event = - /// Event::from_json(r#"{"content":"uRuvYr585B80L6rSJiHocw==?iv=oh6LVqdsYYol3JfFnXTbPA==","created_at":1640839235,"id":"2be17aa3031bdcb006f0fce80c146dea9c1c0268b0af2398bb673365c6444d45","kind":4,"pubkey":"f86c44a2de95d9149b51c6a29afeabba264c18e2fa7c49de93424a0c56947785","sig":"a5d9290ef9659083c490b303eb7ee41356d8778ff19f2f91776c8dc4443388a64ffcf336e61af4c25c05ac3ae952d1ced889ed655b67790891222aaa15b99fdd","tags":[["p","13adc511de7e1cfcf1c6b7f6365fb5a03442d7bcacf565ea57fa7770912c023d"]]}"#) - /// .unwrap(); - /// - /// client.like(&event).await.unwrap(); - /// # } - /// ``` #[inline] pub async fn like(&self, event: &Event) -> Result, Error> { self.reaction(event, "+").await @@ -1460,24 +1352,6 @@ impl Client { /// Disike event /// /// - /// - /// # Example - /// ```rust,no_run - /// use std::str::FromStr; - /// - /// use nostr_sdk::prelude::*; - /// - /// # #[tokio::main] - /// # async fn main() { - /// # let my_keys = Keys::generate(); - /// # let client = Client::new(&my_keys); - /// let event = - /// Event::from_json(r#"{"content":"uRuvYr585B80L6rSJiHocw==?iv=oh6LVqdsYYol3JfFnXTbPA==","created_at":1640839235,"id":"2be17aa3031bdcb006f0fce80c146dea9c1c0268b0af2398bb673365c6444d45","kind":4,"pubkey":"f86c44a2de95d9149b51c6a29afeabba264c18e2fa7c49de93424a0c56947785","sig":"a5d9290ef9659083c490b303eb7ee41356d8778ff19f2f91776c8dc4443388a64ffcf336e61af4c25c05ac3ae952d1ced889ed655b67790891222aaa15b99fdd","tags":[["p","13adc511de7e1cfcf1c6b7f6365fb5a03442d7bcacf565ea57fa7770912c023d"]]}"#) - /// .unwrap(); - /// - /// client.dislike(&event).await.unwrap(); - /// # } - /// ``` #[inline] pub async fn dislike(&self, event: &Event) -> Result, Error> { self.reaction(event, "-").await @@ -1495,8 +1369,8 @@ impl Client { /// /// # #[tokio::main] /// # async fn main() { - /// # let my_keys = Keys::generate(); - /// # let client = Client::new(&my_keys); + /// # let keys = Keys::generate(); + /// # let client = Client::new(keys); /// let event = /// Event::from_json(r#"{"content":"uRuvYr585B80L6rSJiHocw==?iv=oh6LVqdsYYol3JfFnXTbPA==","created_at":1640839235,"id":"2be17aa3031bdcb006f0fce80c146dea9c1c0268b0af2398bb673365c6444d45","kind":4,"pubkey":"f86c44a2de95d9149b51c6a29afeabba264c18e2fa7c49de93424a0c56947785","sig":"a5d9290ef9659083c490b303eb7ee41356d8778ff19f2f91776c8dc4443388a64ffcf336e61af4c25c05ac3ae952d1ced889ed655b67790891222aaa15b99fdd","tags":[["p","13adc511de7e1cfcf1c6b7f6365fb5a03442d7bcacf565ea57fa7770912c023d"]]}"#) /// .unwrap(); @@ -1654,8 +1528,18 @@ impl Client { rumor: EventBuilder, expiration: Option, ) -> Result, Error> { - let signer: NostrSigner = self.signer().await?; - let gift_wrap: Event = signer.gift_wrap(receiver, rumor, expiration).await?; + // Acquire signer + let signer = self.signer().await?; + + // Compose rumor + let public_key: PublicKey = signer.public_key().await?; + let rumor: UnsignedEvent = rumor.build(public_key); + + // Build gift wrap + let gift_wrap: Event = + EventBuilder::gift_wrap(&signer, receiver, rumor, expiration).await?; + + // Send self.send_event(gift_wrap).await } @@ -1676,8 +1560,18 @@ impl Client { U: TryIntoUrl, pool::Error: From<::Err>, { - let signer: NostrSigner = self.signer().await?; - let gift_wrap: Event = signer.gift_wrap(receiver, rumor, expiration).await?; + // Acquire signer + let signer = self.signer().await?; + + // Compose rumor + let public_key: PublicKey = signer.public_key().await?; + let rumor: UnsignedEvent = rumor.build(public_key); + + // Build gift wrap + let gift_wrap: Event = + EventBuilder::gift_wrap(&signer, receiver, rumor, expiration).await?; + + // Send self.send_event_to(urls, gift_wrap).await } @@ -1689,8 +1583,8 @@ impl Client { #[inline] #[cfg(feature = "nip59")] pub async fn unwrap_gift_wrap(&self, gift_wrap: &Event) -> Result { - let signer: NostrSigner = self.signer().await?; - Ok(signer.unwrap_gift_wrap(gift_wrap).await?) + let signer = self.signer().await?; + Ok(UnwrappedGift::from_gift_wrap(&signer, gift_wrap).await?) } /// File metadata diff --git a/crates/nostr-sdk/src/gossip/graph.rs b/crates/nostr-sdk/src/gossip/graph.rs index dbb0e00b6..f6cbd4abe 100644 --- a/crates/nostr-sdk/src/gossip/graph.rs +++ b/crates/nostr-sdk/src/gossip/graph.rs @@ -349,7 +349,9 @@ mod tests { let list = relays .into_iter() .filter_map(|(url, m)| Some((Url::parse(url).ok()?, m))); - EventBuilder::relay_list(list).to_event(&keys).unwrap() + EventBuilder::relay_list(list) + .sign_with_keys(&keys) + .unwrap() } async fn setup_graph() -> GossipGraph {