create-fhevm-example 1.3.2 → 1.4.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.
Files changed (125) hide show
  1. package/contracts/advanced/BlindAuction.sol +255 -0
  2. package/contracts/advanced/EncryptedEscrow.sol +315 -0
  3. package/contracts/advanced/HiddenVoting.sol +231 -0
  4. package/contracts/advanced/PrivateKYC.sol +309 -0
  5. package/contracts/advanced/PrivatePayroll.sol +285 -0
  6. package/contracts/basic/decryption/PublicDecryptMultipleValues.sol +160 -0
  7. package/contracts/basic/decryption/PublicDecryptSingleValue.sol +142 -0
  8. package/contracts/basic/decryption/UserDecryptMultipleValues.sol +61 -0
  9. package/contracts/basic/decryption/UserDecryptSingleValue.sol +59 -0
  10. package/contracts/basic/encryption/EncryptMultipleValues.sol +72 -0
  11. package/contracts/basic/encryption/EncryptSingleValue.sol +44 -0
  12. package/contracts/basic/encryption/FHECounter.sol +54 -0
  13. package/contracts/basic/fhe-operations/FHEAdd.sol +51 -0
  14. package/contracts/basic/fhe-operations/FHEArithmetic.sol +99 -0
  15. package/contracts/basic/fhe-operations/FHEComparison.sol +116 -0
  16. package/contracts/basic/fhe-operations/FHEIfThenElse.sol +53 -0
  17. package/contracts/concepts/FHEAccessControl.sol +94 -0
  18. package/contracts/concepts/FHEAntiPatterns.sol +329 -0
  19. package/contracts/concepts/FHEHandles.sol +128 -0
  20. package/contracts/concepts/FHEInputProof.sol +104 -0
  21. package/contracts/gaming/EncryptedLottery.sol +298 -0
  22. package/contracts/gaming/EncryptedPoker.sol +337 -0
  23. package/contracts/gaming/RockPaperScissors.sol +213 -0
  24. package/contracts/openzeppelin/ERC7984.sol +85 -0
  25. package/contracts/openzeppelin/ERC7984ERC20Wrapper.sol +43 -0
  26. package/contracts/openzeppelin/SwapERC7984ToERC20.sol +110 -0
  27. package/contracts/openzeppelin/SwapERC7984ToERC7984.sol +48 -0
  28. package/contracts/openzeppelin/VestingWallet.sol +147 -0
  29. package/contracts/openzeppelin/mocks/ERC20Mock.sol +31 -0
  30. package/dist/scripts/commands/add-mode.d.ts.map +1 -0
  31. package/dist/scripts/{add-mode.js → commands/add-mode.js} +27 -61
  32. package/dist/scripts/commands/doctor.d.ts.map +1 -0
  33. package/dist/scripts/{doctor.js → commands/doctor.js} +2 -2
  34. package/dist/scripts/commands/generate-config.d.ts.map +1 -0
  35. package/dist/scripts/{generate-config.js → commands/generate-config.js} +3 -10
  36. package/dist/scripts/commands/generate-docs.d.ts.map +1 -0
  37. package/dist/scripts/{generate-docs.js → commands/generate-docs.js} +4 -3
  38. package/dist/scripts/commands/maintenance.d.ts.map +1 -0
  39. package/dist/scripts/{maintenance.js → commands/maintenance.js} +11 -10
  40. package/dist/scripts/index.js +14 -33
  41. package/dist/scripts/{builders.d.ts → shared/builders.d.ts} +2 -2
  42. package/dist/scripts/shared/builders.d.ts.map +1 -0
  43. package/dist/scripts/{builders.js → shared/builders.js} +49 -30
  44. package/dist/scripts/{config.d.ts → shared/config.d.ts} +0 -2
  45. package/dist/scripts/shared/config.d.ts.map +1 -0
  46. package/dist/scripts/{config.js → shared/config.js} +48 -59
  47. package/dist/scripts/shared/generators.d.ts +42 -0
  48. package/dist/scripts/shared/generators.d.ts.map +1 -0
  49. package/dist/scripts/{utils.js → shared/generators.js} +34 -271
  50. package/dist/scripts/shared/ui.d.ts.map +1 -0
  51. package/dist/scripts/{ui.js → shared/ui.js} +3 -2
  52. package/dist/scripts/{utils.d.ts → shared/utils.d.ts} +4 -27
  53. package/dist/scripts/shared/utils.d.ts.map +1 -0
  54. package/dist/scripts/shared/utils.js +228 -0
  55. package/fhevm-hardhat-template/.eslintignore +26 -0
  56. package/fhevm-hardhat-template/.eslintrc.yml +21 -0
  57. package/fhevm-hardhat-template/.github/workflows/main.yml +47 -0
  58. package/fhevm-hardhat-template/.github/workflows/manual-windows.yml +28 -0
  59. package/fhevm-hardhat-template/.github/workflows/manual.yml +28 -0
  60. package/fhevm-hardhat-template/.prettierignore +25 -0
  61. package/fhevm-hardhat-template/.prettierrc.yml +15 -0
  62. package/fhevm-hardhat-template/.solcover.js +4 -0
  63. package/fhevm-hardhat-template/.solhint.json +12 -0
  64. package/fhevm-hardhat-template/.solhintignore +3 -0
  65. package/fhevm-hardhat-template/.vscode/extensions.json +3 -0
  66. package/fhevm-hardhat-template/.vscode/settings.json +9 -0
  67. package/fhevm-hardhat-template/LICENSE +33 -0
  68. package/fhevm-hardhat-template/README.md +110 -0
  69. package/fhevm-hardhat-template/contracts/FHECounter.sol +46 -0
  70. package/fhevm-hardhat-template/deploy/deploy.ts +17 -0
  71. package/fhevm-hardhat-template/hardhat.config.ts +90 -0
  72. package/fhevm-hardhat-template/package-lock.json +10405 -0
  73. package/fhevm-hardhat-template/package.json +104 -0
  74. package/fhevm-hardhat-template/tasks/FHECounter.ts +184 -0
  75. package/fhevm-hardhat-template/tasks/accounts.ts +9 -0
  76. package/fhevm-hardhat-template/test/FHECounter.ts +104 -0
  77. package/fhevm-hardhat-template/test/FHECounterSepolia.ts +104 -0
  78. package/fhevm-hardhat-template/tsconfig.json +23 -0
  79. package/package.json +11 -8
  80. package/test/advanced/BlindAuction.ts +246 -0
  81. package/test/advanced/EncryptedEscrow.ts +295 -0
  82. package/test/advanced/HiddenVoting.ts +268 -0
  83. package/test/advanced/PrivateKYC.ts +382 -0
  84. package/test/advanced/PrivatePayroll.ts +253 -0
  85. package/test/basic/decryption/PublicDecryptMultipleValues.ts +254 -0
  86. package/test/basic/decryption/PublicDecryptSingleValue.ts +264 -0
  87. package/test/basic/decryption/UserDecryptMultipleValues.ts +107 -0
  88. package/test/basic/decryption/UserDecryptSingleValue.ts +97 -0
  89. package/test/basic/encryption/EncryptMultipleValues.ts +110 -0
  90. package/test/basic/encryption/EncryptSingleValue.ts +124 -0
  91. package/test/basic/encryption/FHECounter.ts +112 -0
  92. package/test/basic/fhe-operations/FHEAdd.ts +97 -0
  93. package/test/basic/fhe-operations/FHEArithmetic.ts +161 -0
  94. package/test/basic/fhe-operations/FHEComparison.ts +167 -0
  95. package/test/basic/fhe-operations/FHEIfThenElse.ts +97 -0
  96. package/test/concepts/FHEAccessControl.ts +154 -0
  97. package/test/concepts/FHEAntiPatterns.ts +111 -0
  98. package/test/concepts/FHEHandles.ts +156 -0
  99. package/test/concepts/FHEInputProof.ts +151 -0
  100. package/test/gaming/EncryptedLottery.ts +214 -0
  101. package/test/gaming/EncryptedPoker.ts +349 -0
  102. package/test/gaming/RockPaperScissors.ts +205 -0
  103. package/test/openzeppelin/ERC7984.ts +142 -0
  104. package/test/openzeppelin/ERC7984ERC20Wrapper.ts +71 -0
  105. package/test/openzeppelin/SwapERC7984ToERC20.ts +76 -0
  106. package/test/openzeppelin/SwapERC7984ToERC7984.ts +113 -0
  107. package/test/openzeppelin/VestingWallet.ts +89 -0
  108. package/dist/scripts/add-mode.d.ts.map +0 -1
  109. package/dist/scripts/builders.d.ts.map +0 -1
  110. package/dist/scripts/config.d.ts.map +0 -1
  111. package/dist/scripts/doctor.d.ts.map +0 -1
  112. package/dist/scripts/generate-config.d.ts.map +0 -1
  113. package/dist/scripts/generate-docs.d.ts.map +0 -1
  114. package/dist/scripts/help.d.ts +0 -9
  115. package/dist/scripts/help.d.ts.map +0 -1
  116. package/dist/scripts/help.js +0 -73
  117. package/dist/scripts/maintenance.d.ts.map +0 -1
  118. package/dist/scripts/ui.d.ts.map +0 -1
  119. package/dist/scripts/utils.d.ts.map +0 -1
  120. /package/dist/scripts/{add-mode.d.ts → commands/add-mode.d.ts} +0 -0
  121. /package/dist/scripts/{doctor.d.ts → commands/doctor.d.ts} +0 -0
  122. /package/dist/scripts/{generate-config.d.ts → commands/generate-config.d.ts} +0 -0
  123. /package/dist/scripts/{generate-docs.d.ts → commands/generate-docs.d.ts} +0 -0
  124. /package/dist/scripts/{maintenance.d.ts → commands/maintenance.d.ts} +0 -0
  125. /package/dist/scripts/{ui.d.ts → shared/ui.d.ts} +0 -0
@@ -47,8 +47,8 @@ const p = __importStar(require("@clack/prompts"));
47
47
  const picocolors_1 = __importDefault(require("picocolors"));
48
48
  const fs = __importStar(require("fs"));
49
49
  const path = __importStar(require("path"));
50
- const config_1 = require("./config");
51
- const utils_1 = require("./utils");
50
+ const config_1 = require("../shared/config");
51
+ const utils_1 = require("../shared/utils");
52
52
  // =============================================================================
53
53
  // PROJECT DETECTION
54
54
  // =============================================================================
@@ -136,88 +136,54 @@ function updateHardhatConfig(targetDir) {
136
136
  /**
137
137
  * Adds example contract and test files to the project
138
138
  */
139
- async function addExampleFiles(exampleName, targetDir) {
139
+ function addExampleFiles(exampleName, targetDir) {
140
140
  const example = config_1.EXAMPLES[exampleName];
141
141
  if (!example) {
142
142
  throw new Error(`Unknown example: ${exampleName}`);
143
143
  }
144
+ const rootDir = (0, utils_1.getRootDir)();
144
145
  const contractName = (0, utils_1.getContractName)(example.contract);
145
146
  if (!contractName) {
146
147
  throw new Error("Could not extract contract name");
147
148
  }
149
+ const contractSource = path.join(rootDir, example.contract);
150
+ const testSource = path.join(rootDir, example.test);
148
151
  // Handle contract file
149
152
  let contractDest = path.join(targetDir, "contracts", `${contractName}.sol`);
153
+ const contractsDir = path.join(targetDir, "contracts");
154
+ if (!fs.existsSync(contractsDir)) {
155
+ fs.mkdirSync(contractsDir, { recursive: true });
156
+ }
150
157
  if (fs.existsSync(contractDest)) {
151
- const action = await p.select({
152
- message: `${contractName}.sol already exists. What do you want to do?`,
153
- options: [
154
- { value: "skip", label: "Skip contract" },
155
- { value: "overwrite", label: "Overwrite existing file" },
156
- {
157
- value: "rename",
158
- label: `Rename to ${contractName}_fhevm.sol`,
159
- },
160
- ],
161
- });
162
- if (p.isCancel(action)) {
163
- throw new Error("Operation cancelled");
164
- }
165
- if (action === "skip") {
166
- p.log.info(`Skipped: ${contractName}.sol`);
167
- }
168
- else if (action === "rename") {
169
- contractDest = path.join(targetDir, "contracts", `${contractName}_fhevm.sol`);
170
- await (0, utils_1.downloadFileFromGitHub)(example.contract, contractDest);
171
- p.log.success(`Added: ${contractName}_fhevm.sol`);
172
- }
173
- else {
174
- await (0, utils_1.downloadFileFromGitHub)(example.contract, contractDest);
175
- p.log.success(`Overwritten: ${contractName}.sol`);
176
- }
158
+ // File exists - will be handled by caller with prompts
159
+ fs.copyFileSync(contractSource, contractDest);
160
+ p.log.success(`Overwritten: ${contractName}.sol`);
177
161
  }
178
162
  else {
179
- const contractsDir = path.join(targetDir, "contracts");
180
- if (!fs.existsSync(contractsDir)) {
181
- fs.mkdirSync(contractsDir, { recursive: true });
182
- }
183
- await (0, utils_1.downloadFileFromGitHub)(example.contract, contractDest);
163
+ fs.copyFileSync(contractSource, contractDest);
184
164
  p.log.success(`Added: ${contractName}.sol`);
185
165
  }
186
166
  // Handle test file
187
167
  const testFileName = path.basename(example.test);
188
- let testDest = path.join(targetDir, "test", testFileName);
168
+ const testDest = path.join(targetDir, "test", testFileName);
169
+ const testDir = path.join(targetDir, "test");
170
+ if (!fs.existsSync(testDir)) {
171
+ fs.mkdirSync(testDir, { recursive: true });
172
+ }
189
173
  if (fs.existsSync(testDest)) {
190
- const action = await p.select({
191
- message: `${testFileName} already exists. What do you want to do?`,
192
- options: [
193
- { value: "skip", label: "Skip test" },
194
- { value: "overwrite", label: "Overwrite existing file" },
195
- ],
196
- });
197
- if (p.isCancel(action)) {
198
- throw new Error("Operation cancelled");
199
- }
200
- if (action === "skip") {
201
- p.log.info(`Skipped: ${testFileName}`);
202
- }
203
- else {
204
- await (0, utils_1.downloadFileFromGitHub)(example.test, testDest);
205
- p.log.success(`Overwritten: ${testFileName}`);
206
- }
174
+ fs.copyFileSync(testSource, testDest);
175
+ p.log.success(`Overwritten: ${testFileName}`);
207
176
  }
208
177
  else {
209
- const testDir = path.join(targetDir, "test");
210
- if (!fs.existsSync(testDir)) {
211
- fs.mkdirSync(testDir, { recursive: true });
212
- }
213
- await (0, utils_1.downloadFileFromGitHub)(example.test, testDest);
178
+ fs.copyFileSync(testSource, testDest);
214
179
  p.log.success(`Added: ${testFileName}`);
215
180
  }
216
181
  // Handle contract dependencies
217
182
  if (example.dependencies) {
218
183
  p.log.message("");
219
- p.log.message(picocolors_1.default.bold("Downloading contract dependencies..."));
184
+ p.log.message(picocolors_1.default.bold("Copying contract dependencies..."));
220
185
  for (const depPath of example.dependencies) {
186
+ const depSource = path.join(rootDir, depPath);
221
187
  const relativePath = depPath.replace(/^contracts\//, "");
222
188
  const depDestPath = path.join(targetDir, "contracts", relativePath);
223
189
  const depDestDir = path.dirname(depDestPath);
@@ -228,8 +194,8 @@ async function addExampleFiles(exampleName, targetDir) {
228
194
  if (fs.existsSync(depDestPath)) {
229
195
  p.log.info(`Skipped (exists): ${depName}`);
230
196
  }
231
- else {
232
- await (0, utils_1.downloadFileFromGitHub)(depPath, depDestPath);
197
+ else if (fs.existsSync(depSource)) {
198
+ fs.copyFileSync(depSource, depDestPath);
233
199
  p.log.success(`Added: ${depName}`);
234
200
  }
235
201
  }
@@ -313,7 +279,7 @@ async function runAddMode(targetDir) {
313
279
  p.log.message("");
314
280
  p.log.message(picocolors_1.default.bold("Adding example files..."));
315
281
  try {
316
- await addExampleFiles(exampleName, absoluteDir);
282
+ addExampleFiles(exampleName, absoluteDir);
317
283
  }
318
284
  catch (error) {
319
285
  p.log.error("Failed to add example files");
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../../../scripts/commands/doctor.ts"],"names":[],"mappings":";AAEA;;;;;;;GAOG"}
@@ -50,8 +50,8 @@ const path = __importStar(require("path"));
50
50
  const child_process_1 = require("child_process");
51
51
  const p = __importStar(require("@clack/prompts"));
52
52
  const picocolors_1 = __importDefault(require("picocolors"));
53
- const utils_1 = require("./utils");
54
- const config_1 = require("./config");
53
+ const utils_1 = require("../shared/utils");
54
+ const config_1 = require("../shared/config");
55
55
  const ROOT_DIR = (0, utils_1.getRootDir)();
56
56
  // =============================================================================
57
57
  // Checks
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generate-config.d.ts","sourceRoot":"","sources":["../../../scripts/commands/generate-config.ts"],"names":[],"mappings":";AAEA;;;;;GAKG"}
@@ -45,12 +45,12 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
45
45
  Object.defineProperty(exports, "__esModule", { value: true });
46
46
  const fs = __importStar(require("fs"));
47
47
  const path = __importStar(require("path"));
48
- const utils_1 = require("./utils");
48
+ const utils_1 = require("../shared/utils");
49
49
  const picocolors_1 = __importDefault(require("picocolors"));
50
- const ROOT_DIR = path.resolve(__dirname, "..");
50
+ const ROOT_DIR = path.resolve(__dirname, "../..");
51
51
  const CONTRACTS_DIR = path.join(ROOT_DIR, "contracts");
52
52
  const TEST_DIR = path.join(ROOT_DIR, "test");
53
- const OUTPUT_FILE = path.join(ROOT_DIR, "scripts/config.ts");
53
+ const OUTPUT_FILE = path.join(ROOT_DIR, "scripts/shared/config.ts");
54
54
  // =============================================================================
55
55
  // Contract Analysis
56
56
  // =============================================================================
@@ -234,13 +234,6 @@ export interface CategoryConfig {
234
234
  contracts: Array<{ sol: string; test?: string }>;
235
235
  }
236
236
 
237
- // =============================================================================
238
- // GitHub Repository Configuration
239
- // =============================================================================
240
-
241
- export const REPO_URL = "https://github.com/NecipAkgz/fhevm-example-factory";
242
- export const REPO_BRANCH = "main";
243
-
244
237
  // =============================================================================
245
238
  // Example Configurations
246
239
  // =============================================================================
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generate-docs.d.ts","sourceRoot":"","sources":["../../../scripts/commands/generate-docs.ts"],"names":[],"mappings":";AAEA;;;;;GAKG;AAkEH,wBAAsB,qBAAqB,IAAI,OAAO,CAAC,IAAI,CAAC,CAiE3D;AAMD,wBAAsB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAkBhE"}
@@ -49,8 +49,9 @@ const p = __importStar(require("@clack/prompts"));
49
49
  const picocolors_1 = __importDefault(require("picocolors"));
50
50
  const fs = __importStar(require("fs"));
51
51
  const path = __importStar(require("path"));
52
- const config_1 = require("./config");
53
- const utils_1 = require("./utils");
52
+ const config_1 = require("../shared/config");
53
+ const utils_1 = require("../shared/utils");
54
+ const generators_1 = require("../shared/generators");
54
55
  // =============================================================================
55
56
  // Documentation Generator
56
57
  // =============================================================================
@@ -70,7 +71,7 @@ async function generateDocumentation(exampleName) {
70
71
  const testContent = fs.readFileSync(testPath, "utf-8");
71
72
  const contractName = (0, utils_1.getContractName)(example.contract) || "Contract";
72
73
  const testFileName = path.basename(example.test);
73
- const markdown = (0, utils_1.generateGitBookMarkdown)(example.description, contractContent, testContent, contractName, testFileName);
74
+ const markdown = (0, generators_1.generateGitBookMarkdown)(example.description, contractContent, testContent, contractName, testFileName);
74
75
  const outputPath = example.docsOutput
75
76
  ? path.join(rootDir, example.docsOutput)
76
77
  : path.join(rootDir, "docs", `${(0, config_1.getDocsFileName)(name)}.md`);
@@ -0,0 +1 @@
1
+ {"version":3,"file":"maintenance.d.ts","sourceRoot":"","sources":["../../../scripts/commands/maintenance.ts"],"names":[],"mappings":";AAEA;;;;;;;;;GASG;AAuNH,wBAAsB,eAAe,CAAC,WAAW,CAAC,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAqC3E"}
@@ -52,9 +52,10 @@ const p = __importStar(require("@clack/prompts"));
52
52
  const picocolors_1 = __importDefault(require("picocolors"));
53
53
  const fs = __importStar(require("fs"));
54
54
  const path = __importStar(require("path"));
55
- const config_1 = require("./config");
56
- const utils_1 = require("./utils");
57
- const builders_1 = require("./builders");
55
+ const config_1 = require("../shared/config");
56
+ const utils_1 = require("../shared/utils");
57
+ const generators_1 = require("../shared/generators");
58
+ const builders_1 = require("../shared/builders");
58
59
  // =============================================================================
59
60
  // Example Selection
60
61
  // =============================================================================
@@ -98,19 +99,19 @@ async function runTestPipeline(tempDir, exampleCount) {
98
99
  };
99
100
  const s1 = p.spinner();
100
101
  s1.start("Installing dependencies...");
101
- const installResult = await (0, utils_1.runCommandWithStatus)("npm", ["install"], tempDir);
102
+ const installResult = await (0, generators_1.runCommandWithStatus)("npm", ["install"], tempDir);
102
103
  if (!installResult.success) {
103
104
  s1.stop(picocolors_1.default.red("✗ npm install failed"));
104
- p.log.error((0, utils_1.extractErrorMessage)(installResult.output));
105
+ p.log.error((0, generators_1.extractErrorMessage)(installResult.output));
105
106
  return summary;
106
107
  }
107
108
  s1.stop(picocolors_1.default.green("✓ Dependencies installed"));
108
109
  const s2 = p.spinner();
109
110
  s2.start("Compiling contracts...");
110
- const compileResult = await (0, utils_1.runCommandWithStatus)("npm", ["run", "compile"], tempDir);
111
+ const compileResult = await (0, generators_1.runCommandWithStatus)("npm", ["run", "compile"], tempDir);
111
112
  if (!compileResult.success) {
112
113
  s2.stop(picocolors_1.default.red("✗ Compilation failed"));
113
- p.log.error((0, utils_1.extractErrorMessage)(compileResult.output));
114
+ p.log.error((0, generators_1.extractErrorMessage)(compileResult.output));
114
115
  return summary;
115
116
  }
116
117
  s2.stop(picocolors_1.default.green("✓ Contracts compiled"));
@@ -135,10 +136,10 @@ async function runTestPipeline(tempDir, exampleCount) {
135
136
  const progress = `[${i + 1}/${testFiles.length}]`;
136
137
  process.stdout.write(` ${picocolors_1.default.dim(progress)} ${testFile} `);
137
138
  const testStart = Date.now();
138
- const result = await (0, utils_1.runCommandWithStatus)("npx", ["hardhat", "test", `test/${testFile}`], tempDir);
139
+ const result = await (0, generators_1.runCommandWithStatus)("npx", ["hardhat", "test", `test/${testFile}`], tempDir);
139
140
  const duration = ((Date.now() - testStart) / 1000).toFixed(1);
140
141
  if (result.success) {
141
- const testResults = (0, utils_1.extractTestResults)(result.output);
142
+ const testResults = (0, generators_1.extractTestResults)(result.output);
142
143
  const resultInfo = testResults
143
144
  ? picocolors_1.default.dim(`(${testResults.replace(" ✓", "")})`)
144
145
  : "";
@@ -149,7 +150,7 @@ async function runTestPipeline(tempDir, exampleCount) {
149
150
  p.log.message(picocolors_1.default.red(`✗`) + ` ${picocolors_1.default.dim(duration + "s")}`);
150
151
  failedTests++;
151
152
  summary.failedTests.push(testFile);
152
- const errorMsg = (0, utils_1.extractErrorMessage)(result.output);
153
+ const errorMsg = (0, generators_1.extractErrorMessage)(result.output);
153
154
  if (errorMsg) {
154
155
  const shortError = errorMsg.split("\n")[0].slice(0, 80);
155
156
  p.log.message(` ${picocolors_1.default.red(picocolors_1.default.dim(shortError))}`);
@@ -50,13 +50,12 @@ const p = __importStar(require("@clack/prompts"));
50
50
  const picocolors_1 = __importDefault(require("picocolors"));
51
51
  const fs = __importStar(require("fs"));
52
52
  const path = __importStar(require("path"));
53
- const os = __importStar(require("os"));
54
- const config_1 = require("./config");
55
- const utils_1 = require("./utils");
56
- const builders_1 = require("./builders");
57
- const ui_1 = require("./ui");
58
- const add_mode_1 = require("./add-mode");
59
- const generate_docs_1 = require("./generate-docs");
53
+ const config_1 = require("./shared/config");
54
+ const utils_1 = require("./shared/utils");
55
+ const builders_1 = require("./shared/builders");
56
+ const ui_1 = require("./shared/ui");
57
+ const add_mode_1 = require("./commands/add-mode");
58
+ const generate_docs_1 = require("./commands/generate-docs");
60
59
  /** Prompts user to select mode and returns project configuration */
61
60
  async function getProjectConfig() {
62
61
  // Build options - docs only available in local dev mode
@@ -155,19 +154,14 @@ async function scaffoldProject(config) {
155
154
  p.log.error(`Directory already exists: ${resolvedOutput}`);
156
155
  process.exit(1);
157
156
  }
158
- const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "fhevm-"));
159
157
  const s = p.spinner();
160
158
  try {
161
- s.start("Downloading template...");
162
- const tempRepoPath = await (0, utils_1.cloneTemplate)(tempDir);
163
- s.message("Initializing submodules...");
164
- await (0, utils_1.initSubmodule)(tempRepoPath);
165
- s.message("Scaffolding your confidential project...");
159
+ s.start("Scaffolding your confidential project...");
166
160
  if (config.mode === "single") {
167
- await (0, builders_1.createSingleExample)(config.name, resolvedOutput, tempRepoPath);
161
+ (0, builders_1.createSingleExample)(config.name, resolvedOutput);
168
162
  }
169
163
  else {
170
- await (0, builders_1.createCategoryProject)(config.name, resolvedOutput, tempRepoPath);
164
+ (0, builders_1.createCategoryProject)(config.name, resolvedOutput);
171
165
  }
172
166
  s.stop("🎉 Project scaffolded successfully!");
173
167
  const relativePath = path.relative(process.cwd(), resolvedOutput);
@@ -198,11 +192,6 @@ async function scaffoldProject(config) {
198
192
  p.log.error(error instanceof Error ? error.message : String(error));
199
193
  process.exit(1);
200
194
  }
201
- finally {
202
- if (fs.existsSync(tempDir)) {
203
- fs.rmSync(tempDir, { recursive: true, force: true });
204
- }
205
- }
206
195
  p.outro(picocolors_1.default.green("✅ Setup complete. Happy encrypting!"));
207
196
  }
208
197
  /** Main interactive mode entry point */
@@ -282,20 +271,15 @@ async function runDirectMode(args) {
282
271
  catch (error) {
283
272
  (0, utils_1.handleError)(error);
284
273
  }
285
- const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "fhevm-"));
286
274
  try {
287
275
  utils_1.log.info(`\n🚀 Creating ${mode}: ${picocolors_1.default.yellow(name)}`);
288
276
  utils_1.log.dim("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
289
- utils_1.log.dim("Downloading template...");
290
- const tempRepoPath = await (0, utils_1.cloneTemplate)(tempDir);
291
- utils_1.log.dim("Initializing submodules...");
292
- await (0, utils_1.initSubmodule)(tempRepoPath);
293
277
  utils_1.log.dim("Building project...");
294
278
  if (mode === "example") {
295
- await (0, builders_1.createSingleExample)(name, resolved, tempRepoPath);
279
+ (0, builders_1.createSingleExample)(name, resolved);
296
280
  }
297
281
  else {
298
- await (0, builders_1.createCategoryProject)(name, resolved, tempRepoPath);
282
+ (0, builders_1.createCategoryProject)(name, resolved);
299
283
  }
300
284
  utils_1.log.success(`\n✨ Successfully created: ${picocolors_1.default.cyan(output)}`);
301
285
  if (shouldInstall) {
@@ -313,11 +297,6 @@ async function runDirectMode(args) {
313
297
  catch (error) {
314
298
  (0, utils_1.handleError)(error);
315
299
  }
316
- finally {
317
- if (fs.existsSync(tempDir)) {
318
- fs.rmSync(tempDir, { recursive: true, force: true });
319
- }
320
- }
321
300
  }
322
301
  // =============================================================================
323
302
  // QUICK MODE (CLI Arguments)
@@ -383,7 +362,9 @@ ${picocolors_1.default.cyan(picocolors_1.default.bold("⚡ EXAMPLES"))}
383
362
  ${picocolors_1.default.cyan(picocolors_1.default.bold("📦 AVAILABLE"))}
384
363
 
385
364
  Examples: ${picocolors_1.default.dim(Object.keys(config_1.EXAMPLES).slice(0, 5).join(", "))} ${picocolors_1.default.dim("...")} (${Object.keys(config_1.EXAMPLES).length} total)
386
- Categories: ${Object.keys(config_1.CATEGORIES).map((c) => picocolors_1.default.yellow(c)).join(", ")}
365
+ Categories: ${Object.keys(config_1.CATEGORIES)
366
+ .map((c) => picocolors_1.default.yellow(c))
367
+ .join(", ")}
387
368
 
388
369
  ${picocolors_1.default.dim("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━")}
389
370
  ${picocolors_1.default.dim("📚 Docs:")} ${picocolors_1.default.blue("https://github.com/NecipAkgz/fhevm-example-factory")}
@@ -7,11 +7,11 @@
7
7
  /**
8
8
  * Creates a single example project from the template
9
9
  */
10
- export declare function createSingleExample(exampleName: string, outputDir: string, tempRepoPath: string): Promise<void>;
10
+ export declare function createSingleExample(exampleName: string, outputDir: string): void;
11
11
  /**
12
12
  * Creates a category project with multiple examples
13
13
  */
14
- export declare function createCategoryProject(categoryName: string, outputDir: string, tempRepoPath: string): Promise<void>;
14
+ export declare function createCategoryProject(categoryName: string, outputDir: string): void;
15
15
  /**
16
16
  * Creates a temporary test project using LOCAL files (used by maintenance.ts)
17
17
  */
@@ -0,0 +1 @@
1
+ {"version":3,"file":"builders.d.ts","sourceRoot":"","sources":["../../../scripts/shared/builders.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AA6DH;;GAEG;AACH,wBAAgB,mBAAmB,CACjC,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,GAChB,IAAI,CAkDN;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CACnC,YAAY,EAAE,MAAM,EACpB,SAAS,EAAE,MAAM,GAChB,IAAI,CAwEN;AAMD;;GAEG;AACH,wBAAsB,sBAAsB,CAC1C,YAAY,EAAE,MAAM,EAAE,EACtB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,IAAI,CAAC,CAuEf"}
@@ -46,31 +46,39 @@ const fs = __importStar(require("fs"));
46
46
  const path = __importStar(require("path"));
47
47
  const config_1 = require("./config");
48
48
  const utils_1 = require("./utils");
49
+ const generators_1 = require("./generators");
49
50
  // =============================================================================
50
51
  // Helper Functions
51
52
  // =============================================================================
52
53
  /**
53
- * Downloads contract dependencies to the output directory
54
+ * Copies contract dependencies from package to output directory
54
55
  */
55
- async function downloadDependencies(dependencies, outputDir) {
56
+ function copyDependencies(dependencies, outputDir) {
57
+ const rootDir = (0, utils_1.getRootDir)();
56
58
  for (const depPath of dependencies) {
59
+ const sourcePath = path.join(rootDir, depPath);
57
60
  const relativePath = depPath.replace(/^contracts\//, "");
58
61
  const depDestPath = path.join(outputDir, "contracts", relativePath);
59
62
  const depDestDir = path.dirname(depDestPath);
60
63
  if (!fs.existsSync(depDestDir)) {
61
64
  fs.mkdirSync(depDestDir, { recursive: true });
62
65
  }
63
- await (0, utils_1.downloadFileFromGitHub)(depPath, depDestPath);
66
+ if (fs.existsSync(sourcePath)) {
67
+ fs.copyFileSync(sourcePath, depDestPath);
68
+ }
64
69
  }
65
70
  }
66
71
  /**
67
72
  * Initializes git repository (optional, fails silently)
68
73
  */
69
- async function initGitRepo(outputDir) {
74
+ function initGitRepo(outputDir) {
70
75
  try {
71
- await (0, utils_1.runCommand)("git", ["init"], outputDir);
76
+ require("child_process").execSync("git init", {
77
+ cwd: outputDir,
78
+ stdio: "ignore",
79
+ });
72
80
  }
73
- catch (error) {
81
+ catch {
74
82
  // Git init is optional
75
83
  }
76
84
  }
@@ -80,54 +88,65 @@ async function initGitRepo(outputDir) {
80
88
  /**
81
89
  * Creates a single example project from the template
82
90
  */
83
- async function createSingleExample(exampleName, outputDir, tempRepoPath) {
91
+ function createSingleExample(exampleName, outputDir) {
84
92
  const example = config_1.EXAMPLES[exampleName];
85
93
  if (!example) {
86
94
  throw new Error(`Unknown example: ${exampleName}`);
87
95
  }
88
- const templateDir = path.join(tempRepoPath, utils_1.TEMPLATE_DIR_NAME);
96
+ const rootDir = (0, utils_1.getRootDir)();
97
+ const templateDir = (0, utils_1.getTemplateDir)();
89
98
  const contractName = (0, utils_1.getContractName)(example.contract);
90
99
  if (!contractName) {
91
100
  throw new Error("Could not extract contract name");
92
101
  }
93
102
  // 1. Copy template and clean up
94
103
  (0, utils_1.copyDirectoryRecursive)(templateDir, outputDir);
95
- (0, utils_1.cleanupTemplate)(outputDir);
96
- // 2. Download example contract and dependencies
97
- await (0, utils_1.downloadFileFromGitHub)(example.contract, path.join(outputDir, "contracts", `${contractName}.sol`));
104
+ (0, generators_1.cleanupTemplate)(outputDir);
105
+ // 2. Copy example contract from package
106
+ const contractSource = path.join(rootDir, example.contract);
107
+ fs.copyFileSync(contractSource, path.join(outputDir, "contracts", `${contractName}.sol`));
108
+ // 3. Copy dependencies
98
109
  if (example.dependencies) {
99
- await downloadDependencies(example.dependencies, outputDir);
110
+ copyDependencies(example.dependencies, outputDir);
100
111
  }
101
- // 3. Download test file
102
- await (0, utils_1.downloadFileFromGitHub)(example.test, path.join(outputDir, "test", path.basename(example.test)));
103
- // 4. Update deploy script and package.json
104
- fs.writeFileSync(path.join(outputDir, "deploy", "deploy.ts"), (0, utils_1.generateDeployScript)(contractName));
105
- (0, utils_1.updateProjectPackageJson)(outputDir, `fhevm-example-${exampleName}`, example.description, example.npmDependencies);
106
- await initGitRepo(outputDir);
112
+ // 4. Copy test file
113
+ const testSource = path.join(rootDir, example.test);
114
+ fs.copyFileSync(testSource, path.join(outputDir, "test", path.basename(example.test)));
115
+ // 5. Update deploy script and package.json
116
+ fs.writeFileSync(path.join(outputDir, "deploy", "deploy.ts"), (0, generators_1.generateDeployScript)(contractName));
117
+ (0, generators_1.updateProjectPackageJson)(outputDir, `fhevm-example-${exampleName}`, example.description, example.npmDependencies);
118
+ initGitRepo(outputDir);
107
119
  }
108
120
  /**
109
121
  * Creates a category project with multiple examples
110
122
  */
111
- async function createCategoryProject(categoryName, outputDir, tempRepoPath) {
123
+ function createCategoryProject(categoryName, outputDir) {
112
124
  const category = config_1.CATEGORIES[categoryName];
113
125
  if (!category) {
114
126
  throw new Error(`Unknown category: ${categoryName}`);
115
127
  }
116
- const templateDir = path.join(tempRepoPath, utils_1.TEMPLATE_DIR_NAME);
128
+ const rootDir = (0, utils_1.getRootDir)();
129
+ const templateDir = (0, utils_1.getTemplateDir)();
117
130
  // 1. Copy template and clean up
118
131
  (0, utils_1.copyDirectoryRecursive)(templateDir, outputDir);
119
- (0, utils_1.cleanupTemplate)(outputDir);
120
- // 2. Download all contracts and tests
132
+ (0, generators_1.cleanupTemplate)(outputDir);
133
+ // 2. Copy all contracts and tests from package
121
134
  for (const item of category.contracts) {
122
135
  const contractName = (0, utils_1.getContractName)(item.sol);
123
136
  if (contractName) {
124
- await (0, utils_1.downloadFileFromGitHub)(item.sol, path.join(outputDir, "contracts", `${contractName}.sol`));
137
+ const contractSource = path.join(rootDir, item.sol);
138
+ if (fs.existsSync(contractSource)) {
139
+ fs.copyFileSync(contractSource, path.join(outputDir, "contracts", `${contractName}.sol`));
140
+ }
125
141
  }
126
142
  if (item.test) {
127
- await (0, utils_1.downloadFileFromGitHub)(item.test, path.join(outputDir, "test", path.basename(item.test)));
143
+ const testSource = path.join(rootDir, item.test);
144
+ if (fs.existsSync(testSource)) {
145
+ fs.copyFileSync(testSource, path.join(outputDir, "test", path.basename(item.test)));
146
+ }
128
147
  }
129
148
  }
130
- // 3. Collect and download dependencies
149
+ // 3. Collect and copy dependencies
131
150
  const allDependencies = new Set();
132
151
  const allNpmDependencies = {};
133
152
  for (const [exampleName, exampleConfig] of Object.entries(config_1.EXAMPLES)) {
@@ -146,11 +165,11 @@ async function createCategoryProject(categoryName, outputDir, tempRepoPath) {
146
165
  }
147
166
  }
148
167
  if (allDependencies.size > 0) {
149
- await downloadDependencies(Array.from(allDependencies), outputDir);
168
+ copyDependencies(Array.from(allDependencies), outputDir);
150
169
  }
151
170
  // 4. Update package.json
152
- (0, utils_1.updateProjectPackageJson)(outputDir, `fhevm-examples-${categoryName}`, undefined, allNpmDependencies);
153
- await initGitRepo(outputDir);
171
+ (0, generators_1.updateProjectPackageJson)(outputDir, `fhevm-examples-${categoryName}`, undefined, allNpmDependencies);
172
+ initGitRepo(outputDir);
154
173
  }
155
174
  // =============================================================================
156
175
  // Specialized Builders
@@ -163,7 +182,7 @@ async function createLocalTestProject(exampleNames, outputDir) {
163
182
  const templateDir = (0, utils_1.getTemplateDir)();
164
183
  // 1. Setup base project from local template
165
184
  (0, utils_1.copyDirectoryRecursive)(templateDir, outputDir);
166
- (0, utils_1.cleanupTemplate)(outputDir);
185
+ (0, generators_1.cleanupTemplate)(outputDir);
167
186
  const allNpmDeps = {};
168
187
  const allContractDeps = new Set();
169
188
  // 2. Copy local example files
@@ -203,7 +222,7 @@ async function createLocalTestProject(exampleNames, outputDir) {
203
222
  }
204
223
  }
205
224
  // 4. Finalize project
206
- (0, utils_1.updateProjectPackageJson)(outputDir, "fhevm-test-project", `Testing ${exampleNames.length} examples`, Object.keys(allNpmDeps).length > 0 ? allNpmDeps : undefined);
225
+ (0, generators_1.updateProjectPackageJson)(outputDir, "fhevm-test-project", `Testing ${exampleNames.length} examples`, Object.keys(allNpmDeps).length > 0 ? allNpmDeps : undefined);
207
226
  const typesPath = path.join(outputDir, "test", "types.ts");
208
227
  if (!fs.existsSync(typesPath)) {
209
228
  fs.writeFileSync(typesPath, utils_1.TEST_TYPES_CONTENT);
@@ -31,8 +31,6 @@ export interface CategoryConfig {
31
31
  test?: string;
32
32
  }>;
33
33
  }
34
- export declare const REPO_URL = "https://github.com/NecipAkgz/fhevm-example-factory";
35
- export declare const REPO_BRANCH = "main";
36
34
  export declare const EXAMPLES: Record<string, ExampleConfig>;
37
35
  export declare const CATEGORIES: Record<string, CategoryConfig>;
38
36
  /**
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../../scripts/shared/config.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH,MAAM,WAAW,aAAa;IAC5B,yCAAyC;IACzC,QAAQ,EAAE,MAAM,CAAC;IACjB,uCAAuC;IACvC,IAAI,EAAE,MAAM,CAAC;IACb,gDAAgD;IAChD,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,uCAAuC;IACvC,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACzC,yCAAyC;IACzC,WAAW,EAAE,MAAM,CAAC;IACpB,4BAA4B;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,8CAA8C;IAC9C,UAAU,EAAE,MAAM,CAAC;IACnB,8BAA8B;IAC9B,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,cAAc;IAC7B,mBAAmB;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,yCAAyC;IACzC,SAAS,EAAE,KAAK,CAAC;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAClD;AAMD,eAAO,MAAM,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CA+QlD,CAAC;AAMF,eAAO,MAAM,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAoJrD,CAAC;AAMF;;GAEG;AACH,wBAAgB,eAAe,IAAI,MAAM,EAAE,CAE1C;AAED;;GAEG;AACH,wBAAgB,gBAAgB,IAAI,MAAM,EAAE,CAE3C;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa,GAAG,SAAS,CAElE;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,cAAc,GAAG,SAAS,CAEpE;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAE3D"}