create-izi-noir 0.2.2 → 0.2.5
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/dist/index.js +353 -128
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -6,7 +6,7 @@ import { Command } from "commander";
|
|
|
6
6
|
// src/commands/init.ts
|
|
7
7
|
import path2 from "path";
|
|
8
8
|
import { execSync } from "child_process";
|
|
9
|
-
import
|
|
9
|
+
import pc3 from "picocolors";
|
|
10
10
|
|
|
11
11
|
// src/prompts/project.ts
|
|
12
12
|
import prompts from "prompts";
|
|
@@ -17,8 +17,7 @@ var TEMPLATES = [
|
|
|
17
17
|
{ title: "Balance Proof only", value: "balance-proof" }
|
|
18
18
|
];
|
|
19
19
|
var NETWORKS = [
|
|
20
|
-
{ title: "Solana
|
|
21
|
-
{ title: "EVM (Ethereum, Base, etc.)", value: "evm", description: "Uses UltraHonk proofs" }
|
|
20
|
+
{ title: "Solana", value: "solana", description: "Uses Groth16 for on-chain verification" }
|
|
22
21
|
];
|
|
23
22
|
function networkToProvider(network) {
|
|
24
23
|
return network === "solana" ? "arkworks" : "barretenberg";
|
|
@@ -117,44 +116,8 @@ async function isDirectoryEmpty(dir) {
|
|
|
117
116
|
}
|
|
118
117
|
}
|
|
119
118
|
|
|
120
|
-
// src/utils/spinner.ts
|
|
121
|
-
import pc2 from "picocolors";
|
|
122
|
-
var frames = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
|
|
123
|
-
var Spinner = class {
|
|
124
|
-
message;
|
|
125
|
-
interval = null;
|
|
126
|
-
frameIndex = 0;
|
|
127
|
-
constructor(message) {
|
|
128
|
-
this.message = message;
|
|
129
|
-
}
|
|
130
|
-
start() {
|
|
131
|
-
process.stdout.write("\x1B[?25l");
|
|
132
|
-
this.interval = setInterval(() => {
|
|
133
|
-
const frame = pc2.cyan(frames[this.frameIndex]);
|
|
134
|
-
process.stdout.write(`\r${frame} ${this.message}`);
|
|
135
|
-
this.frameIndex = (this.frameIndex + 1) % frames.length;
|
|
136
|
-
}, 80);
|
|
137
|
-
}
|
|
138
|
-
stop(success = true) {
|
|
139
|
-
if (this.interval) {
|
|
140
|
-
clearInterval(this.interval);
|
|
141
|
-
this.interval = null;
|
|
142
|
-
}
|
|
143
|
-
process.stdout.write("\x1B[?25h");
|
|
144
|
-
const icon = success ? pc2.green("\u2713") : pc2.red("\u2717");
|
|
145
|
-
process.stdout.write(`\r${icon} ${this.message}
|
|
146
|
-
`);
|
|
147
|
-
}
|
|
148
|
-
update(message) {
|
|
149
|
-
this.message = message;
|
|
150
|
-
}
|
|
151
|
-
};
|
|
152
|
-
function createSpinner(message) {
|
|
153
|
-
return new Spinner(message);
|
|
154
|
-
}
|
|
155
|
-
|
|
156
119
|
// src/utils/progress.ts
|
|
157
|
-
import
|
|
120
|
+
import pc2 from "picocolors";
|
|
158
121
|
var THINKING_PHRASES = [
|
|
159
122
|
"Initializing ZK environment",
|
|
160
123
|
"Configuring proof system",
|
|
@@ -191,15 +154,15 @@ var ProgressReporter = class {
|
|
|
191
154
|
this.showThinking();
|
|
192
155
|
}
|
|
193
156
|
showThinking() {
|
|
194
|
-
const
|
|
157
|
+
const frames = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
|
|
195
158
|
let frameIndex = 0;
|
|
196
159
|
let dotCount = 0;
|
|
197
160
|
this.thinkingInterval = setInterval(() => {
|
|
198
|
-
const frame =
|
|
161
|
+
const frame = pc2.cyan(frames[frameIndex]);
|
|
199
162
|
const phrase = THINKING_PHRASES[this.thinkingIndex % THINKING_PHRASES.length];
|
|
200
163
|
const dots = ".".repeat(dotCount % 4);
|
|
201
|
-
process.stdout.write(`\r${frame} ${
|
|
202
|
-
frameIndex = (frameIndex + 1) %
|
|
164
|
+
process.stdout.write(`\r${frame} ${pc2.dim(phrase)}${dots} `);
|
|
165
|
+
frameIndex = (frameIndex + 1) % frames.length;
|
|
203
166
|
dotCount++;
|
|
204
167
|
if (dotCount % 12 === 0) {
|
|
205
168
|
this.thinkingIndex++;
|
|
@@ -215,29 +178,29 @@ var ProgressReporter = class {
|
|
|
215
178
|
}
|
|
216
179
|
async reportFile(filename, isLast = false) {
|
|
217
180
|
const icon = getFileIcon(filename);
|
|
218
|
-
const line = ` ${icon} ${
|
|
219
|
-
process.stdout.write(" " + icon + " " +
|
|
181
|
+
const line = ` ${icon} ${pc2.dim("created")} ${pc2.white(filename)}`;
|
|
182
|
+
process.stdout.write(" " + icon + " " + pc2.dim("created") + " ");
|
|
220
183
|
for (const char of filename) {
|
|
221
|
-
process.stdout.write(
|
|
184
|
+
process.stdout.write(pc2.white(char));
|
|
222
185
|
await sleep(8 + Math.random() * 12);
|
|
223
186
|
}
|
|
224
187
|
process.stdout.write("\n");
|
|
225
188
|
this.currentLine = line;
|
|
226
189
|
}
|
|
227
190
|
async reportDirectory(dirname) {
|
|
228
|
-
process.stdout.write(` \u{1F4C1} ${
|
|
191
|
+
process.stdout.write(` \u{1F4C1} ${pc2.dim("mkdir")} ${pc2.blue(dirname)}/
|
|
229
192
|
`);
|
|
230
193
|
await sleep(30);
|
|
231
194
|
}
|
|
232
195
|
showSuccess(message) {
|
|
233
196
|
process.stdout.write("\x1B[?25h");
|
|
234
197
|
console.log();
|
|
235
|
-
console.log(
|
|
198
|
+
console.log(pc2.green("\u2713") + " " + message);
|
|
236
199
|
}
|
|
237
200
|
showError(message) {
|
|
238
201
|
process.stdout.write("\x1B[?25h");
|
|
239
202
|
console.log();
|
|
240
|
-
console.log(
|
|
203
|
+
console.log(pc2.red("\u2717") + " " + message);
|
|
241
204
|
}
|
|
242
205
|
};
|
|
243
206
|
function createProgressReporter() {
|
|
@@ -260,18 +223,18 @@ var InstallProgress = class {
|
|
|
260
223
|
start() {
|
|
261
224
|
process.stdout.write("\x1B[?25l");
|
|
262
225
|
const barWidth = 30;
|
|
263
|
-
const
|
|
226
|
+
const frames = ["\u25D0", "\u25D3", "\u25D1", "\u25D2"];
|
|
264
227
|
let frameIndex = 0;
|
|
265
228
|
this.interval = setInterval(() => {
|
|
266
|
-
const frame =
|
|
229
|
+
const frame = pc2.cyan(frames[frameIndex]);
|
|
267
230
|
const filled = Math.floor(this.progress / 100 * barWidth);
|
|
268
231
|
const empty = barWidth - filled;
|
|
269
|
-
const bar =
|
|
232
|
+
const bar = pc2.green("\u2588".repeat(filled)) + pc2.dim("\u2591".repeat(empty));
|
|
270
233
|
const pkg = this.packages[this.currentPackage % this.packages.length];
|
|
271
234
|
process.stdout.write(
|
|
272
|
-
`\r${frame} Installing dependencies ${bar} ${
|
|
235
|
+
`\r${frame} Installing dependencies ${bar} ${pc2.dim(pkg)} `
|
|
273
236
|
);
|
|
274
|
-
frameIndex = (frameIndex + 1) %
|
|
237
|
+
frameIndex = (frameIndex + 1) % frames.length;
|
|
275
238
|
if (this.progress < 95) {
|
|
276
239
|
this.progress += Math.random() * 3;
|
|
277
240
|
if (this.progress > (this.currentPackage + 1) * 12) {
|
|
@@ -287,7 +250,7 @@ var InstallProgress = class {
|
|
|
287
250
|
}
|
|
288
251
|
process.stdout.write("\x1B[?25h");
|
|
289
252
|
process.stdout.write("\r\x1B[K");
|
|
290
|
-
const icon = success ?
|
|
253
|
+
const icon = success ? pc2.green("\u2713") : pc2.red("\u2717");
|
|
291
254
|
const message = success ? "Dependencies installed" : "Failed to install dependencies";
|
|
292
255
|
console.log(`${icon} ${message}`);
|
|
293
256
|
}
|
|
@@ -295,12 +258,54 @@ var InstallProgress = class {
|
|
|
295
258
|
function createInstallProgress() {
|
|
296
259
|
return new InstallProgress();
|
|
297
260
|
}
|
|
261
|
+
var GitProgress = class {
|
|
262
|
+
interval = null;
|
|
263
|
+
phases = [
|
|
264
|
+
"Initializing repository",
|
|
265
|
+
"Setting up version control",
|
|
266
|
+
"Creating .git directory",
|
|
267
|
+
"Configuring git objects",
|
|
268
|
+
"Preparing initial branch"
|
|
269
|
+
];
|
|
270
|
+
phaseIndex = 0;
|
|
271
|
+
dotCount = 0;
|
|
272
|
+
start() {
|
|
273
|
+
process.stdout.write("\x1B[?25l");
|
|
274
|
+
const frames = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
|
|
275
|
+
let frameIndex = 0;
|
|
276
|
+
this.interval = setInterval(() => {
|
|
277
|
+
const frame = pc2.cyan(frames[frameIndex]);
|
|
278
|
+
const phase = this.phases[this.phaseIndex % this.phases.length];
|
|
279
|
+
const dots = ".".repeat(this.dotCount % 4);
|
|
280
|
+
process.stdout.write(`\r${frame} ${pc2.dim(phase)}${dots} `);
|
|
281
|
+
frameIndex = (frameIndex + 1) % frames.length;
|
|
282
|
+
this.dotCount++;
|
|
283
|
+
if (this.dotCount % 8 === 0) {
|
|
284
|
+
this.phaseIndex++;
|
|
285
|
+
}
|
|
286
|
+
}, 80);
|
|
287
|
+
}
|
|
288
|
+
stop(success = true) {
|
|
289
|
+
if (this.interval) {
|
|
290
|
+
clearInterval(this.interval);
|
|
291
|
+
this.interval = null;
|
|
292
|
+
}
|
|
293
|
+
process.stdout.write("\x1B[?25h");
|
|
294
|
+
process.stdout.write("\r\x1B[K");
|
|
295
|
+
const icon = success ? pc2.green("\u2713") : pc2.red("\u2717");
|
|
296
|
+
const message = success ? "Git repository initialized" : "Failed to initialize git";
|
|
297
|
+
console.log(`${icon} ${message}`);
|
|
298
|
+
}
|
|
299
|
+
};
|
|
300
|
+
function createGitProgress() {
|
|
301
|
+
return new GitProgress();
|
|
302
|
+
}
|
|
298
303
|
|
|
299
304
|
// src/generators/package-json.ts
|
|
300
305
|
function generatePackageJson(options) {
|
|
301
306
|
const isSolana = options.provider === "arkworks";
|
|
302
307
|
const dependencies = {
|
|
303
|
-
"@izi-noir/sdk": "^0.1.
|
|
308
|
+
"@izi-noir/sdk": "^0.1.5",
|
|
304
309
|
"@noir-lang/acvm_js": "1.0.0-beta.13-1d260df.nightly",
|
|
305
310
|
"@noir-lang/noirc_abi": "1.0.0-beta.13-1d260df.nightly",
|
|
306
311
|
"react": "^18.3.1",
|
|
@@ -599,9 +604,17 @@ export default defineConfig({
|
|
|
599
604
|
},
|
|
600
605
|
define: {
|
|
601
606
|
"global": "globalThis",
|
|
607
|
+
"process.env": {},
|
|
602
608
|
},
|
|
603
609
|
optimizeDeps: {
|
|
604
|
-
exclude: [
|
|
610
|
+
exclude: [
|
|
611
|
+
"@noir-lang/noir_wasm",
|
|
612
|
+
"@noir-lang/noir_js",
|
|
613
|
+
"@noir-lang/acvm_js",
|
|
614
|
+
"@noir-lang/noirc_abi",
|
|
615
|
+
"@aztec/bb.js",
|
|
616
|
+
"@izi-noir/sdk",
|
|
617
|
+
],
|
|
605
618
|
include: ["buffer", "util"],
|
|
606
619
|
},
|
|
607
620
|
build: {
|
|
@@ -636,6 +649,9 @@ function generateIndexHtml(options) {
|
|
|
636
649
|
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
|
637
650
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
638
651
|
<title>${options.projectName} - ZK Proof Demo</title>
|
|
652
|
+
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
653
|
+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
654
|
+
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500;600&display=swap" rel="stylesheet">
|
|
639
655
|
</head>
|
|
640
656
|
<body>
|
|
641
657
|
<div id="root"></div>
|
|
@@ -768,10 +784,17 @@ import { Chain, Network } from '@izi-noir/sdk';` : "";
|
|
|
768
784
|
</div>
|
|
769
785
|
|
|
770
786
|
<div className="verify-box">
|
|
787
|
+
{publicInputs && (
|
|
788
|
+
<div className="public-inputs-display">
|
|
789
|
+
<span>Public inputs:</span>
|
|
790
|
+
<code>{JSON.stringify(publicInputs)}</code>
|
|
791
|
+
</div>
|
|
792
|
+
)}
|
|
771
793
|
<button
|
|
772
794
|
onClick={handleVerify}
|
|
773
795
|
disabled={!vkAccount || isVerifying}
|
|
774
796
|
className="btn btn-primary"
|
|
797
|
+
style={{ marginTop: publicInputs ? '0.5rem' : 0 }}
|
|
775
798
|
>
|
|
776
799
|
{isVerifying ? 'Verifying...' : verified ? 'Verified!' : 'Verify On-Chain'}
|
|
777
800
|
</button>
|
|
@@ -839,6 +862,7 @@ function App() {
|
|
|
839
862
|
const [proofTime, setProofTime] = useState<number | null>(null);
|
|
840
863
|
const [proofError, setProofError] = useState<string | null>(null);
|
|
841
864
|
const [localVerified, setLocalVerified] = useState<boolean | null>(null);
|
|
865
|
+
const [publicInputs, setPublicInputs] = useState<string[] | null>(null);
|
|
842
866
|
|
|
843
867
|
// IziNoir instance
|
|
844
868
|
const [iziInstance, setIziInstance] = useState<IziNoir | null>(null);
|
|
@@ -855,6 +879,7 @@ ${solanaState}
|
|
|
855
879
|
setProof(null);
|
|
856
880
|
setProofTime(null);
|
|
857
881
|
setLocalVerified(null);
|
|
882
|
+
setPublicInputs(null);
|
|
858
883
|
setNoirCode(null);
|
|
859
884
|
}
|
|
860
885
|
}, [selectedCircuit]);
|
|
@@ -927,6 +952,7 @@ ${solanaState}
|
|
|
927
952
|
const endTime = performance.now();
|
|
928
953
|
setProof(proofBytes);
|
|
929
954
|
setProofTime(Math.round(endTime - startTime));
|
|
955
|
+
setPublicInputs(publicInputsHex);
|
|
930
956
|
} catch (error) {
|
|
931
957
|
console.error('Proof generation error:', error);
|
|
932
958
|
setProofError((error as Error).message);
|
|
@@ -940,7 +966,7 @@ ${solanaHandlers}
|
|
|
940
966
|
<div className="app">
|
|
941
967
|
<header>
|
|
942
968
|
<h1>${options.projectName}</h1>
|
|
943
|
-
<p>
|
|
969
|
+
<p>Built with IZI-NOIR</p>
|
|
944
970
|
</header>
|
|
945
971
|
|
|
946
972
|
<main>
|
|
@@ -1103,29 +1129,65 @@ function capitalizeFirst(str) {
|
|
|
1103
1129
|
return str.charAt(0).toUpperCase() + str.slice(1);
|
|
1104
1130
|
}
|
|
1105
1131
|
function generateAppCss() {
|
|
1106
|
-
return
|
|
1132
|
+
return `/* ================================
|
|
1133
|
+
CSS Variables - IZI-NOIR Theme
|
|
1134
|
+
================================ */
|
|
1135
|
+
:root {
|
|
1136
|
+
--solana-purple: #9945FF;
|
|
1137
|
+
--solana-green: #14F195;
|
|
1138
|
+
--noir-primary: #050505;
|
|
1139
|
+
--noir-elevated: #0A0A0A;
|
|
1140
|
+
--noir-orange: #FF6B35;
|
|
1141
|
+
--izi-cyan: #00D4FF;
|
|
1142
|
+
--text: #ffffff;
|
|
1143
|
+
--text-muted: #888888;
|
|
1144
|
+
--border: rgba(255, 255, 255, 0.1);
|
|
1145
|
+
}
|
|
1146
|
+
|
|
1147
|
+
/* ================================
|
|
1148
|
+
Reset & Base Styles
|
|
1149
|
+
================================ */
|
|
1150
|
+
* {
|
|
1107
1151
|
box-sizing: border-box;
|
|
1108
1152
|
margin: 0;
|
|
1109
1153
|
padding: 0;
|
|
1110
1154
|
}
|
|
1111
1155
|
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
--green: #14F195;
|
|
1115
|
-
--bg: #0a0a0a;
|
|
1116
|
-
--bg-elevated: #111111;
|
|
1117
|
-
--border: #222222;
|
|
1118
|
-
--text: #ffffff;
|
|
1119
|
-
--text-muted: #888888;
|
|
1156
|
+
html {
|
|
1157
|
+
scroll-behavior: smooth;
|
|
1120
1158
|
}
|
|
1121
1159
|
|
|
1122
1160
|
body {
|
|
1123
|
-
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI',
|
|
1124
|
-
background: var(--
|
|
1161
|
+
font-family: 'Inter', system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
|
|
1162
|
+
background-color: var(--noir-primary);
|
|
1163
|
+
/* Noise texture + radial gradients like the main frontend */
|
|
1164
|
+
background-image:
|
|
1165
|
+
url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='noise'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.8' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23noise)' opacity='0.015'/%3E%3C/svg%3E"),
|
|
1166
|
+
radial-gradient(
|
|
1167
|
+
ellipse 60% 40% at 50% 30%,
|
|
1168
|
+
rgba(153, 69, 255, 0.06) 0%,
|
|
1169
|
+
transparent 50%
|
|
1170
|
+
),
|
|
1171
|
+
radial-gradient(
|
|
1172
|
+
ellipse 80% 50% at 50% 110%,
|
|
1173
|
+
rgba(20, 241, 149, 0.04) 0%,
|
|
1174
|
+
transparent 40%
|
|
1175
|
+
);
|
|
1176
|
+
background-attachment: fixed;
|
|
1125
1177
|
color: var(--text);
|
|
1126
1178
|
line-height: 1.6;
|
|
1179
|
+
-webkit-font-smoothing: antialiased;
|
|
1180
|
+
-moz-osx-font-smoothing: grayscale;
|
|
1181
|
+
}
|
|
1182
|
+
|
|
1183
|
+
::selection {
|
|
1184
|
+
background: rgba(153, 69, 255, 0.3);
|
|
1185
|
+
color: white;
|
|
1127
1186
|
}
|
|
1128
1187
|
|
|
1188
|
+
/* ================================
|
|
1189
|
+
Layout
|
|
1190
|
+
================================ */
|
|
1129
1191
|
.app {
|
|
1130
1192
|
min-height: 100vh;
|
|
1131
1193
|
display: flex;
|
|
@@ -1136,11 +1198,14 @@ header {
|
|
|
1136
1198
|
padding: 2rem;
|
|
1137
1199
|
text-align: center;
|
|
1138
1200
|
border-bottom: 1px solid var(--border);
|
|
1201
|
+
backdrop-filter: blur(8px);
|
|
1202
|
+
background: rgba(0, 0, 0, 0.3);
|
|
1139
1203
|
}
|
|
1140
1204
|
|
|
1141
1205
|
header h1 {
|
|
1142
1206
|
font-size: 2rem;
|
|
1143
|
-
|
|
1207
|
+
font-weight: 700;
|
|
1208
|
+
background: linear-gradient(135deg, var(--solana-purple) 0%, var(--noir-orange) 100%);
|
|
1144
1209
|
-webkit-background-clip: text;
|
|
1145
1210
|
-webkit-text-fill-color: transparent;
|
|
1146
1211
|
background-clip: text;
|
|
@@ -1159,34 +1224,51 @@ main {
|
|
|
1159
1224
|
width: 100%;
|
|
1160
1225
|
}
|
|
1161
1226
|
|
|
1227
|
+
/* ================================
|
|
1228
|
+
Section Cards - Glassmorphism
|
|
1229
|
+
================================ */
|
|
1162
1230
|
.section {
|
|
1163
1231
|
margin-bottom: 2rem;
|
|
1164
1232
|
padding: 1.5rem;
|
|
1165
|
-
background:
|
|
1233
|
+
background: rgba(0, 0, 0, 0.3);
|
|
1234
|
+
backdrop-filter: blur(8px);
|
|
1166
1235
|
border: 1px solid var(--border);
|
|
1167
|
-
border-radius:
|
|
1236
|
+
border-radius: 16px;
|
|
1237
|
+
transition: border-color 0.3s ease, box-shadow 0.3s ease;
|
|
1238
|
+
}
|
|
1239
|
+
|
|
1240
|
+
.section:hover {
|
|
1241
|
+
border-color: rgba(255, 255, 255, 0.15);
|
|
1242
|
+
box-shadow: 0 0 30px rgba(153, 69, 255, 0.1);
|
|
1168
1243
|
}
|
|
1169
1244
|
|
|
1170
1245
|
.section h2 {
|
|
1171
1246
|
font-size: 1.25rem;
|
|
1247
|
+
font-weight: 600;
|
|
1172
1248
|
margin-bottom: 1rem;
|
|
1173
1249
|
color: var(--text);
|
|
1174
1250
|
}
|
|
1175
1251
|
|
|
1252
|
+
/* ================================
|
|
1253
|
+
Form Controls
|
|
1254
|
+
================================ */
|
|
1176
1255
|
.select {
|
|
1177
1256
|
width: 100%;
|
|
1178
|
-
padding: 0.75rem;
|
|
1179
|
-
background:
|
|
1257
|
+
padding: 0.75rem 1rem;
|
|
1258
|
+
background: rgba(0, 0, 0, 0.4);
|
|
1180
1259
|
border: 1px solid var(--border);
|
|
1181
|
-
border-radius:
|
|
1260
|
+
border-radius: 12px;
|
|
1182
1261
|
color: var(--text);
|
|
1262
|
+
font-family: inherit;
|
|
1183
1263
|
font-size: 1rem;
|
|
1184
1264
|
cursor: pointer;
|
|
1265
|
+
transition: border-color 0.3s ease, box-shadow 0.3s ease;
|
|
1185
1266
|
}
|
|
1186
1267
|
|
|
1187
1268
|
.select:focus {
|
|
1188
1269
|
outline: none;
|
|
1189
|
-
border-color: var(--purple);
|
|
1270
|
+
border-color: var(--solana-purple);
|
|
1271
|
+
box-shadow: 0 0 20px rgba(153, 69, 255, 0.2);
|
|
1190
1272
|
}
|
|
1191
1273
|
|
|
1192
1274
|
.inputs-grid {
|
|
@@ -1211,71 +1293,93 @@ main {
|
|
|
1211
1293
|
|
|
1212
1294
|
.input-badge {
|
|
1213
1295
|
font-size: 0.625rem;
|
|
1214
|
-
padding: 0.125rem 0.
|
|
1215
|
-
border-radius:
|
|
1296
|
+
padding: 0.125rem 0.5rem;
|
|
1297
|
+
border-radius: 6px;
|
|
1216
1298
|
text-transform: uppercase;
|
|
1217
1299
|
font-weight: 600;
|
|
1300
|
+
letter-spacing: 0.05em;
|
|
1218
1301
|
}
|
|
1219
1302
|
|
|
1220
1303
|
.input-badge.public {
|
|
1221
|
-
background:
|
|
1222
|
-
color:
|
|
1304
|
+
background: rgba(20, 241, 149, 0.2);
|
|
1305
|
+
color: var(--solana-green);
|
|
1306
|
+
border: 1px solid rgba(20, 241, 149, 0.3);
|
|
1223
1307
|
}
|
|
1224
1308
|
|
|
1225
1309
|
.input-badge.private {
|
|
1226
|
-
background:
|
|
1227
|
-
color:
|
|
1310
|
+
background: rgba(153, 69, 255, 0.2);
|
|
1311
|
+
color: var(--solana-purple);
|
|
1312
|
+
border: 1px solid rgba(153, 69, 255, 0.3);
|
|
1228
1313
|
}
|
|
1229
1314
|
|
|
1230
1315
|
.input-group input {
|
|
1231
|
-
padding: 0.75rem;
|
|
1232
|
-
background:
|
|
1316
|
+
padding: 0.75rem 1rem;
|
|
1317
|
+
background: rgba(0, 0, 0, 0.4);
|
|
1233
1318
|
border: 1px solid var(--border);
|
|
1234
|
-
border-radius:
|
|
1319
|
+
border-radius: 12px;
|
|
1235
1320
|
color: var(--text);
|
|
1321
|
+
font-family: 'JetBrains Mono', 'Fira Code', monospace;
|
|
1236
1322
|
font-size: 1rem;
|
|
1323
|
+
transition: border-color 0.3s ease, box-shadow 0.3s ease;
|
|
1237
1324
|
}
|
|
1238
1325
|
|
|
1239
1326
|
.input-group input:focus {
|
|
1240
1327
|
outline: none;
|
|
1241
|
-
border-color: var(--purple);
|
|
1328
|
+
border-color: var(--solana-purple);
|
|
1329
|
+
box-shadow: 0 0 20px rgba(153, 69, 255, 0.2);
|
|
1242
1330
|
}
|
|
1243
1331
|
|
|
1332
|
+
/* ================================
|
|
1333
|
+
Buttons - Animated Gradient
|
|
1334
|
+
================================ */
|
|
1244
1335
|
.btn {
|
|
1245
1336
|
padding: 0.75rem 1.5rem;
|
|
1246
1337
|
font-size: 1rem;
|
|
1247
1338
|
font-weight: 600;
|
|
1248
1339
|
border: none;
|
|
1249
|
-
border-radius:
|
|
1340
|
+
border-radius: 12px;
|
|
1250
1341
|
cursor: pointer;
|
|
1251
|
-
transition: all 0.
|
|
1342
|
+
transition: all 0.3s ease;
|
|
1252
1343
|
}
|
|
1253
1344
|
|
|
1254
1345
|
.btn:disabled {
|
|
1255
|
-
opacity: 0.
|
|
1346
|
+
opacity: 0.4;
|
|
1256
1347
|
cursor: not-allowed;
|
|
1257
1348
|
}
|
|
1258
1349
|
|
|
1259
1350
|
.btn-primary {
|
|
1260
|
-
background: linear-gradient(
|
|
1351
|
+
background: linear-gradient(
|
|
1352
|
+
90deg,
|
|
1353
|
+
var(--solana-purple) 0%,
|
|
1354
|
+
var(--solana-purple) 50%,
|
|
1355
|
+
var(--solana-green) 100%
|
|
1356
|
+
);
|
|
1357
|
+
background-size: 200% 100%;
|
|
1358
|
+
background-position: 0% 0%;
|
|
1261
1359
|
color: white;
|
|
1360
|
+
box-shadow: 0 0 20px rgba(153, 69, 255, 0.3);
|
|
1262
1361
|
}
|
|
1263
1362
|
|
|
1264
1363
|
.btn-primary:hover:not(:disabled) {
|
|
1364
|
+
background-position: 100% 0%;
|
|
1265
1365
|
transform: translateY(-2px);
|
|
1266
|
-
box-shadow: 0
|
|
1366
|
+
box-shadow: 0 0 30px rgba(20, 241, 149, 0.3);
|
|
1267
1367
|
}
|
|
1268
1368
|
|
|
1269
1369
|
.btn-secondary {
|
|
1270
|
-
background:
|
|
1370
|
+
background: rgba(0, 0, 0, 0.4);
|
|
1271
1371
|
border: 1px solid var(--border);
|
|
1272
1372
|
color: var(--text);
|
|
1273
1373
|
}
|
|
1274
1374
|
|
|
1275
1375
|
.btn-secondary:hover:not(:disabled) {
|
|
1276
|
-
border-color: var(--purple);
|
|
1376
|
+
border-color: var(--solana-purple);
|
|
1377
|
+
box-shadow: 0 0 20px rgba(153, 69, 255, 0.15);
|
|
1277
1378
|
}
|
|
1278
1379
|
|
|
1380
|
+
/* ================================
|
|
1381
|
+
Results Grid
|
|
1382
|
+
================================ */
|
|
1279
1383
|
.results {
|
|
1280
1384
|
display: grid;
|
|
1281
1385
|
grid-template-columns: repeat(3, 1fr);
|
|
@@ -1283,22 +1387,36 @@ main {
|
|
|
1283
1387
|
margin-top: 1rem;
|
|
1284
1388
|
}
|
|
1285
1389
|
|
|
1390
|
+
@media (max-width: 640px) {
|
|
1391
|
+
.results {
|
|
1392
|
+
grid-template-columns: 1fr;
|
|
1393
|
+
}
|
|
1394
|
+
}
|
|
1395
|
+
|
|
1286
1396
|
.result-card {
|
|
1287
|
-
padding:
|
|
1288
|
-
background:
|
|
1397
|
+
padding: 1.25rem;
|
|
1398
|
+
background: rgba(0, 0, 0, 0.3);
|
|
1289
1399
|
border: 1px solid var(--border);
|
|
1290
|
-
border-radius:
|
|
1400
|
+
border-radius: 12px;
|
|
1291
1401
|
text-align: center;
|
|
1402
|
+
transition: border-color 0.3s ease, transform 0.3s ease, box-shadow 0.3s ease;
|
|
1403
|
+
}
|
|
1404
|
+
|
|
1405
|
+
.result-card:hover {
|
|
1406
|
+
border-color: rgba(255, 255, 255, 0.15);
|
|
1407
|
+
transform: translateY(-4px);
|
|
1408
|
+
box-shadow: 0 0 25px rgba(153, 69, 255, 0.15);
|
|
1292
1409
|
}
|
|
1293
1410
|
|
|
1294
1411
|
.result-value {
|
|
1295
|
-
font-size: 1.
|
|
1296
|
-
font-weight:
|
|
1412
|
+
font-size: 1.5rem;
|
|
1413
|
+
font-weight: 700;
|
|
1414
|
+
font-family: 'JetBrains Mono', monospace;
|
|
1297
1415
|
display: block;
|
|
1298
1416
|
}
|
|
1299
1417
|
|
|
1300
1418
|
.result-value.success {
|
|
1301
|
-
color: var(--green);
|
|
1419
|
+
color: var(--solana-green);
|
|
1302
1420
|
}
|
|
1303
1421
|
|
|
1304
1422
|
.result-value.error {
|
|
@@ -1309,22 +1427,40 @@ main {
|
|
|
1309
1427
|
font-size: 0.75rem;
|
|
1310
1428
|
color: var(--text-muted);
|
|
1311
1429
|
text-transform: uppercase;
|
|
1312
|
-
|
|
1430
|
+
letter-spacing: 0.1em;
|
|
1431
|
+
margin-top: 0.5rem;
|
|
1313
1432
|
display: block;
|
|
1314
1433
|
}
|
|
1315
1434
|
|
|
1435
|
+
/* ================================
|
|
1436
|
+
Messages
|
|
1437
|
+
================================ */
|
|
1316
1438
|
.error {
|
|
1317
|
-
color: #
|
|
1439
|
+
color: #ff6b6b;
|
|
1318
1440
|
font-size: 0.875rem;
|
|
1319
1441
|
margin-top: 0.5rem;
|
|
1442
|
+
padding: 0.75rem 1rem;
|
|
1443
|
+
background: rgba(255, 107, 107, 0.1);
|
|
1444
|
+
border: 1px solid rgba(255, 107, 107, 0.2);
|
|
1445
|
+
border-radius: 8px;
|
|
1446
|
+
word-break: break-word;
|
|
1447
|
+
overflow-wrap: break-word;
|
|
1448
|
+
max-width: 100%;
|
|
1320
1449
|
}
|
|
1321
1450
|
|
|
1322
1451
|
.success {
|
|
1323
|
-
color: var(--green);
|
|
1452
|
+
color: var(--solana-green);
|
|
1324
1453
|
font-size: 0.875rem;
|
|
1325
1454
|
margin-top: 0.5rem;
|
|
1455
|
+
padding: 0.75rem 1rem;
|
|
1456
|
+
background: rgba(20, 241, 149, 0.1);
|
|
1457
|
+
border: 1px solid rgba(20, 241, 149, 0.2);
|
|
1458
|
+
border-radius: 8px;
|
|
1326
1459
|
}
|
|
1327
1460
|
|
|
1461
|
+
/* ================================
|
|
1462
|
+
Noir Code Details
|
|
1463
|
+
================================ */
|
|
1328
1464
|
.noir-details {
|
|
1329
1465
|
margin-top: 1rem;
|
|
1330
1466
|
}
|
|
@@ -1333,12 +1469,21 @@ main {
|
|
|
1333
1469
|
cursor: pointer;
|
|
1334
1470
|
color: var(--text-muted);
|
|
1335
1471
|
font-size: 0.875rem;
|
|
1472
|
+
padding: 0.5rem 0;
|
|
1473
|
+
transition: color 0.3s ease;
|
|
1336
1474
|
}
|
|
1337
1475
|
|
|
1338
1476
|
.noir-details summary:hover {
|
|
1339
|
-
color: var(--
|
|
1477
|
+
color: var(--solana-purple);
|
|
1340
1478
|
}
|
|
1341
1479
|
|
|
1480
|
+
.noir-details[open] summary {
|
|
1481
|
+
color: var(--solana-purple);
|
|
1482
|
+
}
|
|
1483
|
+
|
|
1484
|
+
/* ================================
|
|
1485
|
+
Deploy & Verify Section
|
|
1486
|
+
================================ */
|
|
1342
1487
|
.deploy-verify-row {
|
|
1343
1488
|
display: grid;
|
|
1344
1489
|
grid-template-columns: 1fr 1fr;
|
|
@@ -1346,38 +1491,118 @@ main {
|
|
|
1346
1491
|
margin-top: 1rem;
|
|
1347
1492
|
}
|
|
1348
1493
|
|
|
1494
|
+
@media (max-width: 640px) {
|
|
1495
|
+
.deploy-verify-row {
|
|
1496
|
+
grid-template-columns: 1fr;
|
|
1497
|
+
}
|
|
1498
|
+
}
|
|
1499
|
+
|
|
1349
1500
|
.deploy-box,
|
|
1350
1501
|
.verify-box {
|
|
1351
|
-
padding:
|
|
1352
|
-
background:
|
|
1502
|
+
padding: 1.25rem;
|
|
1503
|
+
background: rgba(0, 0, 0, 0.3);
|
|
1504
|
+
border: 1px solid var(--border);
|
|
1505
|
+
border-radius: 12px;
|
|
1506
|
+
overflow: hidden;
|
|
1507
|
+
word-break: break-word;
|
|
1508
|
+
transition: border-color 0.3s ease, box-shadow 0.3s ease;
|
|
1509
|
+
}
|
|
1510
|
+
|
|
1511
|
+
.deploy-box:hover,
|
|
1512
|
+
.verify-box:hover {
|
|
1513
|
+
border-color: rgba(255, 255, 255, 0.15);
|
|
1514
|
+
box-shadow: 0 0 20px rgba(153, 69, 255, 0.1);
|
|
1515
|
+
}
|
|
1516
|
+
|
|
1517
|
+
.public-inputs-display {
|
|
1518
|
+
margin-top: 0.75rem;
|
|
1519
|
+
font-size: 0.75rem;
|
|
1520
|
+
color: var(--text-muted);
|
|
1521
|
+
}
|
|
1522
|
+
|
|
1523
|
+
.public-inputs-display code {
|
|
1524
|
+
display: block;
|
|
1525
|
+
margin-top: 0.5rem;
|
|
1526
|
+
padding: 0.75rem;
|
|
1527
|
+
background: rgba(0, 0, 0, 0.4);
|
|
1353
1528
|
border: 1px solid var(--border);
|
|
1354
1529
|
border-radius: 8px;
|
|
1530
|
+
font-family: 'JetBrains Mono', monospace;
|
|
1531
|
+
font-size: 0.7rem;
|
|
1532
|
+
overflow-x: auto;
|
|
1533
|
+
max-width: 100%;
|
|
1355
1534
|
}
|
|
1356
1535
|
|
|
1536
|
+
/* ================================
|
|
1537
|
+
Footer
|
|
1538
|
+
================================ */
|
|
1357
1539
|
footer {
|
|
1358
1540
|
padding: 1.5rem;
|
|
1359
1541
|
text-align: center;
|
|
1360
1542
|
border-top: 1px solid var(--border);
|
|
1543
|
+
backdrop-filter: blur(8px);
|
|
1544
|
+
background: rgba(0, 0, 0, 0.3);
|
|
1361
1545
|
color: var(--text-muted);
|
|
1362
1546
|
font-size: 0.875rem;
|
|
1363
1547
|
}
|
|
1364
1548
|
|
|
1365
1549
|
footer a {
|
|
1366
|
-
color: var(--purple);
|
|
1550
|
+
color: var(--solana-purple);
|
|
1367
1551
|
text-decoration: none;
|
|
1552
|
+
transition: color 0.3s ease;
|
|
1368
1553
|
}
|
|
1369
1554
|
|
|
1370
1555
|
footer a:hover {
|
|
1371
|
-
|
|
1556
|
+
color: var(--solana-green);
|
|
1557
|
+
}
|
|
1558
|
+
|
|
1559
|
+
/* ================================
|
|
1560
|
+
Custom Scrollbar
|
|
1561
|
+
================================ */
|
|
1562
|
+
::-webkit-scrollbar {
|
|
1563
|
+
width: 6px;
|
|
1564
|
+
height: 6px;
|
|
1565
|
+
}
|
|
1566
|
+
|
|
1567
|
+
::-webkit-scrollbar-track {
|
|
1568
|
+
background: var(--noir-primary);
|
|
1569
|
+
}
|
|
1570
|
+
|
|
1571
|
+
::-webkit-scrollbar-thumb {
|
|
1572
|
+
background: rgba(255, 255, 255, 0.1);
|
|
1573
|
+
border-radius: 9999px;
|
|
1574
|
+
}
|
|
1575
|
+
|
|
1576
|
+
::-webkit-scrollbar-thumb:hover {
|
|
1577
|
+
background: rgba(255, 255, 255, 0.2);
|
|
1578
|
+
}
|
|
1579
|
+
|
|
1580
|
+
/* ================================
|
|
1581
|
+
Accessibility - Reduced Motion
|
|
1582
|
+
================================ */
|
|
1583
|
+
@media (prefers-reduced-motion: reduce) {
|
|
1584
|
+
*,
|
|
1585
|
+
*::before,
|
|
1586
|
+
*::after {
|
|
1587
|
+
animation-duration: 0.01ms !important;
|
|
1588
|
+
animation-iteration-count: 1 !important;
|
|
1589
|
+
transition-duration: 0.01ms !important;
|
|
1590
|
+
}
|
|
1372
1591
|
}
|
|
1373
1592
|
`;
|
|
1374
1593
|
}
|
|
1375
1594
|
function generateIndexCss() {
|
|
1376
|
-
return
|
|
1595
|
+
return `/* Base styles - fonts are loaded in index.html */
|
|
1596
|
+
body {
|
|
1377
1597
|
margin: 0;
|
|
1378
1598
|
-webkit-font-smoothing: antialiased;
|
|
1379
1599
|
-moz-osx-font-smoothing: grayscale;
|
|
1380
1600
|
}
|
|
1601
|
+
|
|
1602
|
+
/* Ensure mono font is applied to code elements */
|
|
1603
|
+
code, pre, .mono {
|
|
1604
|
+
font-family: 'JetBrains Mono', 'Fira Code', 'Cascadia Code', monospace;
|
|
1605
|
+
}
|
|
1381
1606
|
`;
|
|
1382
1607
|
}
|
|
1383
1608
|
function generateViteEnvDts() {
|
|
@@ -1556,14 +1781,14 @@ async function initCommand(projectName, options) {
|
|
|
1556
1781
|
});
|
|
1557
1782
|
}
|
|
1558
1783
|
if (!projectOptions) {
|
|
1559
|
-
console.log(
|
|
1784
|
+
console.log(pc3.yellow("\nOperation cancelled."));
|
|
1560
1785
|
process.exit(0);
|
|
1561
1786
|
}
|
|
1562
1787
|
const projectDir = path2.resolve(process.cwd(), projectOptions.projectName);
|
|
1563
1788
|
if (await directoryExists(projectDir)) {
|
|
1564
1789
|
if (!await isDirectoryEmpty(projectDir)) {
|
|
1565
1790
|
console.log(
|
|
1566
|
-
|
|
1791
|
+
pc3.red(`
|
|
1567
1792
|
Error: Directory "${projectOptions.projectName}" already exists and is not empty.`)
|
|
1568
1793
|
);
|
|
1569
1794
|
process.exit(1);
|
|
@@ -1575,23 +1800,23 @@ Error: Directory "${projectOptions.projectName}" already exists and is not empty
|
|
|
1575
1800
|
await progress.startThinking();
|
|
1576
1801
|
await new Promise((r) => setTimeout(r, 800));
|
|
1577
1802
|
progress.stopThinking();
|
|
1578
|
-
console.log(
|
|
1803
|
+
console.log(pc3.bold("\n Scaffolding your ZK project...\n"));
|
|
1579
1804
|
await createProjectStructure(projectDir, projectOptions, progress);
|
|
1580
1805
|
progress.showSuccess("Project structure created");
|
|
1581
1806
|
} catch (error) {
|
|
1582
1807
|
progress.showError("Failed to create project structure");
|
|
1583
|
-
console.error(
|
|
1808
|
+
console.error(pc3.red("\n"), error);
|
|
1584
1809
|
process.exit(1);
|
|
1585
1810
|
}
|
|
1586
1811
|
if (!projectOptions.skipGit) {
|
|
1587
|
-
const
|
|
1588
|
-
|
|
1812
|
+
const gitProgress = createGitProgress();
|
|
1813
|
+
gitProgress.start();
|
|
1589
1814
|
try {
|
|
1590
1815
|
execSync("git init", { cwd: projectDir, stdio: "ignore" });
|
|
1591
|
-
|
|
1816
|
+
gitProgress.stop(true);
|
|
1592
1817
|
} catch {
|
|
1593
|
-
|
|
1594
|
-
console.log(
|
|
1818
|
+
gitProgress.stop(false);
|
|
1819
|
+
console.log(pc3.yellow(" Warning: Failed to initialize git repository"));
|
|
1595
1820
|
}
|
|
1596
1821
|
}
|
|
1597
1822
|
if (!projectOptions.skipInstall) {
|
|
@@ -1602,7 +1827,7 @@ Error: Directory "${projectOptions.projectName}" already exists and is not empty
|
|
|
1602
1827
|
installProgress.stop(true);
|
|
1603
1828
|
} catch {
|
|
1604
1829
|
installProgress.stop(false);
|
|
1605
|
-
console.log(
|
|
1830
|
+
console.log(pc3.yellow(' Run "npm install" manually.'));
|
|
1606
1831
|
}
|
|
1607
1832
|
}
|
|
1608
1833
|
printSuccessMessage(projectOptions);
|
|
@@ -1656,26 +1881,26 @@ async function createProjectStructure(projectDir, options, progress) {
|
|
|
1656
1881
|
}
|
|
1657
1882
|
function printSuccessMessage(options) {
|
|
1658
1883
|
console.log();
|
|
1659
|
-
console.log(
|
|
1884
|
+
console.log(pc3.green("\u2713") + " Project created successfully!");
|
|
1660
1885
|
console.log();
|
|
1661
1886
|
console.log("Next steps:");
|
|
1662
1887
|
console.log();
|
|
1663
|
-
console.log(
|
|
1888
|
+
console.log(pc3.cyan(` cd ${options.projectName}`));
|
|
1664
1889
|
if (options.skipInstall) {
|
|
1665
|
-
console.log(
|
|
1890
|
+
console.log(pc3.cyan(" npm install"));
|
|
1666
1891
|
}
|
|
1667
|
-
console.log(
|
|
1892
|
+
console.log(pc3.cyan(" npm run dev"));
|
|
1668
1893
|
console.log();
|
|
1669
|
-
console.log("Then open " +
|
|
1894
|
+
console.log("Then open " + pc3.blue("http://localhost:5173") + " in your browser.");
|
|
1670
1895
|
console.log();
|
|
1671
1896
|
console.log("To add circuits:");
|
|
1672
1897
|
console.log();
|
|
1673
|
-
console.log(
|
|
1674
|
-
console.log(
|
|
1675
|
-
console.log(
|
|
1898
|
+
console.log(pc3.dim(" 1. Create a new circuit in circuits/*.ts"));
|
|
1899
|
+
console.log(pc3.dim(" 2. Export it from circuits/index.ts"));
|
|
1900
|
+
console.log(pc3.dim(" 3. Add it to CIRCUITS array in src/App.tsx"));
|
|
1676
1901
|
console.log();
|
|
1677
1902
|
console.log(
|
|
1678
|
-
|
|
1903
|
+
pc3.dim("Learn more: ") + pc3.blue("https://github.com/izi-noir/izi-noir")
|
|
1679
1904
|
);
|
|
1680
1905
|
console.log();
|
|
1681
1906
|
}
|