Generate 10 verifiable agents.
Step 3 of 8
-
Choose capabilities
-
Select a recommended pack of 10 verbs, or cherry-pick up to 10 from any group.
+
Enter tenant / ENS name
+
This is your organization or agent identity used for namespace generation.
@@ -337,6 +339,12 @@
Bring one ENS name.
Generate 10 verifiable agents.Selected: 0 / 10
+
+
+
+ Please enter a valid .eth name
+ Must end in .eth · The name you own or control
+
@@ -429,15 +437,7 @@
Browser-side key generation
Payment/provisioning is required for CommandLayer-native namespace activation.
-
-
Sign in with Ethereum
-
Authenticate the wallet that will submit this activation request.
-
Your Ethereum wallet authenticates the claim request. Your Ed25519 key signs agent receipts.
-
-
Status: Not authenticated
-
-
-
+
@@ -585,7 +585,7 @@
Payment and provisioning are coming next.
pubKeyB64:'', privKeyB64:'', kid:'',
keyGenerated:false, keyDownloaded:false, keyAcked:false,
_cardJson:'',
- authenticatedAddress:'', authStatus:'NOT_AUTHENTICATED', authChainId:null
+ authenticatedAddress:'', authStatus:'NOT_AUTHENTICATED', authChainId:null, siweAuthenticated:false
};
// ── HELPERS ───────────────────────────────────────────────────────────────────
@@ -644,24 +644,10 @@ Payment and provisioning are coming next.
// ── STEP 1 ────────────────────────────────────────────────────────────────────
function goStep1() {
- const val = document.getElementById('ensInput').value.trim().toLowerCase();
- const err = document.getElementById('ensError');
- if (!val.endsWith('.eth') || val.length < 6) {
- err.classList.add('show');
- document.getElementById('ensInput').classList.add('error');
- return;
- }
- err.classList.remove('show');
- document.getElementById('ensInput').classList.remove('error');
- document.getElementById('ensInput').classList.add('valid');
- state.ens = val;
- // update mode examples
- updateModeExamples();
- buildPacksGrid();
- buildCherryGroups();
+ if (!state.siweAuthenticated) return;
goToStep(2);
}
-document.getElementById('ensInput').addEventListener('keydown', e => { if(e.key==='Enter') goStep1(); });
+document.getElementById('ensInput').addEventListener('keydown', e => { if(e.key==='Enter') goStep3(); });
// ── STEP 2: MODE ──────────────────────────────────────────────────────────────
function updateModeExamples() {
@@ -761,6 +747,20 @@ Payment and provisioning are coming next.
}
function goStep3() {
+ const val = document.getElementById('ensInput').value.trim().toLowerCase();
+ const err = document.getElementById('ensError');
+ if (!val.endsWith('.eth') || val.length < 6) {
+ err.classList.add('show');
+ document.getElementById('ensInput').classList.add('error');
+ return;
+ }
+ err.classList.remove('show');
+ document.getElementById('ensInput').classList.remove('error');
+ document.getElementById('ensInput').classList.add('valid');
+ state.ens = val;
+ updateModeExamples();
+ buildPacksGrid();
+ buildCherryGroups();
if (getVerbs().length === 0) { alert('Please select a pack or cherry-pick at least one verb.'); return; }
buildENSRecords();
buildSDKConfig();
@@ -783,26 +783,36 @@ Payment and provisioning are coming next.
}
}
-async function signInWithEthereum(){
+window.signInWithEthereum = async function signInWithEthereum(){
const statusEl=document.getElementById('siweStatus');
const walletEl=document.getElementById('siweWallet');
+ const errorEl=document.getElementById('siweError');
+ const btn=document.getElementById('siweAuthBtn');
+ const nextBtn=document.getElementById('step1Next');
try {
- if(!window.ethereum){ throw new Error('NO_WALLET'); }
+ 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.'); }
updateSiweModeHint();
- statusEl.textContent='Status: Requesting signature...';
- const [address]=await window.ethereum.request({ method:'eth_requestAccounts' });
+ const accounts=await window.ethereum.request({ method:'eth_requestAccounts' });
+ const address=accounts && accounts[0];
+ if(!address){ throw new Error('No wallet account selected.'); }
+ const chainIdHex=await window.ethereum.request({ method:'eth_chainId' });
+ const chainId=parseInt(chainIdHex,16);
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.'); }
const nonceData=await nonceRes.json();
- if(!nonceData.ok){ throw new Error('NONCE_FAILED'); }
+ if(!nonceData.ok || !nonceData.nonce){ throw new Error('Could not get SIWE nonce from /api/auth/nonce.'); }
const domain=window.location.host;
const uri=window.location.origin;
- const chainHex=await window.ethereum.request({ method:'eth_chainId' });
- const chainId=parseInt(chainHex,16);
const issuedAt=new Date().toISOString();
const msg=`${domain} wants you to sign in with your Ethereum account:
${address}
-CommandLayer Claim activation
+Authenticate with CommandLayer Claim activation.
URI: ${uri}
Version: 1
@@ -813,19 +823,27 @@ Payment and provisioning are coming next.
const verifyRes=await fetch('/api/auth/verify',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({message:msg,signature})});
const verify=await verifyRes.json();
if(!verify.ok){ throw new Error(verify.error||'Authentication failed'); }
- state.authenticatedAddress=verify.address; state.authStatus=verify.status; state.authChainId=verify.chainId;
- statusEl.textContent='Status: Authenticated';
+ 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';
+ nextBtn.disabled=false;
} catch (err) {
- const msg=(err && err.message)||'';
- if(msg==='NO_WALLET') statusEl.textContent='Status: No wallet found.';
- else if(msg.includes('User rejected') || msg.includes('rejected')) statusEl.textContent='Status: Wallet rejected signature.';
- else if(msg.includes('dependency unavailable')) statusEl.textContent='Status: Auth dependency unavailable.';
- else if(msg.includes('domain mismatch')) statusEl.textContent='Status: Domain mismatch.';
- else if(msg.includes('signature') || msg.includes('SIWE')) statusEl.textContent='Status: Signature invalid.';
- else statusEl.textContent='Status: Authentication failed.';
+ const msg=((err && err.message)||'Authentication failed.').trim();
+ if(err && err.code===4001){
+ errorEl.textContent='Wallet signature rejected.';
+ }else{
+ errorEl.textContent=msg;
+ }
+ errorEl.style.display='block';
+ statusEl.textContent='Not connected';
+ btn.disabled=false;
+ btn.textContent='Sign-In with Ethereum';
+ nextBtn.disabled=true;
+ state.siweAuthenticated=false;
+ console.error('SIWE auth failed', err);
}
-}
+};
function goStep5Auth(){
updateSiweModeHint();
@@ -1145,7 +1163,7 @@ Payment and provisioning are coming next.
state = {
step:1, ens:'', activationMode:'cl', capMode:'packs', selectedPack:null, cherryVerbs:[],
pubKeyB64:'', privKeyB64:'', kid:'', keyGenerated:false, keyDownloaded:false, keyAcked:false,
- _cardJson:''
+ _cardJson:'', authenticatedAddress:'', authStatus:'NOT_AUTHENTICATED', authChainId:null, siweAuthenticated:false
};
document.getElementById('ensInput').value='';
document.getElementById('ensInput').classList.remove('valid','error');