lib

Core libraries for Radroots
git clone https://radroots.dev/git/lib.git
Log | Files | Refs | README | LICENSE

commit 37d0f68ad69c884d2b133ff4bef49c2131119a4b
parent 0dfe1fbee00440940826e57ec80a89a266d938bb
Author: triesap <tyson@radroots.org>
Date:   Sat, 28 Mar 2026 18:01:44 +0000

nostr-connect: add typed pending poll outcomes

Diffstat:
Mcrates/nostr-connect/src/lib.rs | 3++-
Mcrates/nostr-connect/src/message.rs | 34++++++++++++++++++++++++++++++++++
Mcrates/nostr-connect/tests/coverage.rs | 48++++++++++++++++++++++++++++++++++++++++++++++--
3 files changed, 82 insertions(+), 3 deletions(-)

diff --git a/crates/nostr-connect/src/lib.rs b/crates/nostr-connect/src/lib.rs @@ -9,7 +9,8 @@ pub mod uri; pub mod prelude { pub use crate::error::RadrootsNostrConnectError; pub use crate::message::{ - RADROOTS_NOSTR_CONNECT_RPC_KIND, RadrootsNostrConnectRequest, + RADROOTS_NOSTR_CONNECT_PENDING_CONNECTION_ERROR, RADROOTS_NOSTR_CONNECT_RPC_KIND, + RadrootsNostrConnectPendingConnectionPollOutcome, RadrootsNostrConnectRequest, RadrootsNostrConnectRequestMessage, RadrootsNostrConnectResponse, RadrootsNostrConnectResponseEnvelope, }; diff --git a/crates/nostr-connect/src/message.rs b/crates/nostr-connect/src/message.rs @@ -241,6 +241,17 @@ pub struct RadrootsNostrConnectResponseEnvelope { pub error: Option<String>, } +pub const RADROOTS_NOSTR_CONNECT_PENDING_CONNECTION_ERROR: &str = "connection is pending"; + +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum RadrootsNostrConnectPendingConnectionPollOutcome { + PendingApproval, + Approved(PublicKey), + Rejected { message: String }, + AuthChallenge { url: String }, + UnexpectedResponse { response: String }, +} + #[derive(Debug, Clone, PartialEq, Eq)] pub enum RadrootsNostrConnectResponse { ConnectAcknowledged, @@ -266,6 +277,29 @@ pub enum RadrootsNostrConnectResponse { } impl RadrootsNostrConnectResponse { + pub fn into_pending_connection_poll_outcome( + self, + ) -> RadrootsNostrConnectPendingConnectionPollOutcome { + match self { + 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::AuthUrl(url) => { + RadrootsNostrConnectPendingConnectionPollOutcome::AuthChallenge { url } + } + other => RadrootsNostrConnectPendingConnectionPollOutcome::UnexpectedResponse { + response: format!("{other:?}"), + }, + } + } + pub fn into_envelope( self, id: impl Into<String>, diff --git a/crates/nostr-connect/tests/coverage.rs b/crates/nostr-connect/tests/coverage.rs @@ -1,7 +1,8 @@ use nostr::{Event, EventBuilder, Keys, PublicKey, RelayUrl, SecretKey, Timestamp, UnsignedEvent}; use radroots_nostr_connect::prelude::{ - RadrootsNostrConnectError, RadrootsNostrConnectMethod, RadrootsNostrConnectPermission, - RadrootsNostrConnectPermissions, RadrootsNostrConnectRequest, + RADROOTS_NOSTR_CONNECT_PENDING_CONNECTION_ERROR, RadrootsNostrConnectError, + RadrootsNostrConnectMethod, RadrootsNostrConnectPendingConnectionPollOutcome, + RadrootsNostrConnectPermission, RadrootsNostrConnectPermissions, RadrootsNostrConnectRequest, RadrootsNostrConnectRequestMessage, RadrootsNostrConnectResponse, RadrootsNostrConnectResponseEnvelope, RadrootsNostrConnectUri, }; @@ -1005,3 +1006,46 @@ fn response_surface_covers_success_and_error_paths() { Err(RadrootsNostrConnectError::InvalidResponsePayload { .. }) )); } + +#[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(), + RadrootsNostrConnectPendingConnectionPollOutcome::PendingApproval + ); + + assert_eq!( + RadrootsNostrConnectResponse::UserPublicKey(test_public_key()) + .into_pending_connection_poll_outcome(), + RadrootsNostrConnectPendingConnectionPollOutcome::Approved(test_public_key()) + ); + + assert_eq!( + RadrootsNostrConnectResponse::Error { + result: Some(json!("partial")), + error: "rejected".to_owned(), + } + .into_pending_connection_poll_outcome(), + RadrootsNostrConnectPendingConnectionPollOutcome::Rejected { + message: "rejected".to_owned(), + } + ); + + assert_eq!( + RadrootsNostrConnectResponse::AuthUrl("https://auth.example.com/challenge".to_owned()) + .into_pending_connection_poll_outcome(), + RadrootsNostrConnectPendingConnectionPollOutcome::AuthChallenge { + url: "https://auth.example.com/challenge".to_owned(), + } + ); + + assert!(matches!( + RadrootsNostrConnectResponse::Pong.into_pending_connection_poll_outcome(), + RadrootsNostrConnectPendingConnectionPollOutcome::UnexpectedResponse { response } + if response == "Pong" + )); +}