diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..d78c52f --- /dev/null +++ b/.prettierignore @@ -0,0 +1,8 @@ +node_modules +.next +dist +artifacts +cache +coverage +*.lock +pnpm-lock.yaml diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..b6b0fde --- /dev/null +++ b/.prettierrc @@ -0,0 +1,10 @@ +{ + "semi": true, + "singleQuote": true, + "tabWidth": 2, + "trailingComma": "es5", + "printWidth": 100, + "bracketSpacing": true, + "arrowParens": "always", + "endOfLine": "lf" +} diff --git a/README.md b/README.md index 8d2c8f0..f40bf8d 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,7 @@ +## 🚀 CASTQUEST V3 — Autonomous Multi-Chain Creative Economy + +[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2FCastQuest%2Fcast&root-directory=apps/web) + ## 📚 Documentation All documentation lives in the `docs-site/` directory. diff --git a/apps/web/.env.example b/apps/web/.env.example new file mode 100644 index 0000000..fb2a6df --- /dev/null +++ b/apps/web/.env.example @@ -0,0 +1,31 @@ +# Required +NEXT_PUBLIC_WALLETCONNECT_PROJECT_ID=your_walletconnect_project_id + +# Alchemy API Key (for RPC) +NEXT_PUBLIC_ALCHEMY_API_KEY=your_alchemy_api_key + +# Chain Configuration (default: 8453 = Base mainnet) +NEXT_PUBLIC_CHAIN_ID=8453 + +# Contract Addresses (Base Mainnet) +NEXT_PUBLIC_CAST_TOKEN_ADDRESS=0x0000000000000000000000000000000000000000 +NEXT_PUBLIC_MARKETPLACE_ADDRESS=0x0000000000000000000000000000000000000000 +NEXT_PUBLIC_GOVERNANCE_ADDRESS=0x0000000000000000000000000000000000000000 + +# Indexer / API +NEXT_PUBLIC_API_URL=https://api.castquest.xyz +NEXT_PUBLIC_GRAPHQL_URL=https://api.castquest.xyz/graphql + +# Farcaster (for frame integration) +FARCASTER_APP_FID= +FARCASTER_APP_MNEMONIC= + +# Database (server-side only) +DATABASE_URL=postgresql://user:password@localhost:5432/castquest + +# OpenAI (for agentic features) +OPENAI_API_KEY= + +# Turbo Remote Cache (optional) +TURBO_TOKEN= +TURBO_TEAM= diff --git a/apps/web/__tests__/lib/utils.test.ts b/apps/web/__tests__/lib/utils.test.ts new file mode 100644 index 0000000..5e638a9 --- /dev/null +++ b/apps/web/__tests__/lib/utils.test.ts @@ -0,0 +1,25 @@ +import { describe, it, expect } from 'vitest'; +import { cn } from '../../lib/utils'; + +describe('cn() utility', () => { + it('combines class names', () => { + expect(cn('foo', 'bar')).toBe('foo bar'); + }); + + it('handles conditional classes', () => { + expect(cn('base', true && 'active', false && 'inactive')).toBe('base active'); + }); + + it('deduplicates Tailwind classes', () => { + const result = cn('text-sm text-lg'); + expect(result).toBe('text-lg'); + }); + + it('handles undefined and null', () => { + expect(cn('foo', undefined, null, 'bar')).toBe('foo bar'); + }); + + it('handles object syntax', () => { + expect(cn({ foo: true, bar: false, baz: true })).toBe('foo baz'); + }); +}); diff --git a/apps/web/app/admin/agents/page.tsx b/apps/web/app/admin/agents/page.tsx new file mode 100644 index 0000000..47fd828 --- /dev/null +++ b/apps/web/app/admin/agents/page.tsx @@ -0,0 +1,55 @@ +import { ShellLayout } from '../../../components/layout/ShellLayout'; +import { Card } from '../../../components/ui/Card'; + +const agents = [ + { id: 'pricing-1', name: 'PricingAgent', status: 'active', tasks: 142, errors: 0 }, + { id: 'monitor-1', name: 'MonitoringAgent', status: 'active', tasks: 89, errors: 1 }, + { id: 'creation-1', name: 'CreationAgent', status: 'idle', tasks: 56, errors: 0 }, + { id: 'auction-1', name: 'AuctionAgent', status: 'active', tasks: 203, errors: 2 }, + { id: 'fraud-1', name: 'FraudAgent', status: 'active', tasks: 31, errors: 0 }, + { id: 'curation-1', name: 'CurationAgent', status: 'idle', tasks: 77, errors: 0 }, +]; + +const statusColor: Record = { + active: 'bg-emerald-500', + idle: 'bg-yellow-500', + error: 'bg-red-500', +}; + +export default function AgentsPage() { + return ( + + +
+ + + + + + + + + + + + {agents.map((agent) => ( + + + + + + + + ))} + +
IDNameStatusTasksErrors
{agent.id}{agent.name} + + + {agent.status} + + {agent.tasks} 0 ? 'text-red-400' : ''}`}>{agent.errors}
+
+
+
+ ); +} diff --git a/apps/web/app/admin/audit/page.tsx b/apps/web/app/admin/audit/page.tsx new file mode 100644 index 0000000..bf3fcd0 --- /dev/null +++ b/apps/web/app/admin/audit/page.tsx @@ -0,0 +1,41 @@ +import { ShellLayout } from '../../../components/layout/ShellLayout'; +import { Card } from '../../../components/ui/Card'; + +const auditLogs = [ + { id: 1, time: '2025-03-13 05:30:12', actor: '0xabc…def', action: 'MarketplaceListing', details: 'Listed GAME token #142' }, + { id: 2, time: '2025-03-13 05:28:44', actor: 'PricingAgent', action: 'PriceUpdate', details: 'CAST/USDC: $0.0412' }, + { id: 3, time: '2025-03-13 05:25:11', actor: '0xfed…123', action: 'GovernanceVote', details: 'Proposal #12 — Yes' }, + { id: 4, time: '2025-03-13 05:20:09', actor: 'FraudAgent', action: 'FlaggedActivity', details: 'Suspicious wallet 0x…' }, + { id: 5, time: '2025-03-13 05:15:33', actor: '0x111…222', action: 'TokenMint', details: 'MEDIA token #203 minted' }, +]; + +export default function AuditPage() { + return ( + + +
+ + + + + + + + + + + {auditLogs.map((log) => ( + + + + + + + ))} + +
TimeActorActionDetails
{log.time}{log.actor}{log.action}{log.details}
+
+
+
+ ); +} diff --git a/apps/web/app/admin/settings/page.tsx b/apps/web/app/admin/settings/page.tsx new file mode 100644 index 0000000..7f1442a --- /dev/null +++ b/apps/web/app/admin/settings/page.tsx @@ -0,0 +1,55 @@ +import { ShellLayout } from '../../../components/layout/ShellLayout'; +import { Card } from '../../../components/ui/Card'; + +export default function SettingsPage() { + return ( + +
+ +
+
+ Protocol Fee + 2.5% +
+
+ Buyback Rate + 20% +
+
+ Min Stake + 100 CAST +
+
+ Governance Quorum + 10% +
+
+
+ +
+
+ Primary Chain + Base (8453) +
+
+ L3 Rollup + Active +
+
+
+ +
+
+ Max Concurrent Agents + 10 +
+
+ Agent Timeout + 30s +
+
+
+
+
+ ); +} diff --git a/apps/web/app/admin/treasury/page.tsx b/apps/web/app/admin/treasury/page.tsx new file mode 100644 index 0000000..dc7020f --- /dev/null +++ b/apps/web/app/admin/treasury/page.tsx @@ -0,0 +1,50 @@ +import { ShellLayout } from '../../../components/layout/ShellLayout'; +import { Card } from '../../../components/ui/Card'; + +export default function TreasuryPage() { + const metrics = [ + { label: 'Total Value Locked', value: '$2.4M', change: '+12.3%' }, + { label: 'Protocol Revenue (7d)', value: '$48.2K', change: '+5.1%' }, + { label: 'CAST Buybacks (7d)', value: '$12.8K', change: '+8.7%' }, + { label: 'Yield Generated (7d)', value: '$3.2K', change: '+2.4%' }, + ]; + + return ( + +
+
+ {metrics.map((m) => ( + +

{m.label}

+

{m.value}

+

{m.change}

+
+ ))} +
+ +
+ {[ + { label: 'Liquidity Pools', pct: 45 }, + { label: 'CAST Buybacks', pct: 25 }, + { label: 'Development Fund', pct: 20 }, + { label: 'Community Grants', pct: 10 }, + ].map((item) => ( +
+
+ {item.label} + {item.pct}% +
+
+
+
+
+ ))} +
+ +
+ + ); +} diff --git a/apps/web/app/layout.tsx b/apps/web/app/layout.tsx index 9330d0f..ccb238e 100644 --- a/apps/web/app/layout.tsx +++ b/apps/web/app/layout.tsx @@ -1,9 +1,22 @@ import './globals.css'; import type { ReactNode } from 'react'; +import type { Metadata, Viewport } from 'next'; -export const metadata = { - title: 'CASTQUEST V3', - description: 'Autonomous multi-chain creative economy' +export const metadata: Metadata = { + title: 'CastQuest V3', + description: 'Autonomous multi-chain creative economy', + manifest: '/manifest.json', + appleWebApp: { + capable: true, + statusBarStyle: 'black-translucent', + title: 'CastQuest', + }, +}; + +export const viewport: Viewport = { + width: 'device-width', + initialScale: 1, + themeColor: '#22d3ee', }; export default function RootLayout({ children }: { children: ReactNode }) { @@ -22,7 +35,7 @@ export default function RootLayout({ children }: { children: ReactNode }) {
-