From f7f8c140c32d42fc586127b6f21dffce9b9c00ca Mon Sep 17 00:00:00 2001 From: Dorian Date: Fri, 6 Mar 2026 01:28:29 +0000 Subject: [PATCH] fix(app): store NWC wallet secret in encrypted vault instead of plaintext localStorage Replace localStorage.getItem/setItem with storeApiKey/getApiKey/deleteApiKey from key-vault. Make loadConnection(), connect(), and disconnect() async. Co-Authored-By: Claude Opus 4.6 --- packages/app/src/composables/useNWC.ts | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/packages/app/src/composables/useNWC.ts b/packages/app/src/composables/useNWC.ts index 44e8f686..5009cda8 100644 --- a/packages/app/src/composables/useNWC.ts +++ b/packages/app/src/composables/useNWC.ts @@ -1,6 +1,7 @@ import { ref } from 'vue' +import { storeApiKey, getApiKey, deleteApiKey } from '@/utils/key-vault' -const STORAGE_KEY = 'aiui-nwc-connection' +const VAULT_PROVIDER = 'nwc' export interface NWCConnection { relayUrl: string @@ -12,9 +13,9 @@ const isConnected = ref(false) const balance = ref(null) const connectionString = ref(null) -function loadConnection(): NWCConnection | null { +async function loadConnection(): Promise { try { - const stored = localStorage.getItem(STORAGE_KEY) + const stored = await getApiKey(VAULT_PROVIDER) if (stored) { connectionString.value = stored isConnected.value = true @@ -39,25 +40,25 @@ function parseConnectionString(str: string): NWCConnection | null { } export function useNWC() { - function connect(nwcString: string): boolean { + async function connect(nwcString: string): Promise { const parsed = parseConnectionString(nwcString) if (!parsed) return false - localStorage.setItem(STORAGE_KEY, nwcString) + await storeApiKey(VAULT_PROVIDER, nwcString) connectionString.value = nwcString isConnected.value = true return true } - function disconnect() { - localStorage.removeItem(STORAGE_KEY) + async function disconnect() { + await deleteApiKey(VAULT_PROVIDER) connectionString.value = null isConnected.value = false balance.value = null } async function getBalance(): Promise { - const conn = loadConnection() + const conn = await loadConnection() if (!conn) return null // NIP-47: Send get_balance request via relay @@ -66,7 +67,7 @@ export function useNWC() { } async function payInvoice(bolt11: string): Promise<{ success: boolean; preimage?: string; error?: string }> { - const conn = loadConnection() + const conn = await loadConnection() if (!conn) return { success: false, error: 'Not connected' } // NIP-47: Send pay_invoice request via relay