diff --git a/src/App.tsx b/src/App.tsx index 49931b9..6f9a35d 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,17 +1,28 @@ -import { BrowserRouter, Routes, Route, Navigate } from "react-router-dom"; +import { BrowserRouter, Routes, Route, Navigate, useParams } from "react-router-dom"; +import { useEffect, useState } from "react"; import Layout from "./components/Layout"; +import AppNavbar from "./components/navigation/AppNavbar"; +import { WalletProvider } from "./components/wallet-connect/Walletcontext"; import Home from "./pages/Home"; import Dashboard from "./pages/Dashboard"; import Streams from "./pages/Streams"; import Recipient from "./pages/Recipient"; import ConnectWallet from "./pages/ConnectWallet"; -import { useState, useEffect } from "react"; import Landing from "./pages/Landing"; -import AppNavbar from "./components/navigation/AppNavbar"; -import { WalletProvider } from "./components/wallet-connect/Walletcontext"; -import ErrorPage from './pages/ErrorPage'; +import TreasuryPage from "./pages/TreasuryPage"; +import ErrorPage from "./pages/ErrorPage"; import NotFound from "./pages/NotFound"; +function LegacyStreamRedirect() { + const { streamId } = useParams(); + return ( + + ); +} + export default function App() { const [theme, setTheme] = useState<"light" | "dark">(() => { const saved = localStorage.getItem("theme"); @@ -86,18 +97,23 @@ export default function App() { return ( - {/* Global navbar — anon vs connected state handled internally */} } /> } /> } /> + } /> } /> - }> + } + > } /> } /> + } /> } /> + } /> } /> } /> diff --git a/src/components/AppNavbar.tsx b/src/components/AppNavbar.tsx index a71aea4..e72c2b0 100644 --- a/src/components/AppNavbar.tsx +++ b/src/components/AppNavbar.tsx @@ -16,12 +16,12 @@ function truncateAddress(addr: string): string { function usePageTitle(): string { const { pathname } = useLocation(); - const map: Record = { - "/app": "Dashboard", - "/app/streams": "Streams", - "/app/recipient": "Recipient", - }; - return map[pathname] ?? "Dashboard"; + if (pathname === "/app") return "Dashboard"; + if (pathname.startsWith("/app/streams/")) return "Stream Detail"; + if (pathname.startsWith("/app/streams")) return "Streams"; + if (pathname.startsWith("/app/recipient")) return "Recipient"; + if (pathname.startsWith("/app/treasurypage")) return "Treasury"; + return "Dashboard"; } function MoonIcon() { @@ -310,4 +310,4 @@ const styles: Record = { dropdown: { position: "absolute", right: 0, top: "calc(100% + 8px)", minWidth: "185px", background: "var(--navbar-bg)", border: "1px solid var(--navbar-border)", borderRadius: "10px", boxShadow: "var(--navbar-shadow)", padding: "5px", zIndex: 200 }, dropdownItem: { display: "flex", alignItems: "center", gap: "8px", width: "100%", padding: "8px 10px", border: "none", background: "transparent", color: "var(--text)", fontFamily: "'Plus Jakarta Sans', system-ui, sans-serif", fontSize: "0.85rem", fontWeight: 500, cursor: "pointer", borderRadius: "6px", textAlign: "left", minHeight: "36px", transition: "background 0.15s" }, dropdownDivider: { height: "1px", background: "var(--navbar-border)", margin: "4px 0" }, -}; \ No newline at end of file +}; diff --git a/src/components/CreateStreamModal.tsx b/src/components/CreateStreamModal.tsx index fb70516..ad247a2 100644 --- a/src/components/CreateStreamModal.tsx +++ b/src/components/CreateStreamModal.tsx @@ -18,11 +18,21 @@ function isValidStellarAddress(value: string): boolean { interface CreateStreamModalProps { isOpen: boolean; onClose: () => void; - /** Called when user completes the flow and clicks "Create stream" on step 3. Use to show success modal. */ - onStreamCreated?: () => void; + onSubmit?: (payload: CreateStreamFormData) => void; } -export default function CreateStreamModal({ isOpen, onClose, onStreamCreated }: CreateStreamModalProps) { +export interface CreateStreamFormData { + recipient: string; + depositAmount: number; + accrualRate: number; + durationInMonths: number; + startTimeOption: 'now' | 'custom'; + customStartDate: string; + cliffEnabled: boolean; + cliffDate: string; +} + +export default function CreateStreamModal({ isOpen, onClose, onSubmit }: CreateStreamModalProps) { const [recipient, setRecipient] = useState(''); const [depositAmount, setDepositAmount] = useState(''); const [accrualRate, setAccrualRate] = useState('38.62'); @@ -37,12 +47,12 @@ export default function CreateStreamModal({ isOpen, onClose, onStreamCreated }: const [isSubmitting, setIsSubmitting] = useState(false); const userDeposit = 200.0; const requiredDeposit = (parseFloat(accrualRate || '0') * parseFloat(duration || '0')).toFixed(2); - const displayDeposit = depositAmount.trim() ? parseFloat(depositAmount.replace(/,/g, '')).toFixed(2) : requiredDeposit; useEffect(() => { if (!isOpen) return; const handleKeyDown = (e: KeyboardEvent) => { if (e.key === 'Escape') { + if (isSubmitting) return; onClose(); } if (e.key === 'Tab') { @@ -63,7 +73,24 @@ export default function CreateStreamModal({ isOpen, onClose, onStreamCreated }: }; document.addEventListener('keydown', handleKeyDown); return () => document.removeEventListener('keydown', handleKeyDown); - }, [isOpen, onClose]); + }, [isOpen, isSubmitting, onClose]); + + useEffect(() => { + if (!isOpen) { + setIsSubmitting(false); + } + }, [isOpen]); + + const buildSubmissionPayload = (): CreateStreamFormData => ({ + recipient: recipient.trim(), + depositAmount: parseFloat(depositAmount.replace(/,/g, '')), + accrualRate: parseFloat(accrualRate), + durationInMonths: parseFloat(duration), + startTimeOption, + customStartDate, + cliffEnabled, + cliffDate, + }); const validateStep1 = (): boolean => { if (!recipient.trim()) { @@ -138,12 +165,14 @@ export default function CreateStreamModal({ isOpen, onClose, onStreamCreated }: setError(null); setCurrentStep(3); } else if (currentStep === 3) { + if (isSubmitting) return; setIsSubmitting(true); - onStreamCreated?.(); - setTimeout(() => { - onClose(); + setError(null); + onSubmit?.(buildSubmissionPayload()); + if (!onSubmit) { setIsSubmitting(false); - }, 400); + onClose(); + } } }; @@ -158,13 +187,14 @@ export default function CreateStreamModal({ isOpen, onClose, onStreamCreated }: }; const handleCancel = () => { + if (isSubmitting) return; onClose(); }; if (!isOpen) return null; return ( -
+

Create stream

- diff --git a/src/components/Layout.css b/src/components/Layout.css index b2b0a87..115cd07 100644 --- a/src/components/Layout.css +++ b/src/components/Layout.css @@ -1,6 +1,6 @@ .app-layout { display: flex; - flex-direction: column; /* ← change row to column */ + flex-direction: column; min-height: 100vh; position: relative; background: var(--bg); @@ -12,8 +12,6 @@ overflow: hidden; } -.app-layout__sidebar { - width: 220px; .app-sidebar { width: 244px; background: var(--surface); @@ -94,6 +92,12 @@ color: #ecf4ff; } +.app-nav-link.is-active { + background: rgba(45, 212, 191, 0.12); + border: 1px solid rgba(45, 212, 191, 0.2); + color: #ecfeff; +} + .app-nav-badge { width: 1.6rem; height: 1.6rem; @@ -148,6 +152,7 @@ flex-direction: column; flex: 1; min-width: 0; + min-height: 0; } .app-mobile-topbar { diff --git a/src/components/Layout.tsx b/src/components/Layout.tsx index 28a6279..7b43ef9 100644 --- a/src/components/Layout.tsx +++ b/src/components/Layout.tsx @@ -1,8 +1,8 @@ import { useState } from "react"; -import { Link, Outlet } from "react-router-dom"; +import { NavLink, Outlet, useLocation } from "react-router-dom"; import ConnectWalletModal from "./ConnectWalletModal"; import Footer from "./Footer"; -import "./layout.css"; +import "./Layout.css"; type NavItem = { to: string; label: string; shortLabel: string }; @@ -17,75 +17,98 @@ interface LayoutProps { theme?: "light" | "dark"; } -export default function Layout({ theme: _theme = "light" }: LayoutProps) { +export default function Layout({ + onThemeToggle: _onThemeToggle, + theme: _theme = "light", +}: LayoutProps) { + const location = useLocation(); const [isModalOpen, setIsModalOpen] = useState(false); const [isSidebarCollapsed, setIsSidebarCollapsed] = useState(false); const [isMobileSidebarOpen, setIsMobileSidebarOpen] = useState(false); - + const showFooter = !location.pathname.includes("/treasurypage"); const closeMobileSidebar = () => setIsMobileSidebarOpen(false); return (
- - +
+
+ +
Fluxora
+
- - +
+ +
-
-
- -
Fluxora
-
- -
- -
- -
+ {showFooter ?
: null} +
+ ) : null} +
+ +
+
+
+ {state === "pending" ? ( + + +
+

+ {title} +

+

+ {description} +

+
+
+ + {details.length > 0 ? ( +
+ {details.map((detail) => ( +
+ {detail.label} + + {detail.value} + +
+ ))} +
+ ) : null} + + {note ? ( +
+

{noteTitle}

+

{note}

+
+ ) : null} + + {actions.length > 0 ? ( +
+ {actions.map((action, index) => { + const variantClassName = + action.variant === "secondary" + ? styles.actionSecondary + : action.variant === "ghost" + ? styles.actionGhost + : styles.actionPrimary; + + return ( + + ); + })} +
+ ) : null} +
+
+
+ ); +} diff --git a/src/components/TreasuryOverviewLoading.tsx b/src/components/TreasuryOverviewLoading.tsx index 083e907..3c5d796 100644 --- a/src/components/TreasuryOverviewLoading.tsx +++ b/src/components/TreasuryOverviewLoading.tsx @@ -1,4 +1,3 @@ -import React from "react"; import { Skeleton, SkeletonCard } from "./Skeleton"; import "./skeleton.css"; diff --git a/src/components/treasuryOverviewPage/Header.tsx b/src/components/treasuryOverviewPage/Header.tsx index 4cddc07..b3f8f2f 100644 --- a/src/components/treasuryOverviewPage/Header.tsx +++ b/src/components/treasuryOverviewPage/Header.tsx @@ -11,7 +11,7 @@ export default function Header() {
); -} \ No newline at end of file +} diff --git a/src/components/treasuryOverviewPage/Metric.ts b/src/components/treasuryOverviewPage/Metric.ts index ca9b4d4..a58551d 100644 --- a/src/components/treasuryOverviewPage/Metric.ts +++ b/src/components/treasuryOverviewPage/Metric.ts @@ -1,10 +1,9 @@ -import React from "react"; -import { ReactNode } from "react"; +import type { ReactNode } from "react"; export interface Metric { // icon can be a URL string, an emoji, or a full React node such as an - icon: React.ReactNode; + icon: ReactNode; label: string; value: string; desc: string; -} \ No newline at end of file +} diff --git a/src/components/treasuryOverviewPage/RecentStreams.tsx b/src/components/treasuryOverviewPage/RecentStreams.tsx index 6d100fe..1fc6a4e 100644 --- a/src/components/treasuryOverviewPage/RecentStreams.tsx +++ b/src/components/treasuryOverviewPage/RecentStreams.tsx @@ -9,7 +9,7 @@ export default function RecentStreams() {

Recent streams

); -} \ No newline at end of file +} diff --git a/src/components/treasuryOverviewPage/StreamRow.tsx b/src/components/treasuryOverviewPage/StreamRow.tsx index e501270..e505575 100644 --- a/src/components/treasuryOverviewPage/StreamRow.tsx +++ b/src/components/treasuryOverviewPage/StreamRow.tsx @@ -26,7 +26,7 @@ export default function StreamRow({ stream }: Props) {
- Available to withdraw immediately + {balance > 0 + ? "Available to withdraw immediately" + : "Your available balance is fully settled"}
- + + + + +

{stream.summary}

+ +
+
+ Recipient + {stream.recipientName} + {stream.recipientAddress} +
+
+ Streaming rate + {formatMonthlyRate(stream.monthlyRate)} +
+ Runs through {formatDate(stream.endDate)} +
+
+
+ Withdrawable now + {formatUsdc(stream.withdrawableAmount)} +
+ Next unlock {formatDate(stream.nextUnlockDate)} +
+
+
+ +
+
+ Funding window progress + {stream.progress}% +
+ +
+ + {expanded ? ( +
+
+ + + +
+ +
+
+

Deep-dive summary

+
+
+ Treasury +
+ {stream.treasuryName} +
+ {stream.treasuryAddress} +
+
+
+
+ Cliff date +
+ {formatDate(stream.cliffDate)} +
+
+
+ Health note +
+ {stream.healthNote} +
+
+
+ Audit note +
+ {stream.auditNote} +
+
+
+
+ + +
+
+ ) : null} + + ); +} + +function StreamDetail({ + stream, + onBack, + onCreateSimilar, + onCopyAddress, +}: { + stream: StreamRecord; + onBack: () => void; + onCreateSimilar: () => void; + onCopyAddress: () => void; +}) { + return ( + <> + + +
+
+

Stream deep dive

+
+

{stream.name}

+ + +
+

{stream.summary}

+
+ {stream.id} + {stream.recipientName} + {formatMonthlyRate(stream.monthlyRate)} + Ends {formatDate(stream.endDate)} +
+
+ +
+ + + View in explorer + + +
+
+ +
+ + + + +
+ +
+
+
+

Configuration

+
+
+ Recipient +
+ {stream.recipientName} +
+ {stream.recipientAddress} +
+
+
+
+ Treasury source +
+ {stream.treasuryName} +
+ {stream.treasuryAddress} +
+
+
+
+ Asset +
{stream.asset}
+
+
+ Streaming rate +
+ {formatMonthlyRate(stream.monthlyRate)} +
+
+
+ Start date +
+ {formatDate(stream.startDate)} +
+
+
+ Cliff date +
+ {formatDate(stream.cliffDate)} +
+
+
+ End date +
+ {formatDate(stream.endDate)} +
+
+
+ Next unlock +
+ {formatDate(stream.nextUnlockDate)} +
+
+
+
+ +
+

Timeline

+
+ {stream.timeline.map((event) => ( +
+
+ {formatDate(event.date)} +
+
{event.title}
+
{event.detail}
+
+ ))} +
+
+
+ + +
+ + ); +} + +function StreamNotFound({ + streamId, + onBack, + onCreateStream, +}: { + streamId: string; + onBack: () => void; + onCreateStream: () => void; +}) { + return ( +
+

Stream detail

+

We couldn't find {streamId}

+

+ The requested stream does not exist in the current demo dataset. Head + back to the streams list or create a new one from this branch. +

+
+ + +
+
+ ); } -// ── Main Page ───────────────────────────────────────────────────────────────── export default function Streams() { + const navigate = useNavigate(); + const { streamId } = useParams(); + const [loading, setLoading] = useState(true); - // Replace with real stream data from API/wallet - const [streams] = useState([]); - // Replace with real wallet connection state + const [createdStreams, setCreatedStreams] = useState([]); + const [statusFilter, setStatusFilter] = useState("All"); + const [expandedStreamId, setExpandedStreamId] = useState( + streamRecords[0]?.id ?? "", + ); + const [isCreateModalOpen, setIsCreateModalOpen] = useState(false); + const [createFeedback, setCreateFeedback] = + useState(null); + const [toastMessage, setToastMessage] = useState(""); const walletConnected = true; useEffect(() => { - const t = setTimeout(() => setLoading(false), 2000); - return () => clearTimeout(t); + const timer = window.setTimeout(() => setLoading(false), 2000); + return () => window.clearTimeout(timer); }, []); + useEffect(() => { + if (!toastMessage) return undefined; + + const timer = window.setTimeout(() => setToastMessage(""), 2200); + return () => window.clearTimeout(timer); + }, [toastMessage]); + if (loading) return ; - const [isCreateModalOpen, setIsCreateModalOpen] = useState(false); - const [isSuccessModalOpen, setIsSuccessModalOpen] = useState(false); - const [createdStream] = useState({ id: "529", url: "https://fluxora.io/stream/529" }); + const allStreams = [...createdStreams, ...streamRecords]; + const activeStreams = allStreams.filter((stream) => stream.status === "Active"); + const monthlyOutflow = activeStreams.reduce( + (total, stream) => total + stream.monthlyRate, + 0, + ); + const withdrawableNow = allStreams.reduce( + (total, stream) => total + stream.withdrawableAmount, + 0, + ); + const nextUnlock = activeStreams + .map((stream) => stream.nextUnlockDate) + .filter(Boolean) + .sort()[0]; + const visibleStreams = + statusFilter === "All" + ? allStreams + : allStreams.filter((stream) => stream.status === statusFilter); + const selectedStream = streamId + ? allStreams.find((stream) => stream.id === streamId) + : undefined; + const hasStreams = allStreams.length > 0; + const showEmptyState = !selectedStream && (!walletConnected || !hasStreams); + const effectiveExpandedId = visibleStreams.some( + (stream) => stream.id === expandedStreamId, + ) + ? expandedStreamId + : visibleStreams[0]?.id; - return ( -
-

Streams

-

- Create and manage USDC streams. Set rate, duration, and cliff from the treasury. -

+ const handleCreateStream = () => { + setIsCreateModalOpen(true); + }; + + const handleCopyRecipient = async (stream: StreamRecord) => { + try { + await navigator.clipboard.writeText(stream.recipientAddress); + setToastMessage(`Recipient for ${stream.name} copied.`); + } catch { + setToastMessage("Clipboard access is unavailable in this browser."); + } + }; + + const runCreateStreamTransaction = async ( + payload: CreateStreamFormData, + previousFeedback?: CreateTransactionFeedback, + ) => { + const streamNumber = streamRecords.length + createdStreams.length + 1; + const generatedId = + previousFeedback?.streamId ?? + `STR-${String(streamNumber).padStart(3, "0")}`; + const streamUrl = + previousFeedback?.streamUrl ?? + new URL(`/app/streams/${generatedId}`, window.location.origin).toString(); + + setIsCreateModalOpen(false); + setCreateFeedback({ + status: "pending", + streamId: generatedId, + streamUrl, + payload, + }); + + try { + const outcome = await simulateTransaction({ + actionLabel: "Stream creation", + }); + const createdRecord = createStreamRecord(payload, generatedId); + + setCreatedStreams((current) => + current.some((stream) => stream.id === generatedId) + ? current + : [createdRecord, ...current], + ); + setCreateFeedback({ + status: "success", + streamId: generatedId, + streamUrl, + payload, + completedAt: outcome.completedAt, + ledgerLabel: outcome.ledgerLabel, + transactionHash: outcome.transactionHash, + }); + } catch (error) { + setCreateFeedback({ + status: "failure", + streamId: generatedId, + streamUrl, + payload, + errorMessage: + error instanceof Error + ? error.message + : "We couldn't create the stream right now.", + }); + } + }; + + const createFeedbackDetails = createFeedback + ? createFeedback.status === "success" + ? [ + { label: "Stream ID", value: createFeedback.streamId, mono: true }, + { + label: "Recipient", + value: formatAddress(createFeedback.payload.recipient), + mono: true, + }, + { + label: "Locked amount", + value: `${createFeedback.payload.depositAmount.toFixed(2)} USDC`, + }, + { + label: "Transaction hash", + value: createFeedback.transactionHash ?? "Pending hash", + mono: true, + }, + { + label: "Finalized", + value: `${createFeedback.completedAt} • ${createFeedback.ledgerLabel}`, + }, + ] + : [ + { + label: "Recipient", + value: formatAddress(createFeedback.payload.recipient), + mono: true, + }, + { + label: "Funding request", + value: `${createFeedback.payload.depositAmount.toFixed(2)} USDC`, + }, + { + label: "Stream rate", + value: `${createFeedback.payload.accrualRate.toFixed(2)} USDC / month`, + }, + { + label: "Start", + value: + createFeedback.payload.startTimeOption === "custom" && + createFeedback.payload.customStartDate + ? new Date(createFeedback.payload.customStartDate).toLocaleString() + : "Immediately after approval", + }, + ] + : []; + + const createFeedbackActions = createFeedback + ? createFeedback.status === "success" + ? [ + { + label: "View stream", + onClick: () => { + const currentStreamId = createFeedback.streamId; + setCreateFeedback(null); + navigate(`/app/streams/${currentStreamId}`); + }, + autoFocus: true, + }, + { + label: "Create another", + onClick: () => { + setCreateFeedback(null); + setIsCreateModalOpen(true); + }, + variant: "secondary" as const, + }, + { + label: "Close", + onClick: () => setCreateFeedback(null), + variant: "ghost" as const, + }, + ] + : createFeedback.status === "failure" + ? [ + { + label: "Retry transaction", + onClick: () => + void runCreateStreamTransaction( + createFeedback.payload, + createFeedback, + ), + autoFocus: true, + }, + { + label: "Back to form", + onClick: () => { + setCreateFeedback(null); + setIsCreateModalOpen(true); + }, + variant: "secondary" as const, + }, + { + label: "Dismiss", + onClick: () => setCreateFeedback(null), + variant: "ghost" as const, + }, + ] + : [] + : []; + + if (streamId && !selectedStream) { + return ( + <> + navigate("/app/streams")} + onCreateStream={handleCreateStream} + /> - {streams.length === 0 ? ( - setIsCreateModalOpen(true) : undefined} + setIsCreateModalOpen(false)} + onSubmit={(payload) => void runCreateStreamTransaction(payload)} /> + setCreateFeedback(null)} + /> + + ); + } + + return ( +
+ {selectedStream ? ( + navigate("/app/streams")} + onCreateSimilar={handleCreateStream} + onCopyAddress={() => void handleCopyRecipient(selectedStream)} + /> + ) : showEmptyState ? ( +
+

Streams

+

+ Create and manage USDC streams. Set rate, duration, and cliff from + the treasury. +

+ navigate("/connect-wallet") + } + /> +
) : ( -
- - - - - - - - - - - {streams.map((stream) => ( - - - - - - + <> +
+
+

Treasury streaming

+

Streams

+

+ Review every stream from a single operational surface, then open + a deeper layout when treasury context, recipient balance, or + audit notes need closer attention. +

+
+
+ + +
+
+ +
+
+ Active streams + {activeStreams.length} +

Currently accruing from treasury capital.

+
+
+ Monthly outflow + {formatUsdc(monthlyOutflow)} +

Projected accrual across active streams each month.

+
+
+ Withdrawable now + {formatUsdc(withdrawableNow)} +

Available to recipients right now without a refill.

+
+
+ Next unlock + {formatDate(nextUnlock)} +

Earliest upcoming release window across active streams.

+
+
+ +
+
+
+

Deep-dive ready list

+

+ Expand a row for the operational summary or open the full + stream detail route for the complete layout. +

+
+
+ {STATUS_FILTERS.map((filter) => ( + + ))} +
+
+ +
+ {visibleStreams.map((stream) => ( + + setExpandedStreamId((current) => + current === stream.id ? "" : stream.id, + ) + } + onOpenDetail={() => navigate(`/app/streams/${stream.id}`)} + /> ))} -
-
StreamRecipientRateStatus
{stream.id}{stream.recipient}{stream.rate}{stream.status}
-
+
+ + )} setIsCreateModalOpen(false)} - onStreamCreated={() => { - setIsCreateModalOpen(false); - setIsSuccessModalOpen(true); - }} + onSubmit={(payload) => void runCreateStreamTransaction(payload)} /> - setIsSuccessModalOpen(false)} - streamId={createdStream.id} - streamUrl={createdStream.url} - onCreateAnother={() => { - setIsSuccessModalOpen(false); - setIsCreateModalOpen(true); - }} + setCreateFeedback(null)} /> + + {toastMessage ? ( +
+ {toastMessage} +
+ ) : null}
); } - -// ── Styles ──────────────────────────────────────────────────────────────────── -const tableWrap: React.CSSProperties = { - marginTop: "1.5rem", - background: "var(--surface)", - border: "1px solid var(--border)", - borderRadius: 12, - overflow: "hidden", -}; - -const table: React.CSSProperties = { - width: '100%', - borderCollapse: 'collapse', -}; diff --git a/tsconfig.tsbuildinfo b/tsconfig.tsbuildinfo index 0559334..28bc442 100644 --- a/tsconfig.tsbuildinfo +++ b/tsconfig.tsbuildinfo @@ -1 +1 @@ -{"root":["./src/App.tsx","./src/main.tsx","./src/vite-env.d.ts","./src/components/AppNavbar.tsx","./src/components/ConnectButton.tsx","./src/components/ConnectWalletModal.example.tsx","./src/components/ConnectWalletModal.tsx","./src/components/CreateStreamModal.tsx","./src/components/EmptyState.tsx","./src/components/Footer.tsx","./src/components/GetStartedCTA.tsx","./src/components/GlowingDot.tsx","./src/components/Layout.tsx","./src/components/Navbar.tsx","./src/components/NewsletterSection.tsx","./src/components/RecentStreams.tsx","./src/components/RecipientEmptyState.tsx","./src/components/RecipientLoading.tsx","./src/components/Sidebar.tsx","./src/components/Skeleton.tsx","./src/components/StreamsLoading.tsx","./src/components/TreasuryEmptyState.tsx","./src/components/TreasuryOverviewLoading.tsx","./src/components/ValuePropositionSection.tsx","./src/components/WalletIcon.tsx","./src/components/Streams/StreamCreatedModal.tsx","./src/components/landing-page/HeroSection.tsx","./src/components/landing-page/TrustSection.tsx","./src/components/treasuryOverviewPage/DemoBanner.tsx","./src/components/treasuryOverviewPage/Header.tsx","./src/components/treasuryOverviewPage/Metric.ts","./src/components/treasuryOverviewPage/MetricCard.tsx","./src/components/treasuryOverviewPage/Metrics.tsx","./src/components/treasuryOverviewPage/RecentStreams.tsx","./src/components/treasuryOverviewPage/StatusPill.tsx","./src/components/treasuryOverviewPage/Stream.ts","./src/components/treasuryOverviewPage/StreamRow.tsx","./src/components/treasuryOverviewPage/StreamsTable.tsx","./src/components/treasuryOverviewPage/sample-streams.tsx","./src/components/treasuryOverviewPage/useTreasury.ts","./src/components/wallet-connect/Walletbutton.tsx","./src/components/wallet-connect/Walletconnectmodal.tsx","./src/components/wallet-connect/Walletcontext.tsx","./src/lib/utils.ts","./src/pages/ConnectWallet.tsx","./src/pages/Dashboard.tsx","./src/pages/ErrorPage.tsx","./src/pages/Home.tsx","./src/pages/Landing.tsx","./src/pages/LandingPage.tsx","./src/pages/NotFound.tsx","./src/pages/Recipient.tsx","./src/pages/Streams.tsx","./src/pages/TreasuryPage.tsx"],"errors":true,"version":"5.9.3"} \ No newline at end of file +{"root":["./src/App.tsx","./src/main.tsx","./src/vite-env.d.ts","./src/components/AppNavbar.tsx","./src/components/ConnectButton.tsx","./src/components/ConnectWalletModal.example.tsx","./src/components/ConnectWalletModal.tsx","./src/components/CreateStreamModal.tsx","./src/components/EmptyState.tsx","./src/components/Footer.tsx","./src/components/GetStartedCTA.tsx","./src/components/GlowingDot.tsx","./src/components/Layout.tsx","./src/components/Navbar.tsx","./src/components/NewsletterSection.tsx","./src/components/RecentStreams.tsx","./src/components/RecipientEmptyState.tsx","./src/components/RecipientLoading.tsx","./src/components/Sidebar.tsx","./src/components/Skeleton.tsx","./src/components/StreamsLoading.tsx","./src/components/TransactionFeedbackModal.tsx","./src/components/TreasuryEmptyState.tsx","./src/components/TreasuryOverviewLoading.tsx","./src/components/ValuePropositionSection.tsx","./src/components/WalletIcon.tsx","./src/components/Streams/StreamCreatedModal.tsx","./src/components/landing-page/HeroSection.tsx","./src/components/landing-page/TrustSection.tsx","./src/components/navigation/AppNavbar.tsx","./src/components/navigation/NavLink.tsx","./src/components/navigation/WalletStatus.tsx","./src/components/treasuryOverviewPage/DemoBanner.tsx","./src/components/treasuryOverviewPage/Header.tsx","./src/components/treasuryOverviewPage/Metric.ts","./src/components/treasuryOverviewPage/MetricCard.tsx","./src/components/treasuryOverviewPage/Metrics.tsx","./src/components/treasuryOverviewPage/RecentStreams.tsx","./src/components/treasuryOverviewPage/StatusPill.tsx","./src/components/treasuryOverviewPage/Stream.ts","./src/components/treasuryOverviewPage/StreamRow.tsx","./src/components/treasuryOverviewPage/StreamsTable.tsx","./src/components/treasuryOverviewPage/sample-streams.tsx","./src/components/treasuryOverviewPage/useTreasury.ts","./src/components/wallet-connect/Walletbutton.tsx","./src/components/wallet-connect/Walletconnectmodal.tsx","./src/components/wallet-connect/Walletcontext.tsx","./src/data/streamRecords.ts","./src/lib/transactionFeedback.ts","./src/lib/utils.ts","./src/pages/ConnectWallet.tsx","./src/pages/Dashboard.tsx","./src/pages/ErrorPage.tsx","./src/pages/Home.tsx","./src/pages/Landing.tsx","./src/pages/LandingPage.tsx","./src/pages/NotFound.tsx","./src/pages/Recipient.tsx","./src/pages/Streams.tsx","./src/pages/TreasuryPage.tsx"],"version":"5.9.3"} \ No newline at end of file