refactor signer

This commit is contained in:
2026-07-23 11:14:56 +07:00
parent ab665cd661
commit bf6ae65b05
22 changed files with 291 additions and 567 deletions

View File

@@ -15,11 +15,13 @@ mod blossom;
mod constants;
mod nip05;
mod nip4e;
mod signer;
pub use blossom::*;
pub use constants::*;
pub use nip4e::*;
pub use nip05::*;
pub use signer::UniversalSigner;
pub fn init(window: &mut Window, cx: &mut App) {
// rustls uses the `aws_lc_rs` provider by default
@@ -44,6 +46,8 @@ impl Global for GlobalNostrRegistry {}
/// Signer event.
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub enum StateEvent {
/// The signer has changed
SignerChanged,
/// Connecting to the bootstrapping relay
Connecting,
/// Connected to the bootstrapping relay
@@ -59,6 +63,10 @@ impl StateEvent {
{
Self::Error(error.into())
}
pub fn signer_changed(&self) -> bool {
matches!(self, StateEvent::SignerChanged)
}
}
/// Nostr Registry
@@ -67,8 +75,11 @@ pub struct NostrRegistry {
/// Nostr client
client: Client,
/// Currently active signer
pub signer: Entity<Option<Keys>>,
/// Universal signer
signer: UniversalSigner,
/// Current user's public key
current_user: Option<PublicKey>,
/// Tasks for asynchronous operations
tasks: Vec<Task<Result<(), Error>>>,
@@ -89,7 +100,8 @@ impl NostrRegistry {
/// Create a new nostr instance
fn new(window: &mut Window, cx: &mut Context<Self>) -> Self {
let signer = cx.new(|_| None);
let signer = UniversalSigner::new(Keys::generate());
let authenticator = SignerAuthenticator::new(signer.clone());
// Construct the nostr lmdb instance
#[cfg(not(target_arch = "wasm32"))]
@@ -105,6 +117,7 @@ impl NostrRegistry {
// Construct the nostr client
let client = ClientBuilder::default()
.database(database)
.authenticator(authenticator)
.gossip(NostrGossipMemory::unbounded())
.gossip_config(GossipConfig::default().no_background_refresh())
.connect_timeout(Duration::from_secs(10))
@@ -121,6 +134,7 @@ impl NostrRegistry {
Self {
client,
signer,
current_user: None,
tasks: vec![],
}
}
@@ -130,22 +144,33 @@ impl NostrRegistry {
self.client.clone()
}
/// Get the signer
pub fn signer(&self, cx: &App) -> Option<Keys> {
self.signer.read(cx).clone()
/// Get the current signer
pub fn signer(&self) -> UniversalSigner {
self.signer.clone()
}
/// Get the public key of the signer
pub fn signer_pubkey(&self, cx: &App) -> Option<PublicKey> {
self.signer.read(cx).as_ref().map(|s| s.public_key())
/// Get the current user's public key
pub fn current_user(&self) -> Option<PublicKey> {
self.current_user
}
/// Set the signer to the given keys
pub fn set_signer(&mut self, new_keys: Keys, cx: &mut Context<Self>) {
self.signer.update(cx, |this, cx| {
*this = Some(new_keys);
cx.notify();
});
/// Update the signer
pub fn set_signer<T>(&mut self, new_signer: T, cx: &mut Context<Self>)
where
T: AsyncGetPublicKey + AsyncSignEvent + AsyncNip44 + 'static,
<T as AsyncGetPublicKey>::Error: std::error::Error + Send + Sync + 'static,
<T as AsyncSignEvent>::Error: std::error::Error + Send + Sync + 'static,
<T as AsyncNip44>::Error: std::error::Error + Send + Sync + 'static,
{
cx.spawn(async move |this, cx| {
let current_user = new_signer.get_public_key_async().await.ok();
this.update(cx, |this, cx| {
this.current_user = current_user;
cx.emit(StateEvent::SignerChanged);
})
.ok();
})
.detach();
}
/// Connect to the bootstrapping relays
@@ -299,10 +324,7 @@ impl NostrRegistry {
pub fn wot_search(&self, query: &str, cx: &App) -> Task<Result<Vec<PublicKey>, Error>> {
let client = self.client();
let query = query.to_string();
let Some(signer) = self.signer.read(cx).clone() else {
return Task::ready(Err(anyhow!("Signer is required")));
};
let signer = self.signer.clone();
cx.background_spawn(async move {
// Construct a vertex request event