codecrypto-cli 1.0.7 → 1.0.9

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 (154) hide show
  1. package/dist/commands/auth.d.ts.map +1 -1
  2. package/dist/commands/auth.js +64 -7
  3. package/dist/commands/auth.js.map +1 -1
  4. package/dist/commands/deploy-sc.d.ts.map +1 -1
  5. package/dist/commands/deploy-sc.js +162 -0
  6. package/dist/commands/deploy-sc.js.map +1 -1
  7. package/dist/commands/deploy.d.ts.map +1 -1
  8. package/dist/commands/deploy.js +556 -18
  9. package/dist/commands/deploy.js.map +1 -1
  10. package/dist/commands/doctor.d.ts +3 -0
  11. package/dist/commands/doctor.d.ts.map +1 -0
  12. package/dist/commands/doctor.js +518 -0
  13. package/dist/commands/doctor.js.map +1 -0
  14. package/dist/index.js +2 -0
  15. package/dist/index.js.map +1 -1
  16. package/docker-build/Dockerfile +18 -0
  17. package/docker-build/standalone/.next/BUILD_ID +1 -0
  18. package/docker-build/standalone/.next/app-path-routes-manifest.json +6 -0
  19. package/docker-build/standalone/.next/build-manifest.json +19 -0
  20. package/docker-build/standalone/.next/package.json +1 -0
  21. package/docker-build/standalone/.next/prerender-manifest.json +114 -0
  22. package/docker-build/standalone/.next/required-server-files.json +164 -0
  23. package/docker-build/standalone/.next/routes-manifest.json +68 -0
  24. package/docker-build/standalone/.next/server/app/_global-error/page/app-paths-manifest.json +3 -0
  25. package/docker-build/standalone/.next/server/app/_global-error/page/build-manifest.json +16 -0
  26. package/docker-build/standalone/.next/server/app/_global-error/page/next-font-manifest.json +6 -0
  27. package/docker-build/standalone/.next/server/app/_global-error/page/react-loadable-manifest.json +1 -0
  28. package/docker-build/standalone/.next/server/app/_global-error/page/server-reference-manifest.json +4 -0
  29. package/docker-build/standalone/.next/server/app/_global-error/page.js +11 -0
  30. package/docker-build/standalone/.next/server/app/_global-error/page.js.map +5 -0
  31. package/docker-build/standalone/.next/server/app/_global-error/page.js.nft.json +1 -0
  32. package/docker-build/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +2 -0
  33. package/docker-build/standalone/.next/server/app/_global-error.html +2 -0
  34. package/docker-build/standalone/.next/server/app/_global-error.meta +15 -0
  35. package/docker-build/standalone/.next/server/app/_global-error.rsc +13 -0
  36. package/docker-build/standalone/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +5 -0
  37. package/docker-build/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +13 -0
  38. package/docker-build/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +6 -0
  39. package/docker-build/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +4 -0
  40. package/docker-build/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -0
  41. package/docker-build/standalone/.next/server/app/_not-found/page/app-paths-manifest.json +3 -0
  42. package/docker-build/standalone/.next/server/app/_not-found/page/build-manifest.json +16 -0
  43. package/docker-build/standalone/.next/server/app/_not-found/page/next-font-manifest.json +11 -0
  44. package/docker-build/standalone/.next/server/app/_not-found/page/react-loadable-manifest.json +1 -0
  45. package/docker-build/standalone/.next/server/app/_not-found/page/server-reference-manifest.json +4 -0
  46. package/docker-build/standalone/.next/server/app/_not-found/page.js +14 -0
  47. package/docker-build/standalone/.next/server/app/_not-found/page.js.map +5 -0
  48. package/docker-build/standalone/.next/server/app/_not-found/page.js.nft.json +1 -0
  49. package/docker-build/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +2 -0
  50. package/docker-build/standalone/.next/server/app/_not-found.html +1 -0
  51. package/docker-build/standalone/.next/server/app/_not-found.meta +16 -0
  52. package/docker-build/standalone/.next/server/app/_not-found.rsc +14 -0
  53. package/docker-build/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +14 -0
  54. package/docker-build/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +6 -0
  55. package/docker-build/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +5 -0
  56. package/docker-build/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +5 -0
  57. package/docker-build/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +4 -0
  58. package/docker-build/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -0
  59. package/docker-build/standalone/.next/server/app/favicon.ico/route/app-paths-manifest.json +3 -0
  60. package/docker-build/standalone/.next/server/app/favicon.ico/route/build-manifest.json +11 -0
  61. package/docker-build/standalone/.next/server/app/favicon.ico/route.js +6 -0
  62. package/docker-build/standalone/.next/server/app/favicon.ico/route.js.map +5 -0
  63. package/docker-build/standalone/.next/server/app/favicon.ico/route.js.nft.json +1 -0
  64. package/docker-build/standalone/.next/server/app/favicon.ico.body +0 -0
  65. package/docker-build/standalone/.next/server/app/favicon.ico.meta +1 -0
  66. package/docker-build/standalone/.next/server/app/index.html +1 -0
  67. package/docker-build/standalone/.next/server/app/index.meta +14 -0
  68. package/docker-build/standalone/.next/server/app/index.rsc +16 -0
  69. package/docker-build/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +5 -0
  70. package/docker-build/standalone/.next/server/app/index.segments/_full.segment.rsc +16 -0
  71. package/docker-build/standalone/.next/server/app/index.segments/_head.segment.rsc +6 -0
  72. package/docker-build/standalone/.next/server/app/index.segments/_index.segment.rsc +5 -0
  73. package/docker-build/standalone/.next/server/app/index.segments/_tree.segment.rsc +4 -0
  74. package/docker-build/standalone/.next/server/app/page/app-paths-manifest.json +3 -0
  75. package/docker-build/standalone/.next/server/app/page/build-manifest.json +16 -0
  76. package/docker-build/standalone/.next/server/app/page/next-font-manifest.json +11 -0
  77. package/docker-build/standalone/.next/server/app/page/react-loadable-manifest.json +1 -0
  78. package/docker-build/standalone/.next/server/app/page/server-reference-manifest.json +4 -0
  79. package/docker-build/standalone/.next/server/app/page.js +16 -0
  80. package/docker-build/standalone/.next/server/app/page.js.map +5 -0
  81. package/docker-build/standalone/.next/server/app/page.js.nft.json +1 -0
  82. package/docker-build/standalone/.next/server/app/page_client-reference-manifest.js +2 -0
  83. package/docker-build/standalone/.next/server/app-paths-manifest.json +6 -0
  84. package/docker-build/standalone/.next/server/chunks/66d90_example-navidad__next-internal_server_app_favicon_ico_route_actions_a30dceae.js +3 -0
  85. package/docker-build/standalone/.next/server/chunks/[externals]_next_dist_03fe02e0._.js +3 -0
  86. package/docker-build/standalone/.next/server/chunks/[root-of-the-server]__4b49000d._.js +21 -0
  87. package/docker-build/standalone/.next/server/chunks/[turbopack]_runtime.js +795 -0
  88. package/docker-build/standalone/.next/server/chunks/ssr/10072_infra_example-navidad__next-internal_server_app_page_actions_a387aef9.js +3 -0
  89. package/docker-build/standalone/.next/server/chunks/ssr/2025_cc_CODECRYPTO_infra_example-navidad_377109b0._.js +3 -0
  90. package/docker-build/standalone/.next/server/chunks/ssr/2025_cc_CODECRYPTO_infra_example-navidad_90799f30._.js +4 -0
  91. package/docker-build/standalone/.next/server/chunks/ssr/2025_cc_CODECRYPTO_infra_example-navidad_app_b9057478._.js +3 -0
  92. package/docker-build/standalone/.next/server/chunks/ssr/66d90_example-navidad__next-internal_server_app__global-error_page_actions_a079475f.js +3 -0
  93. package/docker-build/standalone/.next/server/chunks/ssr/66d90_example-navidad__next-internal_server_app__not-found_page_actions_ac88cec2.js +3 -0
  94. package/docker-build/standalone/.next/server/chunks/ssr/77a20_next_dist_51be1544._.js +4 -0
  95. package/docker-build/standalone/.next/server/chunks/ssr/77a20_next_dist_8dba0557._.js +6 -0
  96. package/docker-build/standalone/.next/server/chunks/ssr/77a20_next_dist_client_components_41330064._.js +3 -0
  97. package/docker-build/standalone/.next/server/chunks/ssr/77a20_next_dist_client_components_builtin_forbidden_ff3a0457.js +3 -0
  98. package/docker-build/standalone/.next/server/chunks/ssr/77a20_next_dist_client_components_builtin_global-error_e0d57e6e.js +3 -0
  99. package/docker-build/standalone/.next/server/chunks/ssr/77a20_next_dist_client_components_builtin_unauthorized_f1c47e13.js +3 -0
  100. package/docker-build/standalone/.next/server/chunks/ssr/77a20_next_dist_d332f292._.js +3 -0
  101. package/docker-build/standalone/.next/server/chunks/ssr/77a20_next_dist_esm_build_templates_app-page_cf6afba1.js +4 -0
  102. package/docker-build/standalone/.next/server/chunks/ssr/[root-of-the-server]__02f3f427._.js +3 -0
  103. package/docker-build/standalone/.next/server/chunks/ssr/[root-of-the-server]__2f460610._.js +4 -0
  104. package/docker-build/standalone/.next/server/chunks/ssr/[root-of-the-server]__4722e53c._.js +3 -0
  105. package/docker-build/standalone/.next/server/chunks/ssr/[root-of-the-server]__53b749fa._.js +3 -0
  106. package/docker-build/standalone/.next/server/chunks/ssr/[root-of-the-server]__61942f2d._.js +3 -0
  107. package/docker-build/standalone/.next/server/chunks/ssr/[root-of-the-server]__7707ad1b._.js +3 -0
  108. package/docker-build/standalone/.next/server/chunks/ssr/[root-of-the-server]__864cadbf._.js +10 -0
  109. package/docker-build/standalone/.next/server/chunks/ssr/[root-of-the-server]__9939e281._.js +3 -0
  110. package/docker-build/standalone/.next/server/chunks/ssr/[root-of-the-server]__b4b0aa8a._.js +3 -0
  111. package/docker-build/standalone/.next/server/chunks/ssr/[root-of-the-server]__d2b7072b._.js +3 -0
  112. package/docker-build/standalone/.next/server/chunks/ssr/[turbopack]_runtime.js +795 -0
  113. package/docker-build/standalone/.next/server/functions-config-manifest.json +4 -0
  114. package/docker-build/standalone/.next/server/middleware-build-manifest.js +20 -0
  115. package/docker-build/standalone/.next/server/middleware-manifest.json +6 -0
  116. package/docker-build/standalone/.next/server/next-font-manifest.js +1 -0
  117. package/docker-build/standalone/.next/server/next-font-manifest.json +15 -0
  118. package/docker-build/standalone/.next/server/pages/404.html +1 -0
  119. package/docker-build/standalone/.next/server/pages/500.html +2 -0
  120. package/docker-build/standalone/.next/server/pages-manifest.json +4 -0
  121. package/docker-build/standalone/.next/server/server-reference-manifest.js +1 -0
  122. package/docker-build/standalone/.next/server/server-reference-manifest.json +5 -0
  123. package/docker-build/standalone/.next/static/_NbfI2TKfapiyxsQgIG3h/_buildManifest.js +11 -0
  124. package/docker-build/standalone/.next/static/_NbfI2TKfapiyxsQgIG3h/_clientMiddlewareManifest.json +1 -0
  125. package/docker-build/standalone/.next/static/_NbfI2TKfapiyxsQgIG3h/_ssgManifest.js +1 -0
  126. package/docker-build/standalone/.next/static/chunks/57d1af92f5dc15fa.js +1 -0
  127. package/docker-build/standalone/.next/static/chunks/6ae71d5e8ea4d1eb.js +1 -0
  128. package/docker-build/standalone/.next/static/chunks/70977d70c9306213.js +1 -0
  129. package/docker-build/standalone/.next/static/chunks/777dac7104fe2a30.js +5 -0
  130. package/docker-build/standalone/.next/static/chunks/a6dad97d9634a72d.js +1 -0
  131. package/docker-build/standalone/.next/static/chunks/a6dad97d9634a72d.js.map +1 -0
  132. package/docker-build/standalone/.next/static/chunks/d6aec49b013224a2.css +3 -0
  133. package/docker-build/standalone/.next/static/chunks/turbopack-0ce517fb6224c1f0.js +4 -0
  134. package/docker-build/standalone/.next/static/media/4fa387ec64143e14-s.c1fdd6c2.woff2 +0 -0
  135. package/docker-build/standalone/.next/static/media/7178b3e590c64307-s.b97b3418.woff2 +0 -0
  136. package/docker-build/standalone/.next/static/media/797e433ab948586e-s.p.dbea232f.woff2 +0 -0
  137. package/docker-build/standalone/.next/static/media/8a480f0b521d4e75-s.8e0177b5.woff2 +0 -0
  138. package/docker-build/standalone/.next/static/media/bbc41e54d2fcbd21-s.799d8ef8.woff2 +0 -0
  139. package/docker-build/standalone/.next/static/media/caa3a2e1cccd8315-s.p.853070df.woff2 +0 -0
  140. package/docker-build/standalone/.next/static/media/favicon.0b3bf435.ico +0 -0
  141. package/docker-build/standalone/package.json +26 -0
  142. package/docker-build/standalone/public/file.svg +1 -0
  143. package/docker-build/standalone/public/globe.svg +1 -0
  144. package/docker-build/standalone/public/next.svg +1 -0
  145. package/docker-build/standalone/public/vercel.svg +1 -0
  146. package/docker-build/standalone/public/window.svg +1 -0
  147. package/docker-build/standalone/server.js +38 -0
  148. package/package.json +1 -1
  149. package/src/commands/auth.ts +71 -8
  150. package/src/commands/deploy-sc.ts +182 -0
  151. package/src/commands/deploy.ts +592 -21
  152. package/src/commands/doctor.ts +498 -0
  153. package/src/index.ts +2 -0
  154. package/token.json +69 -0
@@ -34,6 +34,7 @@ export const authCommand = new Command('auth')
34
34
  .option('--server-url <url>', 'Server URL', API_BASE_URL)
35
35
  .option('--poll-interval <seconds>', 'Polling interval in seconds', '3')
36
36
  .option('--debug', 'Show debug information', false)
37
+ .option('--force', 'Force creation of new token even if one exists', false)
37
38
  .action(async (options) => {
38
39
  console.log(chalk.blue('\n🔐 CodeCrypto Authentication\n'));
39
40
 
@@ -41,6 +42,40 @@ export const authCommand = new Command('auth')
41
42
  const pollInterval = parseInt(options.pollInterval || '3', 10) * 1000;
42
43
 
43
44
  try {
45
+ // Verificar si ya existe un token guardado
46
+ const homeDir = os.homedir();
47
+ const codecryptoDir = path.join(homeDir, '.codecrypto');
48
+ const tokenFile = path.join(codecryptoDir, 'token.json');
49
+
50
+ // Verificar si ya existe un token y si se debe crear uno nuevo
51
+ if (!options.force && fs.existsSync(tokenFile)) {
52
+ try {
53
+ const existingTokenData = JSON.parse(fs.readFileSync(tokenFile, 'utf-8'));
54
+ if (existingTokenData.token && existingTokenData.email) {
55
+ console.log(chalk.yellow('⚠️ Found existing authentication token'));
56
+ console.log(chalk.gray(` Email: ${chalk.cyan(existingTokenData.email)}`));
57
+ console.log(chalk.gray(` Created: ${chalk.cyan(existingTokenData.createdAt || 'unknown')}`));
58
+ console.log(chalk.yellow('\n💡 You already have a valid token. Creating a new one will generate a new token in the database.'));
59
+ console.log(chalk.yellow(' To use the existing token, you can skip this authentication.'));
60
+ console.log(chalk.yellow(' To create a new token, use: codecrypto auth --force\n'));
61
+
62
+ // Por defecto, no crear un nuevo token si ya existe uno
63
+ console.log(chalk.green('✅ Using existing token. No new token will be created.'));
64
+ console.log(chalk.gray(` Token location: ${chalk.cyan(tokenFile)}\n`));
65
+ process.exit(0);
66
+ }
67
+ } catch (error) {
68
+ // Si hay error leyendo el token existente, continuar con la creación
69
+ if (options.debug) {
70
+ console.log(chalk.yellow(`[DEBUG] Could not read existing token: ${error}`));
71
+ }
72
+ }
73
+ }
74
+
75
+ if (options.force && fs.existsSync(tokenFile)) {
76
+ console.log(chalk.yellow('⚠️ Force flag detected. Creating new token (this will not invalidate the previous one).\n'));
77
+ }
78
+
44
79
  // Paso 1: Solicitar código de autenticación
45
80
  const requestSpinner = ora('Requesting authentication code...').start();
46
81
 
@@ -59,6 +94,12 @@ export const authCommand = new Command('auth')
59
94
 
60
95
  const jsonData = await response.json();
61
96
 
97
+ // Mostrar respuesta raw
98
+ console.log(chalk.gray('\n[RAW RESPONSE] POST /api/tokens:'));
99
+ console.log(chalk.gray('─'.repeat(60)));
100
+ console.log(JSON.stringify(jsonData, null, 2));
101
+ console.log(chalk.gray('─'.repeat(60)));
102
+
62
103
  if (options.debug) {
63
104
  console.log(chalk.gray(`\n[DEBUG] POST Response: ${JSON.stringify(jsonData, null, 2)}`));
64
105
  }
@@ -122,7 +163,7 @@ export const authCommand = new Command('auth')
122
163
  process.exit(1);
123
164
  }
124
165
 
125
- const tokenUrl = `${serverUrl}/token`;
166
+ const tokenUrl = `${serverUrl}/login?token=${tokenId}`;
126
167
 
127
168
  // Mostrar información al usuario con el ID REAL obtenido
128
169
  console.log(chalk.green('\n✅ Authentication code generated!'));
@@ -139,6 +180,7 @@ export const authCommand = new Command('auth')
139
180
 
140
181
  let verifiedToken: string | null = null;
141
182
  let tokenEmail: string | null = null;
183
+ let verificationData: any = null; // Guardar toda la respuesta de verificación
142
184
  let attempts = 0;
143
185
 
144
186
  // Función helper para extraer el token JWT y el email de la respuesta
@@ -233,15 +275,24 @@ export const authCommand = new Command('auth')
233
275
  if (verifyResponse.ok) {
234
276
  const verifyData = await verifyResponse.json();
235
277
 
278
+ // Mostrar respuesta raw solo en el primer intento exitoso o si hay token
279
+ const extracted = extractToken(verifyData);
280
+ if (extracted.token && !verifiedToken) {
281
+ console.log(chalk.gray('\n[RAW RESPONSE] GET /api/tokens/{id}:'));
282
+ console.log(chalk.gray('─'.repeat(60)));
283
+ //console.log(JSON.stringify(verifyData, null, 2));
284
+ console.log(chalk.gray('─'.repeat(60)));
285
+ }
286
+
236
287
  if (options.debug) {
237
288
  console.log(chalk.gray(`\n[DEBUG] Attempt ${attempts + 1} - Response: ${JSON.stringify(verifyData, null, 2)}`));
238
289
  }
239
290
 
240
291
  // Intentar extraer el token
241
- const extracted = extractToken(verifyData);
242
292
  if (extracted.token) {
243
293
  verifiedToken = extracted.token;
244
294
  tokenEmail = extracted.email;
295
+ verificationData = verifyData; // Guardar toda la respuesta
245
296
  break;
246
297
  }
247
298
  } else {
@@ -275,9 +326,7 @@ export const authCommand = new Command('auth')
275
326
  pollSpinner.succeed('Token verified successfully');
276
327
 
277
328
  // Paso 3: Guardar token en ~/.codecrypto
278
- const homeDir = os.homedir();
279
- const codecryptoDir = path.join(homeDir, '.codecrypto');
280
- const tokenFile = path.join(codecryptoDir, 'token.json');
329
+ // Reutilizar las variables ya declaradas arriba
281
330
 
282
331
  const saveSpinner = ora('Saving authentication token...').start();
283
332
 
@@ -287,14 +336,27 @@ export const authCommand = new Command('auth')
287
336
  fs.mkdirSync(codecryptoDir, { recursive: true });
288
337
  }
289
338
 
290
- // Guardar token
291
- const tokenContent = {
339
+ // Guardar datos básicos y extraer globals de la respuesta
340
+ const tokenContent: any = {
341
+ // Datos básicos extraídos
292
342
  token: verifiedToken,
293
343
  email: tokenEmail,
344
+ tokenId: tokenId,
345
+ code: code,
294
346
  serverUrl: serverUrl,
295
- createdAt: new Date().toISOString(),
347
+ verifiedAt: new Date().toISOString(),
296
348
  };
297
349
 
350
+ // Extraer studentGlobalsAll y adminGlobals de verificationResponse.globals
351
+ if (verificationData && verificationData.globals) {
352
+ if (verificationData.globals.studentGlobalsAll) {
353
+ tokenContent.studentGlobalsAll = verificationData.globals.studentGlobalsAll;
354
+ }
355
+ if (verificationData.globals.adminGlobals) {
356
+ tokenContent.adminGlobals = verificationData.globals.adminGlobals;
357
+ }
358
+ }
359
+
298
360
  fs.writeFileSync(tokenFile, JSON.stringify(tokenContent, null, 2), 'utf-8');
299
361
  saveSpinner.succeed('Token saved successfully');
300
362
  } catch (error: any) {
@@ -308,6 +370,7 @@ export const authCommand = new Command('auth')
308
370
  if (tokenEmail) {
309
371
  console.log(chalk.gray(` Email: ${chalk.cyan(tokenEmail)}`));
310
372
  }
373
+ console.log(chalk.gray(` Token ID: ${chalk.cyan(tokenId)}`));
311
374
  console.log('');
312
375
 
313
376
  } catch (error: any) {
@@ -4,6 +4,7 @@ import ora from 'ora';
4
4
  import { execSync } from 'child_process';
5
5
  import * as fs from 'fs';
6
6
  import * as path from 'path';
7
+ import * as os from 'os';
7
8
 
8
9
  export const deployScCommand = new Command('deploy-sc')
9
10
  .description('Deploy smart contract using Foundry')
@@ -15,6 +16,7 @@ export const deployScCommand = new Command('deploy-sc')
15
16
  .option('--verify', 'Verify contract on block explorer', false)
16
17
  .option('--broadcast', 'Broadcast the transaction', true)
17
18
  .option('--slow', 'Use slow mode for deployment', false)
19
+ .option('--debug', 'Show debug information', false)
18
20
  .action(async (scriptPath: string, options) => {
19
21
  console.log(chalk.blue('\n🔷 CodeCrypto Smart Contract Deployment\n'));
20
22
 
@@ -168,6 +170,29 @@ export const deployScCommand = new Command('deploy-sc')
168
170
 
169
171
  deploySpinner.succeed('Smart contract desplegado exitosamente');
170
172
 
173
+ // Buscar y leer el archivo de transacciones generado por Foundry (solo si se hizo broadcast)
174
+ if (options.broadcast) {
175
+ const uploadSpinner = ora('Uploading deployment results to database...').start();
176
+ try {
177
+ await uploadDeploymentResults({
178
+ scriptPath: scriptRelativePath,
179
+ foundryProjectDir,
180
+ rpcUrl: options.url,
181
+ privateKey: privateKey || (options.account !== undefined ? `account-${options.account}` : null),
182
+ debug: options.debug || false,
183
+ });
184
+ uploadSpinner.succeed('Deployment results uploaded successfully');
185
+ } catch (uploadError: any) {
186
+ uploadSpinner.warn(`Failed to upload deployment results: ${uploadError.message}`);
187
+ console.log(chalk.yellow(' Deployment was successful, but results were not saved to database'));
188
+ if (uploadError.message.includes('run-latest.json')) {
189
+ console.log(chalk.yellow(' Note: Make sure --broadcast flag is used to generate transaction files'));
190
+ }
191
+ }
192
+ } else {
193
+ console.log(chalk.gray('\n💡 Deployment results not uploaded (--broadcast was not used)'));
194
+ }
195
+
171
196
  console.log(chalk.green('\n✅ Deployment completed successfully!'));
172
197
  console.log(chalk.gray('Contract details:'));
173
198
  console.log(chalk.white(` Script: ${chalk.cyan(scriptRelativePath)}`));
@@ -198,3 +223,160 @@ export const deployScCommand = new Command('deploy-sc')
198
223
  }
199
224
  });
200
225
 
226
+ // Función para subir los resultados del despliegue a la base de datos
227
+ async function uploadDeploymentResults(config: {
228
+ scriptPath: string;
229
+ foundryProjectDir: string;
230
+ rpcUrl: string;
231
+ privateKey: string | null;
232
+ debug?: boolean;
233
+ }) {
234
+ // 1. Leer token.json para obtener email y serverUrl
235
+ const tokenFilePath = path.join(os.homedir(), '.codecrypto', 'token.json');
236
+ if (!fs.existsSync(tokenFilePath)) {
237
+ throw new Error('Token file not found. Please run "codecrypto auth" first.');
238
+ }
239
+
240
+ let tokenData: any;
241
+ try {
242
+ tokenData = JSON.parse(fs.readFileSync(tokenFilePath, 'utf-8'));
243
+ } catch (error: any) {
244
+ throw new Error(`Failed to read token file: ${error.message}`);
245
+ }
246
+
247
+ const email = tokenData.email;
248
+ const serverUrl = tokenData.serverUrl || 'http://localhost:3000';
249
+ const token = tokenData.token;
250
+
251
+ if (!email) {
252
+ throw new Error('Email not found in token.json');
253
+ }
254
+
255
+ if (!token) {
256
+ throw new Error('Token not found in token.json');
257
+ }
258
+
259
+ // 2. Encontrar el archivo JSON de transacciones
260
+ // Foundry guarda los resultados en: broadcast/{ScriptName}/{chainId}/run-latest.json
261
+ const scriptName = path.basename(config.scriptPath, '.s.sol');
262
+ const broadcastDir = path.join(config.foundryProjectDir, 'broadcast', `${scriptName}.s.sol`);
263
+
264
+ if (!fs.existsSync(broadcastDir)) {
265
+ throw new Error(`Broadcast directory not found: ${broadcastDir}`);
266
+ }
267
+
268
+ // Buscar el archivo run-latest.json en cualquier subdirectorio de chainId
269
+ let transactionsJsonPath: string | null = null;
270
+ const chainDirs = fs.readdirSync(broadcastDir, { withFileTypes: true })
271
+ .filter(dirent => dirent.isDirectory())
272
+ .map(dirent => dirent.name);
273
+
274
+ for (const chainDir of chainDirs) {
275
+ const runLatestPath = path.join(broadcastDir, chainDir, 'run-latest.json');
276
+ if (fs.existsSync(runLatestPath)) {
277
+ transactionsJsonPath = runLatestPath;
278
+ break;
279
+ }
280
+ }
281
+
282
+ if (!transactionsJsonPath) {
283
+ throw new Error(`No run-latest.json found in ${broadcastDir}`);
284
+ }
285
+
286
+ // 3. Leer el JSON de transacciones
287
+ let transactionsData: any;
288
+ try {
289
+ transactionsData = JSON.parse(fs.readFileSync(transactionsJsonPath, 'utf-8'));
290
+ } catch (error: any) {
291
+ throw new Error(`Failed to read transactions file: ${error.message}`);
292
+ }
293
+
294
+ // 4. Obtener el folder (directorio del proyecto)
295
+ const folder = config.foundryProjectDir;
296
+
297
+ // 5. Preparar los datos para enviar
298
+ // Asegurarse de que transactionsData incluye tanto transactions como receipts
299
+ const uploadData = {
300
+ email,
301
+ folder,
302
+ transactions: transactionsData, // Incluye transactions, receipts, y todo lo demás
303
+ rpcUrl: config.rpcUrl,
304
+ privateKey: config.privateKey,
305
+ };
306
+
307
+ // Verificar que tenemos transacciones
308
+ if (!transactionsData.transactions || !Array.isArray(transactionsData.transactions)) {
309
+ throw new Error('No transactions found in run-latest.json');
310
+ }
311
+
312
+ // 6. Hacer la llamada POST al endpoint
313
+ const apiUrl = `${serverUrl}/api/uploadSmartContract`;
314
+
315
+ // Log de la petición (solo si debug está activado)
316
+ if (config.debug) {
317
+ console.log(chalk.gray('\n[UPLOAD REQUEST] POST /api/uploadSmartContract:'));
318
+ console.log(chalk.gray('─'.repeat(60)));
319
+ console.log(chalk.gray(`URL: ${chalk.cyan(apiUrl)}`));
320
+ console.log(chalk.gray(`Method: ${chalk.cyan('POST')}`));
321
+ console.log(chalk.gray('Headers:'));
322
+ console.log(chalk.gray(` Content-Type: ${chalk.cyan('application/json')}`));
323
+ console.log(chalk.gray(` Authorization: ${chalk.cyan('Bearer ' + token.substring(0, 20) + '...')}`));
324
+ console.log(chalk.gray('Body summary:'));
325
+ console.log(chalk.gray(` email: ${chalk.cyan(email)}`));
326
+ console.log(chalk.gray(` folder: ${chalk.cyan(folder)}`));
327
+ console.log(chalk.gray(` rpcUrl: ${chalk.cyan(config.rpcUrl)}`));
328
+ console.log(chalk.gray(` privateKey: ${chalk.cyan(config.privateKey ? `${config.privateKey.substring(0, 10)}...` : 'null')}`));
329
+ console.log(chalk.gray(` transactions.transactions: ${chalk.cyan(transactionsData.transactions.length)} transaction(s)`));
330
+ console.log(chalk.gray(` transactions.receipts: ${chalk.cyan(transactionsData.receipts ? transactionsData.receipts.length : 0)} receipt(s)`));
331
+ console.log(chalk.gray(` transactions.chain: ${chalk.cyan(transactionsData.chain || 'N/A')}`));
332
+ console.log(chalk.gray('─'.repeat(60)));
333
+ console.log(chalk.gray(chalk.yellow('⚠️ Sending full transactions data (not just receipts)...')));
334
+ }
335
+
336
+ try {
337
+ const response = await fetch(apiUrl, {
338
+ method: 'POST',
339
+ headers: {
340
+ 'Content-Type': 'application/json',
341
+ 'Authorization': `Bearer ${token}`,
342
+ },
343
+ body: JSON.stringify(uploadData),
344
+ });
345
+
346
+ // Log de la respuesta (solo si debug está activado)
347
+ const responseText = await response.text();
348
+ if (config.debug) {
349
+ console.log(chalk.gray('\n[UPLOAD RESPONSE] POST /api/uploadSmartContract:'));
350
+ console.log(chalk.gray('─'.repeat(60)));
351
+ console.log(chalk.gray(`Status: ${response.ok ? chalk.green(response.status) : chalk.red(response.status)}`));
352
+ console.log(chalk.gray('Response:'));
353
+ try {
354
+ const responseJson = JSON.parse(responseText);
355
+ console.log(JSON.stringify(responseJson, null, 2));
356
+ } catch {
357
+ console.log(responseText);
358
+ }
359
+ console.log(chalk.gray('─'.repeat(60)));
360
+ }
361
+
362
+ if (!response.ok) {
363
+ let errorMessage: string;
364
+ try {
365
+ const errorJson = JSON.parse(responseText);
366
+ errorMessage = errorJson.error || errorJson.message || responseText;
367
+ } catch {
368
+ errorMessage = responseText || `HTTP error! status: ${response.status}`;
369
+ }
370
+ throw new Error(errorMessage);
371
+ }
372
+
373
+ const result = JSON.parse(responseText);
374
+ return result;
375
+ } catch (error: any) {
376
+ if (error.message) {
377
+ throw error;
378
+ }
379
+ throw new Error(`Failed to upload deployment results: ${error.message || String(error)}`);
380
+ }
381
+ }
382
+