auth.ts
1 import { create } from 'zustand' 2 import { persist } from 'zustand/middleware' 3 4 interface AuthState { 5 isConnected: boolean 6 isConnecting: boolean 7 address: string | null 8 token: string | null 9 chain: 'alpha' | 'delta' | null 10 11 connect: () => Promise<void> 12 disconnect: () => void 13 setToken: (token: string) => void 14 } 15 16 export const useAuthStore = create<AuthState>()( 17 persist( 18 (set, _get) => ({ 19 isConnected: false, 20 isConnecting: false, 21 address: null, 22 token: null, 23 chain: null, 24 25 connect: async () => { 26 set({ isConnecting: true }) 27 28 try { 29 // TODO: Integrate with @alpha-delta/sdk for actual wallet connection 30 // For now, simulate connection with a test address 31 32 // In production: 33 // 1. Import Account from SDK 34 // 2. Get challenge from /api/auth/challenge 35 // 3. Sign challenge with wallet 36 // 4. Verify signature and get JWT from /api/auth/verify 37 38 // Simulated connection for development 39 const testAddress = 'ax1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq' 40 41 // Get challenge 42 const challengeRes = await fetch('/api/auth/challenge', { 43 method: 'POST', 44 headers: { 'Content-Type': 'application/json' }, 45 body: JSON.stringify({ address: testAddress }), 46 }) 47 48 if (!challengeRes.ok) { 49 throw new Error('Failed to get challenge') 50 } 51 52 const { challenge } = await challengeRes.json() 53 54 // Verify (with placeholder signature for dev) 55 const verifyRes = await fetch('/api/auth/verify', { 56 method: 'POST', 57 headers: { 'Content-Type': 'application/json' }, 58 body: JSON.stringify({ 59 address: testAddress, 60 challenge, 61 signature: 'dev-signature', 62 }), 63 }) 64 65 if (!verifyRes.ok) { 66 throw new Error('Failed to verify signature') 67 } 68 69 const { access_token } = await verifyRes.json() 70 71 set({ 72 isConnected: true, 73 isConnecting: false, 74 address: testAddress, 75 token: access_token, 76 chain: testAddress.startsWith('ax1') ? 'alpha' : 'delta', 77 }) 78 } catch (error) { 79 console.error('Connection failed:', error) 80 set({ isConnecting: false }) 81 } 82 }, 83 84 disconnect: () => { 85 set({ 86 isConnected: false, 87 address: null, 88 token: null, 89 chain: null, 90 }) 91 }, 92 93 setToken: (token: string) => { 94 set({ token }) 95 }, 96 }), 97 { 98 name: 'acdc-forge-auth', 99 partialize: (state) => ({ 100 address: state.address, 101 token: state.token, 102 chain: state.chain, 103 isConnected: state.isConnected, 104 }), 105 } 106 ) 107 )