feat: update rust nostr

This commit is contained in:
2024-02-06 19:28:46 +07:00
parent a4069dae99
commit 3c4bd39384
22 changed files with 721 additions and 1114 deletions

View File

@@ -13,11 +13,13 @@ use db::api::v1::Account;
use keyring::Entry;
use nostr_sdk::prelude::*;
use std::sync::Arc;
use std::time::Duration;
use tauri::Manager;
use tauri_plugin_autostart::MacosLauncher;
pub struct Nostr {
pub client: Arc<Client>,
pub contact_list: Option<Vec<Contact>>,
}
fn main() {
@@ -28,7 +30,7 @@ fn main() {
let config_dir = handle.path().app_config_dir().unwrap();
tauri::async_runtime::spawn(async move {
// Create database connection
// Create nostr database connection
let nostr_db = SQLiteDatabase::open(config_dir.join("nostr.db"))
.await
.expect("Open database failed.");
@@ -36,40 +38,18 @@ fn main() {
// Create nostr connection
let client = ClientBuilder::default().database(nostr_db).build();
// create app database connection
// Create app database connection
let db = DATABASE_BUILDER
.create(config_dir.join("app.db"))
.expect("failed to create app database");
// run db migrate
// Run migration for app database
let rw = db
.rw_transaction()
.expect("failed to create rw migration transaction");
rw.migrate::<Account>().expect("failed to migrate Account");
rw.commit().expect("failed to commit migration");
// get stored account
let r = db.r_transaction().expect("failed to create ro transaction");
let accounts: Vec<Account> = 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: Pull bootstrap relays from user's settings
client
@@ -84,9 +64,43 @@ fn main() {
// Connect
client.connect().await;
// Get stored account
let r = db.r_transaction().expect("failed to create ro transaction");
let accounts: Vec<Account> = r
.scan()
.secondary(AccountKey::status)
.expect("failed to scan accounts")
.start_with("active")
.collect();
let mut contact_list = None;
// Run somethings if account existed
if let Some(account) = accounts.into_iter().nth(0) {
// Add signer with stored private key
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;
// Get contact list
contact_list = Some(
client
.get_contact_list(Some(Duration::from_secs(10)))
.await
.unwrap(),
);
}
}
// Init global state
handle.manage(Nostr {
client: client.into(),
contact_list: contact_list.into(),
})
});
@@ -113,6 +127,8 @@ fn main() {
nostr::keys::get_public_key,
nostr::keys::update_signer,
nostr::keys::verify_signer,
nostr::keys::event_to_bech32,
nostr::keys::user_to_bech32,
nostr::metadata::get_metadata,
nostr::event::get_event,
commands::secret::secure_save,

View File

@@ -4,17 +4,26 @@ use std::time::Duration;
use tauri::State;
#[tauri::command(async)]
pub async fn get_event(id: String, nostr: State<'_, Nostr>) -> Result<String, ()> {
pub async fn get_event(id: &str, nostr: State<'_, Nostr>) -> Result<String, ()> {
let client = &nostr.client;
let event_id;
if id.starts_with("note1") {
event_id = EventId::from_bech32(id).unwrap();
} else if id.starts_with("nevent1") {
event_id = EventId::from_bech32(id).unwrap();
} else if id.starts_with("naddr1") {
event_id = EventId::from_bech32(id).unwrap();
} else {
event_id = EventId::from_hex(id).unwrap();
}
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();
.expect("Get event failed");
let event = events.first().unwrap().as_json();
Ok(event)
}

View File

@@ -1,5 +1,6 @@
use crate::Nostr;
use nostr_sdk::prelude::*;
use std::str::FromStr;
use tauri::State;
#[derive(serde::Serialize)]
@@ -23,15 +24,16 @@ pub fn create_keys() -> Result<CreateKeysResponse, ()> {
}
#[tauri::command]
pub fn get_public_key(secret_key: SecretKey) -> Result<String, ()> {
pub fn get_public_key(nsec: String) -> Result<String, ()> {
let secret_key = SecretKey::from_bech32(nsec).unwrap();
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, nostr: State<'_, Nostr>) -> Result<(), ()> {
pub async fn update_signer(nsec: String, nostr: State<'_, Nostr>) -> Result<(), ()> {
let client = &nostr.client;
let secret_key = SecretKey::from_bech32(key).unwrap();
let secret_key = SecretKey::from_bech32(nsec).unwrap();
let keys = Keys::new(secret_key);
let signer = ClientSigner::Keys(keys);
@@ -47,3 +49,19 @@ pub async fn verify_signer(nostr: State<'_, Nostr>) -> Result<bool, ()> {
Ok(status)
}
#[tauri::command]
pub fn event_to_bech32(id: &str, relays: Vec<String>) -> Result<String, ()> {
let event_id = EventId::from_hex(id).unwrap();
let event = Nip19Event::new(event_id, relays);
Ok(event.to_bech32().unwrap())
}
#[tauri::command]
pub fn user_to_bech32(key: &str, relays: Vec<String>) -> Result<String, ()> {
let pubkey = XOnlyPublicKey::from_str(key).unwrap();
let profile = Nip19Profile::new(pubkey, relays);
Ok(profile.to_bech32().unwrap())
}

View File

@@ -1,13 +1,20 @@
use crate::Nostr;
use nostr_sdk::prelude::*;
use std::time::Duration;
use std::{str::FromStr, time::Duration};
use tauri::State;
#[tauri::command(async)]
pub async fn get_metadata(npub: String, nostr: State<'_, Nostr>) -> Result<Metadata, ()> {
pub async fn get_metadata(id: &str, nostr: State<'_, Nostr>) -> Result<Metadata, ()> {
let client = &nostr.client;
let public_key;
let public_key = XOnlyPublicKey::from_bech32(npub).unwrap();
if id.starts_with("nprofile1") {
public_key = XOnlyPublicKey::from_bech32(id).unwrap();
} else if id.starts_with("npub1") {
public_key = XOnlyPublicKey::from_bech32(id).unwrap();
} else {
public_key = XOnlyPublicKey::from_str(id).unwrap();
}
let filter = Filter::new()
.author(public_key)
@@ -19,7 +26,7 @@ pub async fn get_metadata(npub: String, nostr: State<'_, Nostr>) -> Result<Metad
.await
.expect("Get metadata failed");
let event = events.into_iter().nth(0).unwrap();
let event = events.first().unwrap();
let metadata: Metadata = Metadata::from_json(&event.content).unwrap();
Ok(metadata)