sdk

Radroots SDK and bindings
git clone https://radroots.dev/git/sdk.git
Log | Files | Refs | README

commit c866c00b0fc3e591d9f32d176c606ba7b9e54fd3
parent c926ccad3662685142029431c48ef7b9b6013ed8
Author: triesap <tyson@radroots.org>
Date:   Fri, 31 Jul 2026 09:03:21 +0000

nostr: remove live relay-client dependencies

- Route SDK client adapters through radroots_transport_nostr.
- Replace portable-client features with transport-owned feature wiring.
- Normalize adapter tests against the owned transport error contract.
- Refresh lockfile and API-boundary expectations for the move.

Diffstat:
MCargo.lock | 35++++++++++++++++++++++++++++++++---
Mcontracts/releases/api_boundaries.toml | 57---------------------------------------------------------
Mcrates/sdk/Cargo.toml | 9+++++++--
Mcrates/sdk/src/adapters/nostr.rs | 17++++++++---------
Mcrates/sdk/src/sync_runtime.rs | 6+++---
Mcrates/sdk/tests/unit/adapters_nostr_tests.rs | 14++++++++------
Mtools/xtask/src/check.rs | 1-
7 files changed, 58 insertions(+), 81 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock @@ -1029,7 +1029,7 @@ dependencies = [ "futures-channel", "futures-io", "futures-util", - "idna", + "idna 1.1.0", "ipnet", "once_cell", "rand 0.9.4", @@ -1283,6 +1283,16 @@ checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954" [[package]] name = "idna" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" +dependencies = [ + "unicode-bidi", + "unicode-normalization", +] + +[[package]] +name = "idna" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de" @@ -1587,6 +1597,7 @@ dependencies = [ "serde_json", "unicode-normalization", "url", + "url-fork", ] [[package]] @@ -2125,7 +2136,6 @@ name = "radroots_nostr" version = "0.1.0-alpha" dependencies = [ "nostr", - "nostr-sdk", "radroots_event", "radroots_event_codec", "radroots_identity", @@ -2460,6 +2470,7 @@ version = "0.1.0-alpha" dependencies = [ "futures", "nostr", + "nostr-sdk", "radroots_event", "radroots_event_store", "radroots_nostr", @@ -3529,6 +3540,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2896d95c02a80c6d6a5d6e953d479f5ddf2dfdb6a244441010e373ac0fb88971" [[package]] +name = "unicode-bidi" +version = "0.3.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c1cb5db39152898a79168971543b1cb5020dff7fe43c8dc468b0885f5e29df5" + +[[package]] name = "unicode-general-category" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -3584,13 +3601,25 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ff67a8a4397373c3ef660812acab3268222035010ab8680ec4215f38ba3d0eed" dependencies = [ "form_urlencoded", - "idna", + "idna 1.1.0", "percent-encoding", "serde", "serde_derive", ] [[package]] +name = "url-fork" +version = "3.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fa3323c39b8e786154d3000b70ae9af0e9bd746c9791456da0d4a1f68ad89d6" +dependencies = [ + "form_urlencoded", + "idna 0.5.0", + "percent-encoding", + "serde", +] + +[[package]] name = "utf-8" version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" diff --git a/contracts/releases/api_boundaries.toml b/contracts/releases/api_boundaries.toml @@ -98,63 +98,6 @@ allowed_public_paths = [] name = "radroots" allowed_public_paths = [] [[exception]] -id = "RCRV1-API-003" -package = "radroots_nostr" -source = "src/client.rs" -forbidden_path = "nostr_sdk" -items = [ - "client::RadrootsNostrClient::from_inner", - "client::RadrootsNostrClient::into_inner", -] -observed_paths = ["nostr_sdk::Client"] -adr = "docs/decisions/0001-public-api-leakage-migration-baseline.md" -removal_step = 124 -rationale = "Legacy client ownership remains visible only until the Nostr package removes live relay-client dependencies." - -[[exception]] -id = "RCRV1-API-004" -package = "radroots_nostr" -source = "src/error.rs" -forbidden_path = "nostr_sdk" -items = ["error::RadrootsNostrError"] -observed_paths = [ - "nostr_sdk::client::Error", - "nostr_sdk::prelude::DatabaseError", -] -adr = "docs/decisions/0001-public-api-leakage-migration-baseline.md" -removal_step = 124 -rationale = "Legacy SDK error variants remain exact-scoped until normalized adapter errors replace them." - -[[exception]] -id = "RCRV1-API-005" -package = "radroots_nostr" -source = "src/types.rs" -forbidden_path = "nostr_sdk" -items = [ - "types::RadrootsNostrEventStream", - "types::RadrootsNostrMonitor", - "types::RadrootsNostrMonitorNotification", - "types::RadrootsNostrOutput", - "types::RadrootsNostrRelay", - "types::RadrootsNostrRelayPoolNotification", - "types::RadrootsNostrRelayStatus", - "types::RadrootsNostrSubscribeAutoCloseOptions", -] -observed_paths = [ - "nostr_sdk::Relay", - "nostr_sdk::RelayPoolNotification", - "nostr_sdk::RelayStatus", - "nostr_sdk::SubscribeAutoCloseOptions", - "nostr_sdk::pool::stream::BoxedStream", - "nostr_sdk::prelude::Monitor", - "nostr_sdk::prelude::MonitorNotification", - "nostr_sdk::prelude::Output", -] -adr = "docs/decisions/0001-public-api-leakage-migration-baseline.md" -removal_step = 124 -rationale = "Broad live-client aliases are frozen and must be removed with the Nostr client dependency at Step 124." - -[[exception]] id = "RCRV1-API-006" package = "radroots_nostr_connect" source = "src/client.rs" diff --git a/crates/sdk/Cargo.toml b/crates/sdk/Cargo.toml @@ -52,7 +52,13 @@ signing = [ "radroots_protocol/std", "radroots_signing/std", ] -transport-nostr-client = ["signing", "std", "serde_json", "radroots_nostr/client"] +transport-nostr-client = [ + "signing", + "std", + "serde_json", + "dep:radroots_transport_nostr", + "radroots_transport_nostr/client", +] radrootsd-execution = [ "std", "serde_json", @@ -112,7 +118,6 @@ local-signer = ["runtime", "signing", "radroots_nostr/signing"] transport-nostr-runtime = [ "runtime", "dep:radroots_nostr", - "radroots_nostr/client", "radroots_transport_nostr/client", ] local-runtime = [ diff --git a/crates/sdk/src/adapters/nostr.rs b/crates/sdk/src/adapters/nostr.rs @@ -1,17 +1,16 @@ use core::time::Duration; -use radroots_nostr::prelude::{ - RadrootsNostrClient, RadrootsNostrClientOptions, RadrootsNostrError, RadrootsNostrEvent, - RadrootsNostrEventId, RadrootsNostrKeys, RadrootsNostrOutput, +use radroots_nostr::prelude::{RadrootsNostrEvent, RadrootsNostrEventId, RadrootsNostrKeys}; +use radroots_transport_nostr::{ + RadrootsNostrClient, RadrootsNostrClientOptions, RadrootsNostrOutput, + RadrootsRelayTransportError, }; pub fn signerless_client() -> RadrootsNostrClient { RadrootsNostrClient::new_signerless() } -pub fn signerless_client_with_options( - options: RadrootsNostrClientOptions, -) -> Result<RadrootsNostrClient, RadrootsNostrError> { +pub fn signerless_client_with_options(options: RadrootsNostrClientOptions) -> RadrootsNostrClient { RadrootsNostrClient::new_signerless_with_options(options) } @@ -23,7 +22,7 @@ pub async fn configure_write_relays( client: &RadrootsNostrClient, relay_urls: &[String], connect_timeout: Duration, -) -> Result<(), RadrootsNostrError> { +) -> Result<(), RadrootsRelayTransportError> { for relay_url in relay_urls { client.add_write_relay(relay_url).await?; } @@ -36,7 +35,7 @@ pub async fn connected_client_from_keys( keys: RadrootsNostrKeys, relay_urls: &[String], connect_timeout: Duration, -) -> Result<RadrootsNostrClient, RadrootsNostrError> { +) -> Result<RadrootsNostrClient, RadrootsRelayTransportError> { let client = client_from_keys(keys); configure_write_relays(&client, relay_urls, connect_timeout).await?; Ok(client) @@ -57,7 +56,7 @@ pub async fn connected_relay_urls(client: &RadrootsNostrClient) -> Vec<String> { pub async fn publish_signed_event( client: &RadrootsNostrClient, event: &RadrootsNostrEvent, -) -> Result<RadrootsNostrOutput<RadrootsNostrEventId>, RadrootsNostrError> { +) -> Result<RadrootsNostrOutput<RadrootsNostrEventId>, RadrootsRelayTransportError> { client.send_event(event).await } diff --git a/crates/sdk/src/sync_runtime.rs b/crates/sdk/src/sync_runtime.rs @@ -15,8 +15,6 @@ use crate::{RadrootsdExecutionAuth, RadrootsdExecutionProfile}; use radroots_event::id::EventId; #[cfg(feature = "runtime")] use radroots_event_store::{RADROOTS_EVENT_STORE_QUERY_LIMIT_MAX, RadrootsEventStoreStatusSummary}; -#[cfg(all(feature = "runtime", feature = "transport-nostr-runtime"))] -use radroots_nostr::prelude::RadrootsNostrClient; #[cfg(all(feature = "runtime", feature = "radrootsd-execution"))] use radroots_outbox::RadrootsOutboxClaimedEvent; #[cfg(feature = "runtime")] @@ -44,7 +42,9 @@ use radroots_transport::{ #[cfg(all(feature = "runtime", feature = "radrootsd-execution"))] use radroots_transport::{RadrootsTransportSatisfactionClass, RadrootsTransportSatisfactionPolicy}; #[cfg(all(feature = "runtime", feature = "transport-nostr-runtime"))] -use radroots_transport_nostr::{RadrootsNostrClientPublishAdapter, RadrootsNostrTransport}; +use radroots_transport_nostr::{ + RadrootsNostrClient, RadrootsNostrClientPublishAdapter, RadrootsNostrTransport, +}; #[cfg(feature = "runtime")] use radroots_transport_nostr::{ RadrootsOutboxPublishPolicy, RadrootsOutboxPublishReceipt, RadrootsOutboxPublishTargetReceipt, diff --git a/crates/sdk/tests/unit/adapters_nostr_tests.rs b/crates/sdk/tests/unit/adapters_nostr_tests.rs @@ -4,7 +4,7 @@ use super::{ }; use core::time::Duration; use nostr::{EventBuilder, Keys, Kind}; -use radroots_nostr::prelude::RadrootsNostrClientOptions; +use radroots_transport_nostr::{RadrootsNostrClientOptions, RadrootsRelayTransportError}; use tokio::runtime::Runtime; #[test] @@ -13,8 +13,7 @@ fn client_constructors_build_without_runtime_net() { let _client = client_from_keys(keys); let _signerless = signerless_client(); let _signerless_with_options = - signerless_client_with_options(RadrootsNostrClientOptions::new()) - .expect("signerless client with options"); + signerless_client_with_options(RadrootsNostrClientOptions::new()); } #[test] @@ -42,7 +41,7 @@ fn relay_helpers_accept_empty_relay_sets_without_network_endpoints() { let error = configure_write_relays(&client, &invalid_relays, Duration::from_millis(1)) .await .expect_err("invalid relay"); - assert!(format!("{error:?}").contains("Url")); + assert!(matches!(error, RadrootsRelayTransportError::Client(_))); let connected_error = match connected_client_from_keys( keys.clone(), &invalid_relays, @@ -53,7 +52,10 @@ fn relay_helpers_accept_empty_relay_sets_without_network_endpoints() { Ok(_) => panic!("expected invalid connected relay"), Err(error) => error, }; - assert!(format!("{connected_error:?}").contains("Url")); + assert!(matches!( + connected_error, + RadrootsRelayTransportError::Client(_) + )); let disconnected = client_from_keys(keys.clone()); disconnected @@ -78,6 +80,6 @@ fn relay_helpers_accept_empty_relay_sets_without_network_endpoints() { let error = publish_signed_event(&connected, &signed) .await .expect_err("publish without relays"); - assert!(format!("{error:?}").contains("NoRelaysSpecified")); + assert!(matches!(error, RadrootsRelayTransportError::Client(_))); }); } diff --git a/tools/xtask/src/check.rs b/tools/xtask/src/check.rs @@ -564,7 +564,6 @@ fn check_sdk_feature_matrix(root: &Path) -> Result<(), String> { for entry in [ "runtime", "dep:radroots_nostr", - "radroots_nostr/client", "radroots_transport_nostr/client", ] { require_feature_entry(&nostr_runtime, "transport-nostr-runtime", entry)?;