Authenticate the wallet that will request this CommandLayer namespace activation.
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;