/** * AT Protocol OAuth client configuration */ import { BrowserOAuthClient } from '@atproto/oauth-client-browser'; let oauthClient: BrowserOAuthClient | null = null; export function getOAuthClient(): BrowserOAuthClient { if (oauthClient) return oauthClient; oauthClient = new BrowserOAuthClient({ clientMetadata: { client_id: typeof window !== 'undefined' ? `${window.location.origin}/client-metadata.json` : 'https://attoshi.com/client-metadata.json', client_name: '@toshi Wallet', client_uri: 'https://attoshi.com', redirect_uris: ['https://attoshi.com/wallet'], scope: 'atproto', grant_types: ['authorization_code', 'refresh_token'], response_types: ['code'], token_endpoint_auth_method: 'none', application_type: 'web', dpop_bound_access_tokens: true, }, handleResolver: 'https://bsky.social', }); return oauthClient; } export async function login(handle: string): Promise { const client = getOAuthClient(); await client.signIn(handle, { scope: 'atproto', }); } export async function getSession() { const client = getOAuthClient(); const result = await client.init(); return result?.session ?? null; } export async function logout(): Promise { const client = getOAuthClient(); const result = await client.init(); if (result?.session) { // Clear the session // The OAuth client handles cleanup internally } }