diff --git a/public/claim.html b/public/claim.html index ec796d1..b4e04d9 100644 --- a/public/claim.html +++ b/public/claim.html @@ -267,11 +267,12 @@

Bring one ENS name.
Generate 10 verifiable agents.
Step 1 of 8
-
Sign in with Ethereum
-
Authenticate the wallet that will request this CommandLayer namespace activation.
+
Connect wallet
+
Connect an Ethereum wallet to authenticate the activation request. Your wallet signs the login message. Your Ed25519 key signs agent receipts later.
-
Your Ethereum wallet authenticates the claim request.
Your Ed25519 key signs agent receipts later in the flow.
- +
Supported browser wallets include MetaMask, Rabby, Coinbase Wallet, and other EIP-1193 wallets.
+ +
Not connected
@@ -783,6 +784,42 @@

Payment and provisioning are coming next.

} } +window.connectWallet = async function connectWallet(){ + const statusEl=document.getElementById('siweStatus'); + const walletEl=document.getElementById('siweWallet'); + const errorEl=document.getElementById('siweError'); + const connectBtn=document.getElementById('walletConnectBtn'); + const siweBtn=document.getElementById('siweAuthBtn'); + const nextBtn=document.getElementById('step1Next'); + try { + errorEl.style.display='none'; + errorEl.textContent=''; + nextBtn.disabled=true; + connectBtn.disabled=true; + connectBtn.textContent='Connecting...'; + statusEl.textContent='Connecting wallet...'; + if(!window.ethereum){ throw new Error('No Ethereum wallet detected. Install MetaMask, Rabby, Coinbase Wallet, or another browser wallet.'); } + const accounts=await window.ethereum.request({ method:'eth_requestAccounts' }); + const address=accounts && accounts[0]; + if(!address){ throw new Error('Wallet connection rejected.'); } + state.connectedWalletAddress=address; + walletEl.textContent=`Wallet connected: ${shortAddr(address)}`; + statusEl.textContent='Wallet connected'; + connectBtn.textContent='Wallet Connected'; + siweBtn.style.display='inline-flex'; + siweBtn.disabled=false; + } catch (err) { + const msg=((err && err.message)||'Wallet connection rejected.').trim(); + errorEl.textContent=err && err.code===4001 ? 'Wallet connection rejected.' : msg; + errorEl.style.display='block'; + statusEl.textContent='Not connected'; + connectBtn.textContent='Connect Wallet'; + walletEl.textContent=''; + } finally { + connectBtn.disabled=false; + } +}; + window.signInWithEthereum = async function signInWithEthereum(){ const statusEl=document.getElementById('siweStatus'); const walletEl=document.getElementById('siweWallet'); @@ -793,19 +830,19 @@

Payment and provisioning are coming next.

errorEl.style.display='none'; errorEl.textContent=''; btn.disabled=true; - btn.textContent='Waiting for wallet...'; - statusEl.textContent='Requesting wallet signature...'; - if(!window.ethereum){ throw new Error('No Ethereum wallet detected. Install MetaMask, Rabby, or another EIP-1193 wallet.'); } + btn.textContent='Signing...'; + if(!window.ethereum){ throw new Error('No wallet detected'); } + const address=state.connectedWalletAddress; + if(!address){ throw new Error('Connect wallet first.'); } updateSiweModeHint(); - const accounts=await window.ethereum.request({ method:'eth_requestAccounts' }); - const address=accounts && accounts[0]; - if(!address){ throw new Error('No wallet account selected.'); } + statusEl.textContent='Requesting SIWE nonce...'; const chainIdHex=await window.ethereum.request({ method:'eth_chainId' }); const chainId=parseInt(chainIdHex,16); + if(Number.isNaN(chainId) || chainId<=0){ throw new Error('Unsupported chain.'); } const nonceRes=await fetch('/api/auth/nonce',{method:'GET',headers:{'Accept':'application/json'}}); - if(!nonceRes.ok){ throw new Error('Could not get SIWE nonce from /api/auth/nonce.'); } + if(!nonceRes.ok){ throw new Error('Nonce request failed.'); } const nonceData=await nonceRes.json(); - if(!nonceData.ok || !nonceData.nonce){ throw new Error('Could not get SIWE nonce from /api/auth/nonce.'); } + if(!nonceData.ok || !nonceData.nonce){ throw new Error('Nonce request failed.'); } const domain=window.location.host; const uri=window.location.origin; const issuedAt=new Date().toISOString(); @@ -819,22 +856,25 @@

Payment and provisioning are coming next.

Chain ID: ${chainId} Nonce: ${nonceData.nonce} Issued At: ${issuedAt}`; + statusEl.textContent='Awaiting wallet signature...'; const signature=await window.ethereum.request({method:'personal_sign',params:[msg,address]}); const verifyRes=await fetch('/api/auth/verify',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({message:msg,signature})}); + if(!verifyRes.ok){ throw new Error('SIWE verification failed.'); } const verify=await verifyRes.json(); - if(!verify.ok){ throw new Error(verify.error||'Authentication failed'); } + if(!verify.ok){ + const errText=String(verify.error||'SIWE verification failed.').toLowerCase(); + if(errText.includes('domain')) throw new Error('Domain mismatch.'); + if(errText.includes('chain')) throw new Error('Unsupported chain.'); + throw new Error('SIWE verification failed.'); + } state.authenticatedAddress=verify.address; state.authStatus=verify.status; state.authChainId=verify.chainId; state.siweAuthenticated=true; statusEl.textContent='Authenticated'; walletEl.textContent=`Connected wallet: ${shortAddr(verify.address)}`; - btn.textContent='Wallet authenticated'; + btn.textContent='Authenticated'; nextBtn.disabled=false; } catch (err) { - const msg=((err && err.message)||'Authentication failed.').trim(); - if(err && err.code===4001){ - errorEl.textContent='Wallet signature rejected.'; - }else{ - errorEl.textContent=msg; - } + const msg=((err && err.message)||'SIWE verification failed.').trim(); + errorEl.textContent=err && err.code===4001 ? 'Signature rejected.' : msg; errorEl.style.display='block'; statusEl.textContent='Not connected'; btn.disabled=false;