# Session Management The session system provides a unified way to handle different authentication methods: - Secret Key NIP-01 - Nostr Extensions NIP-07 - Bunker URL NIP-46 - Amber or in-device NIP-55 while managing user state and encryption capabilities. ## Overview Sessions are stored in local storage and can be: - Persisted across page reloads - Used with multiple accounts - Switched dynamically - Backed by different signing methods ## Basic Usage ```typescript import {ctx, setContext} from '@welshman/lib' import { getDefaultNetContext, getDefaultAppContext, pubkey, sessions, session, addSession, getNip07 } from '@welshman/app' // Set up app config setContext({ net: getDefaultNetContext(), app: getDefaultAppContext(), }) // Log in via NIP-07 extension (browser wallet) if (await getNip07()) { addSession({ method: 'nip07', pubkey: await getNip07().getPublicKey() }) } // Get current session console.log(session.get()) // Current active session console.log(pubkey.get()) // Current pubkey ``` ## Multiple Sessions ```typescript import {sessions, pubkey, addSession, dropSession} from '@welshman/app' // Add multiple sessions addSession({method: 'nip07', pubkey: 'abc...'}) addSession({method: 'nip46', pubkey: 'def...', secret: '123'}) // Switch between sessions pubkey.set('abc...') // Activates that session // Remove a session dropSession('abc...') // List all sessions console.log(sessions.get()) ``` ## NIP-46 (Bunker) Authentication ```typescript import {Nip46Broker, Nip46Signer} from '@welshman/signer' import {addSession} from '@welshman/app' // Connect to a bunker const clientSecret = makeSecret() const relays = ['wss://relay.damus.io'] const broker = Nip46Broker.get({relays, clientSecret}) // Generate nostrconnect URL for the bunker const connectUrl = await broker.makeNostrconnectUrl({ name: "My App", url: "https://myapp.com" }) // Wait for user to approve in bunker const response = await broker.waitForNostrconnect(connectUrl) // Create session addSession({ method: 'nip46', pubkey: response.event.pubkey, secret: clientSecret, handler: { pubkey: response.event.pubkey, relays } }) ``` ## Using Session Signer ```typescript import {signer, session} from '@welshman/app' import {createEvent, NOTE} from '@welshman/util' // Current session's signer is always ready to use const event = await signer.get().sign( createEvent(NOTE, {content: "Hello Nostr!"}) ) // Encrypt content for private notes const encrypted = await signer.get().nip44.encrypt( pubkey, "Secret message" ) ``` ## Session Persistence Sessions are automatically persisted to local storage. On page load: ```typescript import {pubkey, sessions} from '@welshman/app' // Sessions load automatically from local storage console.log(sessions.get()) // All stored sessions // the current active session console.log(session.get()) // Last active pubkey is restored console.log(pubkey.get()) ``` ## Session Types ```typescript type SessionNip07 = { method: "nip07" pubkey: string } type SessionNip46 = { method: "nip46" pubkey: string secret: string handler: { pubkey: string relays: string[] } } type SessionNip01 = { method: "nip01" pubkey: string secret: string } ``` ## Error Handling ```typescript import {tryCatch} from '@welshman/lib' import {addSession, getNip07} from '@welshman/app' const login = async () => { const nip07 = await tryCatch(getNip07) if (!nip07) { throw new Error("No NIP-07 extension found") } const pubkey = await tryCatch( () => nip07.getPublicKey() ) if (!pubkey) { throw new Error("Failed to get public key") } addSession({method: 'nip07', pubkey}) } ```