From d5b1593aca910c3fd900165688819d6bbb0e8102 Mon Sep 17 00:00:00 2001 From: reya <123083837+reyamir@users.noreply.github.com> Date: Fri, 31 May 2024 08:54:17 +0700 Subject: [PATCH] feat: improve nostr connect flow --- packages/system/src/account.ts | 20 +++++++++++++++++--- packages/system/src/commands.ts | 4 ++-- src-tauri/src/nostr/keys.rs | 32 ++++++++++++++++++++++++++++---- 3 files changed, 47 insertions(+), 9 deletions(-) diff --git a/packages/system/src/account.ts b/packages/system/src/account.ts index a72516db..537639c5 100644 --- a/packages/system/src/account.ts +++ b/packages/system/src/account.ts @@ -1,5 +1,5 @@ import { Metadata } from "@lume/types"; -import { commands } from "./commands"; +import { Result, commands } from "./commands"; export class NostrAccount { static async getAccounts() { @@ -13,7 +13,14 @@ export class NostrAccount { } static async loadAccount(npub: string) { - const query = await commands.loadAccount(npub); + const bunker: string = localStorage.getItem(`${npub}_bunker`); + let query: Result; + + if (bunker?.length && bunker?.startsWith("bunker://")) { + query = await commands.loadAccount(npub, bunker); + } else { + query = await commands.loadAccount(npub, null); + } if (query.status === "ok") { return query.data; @@ -65,7 +72,14 @@ export class NostrAccount { const connect = await commands.connectRemoteAccount(uri); if (connect.status === "ok") { - return connect.data; + const npub = connect.data; + const parsed = new URL(uri); + parsed.searchParams.delete("secret"); + + // save connection string + localStorage.setItem(`${npub}_bunker`, parsed.toString()); + + return npub; } else { throw new Error(connect.error); } diff --git a/packages/system/src/commands.ts b/packages/system/src/commands.ts index 659862da..1a2dd3bd 100644 --- a/packages/system/src/commands.ts +++ b/packages/system/src/commands.ts @@ -65,9 +65,9 @@ try { else return { status: "error", error: e as any }; } }, -async loadAccount(npub: string) : Promise> { +async loadAccount(npub: string, bunker: string | null) : Promise> { try { - return { status: "ok", data: await TAURI_INVOKE("load_account", { npub }) }; + return { status: "ok", data: await TAURI_INVOKE("load_account", { npub, bunker }) }; } catch (e) { if(e instanceof Error) throw e; else return { status: "error", error: e as any }; diff --git a/src-tauri/src/nostr/keys.rs b/src-tauri/src/nostr/keys.rs index ac616c21..3f74af2c 100644 --- a/src-tauri/src/nostr/keys.rs +++ b/src-tauri/src/nostr/keys.rs @@ -102,6 +102,7 @@ pub async fn save_account( #[specta::specta] pub async fn load_account( npub: &str, + bunker: Option<&str>, state: State<'_, Nostr>, app: tauri::AppHandle, ) -> Result { @@ -109,11 +110,28 @@ pub async fn load_account( let keyring = Entry::new(npub, "nostr_secret").unwrap(); if let Ok(password) = keyring.get_password() { - let keys = Keys::parse(password).expect("Secret Key is modified, please check again."); - let signer = NostrSigner::Keys(keys); + match bunker { + Some(uri) => { + let app_keys = Keys::parse(password).expect("Secret Key is modified, please check again."); - // Update signer - client.set_signer(Some(signer)).await; + match NostrConnectURI::parse(uri) { + Ok(bunker_uri) => { + match Nip46Signer::new(bunker_uri, app_keys, Duration::from_secs(30), None).await { + Ok(signer) => client.set_signer(Some(signer.into())).await, + Err(err) => return Err(err.to_string()), + } + } + Err(err) => return Err(err.to_string()), + } + } + None => { + let keys = Keys::parse(password).expect("Secret Key is modified, please check again."); + let signer = NostrSigner::Keys(keys); + + // Update signer + client.set_signer(Some(signer)).await; + } + } // Verify signer let signer = client.signer().await.unwrap(); @@ -207,6 +225,7 @@ pub async fn connect_remote_account(uri: &str, state: State<'_, Nostr>) -> Resul match NostrConnectURI::parse(uri) { Ok(bunker_uri) => { let app_keys = Keys::generate(); + let app_secret = app_keys.secret_key().unwrap().to_string(); // Get remote user let remote_user = bunker_uri.signer_public_key().unwrap(); @@ -214,7 +233,12 @@ pub async fn connect_remote_account(uri: &str, state: State<'_, Nostr>) -> Resul match Nip46Signer::new(bunker_uri, app_keys, Duration::from_secs(120), None).await { Ok(signer) => { + let keyring = Entry::new(&remote_npub, "nostr_secret").unwrap(); + let _ = keyring.set_password(&app_secret); + + // Update signer let _ = client.set_signer(Some(signer.into())).await; + Ok(remote_npub.into()) } Err(err) => Err(err.to_string()),