diff --git a/package-lock.json b/package-lock.json index ce47b26..3fdff94 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,7 +8,7 @@ "name": "wasm-example-app", "version": "0.1.0", "dependencies": { - "@breeztech/breez-sdk-spark": "^0.11.0-dev3", + "@breeztech/breez-sdk-spark": "^0.11.0-dev4", "@headlessui/react": "^1.7.17", "@zxing/browser": "^0.1.5", "@zxing/library": "^0.21.3", @@ -407,9 +407,9 @@ } }, "node_modules/@breeztech/breez-sdk-spark": { - "version": "0.11.0-dev3", - "resolved": "https://registry.npmjs.org/@breeztech/breez-sdk-spark/-/breez-sdk-spark-0.11.0-dev3.tgz", - "integrity": "sha512-Caoyz2EBmipuCgg+sNSLGyPwtnbDzeEnBqMD8+tk3n0hsp90ttYr66jGcnkJsbXjGjhlO7QB0UK5PvW5bp7RvQ==", + "version": "0.11.0-dev4", + "resolved": "https://registry.npmjs.org/@breeztech/breez-sdk-spark/-/breez-sdk-spark-0.11.0-dev4.tgz", + "integrity": "sha512-NoE5n2whvUh5S/H9huk99amFwvRxYB6ge8rCZBXEWJiDJ24h1NeGt8uRDBeYzjE1f76wuYngSBSeoL7DGBW0kQ==", "license": "MIT", "engines": { "node": ">=22" diff --git a/package.json b/package.json index 197226a..682c9e9 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,7 @@ "test:e2e:debug": "playwright test --debug" }, "dependencies": { - "@breeztech/breez-sdk-spark": "^0.11.0-dev3", + "@breeztech/breez-sdk-spark": "^0.11.0-dev4", "@headlessui/react": "^1.7.17", "@zxing/browser": "^0.1.5", "@zxing/library": "^0.21.3", diff --git a/src/App.tsx b/src/App.tsx index c670a47..648bb79 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -45,8 +45,8 @@ const AppContent: React.FC = () => { }; // Navigate to wallet after passkey connect - const handlePasskeyConnect = async (seed: Seed, walletName: string) => { - await sdk.connectWallet(seed, true, walletName); + const handlePasskeyConnect = async (seed: Seed, label: string) => { + await sdk.connectWallet(seed, true, label); setCurrentScreen('wallet'); }; diff --git a/src/hooks/useBreezSdk.ts b/src/hooks/useBreezSdk.ts index 5959c3d..e36639b 100644 --- a/src/hooks/useBreezSdk.ts +++ b/src/hooks/useBreezSdk.ts @@ -70,7 +70,7 @@ export interface BreezSdkState { } export interface BreezSdkActions { - connectWallet: (seed: Seed, restore: boolean, passkeyWalletName?: string) => Promise; + connectWallet: (seed: Seed, restore: boolean, passkeyLabel?: string) => Promise; refreshWalletData: (showLoading?: boolean) => Promise; fetchUnclaimedDeposits: () => Promise; handleLogout: () => Promise; @@ -212,7 +212,7 @@ export function useBreezSdk( // Connection lifecycle // ---------------------------------------- - const connectWallet = useCallback(async (seed: Seed, restore: boolean, passkeyWalletName?: string) => { + const connectWallet = useCallback(async (seed: Seed, restore: boolean, passkeyLabel?: string) => { let connectedSdk: BreezSdk | undefined; try { logger.info(LogCategory.SDK, 'Initiating wallet connection', { restore }); @@ -247,8 +247,8 @@ export function useBreezSdk( logger.authSuccess(seed.type); logger.info(LogCategory.SDK, 'Wallet connected successfully'); - if (passkeyWalletName != null) { - setPasskeyMode(passkeyWalletName); + if (passkeyLabel != null) { + setPasskeyMode(passkeyLabel); } else if (seed.type === 'mnemonic') { saveMnemonic(seed.mnemonic); } @@ -376,7 +376,7 @@ export function useBreezSdk( try { setIsLoading(true); const wallet = await getWallet(); - await connectWallet(wallet.seed, false, wallet.name); + await connectWallet(wallet.seed, false, wallet.label); } catch (e) { logger.error(LogCategory.SDK, 'Failed to reconnect with passkey', { error: formatError(e) }); setError('Failed to authenticate with passkey. Please try again.'); diff --git a/src/pages/PasskeyPage.tsx b/src/pages/PasskeyPage.tsx index 217f03a..522a7f6 100644 --- a/src/pages/PasskeyPage.tsx +++ b/src/pages/PasskeyPage.tsx @@ -5,11 +5,11 @@ import LoadingSpinner from '../components/LoadingSpinner'; import PageLayout from '../components/layout/PageLayout'; import { AlertCard } from '../components/AlertCard'; import { UploadIcon, CheckIcon, FingerprintIcon } from '../components/Icons'; -import { getWallet, listWalletNames, storeWalletName } from '@/services/passkeyService'; +import { getWallet, listLabels, storeLabel } from '@/services/passkeyService'; import { logger, LogCategory } from '@/services/logger'; interface PasskeyPageProps { - onWalletRestored: (seed: Seed, walletName: string) => void; + onWalletRestored: (seed: Seed, label: string) => void; onBack: () => void; } @@ -20,25 +20,25 @@ const PasskeyPage: React.FC = ({ const [hasAcknowledged, setHasAcknowledged] = useState(false); const [isLoading, setIsLoading] = useState(true); const [isConnecting, setIsConnecting] = useState(false); - const [walletNames, setWalletNames] = useState([]); - const [selectedWalletName, setSelectedWalletName] = useState(null); + const [labels, setLabels] = useState([]); + const [selectedLabel, setSelectedLabel] = useState(null); const [error, setError] = useState(null); - const [manualWalletName, setManualWalletName] = useState(''); + const [manualLabel, setManualLabel] = useState(''); const [showManualInput, setShowManualInput] = useState(false); - // Fetch wallet names after acknowledgment + // Fetch labels after acknowledgment useEffect(() => { if (!hasAcknowledged) return; const autoCreate = async () => { setIsConnecting(true); try { const w = await getWallet(); - storeWalletName(w.name).catch((e) => - logger.warn(LogCategory.AUTH, 'Failed to store wallet name', { + storeLabel(w.label).catch((e) => + logger.warn(LogCategory.AUTH, 'Failed to store label', { error: e instanceof Error ? e.message : String(e), }), ); - onWalletRestored(w.seed, w.name); + onWalletRestored(w.seed, w.label); } catch (e) { setError('Failed to set up wallet'); logger.error(LogCategory.AUTH, 'Auto-create wallet failed', { @@ -48,13 +48,13 @@ const PasskeyPage: React.FC = ({ } }; - const fetchWalletNames = async () => { + const fetchLabels = async () => { setIsLoading(true); try { - const names = await listWalletNames(); - setWalletNames(names); + const labels = await listLabels(); + setLabels(labels); - if (names.length === 0) { + if (labels.length === 0) { // No wallets — auto-create default setIsLoading(false); await autoCreate(); @@ -62,11 +62,11 @@ const PasskeyPage: React.FC = ({ } // Pre-select "Default" if present, otherwise first - const defaultIdx = names.indexOf('Default'); - setSelectedWalletName(defaultIdx !== -1 ? names[defaultIdx] : names[0]); + const defaultIdx = labels.indexOf('Default'); + setSelectedLabel(defaultIdx !== -1 ? labels[defaultIdx] : labels[0]); } catch (e) { - setError('Failed to discover wallets'); - logger.error(LogCategory.AUTH, 'Failed to list wallet names', { + setError('Failed to discover labels'); + logger.error(LogCategory.AUTH, 'Failed to list labels', { error: e instanceof Error ? e.message : String(e), }); } finally { @@ -74,28 +74,28 @@ const PasskeyPage: React.FC = ({ } }; - fetchWalletNames(); + fetchLabels(); }, [hasAcknowledged, onWalletRestored]); const handleConnect = async () => { - const manualName = manualWalletName.trim(); - const nameToUse = manualName || selectedWalletName; - if (!nameToUse) return; + const label = manualLabel.trim(); + const labelToUse = label || selectedLabel; + if (!labelToUse) return; setIsConnecting(true); setError(null); try { - if (manualName) { - storeWalletName(nameToUse).catch((e) => + if (label) { + storeLabel(labelToUse).catch((e) => logger.warn(LogCategory.AUTH, 'Failed to store wallet name', { error: e instanceof Error ? e.message : String(e), }), ); } - const w = await getWallet(nameToUse); + const w = await getWallet(labelToUse); logger.info(LogCategory.AUTH, 'Passkey wallet derived'); - onWalletRestored(w.seed, w.name); + onWalletRestored(w.seed, w.label); } catch (e) { setError('Failed to connect'); logger.error(LogCategory.AUTH, 'Passkey wallet restore failed', { @@ -148,7 +148,7 @@ const PasskeyPage: React.FC = ({ return ( } title="Passkey">
- +
); @@ -165,7 +165,7 @@ const PasskeyPage: React.FC = ({ } // 1+ wallets — unified selection list + create option - const canConnect = !!(manualWalletName.trim() || selectedWalletName); + const canConnect = !!(manualLabel.trim() || selectedLabel); const footer = (
= ({

- Select Wallet + Select Label

- {walletNames.map((name) => ( + {labels.map((label) => ( ))} - {/* Create new wallet */} + {/* Create new label */} {!showManualInput ? ( ) : (
= ({ >
- Create a new wallet + Create a new label -
- {manualWalletName.trim() && ( +
+ {manualLabel.trim() && ( )}
setManualWalletName(e.target.value)} + value={manualLabel} + onChange={(e) => setManualLabel(e.target.value)} placeholder="Wallet name" className="w-full bg-spark-surface border border-spark-border rounded-xl px-3 py-2 text-spark-text-primary placeholder:text-spark-text-muted focus:outline-none focus:ring-2 focus:ring-spark-primary/50 focus:border-spark-primary text-sm" autoFocus diff --git a/src/services/passkeyService.ts b/src/services/passkeyService.ts index ee4f8d5..669761a 100644 --- a/src/services/passkeyService.ts +++ b/src/services/passkeyService.ts @@ -13,7 +13,7 @@ import { passkeyPrfProvider } from './passkeyPrfProvider'; import { logger, LogCategory } from './logger'; // Storage key — presence signals passkey mode -const PASSKEY_WALLET_NAME_KEY = 'passkeyWalletName'; +const PASSKEY_LABEL_KEY = 'passkeyLabel'; // Singleton Passkey instance let passkeyInstance: Passkey | null = null; @@ -60,14 +60,14 @@ export async function isPrfAvailable(): Promise { * Passkey mode is signalled by a stored wallet name. */ export function isPasskeyMode(): boolean { - return localStorage.getItem(PASSKEY_WALLET_NAME_KEY) !== null; + return localStorage.getItem(PASSKEY_LABEL_KEY) !== null; } /** * Set passkey mode by storing the wallet name. */ -export function setPasskeyMode(walletName?: string): void { - localStorage.setItem(PASSKEY_WALLET_NAME_KEY, walletName ?? 'Default'); +export function setPasskeyMode(label?: string): void { + localStorage.setItem(PASSKEY_LABEL_KEY, label ?? 'Default'); } /** @@ -76,43 +76,43 @@ export function setPasskeyMode(walletName?: string): void { * still exists on the device and should be reused on next login. */ export function clearPasskeyMode(): void { - localStorage.removeItem(PASSKEY_WALLET_NAME_KEY); + localStorage.removeItem(PASSKEY_LABEL_KEY); } /** - * List available wallet names from nostr relays. + * List available labels from nostr relays. */ -export async function listWalletNames(): Promise { - logger.info(LogCategory.AUTH, 'Listing wallet names from nostr relays'); +export async function listLabels(): Promise { + logger.info(LogCategory.AUTH, 'Listing labels from nostr relays'); const passkey = getOrCreatePasskey(); - return await passkey.listWalletNames(); + return await passkey.listLabels(); } /** - * Store a wallet name to nostr relays so it can be discovered later. + * Store a label to nostr relays so it can be discovered later. */ -export async function storeWalletName(walletName: string): Promise { - logger.info(LogCategory.AUTH, 'Storing wallet name to nostr relays'); +export async function storeLabel(label: string): Promise { + logger.info(LogCategory.AUTH, 'Storing label to nostr relays'); const passkey = getOrCreatePasskey(); - await passkey.storeWalletName(walletName); + await passkey.storeLabel(label); } /** * Derive a Wallet using passkey authentication. * - * Falls back to saved wallet name from localStorage when no name arg provided. + * Falls back to saved label from localStorage when no name arg provided. * - * @param walletName - Optional wallet name. If omitted, uses saved name or SDK default. - * @returns The derived Wallet object containing seed and name. + * @param label - Optional label. If omitted, uses saved name or SDK default. + * @returns The derived Wallet object containing seed and label. */ -export async function getWallet(walletName?: string): Promise { - const effectiveName = walletName ?? localStorage.getItem(PASSKEY_WALLET_NAME_KEY) ?? undefined; +export async function getWallet(label?: string): Promise { + const effectiveLabel = label ?? localStorage.getItem(PASSKEY_LABEL_KEY) ?? undefined; logger.info(LogCategory.AUTH, 'Deriving wallet via passkey'); const passkey = getOrCreatePasskey(); try { - const wallet = await passkey.getWallet(effectiveName); + const wallet = await passkey.getWallet(effectiveLabel); logger.info(LogCategory.AUTH, 'Passkey wallet derived successfully'); return wallet; } catch (e) {