commit c115963d95b5b239ce6ecd4511ee3f67ffb92708
parent c866c00b0fc3e591d9f32d176c606ba7b9e54fd3
Author: triesap <tyson@radroots.org>
Date: Fri, 31 Jul 2026 10:57:58 +0000
sdk: consume the opaque local Nostr signer
- Replace upstream keypair construction in local signer examples and tests.
- Derive local signer identity only through the canonical public-key accessor.
- Keep local and remote test key ownership separate and entirely in memory.
- Preserve configured signing, progress, trade, and runtime consumer coverage.
Diffstat:
4 files changed, 50 insertions(+), 25 deletions(-)
diff --git a/crates/sdk/examples/runtime_local.rs b/crates/sdk/examples/runtime_local.rs
@@ -7,7 +7,6 @@ use radroots_event::listing::operational::{
OperationalListingDeliveryMethod, OperationalListingProduct, OperationalListingPublicLocation,
OperationalListingStatus,
};
-use radroots_nostr::prelude::RadrootsNostrKeys;
use radroots_nostr::signing::LocalSigner;
use radroots_sdk::{
ListingPreparePublishRequest, NostrRelayUrlPolicy, PushOutboxRequest, RadrootsClient,
@@ -20,9 +19,9 @@ const RELAY: &str = "wss://relay.example.com";
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
- let keys = RadrootsNostrKeys::generate();
- let seller = keys.public_key().to_hex();
- let signer = RadrootsSdkLocalKeySigner::from_signer(LocalSigner::new(keys), seller.as_str())?;
+ let signer = LocalSigner::generate()?;
+ let seller = signer.public_key().to_hex();
+ let signer = RadrootsSdkLocalKeySigner::from_signer(signer, seller.as_str())?;
let sdk = RadrootsClient::builder()
.fixed_clock(RadrootsSdkTimestamp::from_unix_seconds(1_700_000_000))
.signer_provider(RadrootsSdkSignerProvider::LocalKey(signer))
diff --git a/crates/sdk/examples/sdk_v1_local_enqueue_and_mock_sync.rs b/crates/sdk/examples/sdk_v1_local_enqueue_and_mock_sync.rs
@@ -7,7 +7,6 @@ use radroots_event::listing::operational::{
OperationalListingDeliveryMethod, OperationalListingProduct, OperationalListingPublicLocation,
OperationalListingStatus,
};
-use radroots_nostr::prelude::RadrootsNostrKeys;
use radroots_nostr::signing::LocalSigner;
use radroots_sdk::{
ListingPreparePublishRequest, NostrRelayUrlPolicy, PushOutboxRequest, RadrootsClient,
@@ -21,9 +20,9 @@ const LOCAL_RELAY: &str = "ws://localhost:7777";
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
- let keys = RadrootsNostrKeys::generate();
- let seller = keys.public_key().to_hex();
- let signer = RadrootsSdkLocalKeySigner::from_signer(LocalSigner::new(keys), seller.as_str())?;
+ let signer = LocalSigner::generate()?;
+ let seller = signer.public_key().to_hex();
+ let signer = RadrootsSdkLocalKeySigner::from_signer(signer, seller.as_str())?;
let sdk = RadrootsClient::builder()
.fixed_clock(RadrootsSdkTimestamp::from_unix_seconds(1_700_000_000))
.signer_provider(RadrootsSdkSignerProvider::LocalKey(signer))
diff --git a/crates/sdk/tests/unit/signer_provider_tests.rs b/crates/sdk/tests/unit/signer_provider_tests.rs
@@ -20,6 +20,10 @@ use uuid::Uuid;
static USER_KEYS: LazyLock<RadrootsNostrKeys> = LazyLock::new(RadrootsNostrKeys::generate);
static USER_PUBLIC_KEY: LazyLock<String> = LazyLock::new(|| USER_KEYS.public_key().to_hex());
+static LOCAL_SIGNER: LazyLock<Arc<LocalSigner>> =
+ LazyLock::new(|| Arc::new(LocalSigner::generate().expect("generated local signer")));
+static LOCAL_SIGNER_PUBLIC_KEY: LazyLock<String> =
+ LazyLock::new(|| LOCAL_SIGNER.public_key().to_hex());
static REMOTE_KEYS: LazyLock<RadrootsNostrKeys> = LazyLock::new(RadrootsNostrKeys::generate);
static CLIENT_KEYS: LazyLock<RadrootsNostrKeys> = LazyLock::new(RadrootsNostrKeys::generate);
@@ -31,9 +35,13 @@ fn user_pubkey() -> &'static str {
USER_PUBLIC_KEY.as_str()
}
-fn local_sdk_signer(keys: RadrootsNostrKeys) -> RadrootsSdkLocalKeySigner {
- let signer_pubkey = keys.public_key().to_hex();
- RadrootsSdkLocalKeySigner::from_signer(LocalSigner::new(keys), signer_pubkey)
+fn local_signer_pubkey() -> &'static str {
+ LOCAL_SIGNER_PUBLIC_KEY.as_str()
+}
+
+fn local_sdk_signer() -> RadrootsSdkLocalKeySigner {
+ let signer: Arc<RadrootsSdkLocalSignerCapability> = LOCAL_SIGNER.clone();
+ RadrootsSdkLocalKeySigner::from_shared_signer(signer, LOCAL_SIGNER.public_key())
.expect("sdk local signer")
}
@@ -54,6 +62,15 @@ fn actor() -> Actor {
.expect("actor")
}
+fn local_actor() -> Actor {
+ Actor::from_public_key_hex(
+ local_signer_pubkey(),
+ ActorSource::ExplicitPublicKey,
+ [AuthorRole::Farmer],
+ )
+ .expect("local signer actor")
+}
+
fn frozen_draft() -> EventDraft {
frozen_draft_with(
"radroots.farm.profile.v1",
@@ -65,6 +82,17 @@ fn frozen_draft() -> EventDraft {
)
}
+fn local_frozen_draft() -> EventDraft {
+ frozen_draft_with(
+ "radroots.farm.profile.v1",
+ local_signer_pubkey(),
+ KIND_FARM,
+ 1_700_000_000,
+ vec![vec!["d".to_owned(), "sdk-local-signer".to_owned()]],
+ "{}",
+ )
+}
+
fn frozen_draft_with(
contract_id: &str,
pubkey: &str,
@@ -235,10 +263,10 @@ impl RadrootsSdkNip46Transport for HangingNip46Transport {
#[tokio::test]
async fn local_key_provider_signs_authorized_frozen_draft() {
- let signer = local_sdk_signer(user_keys());
+ let signer = local_sdk_signer();
let provider = RadrootsSdkSignerProvider::LocalKey(signer.clone());
- let draft = frozen_draft();
- let actor = actor();
+ let draft = local_frozen_draft();
+ let actor = local_actor();
let mut progress = Vec::new();
let receipt = provider
@@ -257,7 +285,7 @@ async fn local_key_provider_signs_authorized_frozen_draft() {
assert_eq!(provider.status(), signer.status());
assert!(provider.capability().nip46_permissions.is_empty());
assert_eq!(receipt.mode, RadrootsSdkSignerMode::LocalKey);
- assert_eq!(receipt.signer_pubkey, user_pubkey());
+ assert_eq!(receipt.signer_pubkey, local_signer_pubkey());
assert_eq!(receipt.signed_event_id, draft.expected_event_id_hex());
assert_eq!(
progress,
@@ -274,9 +302,9 @@ async fn local_key_provider_signs_authorized_frozen_draft() {
#[tokio::test]
async fn local_key_provider_returns_progress_sink_errors_without_transport_state() {
- let signer = local_sdk_signer(user_keys());
- let draft = frozen_draft();
- let actor = actor();
+ let signer = local_sdk_signer();
+ let draft = local_frozen_draft();
+ let actor = local_actor();
let wrong_actor = Actor::from_public_key_hex(
&"a".repeat(64),
ActorSource::ExplicitPublicKey,
@@ -1010,8 +1038,8 @@ async fn sdk_builder_installs_configured_signer_provider() {
.build()
.await
.expect("empty sdk");
- let draft = frozen_draft();
- let signer_actor = actor();
+ let draft = local_frozen_draft();
+ let signer_actor = local_actor();
let error = empty_sdk
.sign_with_configured_signer(RadrootsSdkSignRequest::new(
"farm.publish",
@@ -1026,7 +1054,7 @@ async fn sdk_builder_installs_configured_signer_provider() {
if mode == "configured" && reason.contains("no SDK signer provider")
));
- let signer = local_sdk_signer(user_keys());
+ let signer = local_sdk_signer();
let sdk = crate::RadrootsClient::builder()
.signer_provider(RadrootsSdkSignerProvider::LocalKey(signer))
.build()
diff --git a/crates/sdk/tests/unit/trade_runtime_tests.rs b/crates/sdk/tests/unit/trade_runtime_tests.rs
@@ -18,7 +18,6 @@ use radroots_event::{
},
};
use radroots_identity::PublicKey;
-use radroots_nostr::prelude::RadrootsNostrKeys;
use radroots_nostr::signing::LocalSigner;
use radroots_signing::{Actor, actor::ActorSource};
use radroots_trade::model::RadrootsTradePrivateTermsStateV1;
@@ -37,9 +36,9 @@ fn trade_id() -> TradeId {
}
fn local_signer() -> (String, LocalSigner) {
- let keys = RadrootsNostrKeys::generate();
- let pubkey = keys.public_key().to_hex();
- (pubkey, LocalSigner::new(keys))
+ let signer = LocalSigner::generate().expect("local signer");
+ let pubkey = signer.public_key().to_hex();
+ (pubkey, signer)
}
#[tokio::test]