Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 43 additions & 0 deletions packages/nextjs/app/analyze/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
"use client"

import { useState } from "react"
import { AnalysisInput } from "~~/components/veri-ai/analysis-input"
import { AnalysisResults } from "~~/components/veri-ai/analysis-results"
import { Footer } from "~~/components/veri-ai/footer"
import { Header } from "~~/components/veri-ai/header"
import { AnalysisData, mockAnalysisData } from "~~/data/mock-data"



export default function AnalyzePage() {
const [tokenId, setTokenId] = useState<string>("")
const [analysisData, setAnalysisData] = useState<AnalysisData | null>(null)
const [loading, setLoading] = useState(false)

const handleAnalyze = async (id: string) => {
setTokenId(id)
setLoading(true)

// Simulate API call delay
setTimeout(() => {
setAnalysisData(mockAnalysisData)
setLoading(false)
}, 1500)
}

return (
<div className="min-h-screen bg-background flex flex-col">
<Header />
<main className="flex-1 py-12 px-4">
<div className="max-w-6xl mx-auto">
{!analysisData ? (
<AnalysisInput onAnalyze={handleAnalyze} loading={loading} />
) : (
<AnalysisResults data={analysisData} onNewAnalysis={() => setAnalysisData(null)} />
)}
</div>
</main>
<Footer />
</div>
)
}
75 changes: 15 additions & 60 deletions packages/nextjs/app/page.tsx
Original file line number Diff line number Diff line change
@@ -1,63 +1,18 @@
import Link from "next/link";
import Image from "next/image";
import { ConnectedAddress } from "~~/components/ConnectedAddress";
import { FeaturesSection } from "~~/components/veri-ai/features-section";
import { Footer } from "~~/components/veri-ai/footer";
import { Header } from "~~/components/veri-ai/header";
import { HeroSection } from "~~/components/veri-ai/hero-section";

const Home = () => {
return (
<div className="flex items-center flex-col grow pt-10">
<div className="px-5">
<h1 className="text-center">
<span className="block text-2xl mb-2">Welcome to</span>
<span className="block text-4xl font-bold">Scaffold-Stark 2</span>
</h1>
<ConnectedAddress />
<p className="text-center text-lg">
Edit your smart contract{" "}
<code className="bg-underline italic text-base font-bold max-w-full break-words break-all inline-block">
your_contract.cairo
</code>{" "}
in{" "}
<code className="bg-underline italic text-base font-bold max-w-full break-words break-all inline-block">
packages/snfoundry/contracts/src
</code>
</p>
</div>

<div className="bg-container grow w-full mt-16 px-8 py-12">
<div className="flex justify-center items-center gap-12 flex-col sm:flex-row">
<div className="flex flex-col bg-base-100 relative text-[12px] px-10 py-10 text-center items-center max-w-xs rounded-3xl border border-gradient">
<div className="trapeze"></div>
<Image
src="/debug-icon.svg"
alt="icon"
width={26}
height={30}
></Image>
<p>
Tinker with your smart contract using the{" "}
<Link href="/debug" passHref className="link">
Debug Contracts
</Link>{" "}
tab.
</p>
</div>
<div className="flex flex-col bg-base-100 relative text-[12px] px-10 py-10 text-center items-center max-w-xs rounded-3xl border border-gradient">
<div className="trapeze"></div>
<Image
src="/explorer-icon.svg"
alt="icon"
width={20}
height={32}
></Image>
<p>
Play around with Multiwrite transactions using
useScaffoldMultiWrite() hook
</p>
</div>
</div>
</div>
export default function Home() {
return (
<div className="min-h-screen bg-background">
<Header />
<main>
<HeroSection />
<FeaturesSection />
</main>
<Footer />
</div>
);
};

export default Home;
)
}
22 changes: 22 additions & 0 deletions packages/nextjs/components.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"$schema": "https://ui.shadcn.com/schema.json",
"style": "new-york",
"rsc": true,
"tsx": true,
"tailwind": {
"config": "tailwind.config.ts",
"css": "styles/globals.css",
"baseColor": "neutral",
"cssVariables": true,
"prefix": ""
},
"iconLibrary": "lucide",
"aliases": {
"components": "~~/components",
"utils": "~~/lib/utils",
"ui": "~~/components/ui",
"lib": "~~/lib",
"hooks": "~~/hooks"
},
"registries": {}
}
4 changes: 2 additions & 2 deletions packages/nextjs/components/ScaffoldStarkAppWithProviders.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,9 @@ const ScaffoldStarkApp = ({ children }: { children: React.ReactNode }) => {
<div className="circle-gradient-blue w-[330px] h-[630px]"></div>
</>
)}
<Header />
{/* <Header /> */}
<main className="relative flex flex-col flex-1">{children}</main>
<Footer />
{/* <Footer /> */}
</div>
<Toaster />
</>
Expand Down
57 changes: 57 additions & 0 deletions packages/nextjs/components/ui/button.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import * as React from "react"
import { Slot } from "@radix-ui/react-slot"
import { cva, type VariantProps } from "class-variance-authority"

import { cn } from "~~/lib/utils"

const buttonVariants = cva(
"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
{
variants: {
variant: {
default:
"bg-primary text-primary-foreground shadow hover:bg-primary/90",
destructive:
"bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90",
outline:
"border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground",
secondary:
"bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80",
ghost: "hover:bg-accent hover:text-accent-foreground",
link: "text-primary underline-offset-4 hover:underline",
},
size: {
default: "h-9 px-4 py-2",
sm: "h-8 rounded-md px-3 text-xs",
lg: "h-10 rounded-md px-8",
icon: "h-9 w-9",
},
},
defaultVariants: {
variant: "default",
size: "default",
},
}
)

export interface ButtonProps
extends React.ButtonHTMLAttributes<HTMLButtonElement>,
VariantProps<typeof buttonVariants> {
asChild?: boolean
}

const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
({ className, variant, size, asChild = false, ...props }, ref) => {
const Comp = asChild ? Slot : "button"
return (
<Comp
className={cn(buttonVariants({ variant, size, className }))}
ref={ref}
{...props}
/>
)
}
)
Button.displayName = "Button"

export { Button, buttonVariants }
22 changes: 22 additions & 0 deletions packages/nextjs/components/ui/input.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import * as React from "react"

import { cn } from "~~/lib/utils"

const Input = React.forwardRef<HTMLInputElement, React.ComponentProps<"input">>(
({ className, type, ...props }, ref) => {
return (
<input
type={type}
className={cn(
"flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-base shadow-sm transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
className
)}
ref={ref}
{...props}
/>
)
}
)
Input.displayName = "Input"

export { Input }
80 changes: 80 additions & 0 deletions packages/nextjs/components/veri-ai/analysis-input.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
"use client"

import type React from "react"

import { useState } from "react"
import { Button } from "../ui/button"
import { Input } from "../ui/input"

interface AnalysisInputProps {
onAnalyze: (tokenId: string) => void
loading: boolean
}

export function AnalysisInput({ onAnalyze, loading }: AnalysisInputProps) {
const [tokenId, setTokenId] = useState("")

const handleSubmit = (e: React.FormEvent) => {
e.preventDefault()
if (tokenId.trim()) {
onAnalyze(tokenId)
}
}

return (
<div className="max-w-2xl mx-auto">
<div className="text-center mb-12">
<h1 className="text-4xl font-bold text-foreground mb-4">Analyze an Asset</h1>
<p className="text-lg text-muted-foreground">Enter a token ID to get a comprehensive risk assessment</p>
</div>

<form onSubmit={handleSubmit} className="space-y-6">
<div className="space-y-2">
<label htmlFor="tokenId" className="block text-sm font-medium text-foreground">
Token ID
</label>
<Input
id="tokenId"
placeholder="Enter token ID (e.g., 1, 2, 3...)"
value={tokenId}
onChange={(e) => setTokenId(e.target.value)}
disabled={loading}
className="text-base"
/>
<p className="text-xs text-muted-foreground">Try: 1, 2, 3, 4, or 5 for demo data</p>
</div>

<Button
type="submit"
size="lg"
className="w-full bg-primary hover:bg-primary/90"
disabled={loading || !tokenId.trim()}
>
{loading ? "Analyzing..." : "Analyze Asset"}
</Button>
</form>

<div className="mt-12 p-6 rounded-lg bg-card border border-border">
<h3 className="font-semibold text-foreground mb-4">How it works:</h3>
<ol className="space-y-3 text-sm text-muted-foreground">
<li className="flex gap-3">
<span className="font-bold text-primary">1.</span>
<span>Enter a token ID from the Starknet blockchain</span>
</li>
<li className="flex gap-3">
<span className="font-bold text-primary">2.</span>
<span>Our system retrieves the asset metadata on-chain</span>
</li>
<li className="flex gap-3">
<span className="font-bold text-primary">3.</span>
<span>AI analyzes the asset data for potential risks</span>
</li>
<li className="flex gap-3">
<span className="font-bold text-primary">4.</span>
<span>You receive a detailed risk assessment report</span>
</li>
</ol>
</div>
</div>
)
}
36 changes: 36 additions & 0 deletions packages/nextjs/components/veri-ai/analysis-results.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
"use client"

import { Button } from "../ui/button"
import { RiskScoreCard } from "./risk-score-card"
import { VerificationChecklist } from "./verification-checklist"
import { AssetDetails } from "./asset-details"


interface AnalysisResultsProps {
data: any
onNewAnalysis: () => void
}

export function AnalysisResults({ data, onNewAnalysis }: AnalysisResultsProps) {
return (
<div className="space-y-8">
<div className="flex items-center justify-between">
<h1 className="text-3xl font-bold text-foreground">Analysis Results</h1>
<Button variant="outline" onClick={onNewAnalysis}>
New Analysis
</Button>
</div>

<div className="grid grid-cols-1 lg:grid-cols-3 gap-8">
<div className="lg:col-span-1">
<RiskScoreCard riskScore={data.risk_score} summary={data.summary} />
</div>

<div className="lg:col-span-2 space-y-8">
<VerificationChecklist items={data.evidence_summary} />
<AssetDetails details={data.onchain_identity} />
</div>
</div>
</div>
)
}
Loading
Loading