Skip to content

Commit

Permalink
sdk: automatically resend event after NIP-42 authentication
Browse files Browse the repository at this point in the history
Fixes #509

Signed-off-by: Yuki Kishimoto <[email protected]>
  • Loading branch information
yukibtc committed Dec 2, 2024
1 parent c488a5f commit e146f9a
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 7 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
### Added

* database: impl PartialEq and Eq for `Events` ([Yuki Kishimoto])
* sdk: automatically resend event after NIP-42 authentication ([Yuki Kishimoto])

### Fixed

Expand Down
8 changes: 5 additions & 3 deletions crates/nostr-relay-pool/src/pool/inner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -475,9 +475,11 @@ impl InnerRelayPool {
}
}

if output.success.is_empty() {
return Err(Error::EventNotPublished);
}
// TODO: this complicate things with NIP42 auto auth
// TODO: what to do?
// if output.success.is_empty() {
// return Err(Error::EventNotPublished);
// }

Ok(output)
}
Expand Down
62 changes: 58 additions & 4 deletions crates/nostr-sdk/src/client/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ impl Client {
/// use nostr_sdk::prelude::*;
///
/// let signer = Keys::generate();
/// let opts = Options::default().connection_timeout(Some(Duration::from_secs(30)));
/// let opts = Options::default().gossip(true);
/// let client: Client = Client::builder().signer(signer).opts(opts).build();
/// ```
#[inline]
Expand Down Expand Up @@ -203,6 +203,12 @@ impl Client {
self.opts.update_automatic_authentication(enable);
}

/// Check if signer is configured
pub async fn has_signer(&self) -> bool {
let signer = self.signer.read().await;
signer.is_some()
}

/// Get current nostr signer
///
/// Rise error if it not set.
Expand Down Expand Up @@ -1006,10 +1012,14 @@ impl Client {
pub async fn send_event(&self, event: Event) -> Result<Output<EventId>, Error> {
// NOT gossip, send event to all relays
if !self.opts.gossip {
return Ok(self.pool.send_event(event).await?);
// TODO: avoid event clone
let output = self.pool.send_event(event.clone()).await?;
return self.handle_send_event_output(event, output).await;
}

self.gossip_send_event(event, false).await
// TODO: avoid event clone
let output = self.gossip_send_event(event.clone(), false).await?;
self.handle_send_event_output(event, output).await
}

/// Send multiple events at once to all relays with [`RelayServiceFlags::WRITE`] flag.
Expand All @@ -1026,7 +1036,8 @@ impl Client {
U: TryIntoUrl,
pool::Error: From<<U as TryIntoUrl>::Err>,
{
Ok(self.pool.send_event_to(urls, event).await?)
let output = self.pool.send_event_to(urls, event.clone()).await?;
self.handle_send_event_output(event, output).await
}

/// Send multiple events at once to specific relays
Expand Down Expand Up @@ -1639,6 +1650,49 @@ impl Client {
}
}

// NIP42
impl Client {
async fn handle_send_event_output(
&self,
event: Event,
output: Output<EventId>,
) -> Result<Output<EventId>, Error> {
// NIP42 auth isn't enabled, immediately return the result
if !self.opts.is_nip42_auto_authentication_enabled() {
return Ok(output);
}

// If hasn't signer, immediately return the result
// NIP42 auth can't be done without signer
if !self.has_signer().await {
return Ok(output);
}

// TODO: wait for AUTH
// TODO: temp solution
async_utility::time::sleep(Duration::from_secs(1)).await;

// Filter relays with an auth error
let urls: HashSet<&RelayUrl> = output
.failed
.iter()
.filter_map(|(url, error)| match MachineReadablePrefix::parse(error) {
Some(MachineReadablePrefix::AuthRequired) => Some(url),
_ => None,
})
.collect();

if urls.is_empty() {
return Ok(output);
}

// Resend event
// TODO: this must return the aggregated result (old + new one)
Ok(self.pool.send_event_to(urls, event).await?)
}
}

// Gossip
impl Client {
async fn update_outdated_gossip_graph(
&self,
Expand Down

0 comments on commit e146f9a

Please sign in to comment.