commit 84e28c29959f44d3d9ce2d7a7c730f626ab417a1
parent 37d0f68ad69c884d2b133ff4bef49c2131119a4b
Author: triesap <tyson@radroots.org>
Date: Sat, 28 Mar 2026 19:56:31 +0000
rr-rs: type pending remote signer poll responses
Diffstat:
3 files changed, 45 insertions(+), 11 deletions(-)
diff --git a/crates/nostr-connect/src/message.rs b/crates/nostr-connect/src/message.rs
@@ -256,6 +256,7 @@ pub enum RadrootsNostrConnectPendingConnectionPollOutcome {
pub enum RadrootsNostrConnectResponse {
ConnectAcknowledged,
ConnectSecretEcho(String),
+ PendingConnection,
UserPublicKey(PublicKey),
SignedEvent(Event),
Pong,
@@ -281,15 +282,14 @@ impl RadrootsNostrConnectResponse {
self,
) -> RadrootsNostrConnectPendingConnectionPollOutcome {
match self {
+ Self::PendingConnection => {
+ RadrootsNostrConnectPendingConnectionPollOutcome::PendingApproval
+ }
Self::UserPublicKey(public_key) => {
RadrootsNostrConnectPendingConnectionPollOutcome::Approved(public_key)
}
- Self::Error { result, error } => {
- if result.is_none() && error == RADROOTS_NOSTR_CONNECT_PENDING_CONNECTION_ERROR {
- RadrootsNostrConnectPendingConnectionPollOutcome::PendingApproval
- } else {
- RadrootsNostrConnectPendingConnectionPollOutcome::Rejected { message: error }
- }
+ Self::Error { error, .. } => {
+ RadrootsNostrConnectPendingConnectionPollOutcome::Rejected { message: error }
}
Self::AuthUrl(url) => {
RadrootsNostrConnectPendingConnectionPollOutcome::AuthChallenge { url }
@@ -316,6 +316,11 @@ impl RadrootsNostrConnectResponse {
result: Some(Value::String(secret)),
error: None,
},
+ Self::PendingConnection => RadrootsNostrConnectResponseEnvelope {
+ id,
+ result: None,
+ error: Some(RADROOTS_NOSTR_CONNECT_PENDING_CONNECTION_ERROR.to_owned()),
+ },
Self::UserPublicKey(public_key) => RadrootsNostrConnectResponseEnvelope {
id,
result: Some(Value::String(public_key.to_hex())),
@@ -388,6 +393,12 @@ impl RadrootsNostrConnectResponse {
}
if let Some(error) = envelope.error {
+ if matches!(method, RadrootsNostrConnectMethod::GetPublicKey)
+ && envelope.result.is_none()
+ && error == RADROOTS_NOSTR_CONNECT_PENDING_CONNECTION_ERROR
+ {
+ return Ok(Self::PendingConnection);
+ }
if let RadrootsNostrConnectMethod::Custom(_) = method {
return Ok(Self::Custom {
result: envelope.result,
diff --git a/crates/nostr-connect/tests/coverage.rs b/crates/nostr-connect/tests/coverage.rs
@@ -753,6 +753,18 @@ fn response_surface_covers_success_and_error_paths() {
);
assert_eq!(
RadrootsNostrConnectResponse::from_envelope(
+ &RadrootsNostrConnectMethod::GetPublicKey,
+ RadrootsNostrConnectResponseEnvelope {
+ id: "req-pending".to_owned(),
+ result: None,
+ error: Some(RADROOTS_NOSTR_CONNECT_PENDING_CONNECTION_ERROR.to_owned()),
+ },
+ )
+ .expect("parse typed pending response"),
+ RadrootsNostrConnectResponse::PendingConnection
+ );
+ assert_eq!(
+ RadrootsNostrConnectResponse::from_envelope(
&RadrootsNostrConnectMethod::Ping,
RadrootsNostrConnectResponseEnvelope {
id: "req-error".to_owned(),
@@ -1010,11 +1022,7 @@ fn response_surface_covers_success_and_error_paths() {
#[test]
fn pending_connection_poll_outcome_uses_typed_variants() {
assert_eq!(
- RadrootsNostrConnectResponse::Error {
- result: None,
- error: RADROOTS_NOSTR_CONNECT_PENDING_CONNECTION_ERROR.to_owned(),
- }
- .into_pending_connection_poll_outcome(),
+ RadrootsNostrConnectResponse::PendingConnection.into_pending_connection_poll_outcome(),
RadrootsNostrConnectPendingConnectionPollOutcome::PendingApproval
);
diff --git a/crates/nostr-connect/tests/protocol.rs b/crates/nostr-connect/tests/protocol.rs
@@ -212,6 +212,21 @@ fn auth_url_response_parses_from_result_and_error_fields() {
}
#[test]
+fn get_public_key_pending_response_parses_as_typed_pending_connection() {
+ let response = RadrootsNostrConnectResponse::from_envelope(
+ &RadrootsNostrConnectMethod::GetPublicKey,
+ RadrootsNostrConnectResponseEnvelope {
+ id: "req-pending".to_owned(),
+ result: None,
+ error: Some(RADROOTS_NOSTR_CONNECT_PENDING_CONNECTION_ERROR.to_owned()),
+ },
+ )
+ .expect("parse pending get_public_key response");
+
+ assert_eq!(response, RadrootsNostrConnectResponse::PendingConnection);
+}
+
+#[test]
fn sign_event_response_roundtrips_signed_event_json_string() {
let keys = test_keys();
let event = EventBuilder::text_note("hello world")