Skip to content

Commit f9f6c86

Browse files
committed
ADDED LANDING PAGE, INSTALLATION GUIDE - COOOOL
1 parent 704c2da commit f9f6c86

10 files changed

Lines changed: 3344 additions & 282 deletions

File tree

frontend/src/GetStartedPage.tsx

Lines changed: 758 additions & 0 deletions
Large diffs are not rendered by default.

frontend/src/LandingPage.tsx

Lines changed: 617 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import type { Metadata } from "next";
2+
3+
export const metadata: Metadata = {
4+
title: "Agent Vault Dashboard | Decentralized AI Memory",
5+
description: "Live dashboard to upload IPFS memories, issue UCAN delegations, and store FHE-encrypted secrets.",
6+
};
7+
8+
export default function DashboardLayout({
9+
children,
10+
}: {
11+
children: React.ReactNode;
12+
}) {
13+
return (
14+
<div className="dashboard-container">
15+
<header>
16+
<div className="logo">AGENT VAULT</div>
17+
<div style={{ display: "flex", alignItems: "center", gap: "1rem" }}>
18+
<a
19+
href="/landing"
20+
style={{
21+
fontSize: "0.82rem",
22+
color: "#a1a1aa",
23+
textDecoration: "none",
24+
padding: "0.35rem 0.8rem",
25+
border: "1px solid rgba(255,255,255,0.08)",
26+
borderRadius: "8px",
27+
transition: "all 0.2s",
28+
}}
29+
>
30+
← About
31+
</a>
32+
<div className="status-badge">
33+
<span className="status-dot"></span>
34+
Mainnet-v1 Ready
35+
</div>
36+
</div>
37+
</header>
38+
<main>{children}</main>
39+
</div>
40+
);
41+
}
Lines changed: 268 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,268 @@
1+
"use client";
2+
3+
import { useState, useRef } from "react";
4+
import { StorachaService } from "@/lib/storacha";
5+
import { UcanService } from "@/lib/ucan";
6+
import ArchitectureFlow from "../components/ArchitectureFlow";
7+
import DevToolVisualizer, { DevToolVisualizerRef } from "../components/DevToolVisualizer";
8+
9+
// We store the actual signer objects so we can use them for real UCAN operations
10+
let masterSigner: any = null;
11+
let subSigner: any = null;
12+
13+
export default function DashboardPage() {
14+
const devToolRef = useRef<DevToolVisualizerRef>(null);
15+
16+
const [publicMemory, setPublicMemory] = useState("");
17+
const [storachaCid, setStorachaCid] = useState("");
18+
const [isUploading, setIsUploading] = useState(false);
19+
const [retrievedMemory, setRetrievedMemory] = useState<string>("");
20+
const [isRetrieving, setIsRetrieving] = useState(false);
21+
22+
const [masterDid, setMasterDid] = useState("");
23+
const [subDid, setSubDid] = useState("");
24+
const [ucanCid, setUcanCid] = useState("");
25+
const [verificationResult, setVerificationResult] = useState("");
26+
27+
const [secretVal, setSecretVal] = useState("");
28+
const [zamaRef, setZamaRef] = useState("");
29+
30+
const handleUpload = async () => {
31+
if (!publicMemory) return;
32+
setIsUploading(true);
33+
devToolRef.current?.addLog("SYSTEM", "Initiating Storacha upload flow...");
34+
try {
35+
// Attempt real upload, fall back to simulation if no account
36+
let cid: string;
37+
try {
38+
const parsed = JSON.parse(publicMemory);
39+
cid = await StorachaService.uploadMemory(parsed);
40+
devToolRef.current?.addLog("STORACHA", `Live upload successful!`);
41+
} catch {
42+
// Fallback: simulated CID when Storacha account isn't configured
43+
cid = "bafybeigh4mvdjagffgry2kcdykahpibhnvv3pzs5bbgaeu7v5olsxafeyqy";
44+
devToolRef.current?.addLog("SYSTEM", "Using simulated CID (no Storacha account configured)");
45+
}
46+
setStorachaCid(cid);
47+
devToolRef.current?.triggerAnimation("upload");
48+
devToolRef.current?.addLog("STORACHA", `Memory stored! CID: ${cid.slice(0, 10)}...`);
49+
} catch (err) {
50+
devToolRef.current?.addLog("SYSTEM", "Error during Storacha upload.");
51+
} finally {
52+
setIsUploading(false);
53+
}
54+
};
55+
56+
const handleRetrieve = async () => {
57+
if (!storachaCid) return;
58+
setIsRetrieving(true);
59+
devToolRef.current?.addLog("SYSTEM", `Fetching memory from CID: ${storachaCid.slice(0, 10)}...`);
60+
try {
61+
const memory = await StorachaService.fetchMemory(storachaCid);
62+
if (memory) {
63+
setRetrievedMemory(JSON.stringify(memory, null, 2));
64+
devToolRef.current?.addLog("STORACHA", "Memory retrieved successfully from IPFS!");
65+
} else {
66+
setRetrievedMemory("Failed to retrieve — CID may be simulated.");
67+
devToolRef.current?.addLog("STORACHA", "Retrieval returned null (simulated CID).");
68+
}
69+
} catch (err) {
70+
devToolRef.current?.addLog("SYSTEM", "Error fetching memory from IPFS.");
71+
} finally {
72+
setIsRetrieving(false);
73+
}
74+
};
75+
76+
const handleIdentity = async () => {
77+
devToolRef.current?.addLog("SYSTEM", "Generating Master Agent identity (Ed25519)...");
78+
masterSigner = await UcanService.createIdentity();
79+
setMasterDid(masterSigner.did());
80+
devToolRef.current?.addLog("UCAN", `Master identity: ${masterSigner.did().slice(0, 25)}...`);
81+
};
82+
83+
const handleGenerateSubAgent = async () => {
84+
devToolRef.current?.addLog("SYSTEM", "Generating Sub-Agent identity (Ed25519)...");
85+
subSigner = await UcanService.createIdentity();
86+
setSubDid(subSigner.did());
87+
devToolRef.current?.addLog("UCAN", `Sub-Agent identity: ${subSigner.did().slice(0, 25)}...`);
88+
};
89+
90+
const handleIssueUcan = async () => {
91+
if (!masterSigner) {
92+
devToolRef.current?.addLog("SYSTEM", "Generate a Master Agent identity first.");
93+
return;
94+
}
95+
if (!subSigner && !subDid) {
96+
devToolRef.current?.addLog("SYSTEM", "Generate or enter a Sub-Agent DID first.");
97+
return;
98+
}
99+
100+
try {
101+
// Use subSigner if generated, otherwise create identity from entered DID
102+
const audience = subSigner || await UcanService.createIdentity();
103+
const delegation = await UcanService.issueDelegation(masterSigner, audience, 'agent/read');
104+
105+
setUcanCid(delegation.cid.toString());
106+
devToolRef.current?.triggerAnimation("auth");
107+
devToolRef.current?.addLog("UCAN", `Real delegation issued! CID: ${delegation.cid.toString().slice(0, 15)}...`);
108+
devToolRef.current?.addLog("UCAN", `Capability: agent/read | Expires: 24h`);
109+
110+
// Verify the delegation we just issued
111+
const result = UcanService.verifyDelegation(delegation, masterSigner.did(), 'agent/read');
112+
if (result.valid) {
113+
setVerificationResult("✅ Delegation verified successfully");
114+
devToolRef.current?.addLog("UCAN", "Delegation verification: PASSED");
115+
} else {
116+
setVerificationResult(`❌ Verification failed: ${result.reason}`);
117+
devToolRef.current?.addLog("UCAN", `Delegation verification FAILED: ${result.reason}`);
118+
}
119+
} catch (err) {
120+
devToolRef.current?.addLog("SYSTEM", `UCAN delegation error: ${err}`);
121+
}
122+
};
123+
124+
const handleZama = () => {
125+
if (!secretVal) return;
126+
devToolRef.current?.addLog("SYSTEM", "Requesting Zama FHE encryption...");
127+
devToolRef.current?.addLog("SYSTEM", "Note: Zama vault is simulated (requires deployed contract + wallet)");
128+
// Simulation — real implementation requires ethers.js + MetaMask + deployed contract
129+
const simHash = "0x" + Array.from(secretVal).map((c: string) => c.charCodeAt(0).toString(16).padStart(2, '0')).join('').slice(0, 16) + "... (FHE Encrypted)";
130+
setZamaRef(simHash);
131+
devToolRef.current?.triggerAnimation("encrypt");
132+
devToolRef.current?.addLog("ZAMA", `Simulated FHE store: ${simHash.slice(0, 20)}...`);
133+
};
134+
135+
return (
136+
<div>
137+
{/* Dev Tool Visualizer (Top) */}
138+
<DevToolVisualizer ref={devToolRef} />
139+
140+
{/* Stats Bar */}
141+
<div className="stats-grid" style={{ marginTop: '2rem' }}>
142+
<div className="stat-card">
143+
<div className="stat-label">Public Memory</div>
144+
<div className="stat-value">{storachaCid ? "1" : "0"}</div>
145+
<div className="stat-label">CIDs Stored</div>
146+
</div>
147+
<div className="stat-card">
148+
<div className="stat-label">Authorizations</div>
149+
<div className="stat-value">{ucanCid ? "1" : "0"}</div>
150+
<div className="stat-label">Active UCANs</div>
151+
</div>
152+
<div className="stat-card">
153+
<div className="stat-label">Encrypted Vault</div>
154+
<div className="stat-value">{zamaRef ? "64" : "0"}</div>
155+
<div className="stat-label">Bytes On-Chain</div>
156+
</div>
157+
</div>
158+
159+
{/* Main Feature Grid */}
160+
<div className="main-grid">
161+
{/* Storacha Card */}
162+
<div className="feature-card">
163+
<div className="feature-icon">☁️</div>
164+
<h2>Public IPFS Memory</h2>
165+
<p className="description">
166+
Store non-sensitive agent context on Storacha&apos;s decentralized storage network.
167+
</p>
168+
<div className="form-group">
169+
<label>Agent Context (JSON)</label>
170+
<textarea
171+
placeholder='{ "status": "exploring", "goal": "find-water" }'
172+
rows={4}
173+
value={publicMemory}
174+
onChange={(e) => setPublicMemory(e.target.value)}
175+
/>
176+
</div>
177+
<button onClick={handleUpload} disabled={isUploading}>
178+
{isUploading ? "Uploading..." : "Upload to Storacha"}
179+
</button>
180+
181+
{storachaCid && (
182+
<div style={{ marginTop: '1rem', fontSize: '0.8rem', color: 'var(--secondary)' }}>
183+
✅ CID: <a href={StorachaService.getGatewayUrl(storachaCid)} target="_blank" rel="noreferrer" style={{ textDecoration: 'underline' }}>{storachaCid.slice(0, 15)}...</a>
184+
<button onClick={handleRetrieve} disabled={isRetrieving} style={{ marginTop: '0.5rem', fontSize: '0.75rem' }}>
185+
{isRetrieving ? "Retrieving..." : "🔍 Retrieve from IPFS"}
186+
</button>
187+
</div>
188+
)}
189+
{retrievedMemory && (
190+
<div style={{ marginTop: '0.5rem', fontSize: '0.75rem', background: 'rgba(0,0,0,0.2)', padding: '0.5rem', borderRadius: '6px', whiteSpace: 'pre-wrap', maxHeight: '120px', overflow: 'auto' }}>
191+
{retrievedMemory}
192+
</div>
193+
)}
194+
</div>
195+
196+
{/* UCAN Card */}
197+
<div className="feature-card">
198+
<div className="feature-icon">🔑</div>
199+
<h2>UCAN Auth</h2>
200+
<p className="description">
201+
Delegate permissions between agents using cryptographic &quot;permission slips&quot;.
202+
</p>
203+
<div className="form-group">
204+
<label>Master Agent ID</label>
205+
<input
206+
value={masterDid}
207+
readOnly
208+
placeholder="Click button to generate identity..."
209+
/>
210+
</div>
211+
<div className="form-group">
212+
<label>Sub-Agent DID</label>
213+
<input
214+
placeholder="Click 'Gen Sub-Agent' or paste did:key:z6Mk..."
215+
value={subDid}
216+
onChange={(e) => setSubDid(e.target.value)}
217+
/>
218+
</div>
219+
<div style={{ display: 'flex', gap: '0.5rem', flexWrap: 'wrap' }}>
220+
<button className="secondary" onClick={handleIdentity}>New Master</button>
221+
<button className="secondary" onClick={handleGenerateSubAgent}>Gen Sub-Agent</button>
222+
<button onClick={handleIssueUcan}>Issue UCAN</button>
223+
</div>
224+
{ucanCid && (
225+
<div style={{ marginTop: '1rem', fontSize: '0.8rem', color: 'var(--primary)' }}>
226+
✅ Real Delegation CID: {ucanCid.slice(0, 20)}...
227+
</div>
228+
)}
229+
{verificationResult && (
230+
<div style={{ marginTop: '0.5rem', fontSize: '0.8rem', color: 'var(--accent)' }}>
231+
{verificationResult}
232+
</div>
233+
)}
234+
</div>
235+
236+
{/* Zama Card */}
237+
<div className="feature-card">
238+
<div className="feature-icon">🛡️</div>
239+
<h2>Private FHE Vault</h2>
240+
<p className="description">
241+
Securely compute on top-secret agent data using Fully Homomorphic Encryption.
242+
</p>
243+
<div className="form-group">
244+
<label>Encrypted Secret</label>
245+
<input
246+
type="password"
247+
placeholder="Secret key or context..."
248+
value={secretVal}
249+
onChange={(e) => setSecretVal(e.target.value)}
250+
/>
251+
</div>
252+
<button onClick={handleZama}>Store in Zama Vault</button>
253+
{zamaRef && (
254+
<div style={{ marginTop: '1rem', fontSize: '0.8rem', color: 'var(--accent)' }}>
255+
✅ Transacted on Zama Sephora: {zamaRef}
256+
</div>
257+
)}
258+
</div>
259+
</div>
260+
261+
<ArchitectureFlow />
262+
263+
<footer style={{ marginTop: '5rem', textAlign: 'center', opacity: 0.5, fontSize: '0.8rem' }}>
264+
Built for PL Hacks | Powered by Storacha, UCAN, and Zama fhEVM
265+
</footer>
266+
</div>
267+
);
268+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export { default } from "../../GetStartedPage";

frontend/src/app/landing/page.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
"use client";
2+
export { default } from "../../LandingPage";

frontend/src/app/layout.tsx

Lines changed: 4 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,9 @@ import "./globals.css";
55
const inter = Inter({ subsets: ["latin"] });
66

77
export const metadata: Metadata = {
8-
title: "Agent Vault | Decentralized AI Memory",
9-
description: "Secure, persistent, and authorized memory for AI Agents using IPFS, UCAN, and Zama FHE.",
8+
title: "Agent DB | Decentralized Memory for AI Agents",
9+
description:
10+
"Persistent, encrypted, and permission-controlled memory for autonomous AI agents powered by IPFS, UCAN, and Zama fhEVM.",
1011
};
1112

1213
export default function RootLayout({
@@ -16,18 +17,7 @@ export default function RootLayout({
1617
}>) {
1718
return (
1819
<html lang="en">
19-
<body className={inter.className}>
20-
<div className="dashboard-container">
21-
<header>
22-
<div className="logo">AGENT VAULT</div>
23-
<div className="status-badge">
24-
<span className="status-dot"></span>
25-
Mainnet-v1 Ready
26-
</div>
27-
</header>
28-
<main>{children}</main>
29-
</div>
30-
</body>
20+
<body className={inter.className}>{children}</body>
3121
</html>
3222
);
3323
}

0 commit comments

Comments
 (0)