create-stylus-ide 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Readme.MD +1515 -0
- package/cli.js +28 -0
- package/frontend/.vscode/settings.json +9 -0
- package/frontend/app/api/chat/route.ts +101 -0
- package/frontend/app/api/check-setup/route.ts +93 -0
- package/frontend/app/api/cleanup/route.ts +14 -0
- package/frontend/app/api/compile/route.ts +95 -0
- package/frontend/app/api/compile-stream/route.ts +98 -0
- package/frontend/app/api/complete/route.ts +86 -0
- package/frontend/app/api/deploy/route.ts +118 -0
- package/frontend/app/api/export-abi/route.ts +58 -0
- package/frontend/app/favicon.ico +0 -0
- package/frontend/app/globals.css +177 -0
- package/frontend/app/layout.tsx +29 -0
- package/frontend/app/ml/page.tsx +694 -0
- package/frontend/app/page.tsx +1132 -0
- package/frontend/app/providers.tsx +18 -0
- package/frontend/app/qlearning/page.tsx +188 -0
- package/frontend/app/raytracing/page.tsx +268 -0
- package/frontend/components/abi/ABIDialog.tsx +132 -0
- package/frontend/components/ai/AICompletionPopup.tsx +76 -0
- package/frontend/components/ai/ChatPanel.tsx +292 -0
- package/frontend/components/ai/QuickActions.tsx +128 -0
- package/frontend/components/blockchain/BlockchainContractBanner.tsx +64 -0
- package/frontend/components/blockchain/BlockchainLoadingDialog.tsx +188 -0
- package/frontend/components/deploy/DeployDialog.tsx +334 -0
- package/frontend/components/editor/FileTabs.tsx +181 -0
- package/frontend/components/editor/MonacoEditor.tsx +306 -0
- package/frontend/components/file-tree/ContextMenu.tsx +110 -0
- package/frontend/components/file-tree/DeleteConfirmDialog.tsx +61 -0
- package/frontend/components/file-tree/FileInputDialog.tsx +97 -0
- package/frontend/components/file-tree/FileNode.tsx +60 -0
- package/frontend/components/file-tree/FileTree.tsx +259 -0
- package/frontend/components/file-tree/FileTreeSkeleton.tsx +26 -0
- package/frontend/components/file-tree/FolderNode.tsx +105 -0
- package/frontend/components/github/GitHubLoadingDialog.tsx +201 -0
- package/frontend/components/github/GitHubMetadataBanner.tsx +61 -0
- package/frontend/components/github/LoadFromGitHubDialog.tsx +125 -0
- package/frontend/components/github/URLCopyButton.tsx +60 -0
- package/frontend/components/interact/ContractInteraction.tsx +323 -0
- package/frontend/components/interact/ContractPlaceholder.tsx +41 -0
- package/frontend/components/orbit/BenchmarkDialog.tsx +342 -0
- package/frontend/components/orbit/OrbitExplorer.tsx +273 -0
- package/frontend/components/project/ProjectActions.tsx +176 -0
- package/frontend/components/q-learning/ContractConfig.tsx +172 -0
- package/frontend/components/q-learning/MazeGrid.tsx +346 -0
- package/frontend/components/q-learning/PathAnimation.tsx +384 -0
- package/frontend/components/q-learning/QTableHeatmap.tsx +300 -0
- package/frontend/components/q-learning/TrainingForm.tsx +349 -0
- package/frontend/components/ray-tracing/ContractConfig.tsx +245 -0
- package/frontend/components/ray-tracing/MintingForm.tsx +280 -0
- package/frontend/components/ray-tracing/RenderCanvas.tsx +228 -0
- package/frontend/components/ray-tracing/RenderingPanel.tsx +259 -0
- package/frontend/components/ray-tracing/StyleControls.tsx +217 -0
- package/frontend/components/setup/SetupGuide.tsx +290 -0
- package/frontend/components/ui/KeyboardShortcutHint.tsx +74 -0
- package/frontend/components/ui/alert-dialog.tsx +157 -0
- package/frontend/components/ui/alert.tsx +66 -0
- package/frontend/components/ui/badge.tsx +46 -0
- package/frontend/components/ui/button.tsx +62 -0
- package/frontend/components/ui/card.tsx +92 -0
- package/frontend/components/ui/context-menu.tsx +252 -0
- package/frontend/components/ui/dialog.tsx +143 -0
- package/frontend/components/ui/dropdown-menu.tsx +257 -0
- package/frontend/components/ui/input.tsx +21 -0
- package/frontend/components/ui/label.tsx +24 -0
- package/frontend/components/ui/progress.tsx +31 -0
- package/frontend/components/ui/scroll-area.tsx +58 -0
- package/frontend/components/ui/select.tsx +190 -0
- package/frontend/components/ui/separator.tsx +28 -0
- package/frontend/components/ui/sheet.tsx +139 -0
- package/frontend/components/ui/skeleton.tsx +13 -0
- package/frontend/components/ui/slider.tsx +63 -0
- package/frontend/components/ui/sonner.tsx +40 -0
- package/frontend/components/ui/tabs.tsx +66 -0
- package/frontend/components/ui/textarea.tsx +18 -0
- package/frontend/components/wallet/ConnectButton.tsx +167 -0
- package/frontend/components/wallet/FaucetButton.tsx +256 -0
- package/frontend/components.json +22 -0
- package/frontend/eslint.config.mjs +18 -0
- package/frontend/hooks/useAICompletion.ts +75 -0
- package/frontend/hooks/useBlockchainLoader.ts +58 -0
- package/frontend/hooks/useChats.ts +137 -0
- package/frontend/hooks/useCompilation.ts +173 -0
- package/frontend/hooks/useFileTabs.ts +178 -0
- package/frontend/hooks/useGitHubLoader.ts +50 -0
- package/frontend/hooks/useKeyboardShortcuts.ts +47 -0
- package/frontend/hooks/usePanelState.ts +115 -0
- package/frontend/hooks/useProjectState.ts +276 -0
- package/frontend/hooks/useResponsive.ts +29 -0
- package/frontend/lib/abi-parser.ts +58 -0
- package/frontend/lib/blockchain-api.ts +374 -0
- package/frontend/lib/blockchain-explorers.ts +75 -0
- package/frontend/lib/blockchain-loader.ts +112 -0
- package/frontend/lib/cargo-template.ts +64 -0
- package/frontend/lib/compilation.ts +529 -0
- package/frontend/lib/constants.ts +31 -0
- package/frontend/lib/deployment.ts +176 -0
- package/frontend/lib/file-utils.ts +83 -0
- package/frontend/lib/github-api.ts +246 -0
- package/frontend/lib/github-loader.ts +369 -0
- package/frontend/lib/ml-contract-template.txt +900 -0
- package/frontend/lib/orbit-chains.ts +181 -0
- package/frontend/lib/output-formatter.ts +68 -0
- package/frontend/lib/project-manager.ts +632 -0
- package/frontend/lib/ray-tracing-abi.ts +206 -0
- package/frontend/lib/storage.ts +189 -0
- package/frontend/lib/templates.ts +1662 -0
- package/frontend/lib/url-parser.ts +188 -0
- package/frontend/lib/utils.ts +6 -0
- package/frontend/lib/wagmi-config.ts +24 -0
- package/frontend/next.config.ts +7 -0
- package/frontend/package-lock.json +16259 -0
- package/frontend/package.json +60 -0
- package/frontend/postcss.config.mjs +7 -0
- package/frontend/public/file.svg +1 -0
- package/frontend/public/globe.svg +1 -0
- package/frontend/public/ml-weights/.gitkeep +0 -0
- package/frontend/public/ml-weights/model.pkl +0 -0
- package/frontend/public/ml-weights/model_weights.json +27102 -0
- package/frontend/public/ml-weights/test_samples.json +7888 -0
- package/frontend/public/next.svg +1 -0
- package/frontend/public/vercel.svg +1 -0
- package/frontend/public/window.svg +1 -0
- package/frontend/scripts/check-env.js +52 -0
- package/frontend/scripts/setup.js +285 -0
- package/frontend/tailwind.config.ts +64 -0
- package/frontend/tsconfig.json +34 -0
- package/frontend/types/blockchain.ts +63 -0
- package/frontend/types/github.ts +54 -0
- package/frontend/types/project.ts +106 -0
- package/ml-training/README.md +56 -0
- package/ml-training/train_tiny_model.py +325 -0
- package/ml-training/update_template.py +59 -0
- package/package.json +30 -0
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
|
|
4
|
+
import { WagmiProvider } from 'wagmi';
|
|
5
|
+
import { config } from '@/lib/wagmi-config';
|
|
6
|
+
import { useState } from 'react';
|
|
7
|
+
|
|
8
|
+
export function Providers({ children }: { children: React.ReactNode }) {
|
|
9
|
+
const [queryClient] = useState(() => new QueryClient());
|
|
10
|
+
|
|
11
|
+
return (
|
|
12
|
+
<WagmiProvider config={config}>
|
|
13
|
+
<QueryClientProvider client={queryClient}>
|
|
14
|
+
{children}
|
|
15
|
+
</QueryClientProvider>
|
|
16
|
+
</WagmiProvider>
|
|
17
|
+
);
|
|
18
|
+
}
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
//mazegrid.tsx (your qlearning/page.tsx)
|
|
2
|
+
'use client';
|
|
3
|
+
|
|
4
|
+
import { useState, useRef } from 'react';
|
|
5
|
+
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card';
|
|
6
|
+
import { Brain, ArrowLeft } from 'lucide-react';
|
|
7
|
+
import Link from 'next/link';
|
|
8
|
+
import { ConnectButton } from '@/components/wallet/ConnectButton';
|
|
9
|
+
import { MazeGrid } from '@/components/q-learning/MazeGrid';
|
|
10
|
+
import { ContractConfig } from '@/components/q-learning/ContractConfig';
|
|
11
|
+
import { TrainingForm } from '@/components/q-learning/TrainingForm';
|
|
12
|
+
import { QTableHeatmap } from '@/components/q-learning/QTableHeatmap';
|
|
13
|
+
import { PathAnimation } from '@/components/q-learning/PathAnimation';
|
|
14
|
+
|
|
15
|
+
export default function QLearningDemoPage() {
|
|
16
|
+
// Input field state (can change freely without restarting reads)
|
|
17
|
+
const [contractAddress, setContractAddress] = useState<string>('');
|
|
18
|
+
|
|
19
|
+
// ✅ Stable, “connected” address used for reads
|
|
20
|
+
const [connectedContractAddress, setConnectedContractAddress] = useState<string>('');
|
|
21
|
+
|
|
22
|
+
const [isConnected, setIsConnected] = useState(false);
|
|
23
|
+
const [isTrained, setIsTrained] = useState(false);
|
|
24
|
+
|
|
25
|
+
const [mazeConfig, setMazeConfig] = useState<{
|
|
26
|
+
size: number;
|
|
27
|
+
startRow: number;
|
|
28
|
+
startCol: number;
|
|
29
|
+
goalRow: number;
|
|
30
|
+
goalCol: number;
|
|
31
|
+
} | null>(null);
|
|
32
|
+
|
|
33
|
+
// Use refreshNonce instead of key-remount
|
|
34
|
+
const [refreshKey, setRefreshKey] = useState(0);
|
|
35
|
+
|
|
36
|
+
// ✅ Guard: prevents multiple refresh triggers if TrainingForm calls callback more than once
|
|
37
|
+
const trainingCompleteLockRef = useRef(false);
|
|
38
|
+
|
|
39
|
+
const handleTrainingComplete = () => {
|
|
40
|
+
if (trainingCompleteLockRef.current) return;
|
|
41
|
+
trainingCompleteLockRef.current = true;
|
|
42
|
+
|
|
43
|
+
setRefreshKey((prev) => prev + 1);
|
|
44
|
+
setIsTrained(true);
|
|
45
|
+
|
|
46
|
+
// unlock after a short window (covers receipt/status double-calls)
|
|
47
|
+
setTimeout(() => {
|
|
48
|
+
trainingCompleteLockRef.current = false;
|
|
49
|
+
}, 1500);
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
const activeAddress = connectedContractAddress || '';
|
|
53
|
+
|
|
54
|
+
return (
|
|
55
|
+
<main className="min-h-screen bg-background">
|
|
56
|
+
|
|
57
|
+
<div className="container mx-auto p-6 max-w-7xl">
|
|
58
|
+
{/* Title */}
|
|
59
|
+
<div className="text-center mb-8">
|
|
60
|
+
<div className="flex items-center justify-center gap-3 mb-3">
|
|
61
|
+
<Brain className="h-8 w-8 text-primary" />
|
|
62
|
+
<h1 className="text-3xl font-bold">Q-Learning Maze Agent</h1>
|
|
63
|
+
</div>
|
|
64
|
+
<p className="text-muted-foreground">Reinforcement learning agent that learns to navigate a maze on-chain</p>
|
|
65
|
+
<p className="text-sm text-muted-foreground mt-2">
|
|
66
|
+
Based on <strong>Watkins (1989)</strong> - "Learning from Delayed Rewards"
|
|
67
|
+
</p>
|
|
68
|
+
</div>
|
|
69
|
+
|
|
70
|
+
<div className="grid grid-cols-1 lg:grid-cols-3 gap-6">
|
|
71
|
+
{/* Left Column: Contract Config + Training */}
|
|
72
|
+
<div className="lg:col-span-1 space-y-6">
|
|
73
|
+
<ContractConfig
|
|
74
|
+
contractAddress={contractAddress}
|
|
75
|
+
setContractAddress={setContractAddress}
|
|
76
|
+
isConnected={isConnected}
|
|
77
|
+
setIsConnected={setIsConnected}
|
|
78
|
+
setConnectedContractAddress={setConnectedContractAddress}
|
|
79
|
+
setMazeConfig={setMazeConfig}
|
|
80
|
+
setIsTrained={setIsTrained}
|
|
81
|
+
/>
|
|
82
|
+
|
|
83
|
+
{isConnected && activeAddress && (
|
|
84
|
+
<TrainingForm
|
|
85
|
+
contractAddress={activeAddress}
|
|
86
|
+
isConnected={isConnected}
|
|
87
|
+
onTrainingComplete={handleTrainingComplete}
|
|
88
|
+
/>
|
|
89
|
+
)}
|
|
90
|
+
</div>
|
|
91
|
+
|
|
92
|
+
{/* Center/Right: Visualizations */}
|
|
93
|
+
<div className="lg:col-span-2 space-y-6">
|
|
94
|
+
{/* Maze Grid */}
|
|
95
|
+
<Card>
|
|
96
|
+
<CardHeader>
|
|
97
|
+
<CardTitle>Maze Environment</CardTitle>
|
|
98
|
+
<CardDescription>5×5 grid with walls (gray), start (green), and goal (red)</CardDescription>
|
|
99
|
+
</CardHeader>
|
|
100
|
+
<CardContent>
|
|
101
|
+
{mazeConfig && activeAddress ? (
|
|
102
|
+
<MazeGrid
|
|
103
|
+
// ✅ do NOT key-remount
|
|
104
|
+
refreshNonce={refreshKey}
|
|
105
|
+
size={mazeConfig.size}
|
|
106
|
+
startPos={[mazeConfig.startRow, mazeConfig.startCol]}
|
|
107
|
+
goalPos={[mazeConfig.goalRow, mazeConfig.goalCol]}
|
|
108
|
+
contractAddress={activeAddress}
|
|
109
|
+
isConnected={isConnected}
|
|
110
|
+
/>
|
|
111
|
+
) : (
|
|
112
|
+
<div className="flex items-center justify-center h-96 text-muted-foreground">
|
|
113
|
+
<div className="text-center">
|
|
114
|
+
<Brain className="h-12 w-12 mx-auto mb-3 opacity-50" />
|
|
115
|
+
<p>Connect to a deployed Q-Learning contract to view the maze</p>
|
|
116
|
+
</div>
|
|
117
|
+
</div>
|
|
118
|
+
)}
|
|
119
|
+
</CardContent>
|
|
120
|
+
</Card>
|
|
121
|
+
|
|
122
|
+
{/* Path Animation */}
|
|
123
|
+
{mazeConfig && activeAddress && (
|
|
124
|
+
<PathAnimation
|
|
125
|
+
contractAddress={activeAddress}
|
|
126
|
+
size={mazeConfig.size}
|
|
127
|
+
startPos={[mazeConfig.startRow, mazeConfig.startCol]}
|
|
128
|
+
goalPos={[mazeConfig.goalRow, mazeConfig.goalCol]}
|
|
129
|
+
isConnected={isConnected}
|
|
130
|
+
isTrained={isTrained}
|
|
131
|
+
/>
|
|
132
|
+
)}
|
|
133
|
+
|
|
134
|
+
{/* Q-Table Heatmap */}
|
|
135
|
+
{mazeConfig && activeAddress && (
|
|
136
|
+
<QTableHeatmap
|
|
137
|
+
contractAddress={activeAddress}
|
|
138
|
+
size={mazeConfig.size}
|
|
139
|
+
isConnected={isConnected}
|
|
140
|
+
isTrained={isTrained}
|
|
141
|
+
/>
|
|
142
|
+
)}
|
|
143
|
+
</div>
|
|
144
|
+
</div>
|
|
145
|
+
|
|
146
|
+
{/* How It Works Section */}
|
|
147
|
+
<Card className="mt-6">
|
|
148
|
+
<CardHeader>
|
|
149
|
+
<CardTitle>How Q-Learning Works</CardTitle>
|
|
150
|
+
</CardHeader>
|
|
151
|
+
<CardContent className="space-y-4 text-sm">
|
|
152
|
+
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
|
153
|
+
<div>
|
|
154
|
+
<h4 className="font-semibold mb-2">Bellman Optimality Equation</h4>
|
|
155
|
+
<div className="bg-muted p-3 rounded-md font-mono text-xs">
|
|
156
|
+
Q*(s,a) = R(s,a) + γ·max<sub>a'</sub> Q*(s',a')
|
|
157
|
+
</div>
|
|
158
|
+
<p className="text-muted-foreground mt-2 text-xs">
|
|
159
|
+
The optimal Q-value is the immediate reward plus the discounted maximum future reward.
|
|
160
|
+
</p>
|
|
161
|
+
</div>
|
|
162
|
+
|
|
163
|
+
<div>
|
|
164
|
+
<h4 className="font-semibold mb-2">Q-Learning Update Rule</h4>
|
|
165
|
+
<div className="bg-muted p-3 rounded-md font-mono text-xs">
|
|
166
|
+
Q(s,a) ← Q(s,a) + α[r + γ·max<sub>a'</sub> Q(s',a') - Q(s,a)]
|
|
167
|
+
</div>
|
|
168
|
+
<p className="text-muted-foreground mt-2 text-xs">
|
|
169
|
+
Update Q-values by learning from the temporal difference error.
|
|
170
|
+
</p>
|
|
171
|
+
</div>
|
|
172
|
+
</div>
|
|
173
|
+
|
|
174
|
+
<div className="pt-4 border-t border-border">
|
|
175
|
+
<h4 className="font-semibold mb-2">Parameters</h4>
|
|
176
|
+
<ul className="space-y-1 text-xs text-muted-foreground">
|
|
177
|
+
<li>• <strong>α (alpha)</strong>: Learning rate - how much to update Q-values (0.0 - 1.0)</li>
|
|
178
|
+
<li>• <strong>γ (gamma)</strong>: Discount factor - importance of future rewards (0.0 - 1.0)</li>
|
|
179
|
+
<li>• <strong>ε (epsilon)</strong>: Exploration rate - probability of random actions (0.0 - 1.0)</li>
|
|
180
|
+
<li>• <strong>Episodes</strong>: Number of complete runs from start to goal</li>
|
|
181
|
+
</ul>
|
|
182
|
+
</div>
|
|
183
|
+
</CardContent>
|
|
184
|
+
</Card>
|
|
185
|
+
</div>
|
|
186
|
+
</main>
|
|
187
|
+
);
|
|
188
|
+
}
|
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { useState } from 'react';
|
|
4
|
+
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card';
|
|
5
|
+
import { Sparkles, ArrowLeft } from 'lucide-react';
|
|
6
|
+
import Link from 'next/link';
|
|
7
|
+
import { ConnectButton } from '@/components/wallet/ConnectButton';
|
|
8
|
+
import { ContractConfig } from '@/components/ray-tracing/ContractConfig';
|
|
9
|
+
import { StyleControls } from '@/components/ray-tracing/StyleControls';
|
|
10
|
+
import { RenderCanvas } from '@/components/ray-tracing/RenderCanvas';
|
|
11
|
+
import { MintingForm } from '@/components/ray-tracing/MintingForm';
|
|
12
|
+
import { RenderingPanel } from '@/components/ray-tracing/RenderingPanel';
|
|
13
|
+
|
|
14
|
+
export default function RayTracingDemoPage() {
|
|
15
|
+
// Contract state
|
|
16
|
+
const [mnnAddress, setMnnAddress] = useState<string>('');
|
|
17
|
+
const [nftAddress, setNftAddress] = useState<string>('');
|
|
18
|
+
const [isMnnConnected, setIsMnnConnected] = useState(false);
|
|
19
|
+
const [isNftConnected, setIsNftConnected] = useState(false);
|
|
20
|
+
|
|
21
|
+
// Style parameters (0-100%)
|
|
22
|
+
const [warmth, setWarmth] = useState(75);
|
|
23
|
+
const [intensity, setIntensity] = useState(60);
|
|
24
|
+
const [depth, setDepth] = useState(50);
|
|
25
|
+
|
|
26
|
+
// Predicted colors from MNN
|
|
27
|
+
const [predictedColors, setPredictedColors] = useState<[number, number, number] | null>(null);
|
|
28
|
+
|
|
29
|
+
// Camera position
|
|
30
|
+
const [cameraX, setCameraX] = useState(0);
|
|
31
|
+
const [cameraY, setCameraY] = useState(0);
|
|
32
|
+
const [cameraZ, setCameraZ] = useState(0);
|
|
33
|
+
|
|
34
|
+
// Minted token
|
|
35
|
+
const [mintedTokenId, setMintedTokenId] = useState<bigint | null>(null);
|
|
36
|
+
|
|
37
|
+
// Rendering state
|
|
38
|
+
const [isRendering, setIsRendering] = useState(false);
|
|
39
|
+
const [renderedPixels, setRenderedPixels] = useState<number[] | null>(null);
|
|
40
|
+
|
|
41
|
+
const handleMintSuccess = (tokenId: bigint) => {
|
|
42
|
+
setMintedTokenId(tokenId);
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
return (
|
|
46
|
+
<main className="min-h-screen bg-background">
|
|
47
|
+
|
|
48
|
+
<div className="container mx-auto p-6 max-w-7xl">
|
|
49
|
+
{/* Title */}
|
|
50
|
+
<div className="text-center mb-8">
|
|
51
|
+
<div className="flex items-center justify-center gap-3 mb-3">
|
|
52
|
+
<Sparkles className="h-8 w-8 text-primary" />
|
|
53
|
+
<h1 className="text-3xl font-bold">Ray Tracing NFT Engine</h1>
|
|
54
|
+
</div>
|
|
55
|
+
<p className="text-muted-foreground">
|
|
56
|
+
On-chain 3D graphics with neural network aesthetic generation
|
|
57
|
+
</p>
|
|
58
|
+
<p className="text-sm text-muted-foreground mt-2">
|
|
59
|
+
Dual smart contracts: <strong>Mini Neural Network</strong> (3→4→2) + <strong>Ray Tracing Engine</strong>
|
|
60
|
+
</p>
|
|
61
|
+
</div>
|
|
62
|
+
|
|
63
|
+
<div className="grid grid-cols-1 lg:grid-cols-3 gap-6">
|
|
64
|
+
{/* Left Column: Contract Config + Style Controls + Minting */}
|
|
65
|
+
<div className="lg:col-span-1 space-y-6">
|
|
66
|
+
<ContractConfig
|
|
67
|
+
mnnAddress={mnnAddress}
|
|
68
|
+
setMnnAddress={setMnnAddress}
|
|
69
|
+
nftAddress={nftAddress}
|
|
70
|
+
setNftAddress={setNftAddress}
|
|
71
|
+
isMnnConnected={isMnnConnected}
|
|
72
|
+
setIsMnnConnected={setIsMnnConnected}
|
|
73
|
+
isNftConnected={isNftConnected}
|
|
74
|
+
setIsNftConnected={setIsNftConnected}
|
|
75
|
+
/>
|
|
76
|
+
|
|
77
|
+
{isMnnConnected && (
|
|
78
|
+
<StyleControls
|
|
79
|
+
warmth={warmth}
|
|
80
|
+
setWarmth={setWarmth}
|
|
81
|
+
intensity={intensity}
|
|
82
|
+
setIntensity={setIntensity}
|
|
83
|
+
depth={depth}
|
|
84
|
+
setDepth={setDepth}
|
|
85
|
+
mnnAddress={mnnAddress}
|
|
86
|
+
predictedColors={predictedColors}
|
|
87
|
+
setPredictedColors={setPredictedColors}
|
|
88
|
+
/>
|
|
89
|
+
)}
|
|
90
|
+
|
|
91
|
+
{isNftConnected && predictedColors && (
|
|
92
|
+
<MintingForm
|
|
93
|
+
nftAddress={nftAddress}
|
|
94
|
+
isNftConnected={isNftConnected}
|
|
95
|
+
predictedColors={predictedColors}
|
|
96
|
+
cameraX={cameraX}
|
|
97
|
+
cameraY={cameraY}
|
|
98
|
+
cameraZ={cameraZ}
|
|
99
|
+
onMintSuccess={handleMintSuccess}
|
|
100
|
+
/>
|
|
101
|
+
)}
|
|
102
|
+
</div>
|
|
103
|
+
|
|
104
|
+
{/* Center/Right: Canvas + Rendering */}
|
|
105
|
+
<div className="lg:col-span-2 space-y-6">
|
|
106
|
+
<RenderCanvas
|
|
107
|
+
predictedColors={predictedColors}
|
|
108
|
+
cameraX={cameraX}
|
|
109
|
+
setCameraX={setCameraX}
|
|
110
|
+
cameraY={cameraY}
|
|
111
|
+
setCameraY={setCameraY}
|
|
112
|
+
cameraZ={cameraZ}
|
|
113
|
+
setCameraZ={setCameraZ}
|
|
114
|
+
isRendering={isRendering}
|
|
115
|
+
renderedPixels={renderedPixels}
|
|
116
|
+
nftAddress={nftAddress}
|
|
117
|
+
isNftConnected={isNftConnected}
|
|
118
|
+
/>
|
|
119
|
+
|
|
120
|
+
{/* On-Chain Rendering Panel */}
|
|
121
|
+
|
|
122
|
+
{isNftConnected && (
|
|
123
|
+
<RenderingPanel
|
|
124
|
+
nftAddress={nftAddress}
|
|
125
|
+
isNftConnected={isNftConnected}
|
|
126
|
+
mintedTokenId={mintedTokenId}
|
|
127
|
+
/>
|
|
128
|
+
)}
|
|
129
|
+
|
|
130
|
+
{/* Token Info (shows after minting) */}
|
|
131
|
+
{mintedTokenId !== null && (
|
|
132
|
+
<Card>
|
|
133
|
+
<CardHeader>
|
|
134
|
+
<CardTitle>Your NFT</CardTitle>
|
|
135
|
+
<CardDescription>
|
|
136
|
+
Successfully minted on-chain
|
|
137
|
+
</CardDescription>
|
|
138
|
+
</CardHeader>
|
|
139
|
+
<CardContent>
|
|
140
|
+
<div className="bg-muted p-4 rounded-md space-y-2">
|
|
141
|
+
<div className="flex justify-between text-sm">
|
|
142
|
+
<span className="text-muted-foreground">Token ID:</span>
|
|
143
|
+
<span className="font-mono">{mintedTokenId.toString()}</span>
|
|
144
|
+
</div>
|
|
145
|
+
<div className="flex justify-between text-sm">
|
|
146
|
+
<span className="text-muted-foreground">Contract:</span>
|
|
147
|
+
<span className="font-mono text-xs">{nftAddress.slice(0, 6)}...{nftAddress.slice(-4)}</span>
|
|
148
|
+
</div>
|
|
149
|
+
<div className="flex justify-between text-sm">
|
|
150
|
+
<span className="text-muted-foreground">Status:</span>
|
|
151
|
+
<span className="text-green-500">✓ Minted</span>
|
|
152
|
+
</div>
|
|
153
|
+
</div>
|
|
154
|
+
<p className="text-xs text-muted-foreground mt-3">
|
|
155
|
+
Ready for Step 5: Full on-chain rendering!
|
|
156
|
+
</p>
|
|
157
|
+
</CardContent>
|
|
158
|
+
</Card>
|
|
159
|
+
)}
|
|
160
|
+
</div>
|
|
161
|
+
</div>
|
|
162
|
+
|
|
163
|
+
{/* Deployment Instructions */}
|
|
164
|
+
{!isMnnConnected && !isNftConnected && (
|
|
165
|
+
<Card className="mt-6">
|
|
166
|
+
<CardHeader>
|
|
167
|
+
<CardTitle>Quick Deployment Guide</CardTitle>
|
|
168
|
+
<CardDescription>
|
|
169
|
+
Deploy contracts and start creating on-chain 3D art
|
|
170
|
+
</CardDescription>
|
|
171
|
+
</CardHeader>
|
|
172
|
+
<CardContent className="space-y-4 text-sm">
|
|
173
|
+
<div className="space-y-2">
|
|
174
|
+
<h4 className="font-semibold">Step 1: Deploy Mini Neural Network</h4>
|
|
175
|
+
<ol className="list-decimal list-inside space-y-1 text-xs text-muted-foreground pl-4">
|
|
176
|
+
<li>Go back to IDE homepage</li>
|
|
177
|
+
<li>Load template: "Mini Neural Network (Aesthetic AI)"</li>
|
|
178
|
+
<li>Click "Compile" - should succeed</li>
|
|
179
|
+
<li>Connect wallet (Arbitrum Sepolia)</li>
|
|
180
|
+
<li>Click "Deploy" - pay gas (~$0.01)</li>
|
|
181
|
+
<li>Copy contract address from success message</li>
|
|
182
|
+
<li>Paste address in "MNN Contract" field above</li>
|
|
183
|
+
</ol>
|
|
184
|
+
</div>
|
|
185
|
+
|
|
186
|
+
<div className="space-y-2 pt-2 border-t border-border">
|
|
187
|
+
<h4 className="font-semibold">Step 2: Deploy Ray Tracing NFT</h4>
|
|
188
|
+
<ol className="list-decimal list-inside space-y-1 text-xs text-muted-foreground pl-4">
|
|
189
|
+
<li>Load template: "Ray Tracing NFT Engine"</li>
|
|
190
|
+
<li>Click "Compile" - should succeed</li>
|
|
191
|
+
<li>Click "Deploy" - pay gas (~$0.02)</li>
|
|
192
|
+
<li>Copy contract address</li>
|
|
193
|
+
<li>Paste address in "NFT Contract" field above</li>
|
|
194
|
+
</ol>
|
|
195
|
+
</div>
|
|
196
|
+
|
|
197
|
+
<div className="space-y-2 pt-2 border-t border-border">
|
|
198
|
+
<h4 className="font-semibold">Step 3: Generate & Mint</h4>
|
|
199
|
+
<ol className="list-decimal list-inside space-y-1 text-xs text-muted-foreground pl-4">
|
|
200
|
+
<li>Adjust style sliders (warmth, intensity, depth)</li>
|
|
201
|
+
<li>Click "Preview Colors (FREE)" - 0 gas cost!</li>
|
|
202
|
+
<li>See predicted colors from neural network</li>
|
|
203
|
+
<li>Adjust camera position and background colors</li>
|
|
204
|
+
<li>Click "Mint NFT" - stores parameters on-chain</li>
|
|
205
|
+
<li>Ready for Step 5: Full on-chain ray tracing!</li>
|
|
206
|
+
</ol>
|
|
207
|
+
</div>
|
|
208
|
+
|
|
209
|
+
<div className="bg-green-500/10 border border-green-500/20 p-3 rounded-md text-xs text-green-400 mt-4">
|
|
210
|
+
<p className="font-medium mb-1">💰 Cost Breakdown:</p>
|
|
211
|
+
<ul className="space-y-1">
|
|
212
|
+
<li>• MNN Deploy: ~$0.01 (one-time)</li>
|
|
213
|
+
<li>• NFT Deploy: ~$0.02 (one-time)</li>
|
|
214
|
+
<li>• Preview Colors: FREE (view function)</li>
|
|
215
|
+
<li>• Mint NFT: ~$0.0001 (per mint)</li>
|
|
216
|
+
<li>• Render: ~$0.003 (per render, Step 5)</li>
|
|
217
|
+
</ul>
|
|
218
|
+
</div>
|
|
219
|
+
</CardContent>
|
|
220
|
+
</Card>
|
|
221
|
+
)}
|
|
222
|
+
|
|
223
|
+
{/* How It Works Section */}
|
|
224
|
+
<Card className="mt-6">
|
|
225
|
+
<CardHeader>
|
|
226
|
+
<CardTitle>How Ray Tracing Works</CardTitle>
|
|
227
|
+
</CardHeader>
|
|
228
|
+
<CardContent className="space-y-4 text-sm">
|
|
229
|
+
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
|
230
|
+
<div>
|
|
231
|
+
<h4 className="font-semibold mb-2">Phase 1: Neural Network Preview (FREE)</h4>
|
|
232
|
+
<div className="bg-muted p-3 rounded-md text-xs">
|
|
233
|
+
<code>view_aesthetic(warmth, intensity, depth) → RGB</code>
|
|
234
|
+
</div>
|
|
235
|
+
<p className="text-muted-foreground mt-2 text-xs">
|
|
236
|
+
Mini neural network (3→4→2) predicts aesthetic colors based on style parameters.
|
|
237
|
+
Runs on-chain as VIEW function (0 gas cost).
|
|
238
|
+
</p>
|
|
239
|
+
</div>
|
|
240
|
+
|
|
241
|
+
<div>
|
|
242
|
+
<h4 className="font-semibold mb-2">Phase 2: NFT Minting</h4>
|
|
243
|
+
<div className="bg-muted p-3 rounded-md text-xs">
|
|
244
|
+
<code>mint(colors, camera) → token_id</code>
|
|
245
|
+
</div>
|
|
246
|
+
<p className="text-muted-foreground mt-2 text-xs">
|
|
247
|
+
Store 21 bytes of rendering parameters on-chain. Creates unique NFT that anyone can render later.
|
|
248
|
+
</p>
|
|
249
|
+
</div>
|
|
250
|
+
</div>
|
|
251
|
+
|
|
252
|
+
<div className="pt-4 border-t border-border">
|
|
253
|
+
<h4 className="font-semibold mb-2">Ray-Sphere Intersection Math</h4>
|
|
254
|
+
<div className="bg-muted p-3 rounded-md font-mono text-xs">
|
|
255
|
+
<div>Given: Ray = O + D·t, Sphere = |P - C|² = r²</div>
|
|
256
|
+
<div className="mt-1">Solve: a·t² + b·t + c = 0</div>
|
|
257
|
+
<div className="mt-1">Where: a = D·D, b = 2(O-C)·D, c = (O-C)·(O-C) - r²</div>
|
|
258
|
+
</div>
|
|
259
|
+
<p className="text-muted-foreground mt-2 text-xs">
|
|
260
|
+
Discriminant determines if ray hits sphere. If yes, calculate intersection point and lighting.
|
|
261
|
+
</p>
|
|
262
|
+
</div>
|
|
263
|
+
</CardContent>
|
|
264
|
+
</Card>
|
|
265
|
+
</div>
|
|
266
|
+
</main>
|
|
267
|
+
);
|
|
268
|
+
}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { useState } from 'react';
|
|
4
|
+
import {
|
|
5
|
+
Dialog,
|
|
6
|
+
DialogContent,
|
|
7
|
+
DialogDescription,
|
|
8
|
+
DialogHeader,
|
|
9
|
+
DialogTitle,
|
|
10
|
+
} from '@/components/ui/dialog';
|
|
11
|
+
import { Button } from '@/components/ui/button';
|
|
12
|
+
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs';
|
|
13
|
+
import { Copy, Check, FileJson, FileCode } from 'lucide-react';
|
|
14
|
+
|
|
15
|
+
interface ABIDialogProps {
|
|
16
|
+
open: boolean;
|
|
17
|
+
onOpenChange: (open: boolean) => void;
|
|
18
|
+
abi: string | null;
|
|
19
|
+
solidity: string | null;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export function ABIDialog({ open, onOpenChange, abi, solidity }: ABIDialogProps) {
|
|
23
|
+
const [copiedABI, setCopiedABI] = useState(false);
|
|
24
|
+
const [copiedSolidity, setCopiedSolidity] = useState(false);
|
|
25
|
+
|
|
26
|
+
const copyToClipboard = async (text: string, type: 'abi' | 'solidity') => {
|
|
27
|
+
try {
|
|
28
|
+
await navigator.clipboard.writeText(text);
|
|
29
|
+
if (type === 'abi') {
|
|
30
|
+
setCopiedABI(true);
|
|
31
|
+
setTimeout(() => setCopiedABI(false), 2000);
|
|
32
|
+
} else {
|
|
33
|
+
setCopiedSolidity(true);
|
|
34
|
+
setTimeout(() => setCopiedSolidity(false), 2000);
|
|
35
|
+
}
|
|
36
|
+
} catch (err) {
|
|
37
|
+
console.error('Failed to copy:', err);
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
return (
|
|
42
|
+
<Dialog open={open} onOpenChange={onOpenChange}>
|
|
43
|
+
<DialogContent className="max-w-4xl max-h-[80vh] flex flex-col">
|
|
44
|
+
<DialogHeader>
|
|
45
|
+
<DialogTitle>Contract ABI</DialogTitle>
|
|
46
|
+
<DialogDescription>
|
|
47
|
+
Export your contract's Application Binary Interface
|
|
48
|
+
</DialogDescription>
|
|
49
|
+
</DialogHeader>
|
|
50
|
+
|
|
51
|
+
<Tabs defaultValue="json" className="flex-1 flex flex-col min-h-0">
|
|
52
|
+
<TabsList className="grid w-full grid-cols-2">
|
|
53
|
+
<TabsTrigger value="json" className="flex items-center gap-2">
|
|
54
|
+
<FileJson className="h-4 w-4" />
|
|
55
|
+
JSON ABI
|
|
56
|
+
</TabsTrigger>
|
|
57
|
+
<TabsTrigger value="solidity" className="flex items-center gap-2">
|
|
58
|
+
<FileCode className="h-4 w-4" />
|
|
59
|
+
Solidity Interface
|
|
60
|
+
</TabsTrigger>
|
|
61
|
+
</TabsList>
|
|
62
|
+
|
|
63
|
+
<TabsContent value="json" className="flex-1 flex flex-col min-h-0 mt-4">
|
|
64
|
+
<div className="flex items-center justify-between mb-2">
|
|
65
|
+
<span className="text-sm text-muted-foreground">
|
|
66
|
+
Copy this ABI to interact with your contract
|
|
67
|
+
</span>
|
|
68
|
+
<Button
|
|
69
|
+
variant="outline"
|
|
70
|
+
size="sm"
|
|
71
|
+
onClick={() => abi && copyToClipboard(abi, 'abi')}
|
|
72
|
+
disabled={!abi}
|
|
73
|
+
>
|
|
74
|
+
{copiedABI ? (
|
|
75
|
+
<>
|
|
76
|
+
<Check className="h-4 w-4 mr-2" />
|
|
77
|
+
Copied!
|
|
78
|
+
</>
|
|
79
|
+
) : (
|
|
80
|
+
<>
|
|
81
|
+
<Copy className="h-4 w-4 mr-2" />
|
|
82
|
+
Copy JSON
|
|
83
|
+
</>
|
|
84
|
+
)}
|
|
85
|
+
</Button>
|
|
86
|
+
</div>
|
|
87
|
+
<div className="flex-1 overflow-auto bg-muted rounded-lg p-4 font-mono text-xs">
|
|
88
|
+
{abi ? (
|
|
89
|
+
<pre className="whitespace-pre-wrap wrap-break-words">{abi}</pre>
|
|
90
|
+
) : (
|
|
91
|
+
<p className="text-muted-foreground">No ABI available</p>
|
|
92
|
+
)}
|
|
93
|
+
</div>
|
|
94
|
+
</TabsContent>
|
|
95
|
+
|
|
96
|
+
<TabsContent value="solidity" className="flex-1 flex flex-col min-h-0 mt-4">
|
|
97
|
+
<div className="flex items-center justify-between mb-2">
|
|
98
|
+
<span className="text-sm text-muted-foreground">
|
|
99
|
+
Solidity interface for your contract
|
|
100
|
+
</span>
|
|
101
|
+
<Button
|
|
102
|
+
variant="outline"
|
|
103
|
+
size="sm"
|
|
104
|
+
onClick={() => solidity && copyToClipboard(solidity, 'solidity')}
|
|
105
|
+
disabled={!solidity}
|
|
106
|
+
>
|
|
107
|
+
{copiedSolidity ? (
|
|
108
|
+
<>
|
|
109
|
+
<Check className="h-4 w-4 mr-2" />
|
|
110
|
+
Copied!
|
|
111
|
+
</>
|
|
112
|
+
) : (
|
|
113
|
+
<>
|
|
114
|
+
<Copy className="h-4 w-4 mr-2" />
|
|
115
|
+
Copy Interface
|
|
116
|
+
</>
|
|
117
|
+
)}
|
|
118
|
+
</Button>
|
|
119
|
+
</div>
|
|
120
|
+
<div className="flex-1 overflow-auto bg-muted rounded-lg p-4 font-mono text-xs">
|
|
121
|
+
{solidity ? (
|
|
122
|
+
<pre className="whitespace-pre-wrap wrap-break-words">{solidity}</pre>
|
|
123
|
+
) : (
|
|
124
|
+
<p className="text-muted-foreground">No Solidity interface available</p>
|
|
125
|
+
)}
|
|
126
|
+
</div>
|
|
127
|
+
</TabsContent>
|
|
128
|
+
</Tabs>
|
|
129
|
+
</DialogContent>
|
|
130
|
+
</Dialog>
|
|
131
|
+
);
|
|
132
|
+
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { useState, useEffect } from 'react';
|
|
4
|
+
import { Button } from '@/components/ui/button';
|
|
5
|
+
import { Card } from '@/components/ui/card';
|
|
6
|
+
import { Loader2, Sparkles, Check, X } from 'lucide-react';
|
|
7
|
+
|
|
8
|
+
interface AICompletionPopupProps {
|
|
9
|
+
visible: boolean;
|
|
10
|
+
position: { top: number; left: number };
|
|
11
|
+
onAccept: (completion: string) => void;
|
|
12
|
+
onReject: () => void;
|
|
13
|
+
isLoading: boolean;
|
|
14
|
+
completion: string;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function AICompletionPopup({
|
|
18
|
+
visible,
|
|
19
|
+
position,
|
|
20
|
+
onAccept,
|
|
21
|
+
onReject,
|
|
22
|
+
isLoading,
|
|
23
|
+
completion,
|
|
24
|
+
}: AICompletionPopupProps) {
|
|
25
|
+
if (!visible) return null;
|
|
26
|
+
|
|
27
|
+
return (
|
|
28
|
+
<Card
|
|
29
|
+
className="fixed z-50 p-3 shadow-lg border-primary/50"
|
|
30
|
+
style={{
|
|
31
|
+
top: position.top,
|
|
32
|
+
left: position.left,
|
|
33
|
+
maxWidth: '500px',
|
|
34
|
+
minWidth: '300px',
|
|
35
|
+
}}
|
|
36
|
+
>
|
|
37
|
+
<div className="space-y-3">
|
|
38
|
+
<div className="flex items-center gap-2 text-sm">
|
|
39
|
+
<Sparkles className="h-4 w-4 text-primary" />
|
|
40
|
+
<span className="font-medium">AI Suggestion</span>
|
|
41
|
+
</div>
|
|
42
|
+
|
|
43
|
+
{isLoading ? (
|
|
44
|
+
<div className="flex items-center gap-2 text-sm text-muted-foreground py-4">
|
|
45
|
+
<Loader2 className="h-4 w-4 animate-spin" />
|
|
46
|
+
Generating completion...
|
|
47
|
+
</div>
|
|
48
|
+
) : completion ? (
|
|
49
|
+
<>
|
|
50
|
+
<div className="bg-muted rounded-md p-2 font-mono text-xs max-h-48 overflow-auto">
|
|
51
|
+
<pre className="whitespace-pre-wrap">{completion}</pre>
|
|
52
|
+
</div>
|
|
53
|
+
<div className="flex gap-2">
|
|
54
|
+
<Button
|
|
55
|
+
size="sm"
|
|
56
|
+
onClick={() => onAccept(completion)}
|
|
57
|
+
className="flex-1"
|
|
58
|
+
>
|
|
59
|
+
<Check className="h-4 w-4 mr-1" />
|
|
60
|
+
Accept (Tab)
|
|
61
|
+
</Button>
|
|
62
|
+
<Button
|
|
63
|
+
size="sm"
|
|
64
|
+
variant="outline"
|
|
65
|
+
onClick={onReject}
|
|
66
|
+
>
|
|
67
|
+
<X className="h-4 w-4 mr-1" />
|
|
68
|
+
Reject (Esc)
|
|
69
|
+
</Button>
|
|
70
|
+
</div>
|
|
71
|
+
</>
|
|
72
|
+
) : null}
|
|
73
|
+
</div>
|
|
74
|
+
</Card>
|
|
75
|
+
);
|
|
76
|
+
}
|