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 >
@@ -807,6 +823,25 @@ <h3>Payment and provisioning are coming next.</h3>
807823 }
808824}
809825
826+ function setAuthStatusClasses ( statusType , walletType , hasError ) {
827+ const statusEl = document . getElementById ( 'siweStatus' ) ;
828+ const walletEl = document . getElementById ( 'siweWallet' ) ;
829+ const errorEl = document . getElementById ( 'siweError' ) ;
830+ const walletPill = document . getElementById ( 'walletStatusPill' ) ;
831+ const authPill = document . getElementById ( 'authStatusPill' ) ;
832+ if ( statusEl ) statusEl . className = `auth-status-line ${ statusType || 'neutral' } ` ;
833+ if ( walletEl ) walletEl . className = `auth-status-line ${ walletType || 'neutral' } ` ;
834+ if ( errorEl ) errorEl . style . display = hasError ?'block' :'none' ;
835+ if ( walletPill ) {
836+ walletPill . className = 'auth-pill' + ( state . connectedWalletAddress ?' connected' :'' ) ;
837+ walletPill . textContent = state . connectedWalletAddress ?'Wallet Connected' :'Wallet disconnected' ;
838+ }
839+ if ( authPill ) {
840+ authPill . className = 'auth-pill' + ( state . siweAuthenticated ?' authenticated' :'' ) ;
841+ authPill . textContent = state . siweAuthenticated ?'Authenticated' :'Not authenticated' ;
842+ }
843+ }
844+
810845window . connectWallet = async function connectWallet ( ) {
811846 const statusEl = document . getElementById ( 'siweStatus' ) ;
812847 const walletEl = document . getElementById ( 'siweWallet' ) ;
@@ -820,25 +855,32 @@ <h3>Payment and provisioning are coming next.</h3>
820855 nextBtn . disabled = true ;
821856 connectBtn . disabled = true ;
822857 connectBtn . textContent = 'Connecting...' ;
823- statusEl . textContent = 'Connecting wallet...' ;
858+ statusEl . textContent = 'Status: Connecting wallet...' ;
859+ setAuthStatusClasses ( 'neutral' , 'neutral' , false ) ;
824860 if ( ! window . ethereum ) { throw new Error ( 'No Ethereum wallet detected. Install MetaMask, Rabby, Coinbase Wallet, or another browser wallet.' ) ; }
825861 const accounts = await window . ethereum . request ( { method :'eth_requestAccounts' } ) ;
826862 const rawAddress = accounts && accounts [ 0 ] ;
827863 if ( ! rawAddress ) { throw new Error ( 'Wallet connection rejected.' ) ; }
828864 const checksumAddress = toChecksumAddress ( rawAddress ) ;
829865 state . connectedWalletAddress = checksumAddress ;
866+ walletEl . style . display = 'block' ;
830867 walletEl . textContent = `Wallet connected: ${ shortAddr ( checksumAddress ) } ` ;
831- statusEl . textContent = 'Wallet connected' ;
868+ statusEl . textContent = 'Status: Wallet connected' ;
832869 connectBtn . textContent = 'Wallet Connected' ;
870+ connectBtn . classList . add ( 'btn-ghost' ) ;
833871 siweBtn . style . display = 'inline-flex' ;
834872 siweBtn . disabled = false ;
873+ setAuthStatusClasses ( 'connected' , 'connected' , false ) ;
835874 } catch ( err ) {
836875 const msg = ( ( err && err . message ) || 'Wallet connection rejected.' ) . trim ( ) ;
837876 errorEl . textContent = err && err . code === 4001 ? 'Wallet connection rejected.' : msg ;
838877 errorEl . style . display = 'block' ;
839- statusEl . textContent = 'Not connected' ;
878+ statusEl . textContent = 'Status: Not connected' ;
840879 connectBtn . textContent = 'Connect Wallet' ;
880+ connectBtn . classList . remove ( 'btn-ghost' ) ;
841881 walletEl . textContent = '' ;
882+ walletEl . style . display = 'none' ;
883+ setAuthStatusClasses ( 'neutral' , 'neutral' , true ) ;
842884 } finally {
843885 connectBtn . disabled = false ;
844886 }
@@ -859,7 +901,8 @@ <h3>Payment and provisioning are coming next.</h3>
859901 const address = toChecksumAddress ( state . connectedWalletAddress ) ;
860902 if ( ! address ) { throw new Error ( 'Connect wallet first.' ) ; }
861903 updateSiweModeHint ( ) ;
862- statusEl . textContent = 'Requesting SIWE nonce...' ;
904+ statusEl . textContent = 'Status: Requesting SIWE nonce...' ;
905+ setAuthStatusClasses ( 'connected' , 'connected' , false ) ;
863906 const chainIdHex = await window . ethereum . request ( { method :'eth_chainId' } ) ;
864907 const chainId = parseInt ( chainIdHex , 16 ) ;
865908 if ( Number . isNaN ( chainId ) || chainId <= 0 ) { throw new Error ( 'Unsupported chain.' ) ; }
@@ -880,7 +923,7 @@ <h3>Payment and provisioning are coming next.</h3>
880923Chain ID: ${ chainId }
881924Nonce: ${ nonceData . nonce }
882925Issued At: ${ issuedAt } ` ;
883- statusEl . textContent = 'Awaiting wallet signature...' ;
926+ statusEl . textContent = 'Status: Awaiting wallet signature...' ;
884927 const signature = await window . ethereum . request ( { method :'personal_sign' , params :[ msg , address ] } ) ;
885928 const verifyRes = await fetch ( '/api/auth/verify' , { method :'POST' , headers :{ 'Content-Type' :'application/json' } , body :JSON . stringify ( { message :msg , signature} ) } ) ;
886929 const verify = await verifyRes . json ( ) ;
@@ -891,19 +934,25 @@ <h3>Payment and provisioning are coming next.</h3>
891934 }
892935 state . authenticatedAddress = verify . address ; state . authStatus = verify . status ; state . authChainId = verify . chainId ; state . siweAuthenticated = true ;
893936 await loadOwnedEnsNames ( verify . address ) ;
894- statusEl . textContent = 'Authenticated' ;
895- walletEl . textContent = `Connected wallet: ${ shortAddr ( verify . address ) } ` ;
937+ statusEl . textContent = 'Authentication verified.' ;
938+ walletEl . style . display = 'block' ;
939+ walletEl . textContent = `Wallet connected: ${ shortAddr ( verify . address ) } ` ;
896940 btn . textContent = 'Authenticated' ;
941+ btn . disabled = true ;
942+ btn . classList . add ( 'btn-ghost' ) ;
943+ setAuthStatusClasses ( 'authenticated' , 'connected' , false ) ;
897944 nextBtn . disabled = false ;
898945 } catch ( err ) {
899946 const msg = ( ( err && err . message ) || 'SIWE verification failed.' ) . trim ( ) ;
900947 errorEl . textContent = err && err . code === 4001 ? 'Signature rejected.' : msg ;
901948 errorEl . style . display = 'block' ;
902- statusEl . textContent = 'Not connected' ;
949+ statusEl . textContent = 'Status: Not connected' ;
903950 btn . disabled = false ;
904951 btn . textContent = 'Sign-In with Ethereum' ;
952+ btn . classList . remove ( 'btn-ghost' ) ;
905953 nextBtn . disabled = true ;
906954 state . siweAuthenticated = false ;
955+ setAuthStatusClasses ( state . connectedWalletAddress ?'connected' :'neutral' , state . connectedWalletAddress ?'connected' :'neutral' , true ) ;
907956 console . error ( 'SIWE auth failed' , err ) ;
908957 }
909958} ;
0 commit comments