22
33import React , { useState , useEffect } from 'react'
44import { useRouter } from 'next/navigation'
5- import { isConnected , requestAccess , getAddress } from '@stellar/freighter-api'
5+ import { isConnected , requestAccess , getAddress , signMessage } from '@stellar/freighter-api'
66import { Button } from '@/components/ui/button'
77import { Wallet , LogOut , AlertCircle , Loader2 , ArrowLeft , FlaskConical } from 'lucide-react'
88import Link from 'next/link'
@@ -14,6 +14,7 @@ export default function LoginPage() {
1414 const [ address , setAddress ] = useState < string | null > ( null )
1515 const [ isInitializing , setIsInitializing ] = useState ( true )
1616 const [ isConnecting , setIsConnecting ] = useState ( false )
17+ const [ statusMessage , setStatusMessage ] = useState < string | null > ( null )
1718 const [ isMocking , setIsMocking ] = useState ( false )
1819 const [ error , setError ] = useState < string | null > ( null )
1920
@@ -26,10 +27,17 @@ export default function LoginPage() {
2627 // Verify if still connected
2728 const connectedResponse = await isConnected ( )
2829 if ( connectedResponse . isConnected ) {
29- setAddress ( savedAddress )
30- } else {
31- localStorage . removeItem ( 'stellar_wallet_address' )
30+ // Also check if backend session is still active
31+ const meRes = await fetch ( '/api/auth/me' )
32+ if ( meRes . ok ) {
33+ setAddress ( savedAddress )
34+ router . push ( '/dashboard' )
35+ return
36+ }
3237 }
38+ // Clear if not fully verified
39+ localStorage . removeItem ( 'stellar_wallet_address' )
40+ localStorage . removeItem ( 'tc_dev_access_token' )
3341 }
3442 } catch ( err ) {
3543 console . error ( 'Failed to initialize wallet session:' , err )
@@ -40,11 +48,12 @@ export default function LoginPage() {
4048
4149 // Slight delay to ensure Freighter extension is loaded
4250 setTimeout ( initSession , 500 )
43- } , [ ] )
51+ } , [ router ] )
4452
4553 const handleConnect = async ( ) => {
4654 setError ( null )
4755 setIsConnecting ( true )
56+ setStatusMessage ( 'Connecting wallet...' )
4857 try {
4958 // Check if Freighter is installed
5059 const connectedResponse = await isConnected ( )
@@ -69,17 +78,73 @@ export default function LoginPage() {
6978 walletAddress = addressResponse . address
7079 }
7180
72- if ( walletAddress ) {
73- setAddress ( walletAddress )
74- localStorage . setItem ( 'stellar_wallet_address' , walletAddress )
75- } else {
81+ if ( ! walletAddress ) {
7682 throw new Error ( 'Failed to retrieve wallet address from Freighter.' )
7783 }
84+
85+ // 1. Fetch Nonce & Message
86+ setStatusMessage ( 'Requesting authentication message...' )
87+ const nonceRes = await fetch ( '/api/auth/nonce' , {
88+ method : 'POST' ,
89+ headers : { 'Content-Type' : 'application/json' } ,
90+ body : JSON . stringify ( { walletAddress } ) ,
91+ } )
92+ const nonceData = await nonceRes . json ( )
93+ if ( ! nonceRes . ok ) {
94+ throw new Error ( nonceData ?. error || 'Failed to generate authentication nonce.' )
95+ }
96+
97+ const { nonce, message } = nonceData
98+
99+ // 2. Request signature via Freighter signMessage
100+ setStatusMessage ( 'Approve signature request...' )
101+ const signResponse = await signMessage ( message )
102+
103+ let signature : string | undefined
104+ if ( typeof signResponse === 'string' ) {
105+ signature = signResponse
106+ } else if ( signResponse && typeof signResponse === 'object' ) {
107+ if ( signResponse . error ) {
108+ throw new Error ( signResponse . error . message || signResponse . error || 'Message signing was rejected.' )
109+ }
110+ signature = signResponse . signedMessage
111+ }
112+
113+ if ( ! signature ) {
114+ throw new Error ( 'Message signing was cancelled or failed.' )
115+ }
116+
117+ // 3. Verify Signature & Nonce on Backend
118+ setStatusMessage ( 'Verifying signature...' )
119+ const verifyRes = await fetch ( '/api/auth/verify' , {
120+ method : 'POST' ,
121+ headers : { 'Content-Type' : 'application/json' } ,
122+ body : JSON . stringify ( {
123+ walletAddress,
124+ nonce,
125+ signature,
126+ message,
127+ } ) ,
128+ } )
129+
130+ const verifyData = await verifyRes . json ( )
131+ if ( ! verifyRes . ok ) {
132+ throw new Error ( verifyData ?. error || 'Signature verification failed.' )
133+ }
134+
135+ // 4. Set local storage & redirect
136+ setAddress ( walletAddress )
137+ localStorage . setItem ( 'stellar_wallet_address' , walletAddress )
138+ if ( verifyData . accessToken ) {
139+ localStorage . setItem ( 'tc_dev_access_token' , verifyData . accessToken )
140+ }
141+ router . push ( '/dashboard' )
78142 } catch ( err : any ) {
79143 console . error ( 'Connection error:' , err )
80144 setError ( err ?. message || 'Unable to connect wallet. Please try again.' )
81145 } finally {
82146 setIsConnecting ( false )
147+ setStatusMessage ( null )
83148 }
84149 }
85150
@@ -108,6 +173,7 @@ export default function LoginPage() {
108173 const handleDisconnect = ( ) => {
109174 setAddress ( null )
110175 localStorage . removeItem ( 'stellar_wallet_address' )
176+ localStorage . removeItem ( 'tc_dev_access_token' )
111177 setError ( null )
112178 }
113179
@@ -185,7 +251,7 @@ export default function LoginPage() {
185251 { isConnecting ? (
186252 < >
187253 < Loader2 className = "w-4 h-4 mr-2 animate-spin" />
188- Connecting...
254+ { statusMessage || ' Connecting...' }
189255 </ >
190256 ) : (
191257 'Connect Freighter'
0 commit comments