165165 .status-pill {padding : 3px 10px ;border-radius : 999px ;font-size : 11px ;font-weight : 700 ;white-space : nowrap}
166166 .status-live {background : rgba (5 , 150 , 105 , .1 );color : var (--green );border : 1px solid rgba (5 , 150 , 105 , .25 )}
167167 .status-preview {background : rgba (217 , 119 , 6 , .1 );color : var (--amber );border : 1px solid rgba (217 , 119 , 6 , .25 )}
168+ .auth-state-row {display : flex;gap : 8px ;flex-wrap : wrap;margin-top : 10px }
169+ .auth-pill {padding : 3px 10px ;border-radius : 999px ;font-size : 11px ;font-weight : 700 ;border : 1px solid var (--border );background : # f8fafc ;color : var (--text-2 )}
170+ .auth-pill .connected {background : rgba (37 , 99 , 235 , .12 );color : # 1d4ed8 ;border-color : rgba (37 , 99 , 235 , .28 )}
171+ .auth-pill .authenticated {background : rgba (5 , 150 , 105 , .1 );color : var (--green );border-color : rgba (5 , 150 , 105 , .28 )}
172+ .auth-status-wrap {margin-top : 10px ;display : grid;gap : 6px }
173+ .auth-status-line {font-size : 12px ;line-height : 1.35 ;border-radius : 8px ;padding : 6px 8px ;border : 1px solid transparent}
174+ .auth-status-line .neutral {color : var (--text-2 );background : # f8fafc ;border-color : var (--border )}
175+ .auth-status-line .connected {color : # 1d4ed8 ;background : rgba (37 , 99 , 235 , .08 );border-color : rgba (37 , 99 , 235 , .2 )}
176+ .auth-status-line .authenticated {color : var (--green );background : rgba (5 , 150 , 105 , .08 );border-color : rgba (5 , 150 , 105 , .2 )}
177+ .auth-status-line .error {color : # b42318 ;background : rgba (180 , 35 , 24 , .06 );border-color : rgba (180 , 35 , 24 , .2 )}
168178 .agent-card-body .code-block {border-radius : 0 ;border : none;max-height : 280px ;overflow-y : auto}
169179 /* SUMMARY */
170180 .summary-grid {display : grid;grid-template-columns : 1fr 1fr ;gap : 12px ;margin-bottom : 20px }
@@ -273,9 +283,15 @@ <h1>Bring one ENS name.<br><span class="grad">Generate 10 verifiable agents.</sp
273283 < div style ="font-size:12px;color:var(--muted);margin-bottom:10px "> Supported browser wallets include MetaMask, Rabby, Coinbase Wallet, and other EIP-1193 wallets.</ div >
274284 < button class ="btn btn-secondary " id ="walletConnectBtn " onclick ="connectWallet() "> Connect Wallet</ button >
275285 < button class ="btn btn-secondary " id ="siweAuthBtn " onclick ="signInWithEthereum() " style ="display:none;margin-left:8px "> Sign-In with Ethereum</ button >
276- < div id ="siweStatus " style ="font-size:13px;color:var(--text-2);margin-top:10px "> Not connected</ div >
277- < div id ="siweWallet " style ="font-family:var(--mono);font-size:12px;color:var(--muted);margin-top:4px "> </ div >
278- < div id ="siweError " style ="font-size:12px;color:#b42318;margin-top:8px;display:none "> </ div >
286+ < div class ="auth-state-row ">
287+ < span class ="auth-pill " id ="walletStatusPill "> Wallet disconnected</ span >
288+ < span class ="auth-pill " id ="authStatusPill "> Not authenticated</ span >
289+ </ div >
290+ < div class ="auth-status-wrap ">
291+ < div id ="siweStatus " class ="auth-status-line neutral "> Status: Not connected</ div >
292+ < div id ="siweWallet " class ="auth-status-line neutral " style ="display:none;font-family:var(--mono) "> </ div >
293+ < div id ="siweError " class ="auth-status-line error " style ="display:none "> </ div >
294+ </ div >
279295 < div id ="siweModeHint " style ="font-size:12px;color:var(--muted);margin-top:8px "> </ div >
280296 < div id ="ensOwnedBox " class ="ens-owned-box ">
281297 < div id ="ensOwnedStatus " class ="ens-owned-title "> </ div >
@@ -828,6 +844,25 @@ <h3>Payment and provisioning are coming next.</h3>
828844 }
829845}
830846
847+ function setAuthStatusClasses ( statusType , walletType , hasError ) {
848+ const statusEl = document . getElementById ( 'siweStatus' ) ;
849+ const walletEl = document . getElementById ( 'siweWallet' ) ;
850+ const errorEl = document . getElementById ( 'siweError' ) ;
851+ const walletPill = document . getElementById ( 'walletStatusPill' ) ;
852+ const authPill = document . getElementById ( 'authStatusPill' ) ;
853+ if ( statusEl ) statusEl . className = `auth-status-line ${ statusType || 'neutral' } ` ;
854+ if ( walletEl ) walletEl . className = `auth-status-line ${ walletType || 'neutral' } ` ;
855+ if ( errorEl ) errorEl . style . display = hasError ?'block' :'none' ;
856+ if ( walletPill ) {
857+ walletPill . className = 'auth-pill' + ( state . connectedWalletAddress ?' connected' :'' ) ;
858+ walletPill . textContent = state . connectedWalletAddress ?'Wallet Connected' :'Wallet disconnected' ;
859+ }
860+ if ( authPill ) {
861+ authPill . className = 'auth-pill' + ( state . siweAuthenticated ?' authenticated' :'' ) ;
862+ authPill . textContent = state . siweAuthenticated ?'Authenticated' :'Not authenticated' ;
863+ }
864+ }
865+
831866window . connectWallet = async function connectWallet ( ) {
832867 const statusEl = document . getElementById ( 'siweStatus' ) ;
833868 const walletEl = document . getElementById ( 'siweWallet' ) ;
@@ -841,25 +876,32 @@ <h3>Payment and provisioning are coming next.</h3>
841876 nextBtn . disabled = true ;
842877 connectBtn . disabled = true ;
843878 connectBtn . textContent = 'Connecting...' ;
844- statusEl . textContent = 'Connecting wallet...' ;
879+ statusEl . textContent = 'Status: Connecting wallet...' ;
880+ setAuthStatusClasses ( 'neutral' , 'neutral' , false ) ;
845881 if ( ! window . ethereum ) { throw new Error ( 'No Ethereum wallet detected. Install MetaMask, Rabby, Coinbase Wallet, or another browser wallet.' ) ; }
846882 const accounts = await window . ethereum . request ( { method :'eth_requestAccounts' } ) ;
847883 const rawAddress = accounts && accounts [ 0 ] ;
848884 if ( ! rawAddress ) { throw new Error ( 'Wallet connection rejected.' ) ; }
849885 const checksumAddress = toChecksumAddress ( rawAddress ) ;
850886 state . connectedWalletAddress = checksumAddress ;
887+ walletEl . style . display = 'block' ;
851888 walletEl . textContent = `Wallet connected: ${ shortAddr ( checksumAddress ) } ` ;
852- statusEl . textContent = 'Wallet connected' ;
889+ statusEl . textContent = 'Status: Wallet connected' ;
853890 connectBtn . textContent = 'Wallet Connected' ;
891+ connectBtn . classList . add ( 'btn-ghost' ) ;
854892 siweBtn . style . display = 'inline-flex' ;
855893 siweBtn . disabled = false ;
894+ setAuthStatusClasses ( 'connected' , 'connected' , false ) ;
856895 } catch ( err ) {
857896 const msg = ( ( err && err . message ) || 'Wallet connection rejected.' ) . trim ( ) ;
858897 errorEl . textContent = err && err . code === 4001 ? 'Wallet connection rejected.' : msg ;
859898 errorEl . style . display = 'block' ;
860- statusEl . textContent = 'Not connected' ;
899+ statusEl . textContent = 'Status: Not connected' ;
861900 connectBtn . textContent = 'Connect Wallet' ;
901+ connectBtn . classList . remove ( 'btn-ghost' ) ;
862902 walletEl . textContent = '' ;
903+ walletEl . style . display = 'none' ;
904+ setAuthStatusClasses ( 'neutral' , 'neutral' , true ) ;
863905 } finally {
864906 connectBtn . disabled = false ;
865907 }
@@ -880,7 +922,8 @@ <h3>Payment and provisioning are coming next.</h3>
880922 const address = toChecksumAddress ( state . connectedWalletAddress ) ;
881923 if ( ! address ) { throw new Error ( 'Connect wallet first.' ) ; }
882924 updateSiweModeHint ( ) ;
883- statusEl . textContent = 'Requesting SIWE nonce...' ;
925+ statusEl . textContent = 'Status: Requesting SIWE nonce...' ;
926+ setAuthStatusClasses ( 'connected' , 'connected' , false ) ;
884927 const chainIdHex = await window . ethereum . request ( { method :'eth_chainId' } ) ;
885928 const chainId = parseInt ( chainIdHex , 16 ) ;
886929 if ( Number . isNaN ( chainId ) || chainId <= 0 ) { throw new Error ( 'Unsupported chain.' ) ; }
@@ -901,7 +944,7 @@ <h3>Payment and provisioning are coming next.</h3>
901944Chain ID: ${ chainId }
902945Nonce: ${ nonceData . nonce }
903946Issued At: ${ issuedAt } ` ;
904- statusEl . textContent = 'Awaiting wallet signature...' ;
947+ statusEl . textContent = 'Status: Awaiting wallet signature...' ;
905948 const signature = await window . ethereum . request ( { method :'personal_sign' , params :[ msg , address ] } ) ;
906949 const verifyRes = await fetch ( '/api/auth/verify' , { method :'POST' , headers :{ 'Content-Type' :'application/json' } , body :JSON . stringify ( { message :msg , signature} ) } ) ;
907950 const verify = await verifyRes . json ( ) ;
@@ -912,19 +955,25 @@ <h3>Payment and provisioning are coming next.</h3>
912955 }
913956 state . authenticatedAddress = verify . address ; state . authStatus = verify . status ; state . authChainId = verify . chainId ; state . siweAuthenticated = true ;
914957 await loadOwnedEnsNames ( verify . address ) ;
915- statusEl . textContent = 'Authenticated' ;
916- walletEl . textContent = `Connected wallet: ${ shortAddr ( verify . address ) } ` ;
958+ statusEl . textContent = 'Authentication verified.' ;
959+ walletEl . style . display = 'block' ;
960+ walletEl . textContent = `Wallet connected: ${ shortAddr ( verify . address ) } ` ;
917961 btn . textContent = 'Authenticated' ;
962+ btn . disabled = true ;
963+ btn . classList . add ( 'btn-ghost' ) ;
964+ setAuthStatusClasses ( 'authenticated' , 'connected' , false ) ;
918965 nextBtn . disabled = false ;
919966 } catch ( err ) {
920967 const msg = ( ( err && err . message ) || 'SIWE verification failed.' ) . trim ( ) ;
921968 errorEl . textContent = err && err . code === 4001 ? 'Signature rejected.' : msg ;
922969 errorEl . style . display = 'block' ;
923- statusEl . textContent = 'Not connected' ;
970+ statusEl . textContent = 'Status: Not connected' ;
924971 btn . disabled = false ;
925972 btn . textContent = 'Sign-In with Ethereum' ;
973+ btn . classList . remove ( 'btn-ghost' ) ;
926974 nextBtn . disabled = true ;
927975 state . siweAuthenticated = false ;
976+ setAuthStatusClasses ( state . connectedWalletAddress ?'connected' :'neutral' , state . connectedWalletAddress ?'connected' :'neutral' , true ) ;
928977 console . error ( 'SIWE auth failed' , err ) ;
929978 }
930979} ;
0 commit comments