rust-nostr / nostr

Nostr protocol implementation, SDK and FFI
https://rust-nostr.org/
MIT License
404 stars 89 forks source link

The client sends an event to obtain results in real time #563

Closed Lz020316 closed 1 week ago

Lz020316 commented 1 week ago

hi, yukibtc

I have been using nostr for many days and have learned a lot. Thank you very much.

I am currently writing the program to send note, but I have encountered a problem that when I send to multiple relays, I can only get the result after all relays have been sent. I would like to ask if we have designed any method to monitor the sending result of each relay in real time.

The method I'm using so far is send_event

  let builder = EventBuilder::text_note(content, tags).custom_created_at(Timestamp::now());
  let event = signer.sign_event_builder(builder).await?;
  let eid = client.send_event(event).await?;
reyamir commented 1 week ago

I guess you can setup client.handle_notification to monitor send_event

client.handle_notifications(|notification| async {
  if let RelayPoolNotification::Message { message, relay_url } = notification {
    if let RelayMessage::Event { event, subscription_id, .. } = message {
      // Do something
    }
  }
}).await
yukibtc commented 1 week ago

Yes, with something like this:

// Build event
let event: Event = EventBuilder::text_note("Text note from rust-nostr", [])
        .to_event(&my_keys)?;

// Get event ID (needed to filter the `OK` messages)
let id = event.id;

// Compose notification listener (WITHOUT CALL `.await`!)
let notifications = client
    .handle_notifications(|notification| async {
        if let RelayPoolNotification::Message { relay_url, message } = notification {
            if let RelayMessage::Ok { event_id, status, message} = message {
                if id == event_id {
                    println!("Received OK message from {relay_url}: status={status}, message={message}");
                }
            }
    }
    Ok(false)
});

// This will wait that one of the 2 future terminate.
// `handle_notifications` terminate only on shutdown or if `true` is returned inside the closure
// so the code execution will continue when `send_event` terminate.
tokio::select! {
    output = client.send_event(event) => {
        let output = output?;
        println!("{output:?}");
    }
    _ = notifications => {}
}
Lz020316 commented 1 week ago

Thank you very much, this way has solved my problem very well.