diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 8e0b0261..2c408397 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -2859,6 +2859,7 @@ dependencies = [ "native_db", "native_model", "nostr-sdk", + "once_cell", "serde", "serde_json", "tauri", diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 19c1bd40..d3c2c589 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -11,7 +11,7 @@ rust-version = "1.70" tauri-build = { version = "2.0.0-beta", features = [] } [dependencies] -nostr-sdk = { version = "0.27", features = ["sqlite"] } +nostr-sdk = { version = "0.27", features = ["sqlite"] } tokio = { version = "1", features = ["full"] } serde_json = "1.0" serde = { version = "1.0", features = ["derive"] } @@ -40,6 +40,7 @@ webpage = { version = "2.0", features = ["serde"] } keyring = "2" native_db = "0.5.3" native_model = "0.4.6" +once_cell = "1.19.0" [features] # by default Tauri runs in production mode diff --git a/src-tauri/bin/.keep b/src-tauri/bin/.keep deleted file mode 100644 index e69de29b..00000000 diff --git a/src-tauri/migrations/20230418013219_initial_data.sql b/src-tauri/migrations/20230418013219_initial_data.sql deleted file mode 100644 index 09916b7c..00000000 --- a/src-tauri/migrations/20230418013219_initial_data.sql +++ /dev/null @@ -1,59 +0,0 @@ --- create accounts table -CREATE TABLE - accounts ( - id INTEGER NOT NULL PRIMARY KEY, - pubkey TEXT NOT NULL UNIQUE, - is_active INTEGER NOT NULL DEFAULT 0, - created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP - ); - --- create ndk cache users table -CREATE TABLE - ndk_users ( - pubkey TEXT NOT NULL PRIMARY KEY, - profile TEXT, - createdAt NUMBER - ); - --- create ndk cache events table -CREATE TABLE - ndk_events ( - id TEXT NOT NULL PRIMARY KEY, - pubkey TEXT, - content TEXT, - kind NUMBER, - createdAt NUMBER, - relay TEXT, - event TEXT - ); - --- create ndk cache eventtags table -CREATE TABLE - ndk_eventtags ( - id TEXT NOT NULL PRIMARY KEY, - eventId TEXT, - tag TEXT, - value TEXT, - tagValue TEXT - ); - --- create settings table -CREATE TABLE - settings ( - id INTEGER NOT NULL PRIMARY KEY, - key TEXT NOT NULL, - value TEXT NOT NULL, - created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP - ); - --- create columns table -CREATE TABLE - columns ( - id INTEGER NOT NULL PRIMARY KEY, - account_id INTEGER NOT NULL, - kind INTEGER NOT NULL, - title TEXT NOT NULL, - content TEXT NOT NULL, - created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, - FOREIGN KEY (account_id) REFERENCES accounts (id) - ); diff --git a/src-tauri/src/db.rs b/src-tauri/src/db.rs new file mode 100644 index 00000000..c52cf816 --- /dev/null +++ b/src-tauri/src/db.rs @@ -0,0 +1,29 @@ +use once_cell::sync::Lazy; + +pub(crate) mod api { + use native_db::{native_db, InnerKeyValue}; + use native_model::{native_model, Model}; + use serde::{Deserialize, Serialize}; + + pub mod v1 { + use super::*; + + #[derive(Serialize, Deserialize, Debug)] + #[native_model(id = 1, version = 2)] + #[native_db] + pub struct Account { + #[primary_key] + pub pubkey: String, + #[secondary_key] + status: String, + } + } +} + +pub static DATABASE_BUILDER: Lazy = Lazy::new(|| { + let mut builder = native_db::DatabaseBuilder::new(); + builder + .define::() + .expect("failed to define model Account v1"); + builder +}); diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index d5e212b9..d7b513e9 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -4,15 +4,20 @@ )] pub mod commands; +pub mod db; pub mod nostr; +use crate::db::api::v1::AccountKey; +use crate::db::DATABASE_BUILDER; +use db::api::v1::Account; +use keyring::Entry; use nostr_sdk::prelude::*; use std::sync::Arc; use tauri::Manager; use tauri_plugin_autostart::MacosLauncher; -pub struct AppState { - pub nostr: Arc, +pub struct Nostr { + pub client: Arc, } fn main() { @@ -21,6 +26,16 @@ fn main() { .setup(|app| { let handle = app.handle().clone(); let config_dir = app.path().app_config_dir().unwrap(); + let db = DATABASE_BUILDER + .create(config_dir.join("app.db")) + .expect("failed to create app database"); + + // run db migrate + let rw = db + .rw_transaction() + .expect("failed to create rw migration transaction"); + rw.migrate::().expect("failed to migrate Account"); + rw.commit().expect("failed to commit migration"); tauri::async_runtime::spawn(async move { // Create database connection @@ -31,8 +46,30 @@ fn main() { // Create nostr connection let client = ClientBuilder::default().database(nostr_db).build(); + // get stored account + let r = db.r_transaction().expect("failed to create ro transaction"); + let accounts: Vec = r + .scan() + .secondary(AccountKey::status) + .expect("failed to scan accounts") + .start_with("active") + .collect(); + + if let Some(account) = accounts.into_iter().nth(0) { + let entry = Entry::new("Lume", &account.pubkey).expect("failed to load secret"); + + if let Ok(key) = entry.get_password() { + let secret_key = SecretKey::from_bech32(key).unwrap(); + let keys = Keys::new(secret_key); + let signer = ClientSigner::Keys(keys); + + // update client's signer + client.set_signer(Some(signer)).await; + } + } + // Add some bootstrap relays - // #TODO: Add option to user config bootstrap relay + // #TODO: Pull bootstrap relays from user's settings client .add_relay("wss://nostr.mutinywallet.com") .await @@ -46,8 +83,8 @@ fn main() { client.connect().await; // Init global state - handle.manage(AppState { - nostr: client.into(), + handle.manage(Nostr { + client: client.into(), }) }); diff --git a/src-tauri/src/nostr/event.rs b/src-tauri/src/nostr/event.rs index 0a3bc97a..1c433007 100644 --- a/src-tauri/src/nostr/event.rs +++ b/src-tauri/src/nostr/event.rs @@ -1,11 +1,11 @@ -use crate::AppState; +use crate::Nostr; 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; +pub async fn get_event(id: String, nostr: State<'_, Nostr>) -> Result { + let client = &nostr.client; let event_id = EventId::from_bech32(id).unwrap(); let filter = Filter::new().id(event_id); diff --git a/src-tauri/src/nostr/keys.rs b/src-tauri/src/nostr/keys.rs index 6c9374d1..4578d647 100644 --- a/src-tauri/src/nostr/keys.rs +++ b/src-tauri/src/nostr/keys.rs @@ -1,4 +1,4 @@ -use crate::AppState; +use crate::Nostr; use nostr_sdk::prelude::*; use tauri::State; @@ -29,8 +29,8 @@ pub fn get_public_key(secret_key: SecretKey) -> Result { } #[tauri::command] -pub async fn update_signer(key: String, app_state: State<'_, AppState>) -> Result<(), ()> { - let client = &app_state.nostr; +pub async fn update_signer(key: String, nostr: State<'_, Nostr>) -> Result<(), ()> { + let client = &nostr.client; let secret_key = SecretKey::from_bech32(key).unwrap(); let keys = Keys::new(secret_key); let signer = ClientSigner::Keys(keys); @@ -41,8 +41,8 @@ pub async fn update_signer(key: String, app_state: State<'_, AppState>) -> Resul } #[tauri::command] -pub async fn verify_signer(app_state: State<'_, AppState>) -> Result { - let client = &app_state.nostr; +pub async fn verify_signer(nostr: State<'_, Nostr>) -> Result { + let client = &nostr.client; let status = client.signer().await.is_ok(); Ok(status) diff --git a/src-tauri/src/nostr/metadata.rs b/src-tauri/src/nostr/metadata.rs index e0dd50ae..d7adfb7f 100644 --- a/src-tauri/src/nostr/metadata.rs +++ b/src-tauri/src/nostr/metadata.rs @@ -1,11 +1,11 @@ -use crate::AppState; +use crate::Nostr; 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; +pub async fn get_metadata(npub: String, nostr: State<'_, Nostr>) -> Result { + let client = &nostr.client; let public_key = XOnlyPublicKey::from_bech32(npub).unwrap();