From 7605f51079fe9d4b84b24e666e4a1aab724fd76a Mon Sep 17 00:00:00 2001 From: Avi Date: Tue, 1 Sep 2026 09:11:16 -0500 Subject: [PATCH] fix: keep NIP-46 signer subscription open --- src/signer.rs | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/src/signer.rs b/src/signer.rs index 0ee5d63..56fa85e 100644 --- a/src/signer.rs +++ b/src/signer.rs @@ -647,13 +647,13 @@ async fn run_sign_task(signer: Signer, app: Arc>, uri: C client.connect().and_wait(CONNECT_TIMEOUT).await; // 4. Subscribe to the client's kind 24133 events so we hear its requests. - // `stream_events` opens its internal notification receiver as part of - // subscribing, which must happen BEFORE we announce (step 5): the client - // acknowledges within milliseconds and a receiver created afterwards would - // miss those early messages (tokio broadcast semantics). + // Do not use `stream_events` here: it is an auto-closing historical-event + // helper and ends at EOSE. NIP-46 needs a long-lived subscription because + // the app sends requests after the initial handshake. let filter = Filter::new().kind(Kind::NostrConnect).author(uri.peer); - let mut events = match client.stream_events(filter).await { - Ok(events) => events, + let mut notifications = client.notifications(); + let subscription = match client.subscribe(filter).await { + Ok(subscription) => subscription, Err(err) => { signer.fail(format!("Could not subscribe for messages: {err}")); return; @@ -666,20 +666,22 @@ async fn run_sign_task(signer: Signer, app: Arc>, uri: C return; } - // 6. Answer requests until the connection goes away or we are stopped. + // 6. Answer requests until stopped. Notifications are persistent and do + // not terminate after EOSE, unlike `stream_events`. loop { - let (relay_url, incoming) = match events.next().await { - Some(next) => next, - None => { + let incoming = match notifications.next().await { + Some(nostr_sdk::client::ClientNotification::Event { + subscription_id, + event, + .. + }) if subscription_id == *subscription.id() => event, + Some(nostr_sdk::client::ClientNotification::Shutdown) | None => { signer.fail("The signer connection was closed."); return; } + Some(_) => continue, }; - let event = match incoming { - Ok(event) => event, - Err(_) => continue, - }; - let _ = relay_url; + let event = *incoming; if event.kind != Kind::NostrConnect || event.pubkey != uri.peer { continue; }