diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index 0d270c49..3d9ece47 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -8,12 +8,14 @@ pub mod nostr; use nostr_sdk::{Client, ClientBuilder}; use nostr_sqlite::SQLiteDatabase; +use std::sync::Arc; use tauri::Manager; use tauri_plugin_autostart::MacosLauncher; use tauri_plugin_theme::ThemePlugin; -use tokio::sync::Mutex; -struct NostrClient(Mutex); +pub struct AppState { + pub nostr: Arc, +} fn main() { let mut ctx = tauri::generate_context!(); @@ -24,12 +26,12 @@ fn main() { tauri::async_runtime::spawn(async move { // Create database connection - let database = SQLiteDatabase::open(config_dir.join("nostr.db")) + let nostr_db = SQLiteDatabase::open(config_dir.join("nostr.db")) .await .expect("Open database failed."); // Create nostr connection - let client = ClientBuilder::default().database(database).build(); + let client = ClientBuilder::default().database(nostr_db).build(); // Add bootstrap relay client @@ -47,7 +49,9 @@ fn main() { client.connect().await; // Init global state - handle.manage(NostrClient(client.into())) + handle.manage(AppState { + nostr: client.into(), + }) }); Ok(()) @@ -71,6 +75,9 @@ fn main() { .invoke_handler(tauri::generate_handler![ nostr::keys::create_keys, nostr::keys::get_public_key, + nostr::keys::update_signer, + nostr::metadata::get_metadata, + nostr::event::get_event, commands::secret::secure_save, commands::secret::secure_load, commands::secret::secure_remove, diff --git a/src-tauri/src/nostr.rs b/src-tauri/src/nostr.rs index 703bc087..35697966 100644 --- a/src-tauri/src/nostr.rs +++ b/src-tauri/src/nostr.rs @@ -1 +1,3 @@ +pub mod event; pub mod keys; +pub mod metadata; diff --git a/src-tauri/src/nostr/event.rs b/src-tauri/src/nostr/event.rs new file mode 100644 index 00000000..0a3bc97a --- /dev/null +++ b/src-tauri/src/nostr/event.rs @@ -0,0 +1,20 @@ +use crate::AppState; +use nostr_sdk::prelude::*; +use std::time::Duration; +use tauri::State; + +#[tauri::command(async)] +pub async fn get_event(id: String, app_state: State<'_, AppState>) -> Result { + let client = &app_state.nostr; + + let event_id = EventId::from_bech32(id).unwrap(); + let filter = Filter::new().id(event_id); + + let events = client + .get_events_of(vec![filter], Some(Duration::from_secs(10))) + .await + .expect("Get metadata failed"); + let event = events.into_iter().nth(0).unwrap().as_json(); + + Ok(event) +} diff --git a/src-tauri/src/nostr/keys.rs b/src-tauri/src/nostr/keys.rs index d5af2054..06fd3098 100644 --- a/src-tauri/src/nostr/keys.rs +++ b/src-tauri/src/nostr/keys.rs @@ -1,6 +1,9 @@ +use crate::AppState; use nostr::nips::nip19::ToBech32; use nostr::secp256k1::SecretKey; -use nostr::{Keys, Result}; +use nostr::{FromBech32, Keys, Result}; +use nostr_sdk::ClientSigner; +use tauri::State; #[derive(serde::Serialize)] pub struct CreateKeysResponse { @@ -27,3 +30,15 @@ pub fn get_public_key(secret_key: SecretKey) -> Result { let keys = Keys::new(secret_key); Ok(keys.public_key().to_bech32().expect("secret key failed")) } + +#[tauri::command] +pub async fn update_signer(key: String, app_state: State<'_, AppState>) -> Result<(), ()> { + let client = &app_state.nostr; + let secret_key = SecretKey::from_bech32(key).unwrap(); + let keys = Keys::new(secret_key); + let signer = ClientSigner::Keys(keys); + + client.set_signer(Some(signer)).await; + + Ok(()) +} diff --git a/src-tauri/src/nostr/metadata.rs b/src-tauri/src/nostr/metadata.rs new file mode 100644 index 00000000..e0dd50ae --- /dev/null +++ b/src-tauri/src/nostr/metadata.rs @@ -0,0 +1,26 @@ +use crate::AppState; +use nostr_sdk::prelude::*; +use std::time::Duration; +use tauri::State; + +#[tauri::command(async)] +pub async fn get_metadata(npub: String, app_state: State<'_, AppState>) -> Result { + let client = &app_state.nostr; + + let public_key = XOnlyPublicKey::from_bech32(npub).unwrap(); + + let filter = Filter::new() + .author(public_key) + .kind(Kind::Metadata) + .limit(1); + + let events = client + .get_events_of(vec![filter], Some(Duration::from_secs(10))) + .await + .expect("Get metadata failed"); + + let event = events.into_iter().nth(0).unwrap(); + let metadata: Metadata = Metadata::from_json(&event.content).unwrap(); + + Ok(metadata) +}