codecrypto-cli 1.0.13 ā 1.0.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +345 -21
- package/dist/commands/auth.js +1 -1
- package/dist/commands/auth.js.map +1 -1
- package/dist/commands/deploy-sc.d.ts.map +1 -1
- package/dist/commands/deploy-sc.js +39 -3
- package/dist/commands/deploy-sc.js.map +1 -1
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/doctor.js +240 -13
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/generate-keys.d.ts +3 -0
- package/dist/commands/generate-keys.d.ts.map +1 -0
- package/dist/commands/generate-keys.js +159 -0
- package/dist/commands/generate-keys.js.map +1 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/package.json +4 -3
- package/src/commands/auth.ts +1 -1
- package/src/commands/deploy-sc.ts +43 -3
- package/src/commands/doctor.ts +244 -13
- package/src/commands/generate-keys.ts +139 -0
- package/src/index.ts +2 -0
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.generateKeysCommand = void 0;
|
|
40
|
+
const commander_1 = require("commander");
|
|
41
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
42
|
+
const ora_1 = __importDefault(require("ora"));
|
|
43
|
+
const fs = __importStar(require("fs"));
|
|
44
|
+
const path = __importStar(require("path"));
|
|
45
|
+
const os = __importStar(require("os"));
|
|
46
|
+
const ethers_1 = require("ethers");
|
|
47
|
+
exports.generateKeysCommand = new commander_1.Command('generate-keys')
|
|
48
|
+
.description('Generate Foundry keys file with mnemonic and derived accounts')
|
|
49
|
+
.option('-m, --mnemonic <mnemonic>', 'Mnemonic phrase (if not provided, a random one will be generated)')
|
|
50
|
+
.option('-n, --count <number>', 'Number of accounts to generate', '10')
|
|
51
|
+
.option('-o, --output <path>', 'Output file path', '~/.foundry/keys.json')
|
|
52
|
+
.action(async (options) => {
|
|
53
|
+
console.log(chalk_1.default.blue('\nš CodeCrypto Foundry Keys Generator\n'));
|
|
54
|
+
try {
|
|
55
|
+
// Parse count
|
|
56
|
+
const accountCount = parseInt(options.count, 10);
|
|
57
|
+
if (isNaN(accountCount) || accountCount < 1 || accountCount > 100) {
|
|
58
|
+
console.error(chalk_1.default.red('ā Error: Account count must be between 1 and 100'));
|
|
59
|
+
process.exit(1);
|
|
60
|
+
}
|
|
61
|
+
// Generate or use provided mnemonic
|
|
62
|
+
let mnemonic;
|
|
63
|
+
if (options.mnemonic) {
|
|
64
|
+
mnemonic = options.mnemonic.trim();
|
|
65
|
+
// Validate mnemonic
|
|
66
|
+
if (!ethers_1.ethers.Mnemonic.isValidMnemonic(mnemonic)) {
|
|
67
|
+
console.error(chalk_1.default.red('ā Error: Invalid mnemonic phrase'));
|
|
68
|
+
process.exit(1);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
// Generate random mnemonic
|
|
73
|
+
const spinner = (0, ora_1.default)('Generating random mnemonic...').start();
|
|
74
|
+
mnemonic = ethers_1.ethers.Mnemonic.entropyToPhrase(ethers_1.ethers.randomBytes(16));
|
|
75
|
+
spinner.succeed('Random mnemonic generated');
|
|
76
|
+
}
|
|
77
|
+
// Derive accounts
|
|
78
|
+
const accountsSpinner = (0, ora_1.default)(`Deriving ${accountCount} account(s) from mnemonic...`).start();
|
|
79
|
+
const accounts = [];
|
|
80
|
+
try {
|
|
81
|
+
for (let i = 0; i < accountCount; i++) {
|
|
82
|
+
// Use HDNodeWallet.fromPhrase with the full derivation path
|
|
83
|
+
// This creates a wallet directly from mnemonic at the specified path
|
|
84
|
+
const wallet = ethers_1.ethers.HDNodeWallet.fromPhrase(mnemonic, `m/44'/60'/0'/0/${i}`);
|
|
85
|
+
accounts.push({
|
|
86
|
+
address: wallet.address,
|
|
87
|
+
private_key: wallet.privateKey,
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
accountsSpinner.succeed(`Generated ${accountCount} account(s)`);
|
|
91
|
+
}
|
|
92
|
+
catch (error) {
|
|
93
|
+
accountsSpinner.fail('Failed to derive accounts');
|
|
94
|
+
console.error(chalk_1.default.red(`ā Error: ${error.message}`));
|
|
95
|
+
process.exit(1);
|
|
96
|
+
}
|
|
97
|
+
// Prepare output data
|
|
98
|
+
const keysData = {
|
|
99
|
+
mnemonic,
|
|
100
|
+
accounts,
|
|
101
|
+
};
|
|
102
|
+
// Resolve output path
|
|
103
|
+
let outputPath = options.output;
|
|
104
|
+
if (outputPath.startsWith('~')) {
|
|
105
|
+
outputPath = path.join(os.homedir(), outputPath.slice(1));
|
|
106
|
+
}
|
|
107
|
+
outputPath = path.resolve(outputPath);
|
|
108
|
+
// Create directory if it doesn't exist
|
|
109
|
+
const outputDir = path.dirname(outputPath);
|
|
110
|
+
if (!fs.existsSync(outputDir)) {
|
|
111
|
+
const dirSpinner = (0, ora_1.default)(`Creating directory: ${outputDir}`).start();
|
|
112
|
+
try {
|
|
113
|
+
fs.mkdirSync(outputDir, { recursive: true });
|
|
114
|
+
dirSpinner.succeed(`Directory created: ${outputDir}`);
|
|
115
|
+
}
|
|
116
|
+
catch (error) {
|
|
117
|
+
dirSpinner.fail('Failed to create directory');
|
|
118
|
+
console.error(chalk_1.default.red(`ā Error: ${error.message}`));
|
|
119
|
+
process.exit(1);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
// Write file
|
|
123
|
+
const writeSpinner = (0, ora_1.default)(`Writing keys to ${outputPath}...`).start();
|
|
124
|
+
try {
|
|
125
|
+
fs.writeFileSync(outputPath, JSON.stringify(keysData, null, 2), 'utf-8');
|
|
126
|
+
writeSpinner.succeed(`Keys saved to ${outputPath}`);
|
|
127
|
+
}
|
|
128
|
+
catch (error) {
|
|
129
|
+
writeSpinner.fail('Failed to write file');
|
|
130
|
+
console.error(chalk_1.default.red(`ā Error: ${error.message}`));
|
|
131
|
+
process.exit(1);
|
|
132
|
+
}
|
|
133
|
+
// Display summary
|
|
134
|
+
console.log(chalk_1.default.green('\nā
Keys generated successfully!\n'));
|
|
135
|
+
console.log(chalk_1.default.gray('Summary:'));
|
|
136
|
+
console.log(chalk_1.default.white(` Mnemonic: ${chalk_1.default.cyan(mnemonic)}`));
|
|
137
|
+
console.log(chalk_1.default.white(` Accounts: ${chalk_1.default.cyan(accountCount)}`));
|
|
138
|
+
console.log(chalk_1.default.white(` Output: ${chalk_1.default.cyan(outputPath)}\n`));
|
|
139
|
+
// Display first few accounts
|
|
140
|
+
console.log(chalk_1.default.gray('First 3 accounts:'));
|
|
141
|
+
accounts.slice(0, 3).forEach((account, index) => {
|
|
142
|
+
console.log(chalk_1.default.white(` ${index + 1}. ${chalk_1.default.cyan(account.address)}`));
|
|
143
|
+
console.log(chalk_1.default.gray(` Private Key: ${chalk_1.default.dim(account.private_key)}`));
|
|
144
|
+
});
|
|
145
|
+
if (accountCount > 3) {
|
|
146
|
+
console.log(chalk_1.default.gray(` ... and ${accountCount - 3} more account(s)\n`));
|
|
147
|
+
}
|
|
148
|
+
else {
|
|
149
|
+
console.log('');
|
|
150
|
+
}
|
|
151
|
+
console.log(chalk_1.default.yellow('ā ļø Warning: Keep your mnemonic and private keys secure!'));
|
|
152
|
+
console.log(chalk_1.default.yellow(' Never share them or commit them to version control.\n'));
|
|
153
|
+
}
|
|
154
|
+
catch (error) {
|
|
155
|
+
console.error(chalk_1.default.red(`\nā Error: ${error.message}`));
|
|
156
|
+
process.exit(1);
|
|
157
|
+
}
|
|
158
|
+
});
|
|
159
|
+
//# sourceMappingURL=generate-keys.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generate-keys.js","sourceRoot":"","sources":["../../src/commands/generate-keys.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -42,6 +42,7 @@ const deploy_1 = require("./commands/deploy");
|
|
|
42
42
|
const deploy_sc_1 = require("./commands/deploy-sc");
|
|
43
43
|
const auth_1 = require("./commands/auth");
|
|
44
44
|
const doctor_1 = require("./commands/doctor");
|
|
45
|
+
const generate_keys_1 = require("./commands/generate-keys");
|
|
45
46
|
// Cargar variables de entorno desde ~/.codecrypto/.env si existe
|
|
46
47
|
function loadEnvFile() {
|
|
47
48
|
const homeDir = os.homedir();
|
|
@@ -81,5 +82,6 @@ program.addCommand(deploy_1.deployCommand);
|
|
|
81
82
|
program.addCommand(deploy_sc_1.deployScCommand);
|
|
82
83
|
program.addCommand(auth_1.authCommand);
|
|
83
84
|
program.addCommand(doctor_1.doctorCommand);
|
|
85
|
+
program.addCommand(generate_keys_1.generateKeysCommand);
|
|
84
86
|
program.parse(process.argv);
|
|
85
87
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAEA,yCAAoC;AACpC,uCAAyB;AACzB,2CAA6B;AAC7B,uCAAyB;AACzB,8CAAkD;AAClD,oDAAuD;AACvD,0CAA8C;AAC9C,8CAAkD;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAEA,yCAAoC;AACpC,uCAAyB;AACzB,2CAA6B;AAC7B,uCAAyB;AACzB,8CAAkD;AAClD,oDAAuD;AACvD,0CAA8C;AAC9C,8CAAkD;AAClD,4DAA+D;AAE/D,iEAAiE;AACjE,SAAS,WAAW;IAClB,MAAM,OAAO,GAAG,EAAE,CAAC,OAAO,EAAE,CAAC;IAC7B,MAAM,aAAa,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,aAAa,CAAC,CAAC;IACxD,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC;IAErD,sCAAsC;IACtC,IAAI,EAAE,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;QAC/B,MAAM,UAAU,GAAG,EAAE,CAAC,YAAY,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;QACzD,MAAM,QAAQ,GAAG,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAExC,KAAK,MAAM,IAAI,IAAI,QAAQ,EAAE,CAAC;YAC5B,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;YAC5B,sCAAsC;YACtC,IAAI,CAAC,OAAO,IAAI,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC;gBAAE,SAAS;YAElD,MAAM,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;YACxC,IAAI,UAAU,KAAK,CAAC,CAAC;gBAAE,SAAS;YAEhC,MAAM,GAAG,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC,IAAI,EAAE,CAAC;YACpD,MAAM,KAAK,GAAG,OAAO,CAAC,SAAS,CAAC,UAAU,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;YAEvD,qGAAqG;YACrG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;gBACtB,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;YAC3B,CAAC;QACH,CAAC;IACH,CAAC;IACD,6FAA6F;AAC/F,CAAC;AAED,yCAAyC;AACzC,WAAW,EAAE,CAAC;AAEd,MAAM,OAAO,GAAG,IAAI,mBAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,YAAY,CAAC;KAClB,WAAW,CAAC,oCAAoC,CAAC;KACjD,OAAO,CAAC,OAAO,CAAC,CAAC;AAEpB,qBAAqB;AACrB,OAAO,CAAC,UAAU,CAAC,sBAAa,CAAC,CAAC;AAClC,OAAO,CAAC,UAAU,CAAC,2BAAe,CAAC,CAAC;AACpC,OAAO,CAAC,UAAU,CAAC,kBAAW,CAAC,CAAC;AAChC,OAAO,CAAC,UAAU,CAAC,sBAAa,CAAC,CAAC;AAClC,OAAO,CAAC,UAAU,CAAC,mCAAmB,CAAC,CAAC;AAExC,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "codecrypto-cli",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.15",
|
|
4
4
|
"description": "CLI tool for CodeCrypto operations",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -22,6 +22,7 @@
|
|
|
22
22
|
"dependencies": {
|
|
23
23
|
"chalk": "^4.1.2",
|
|
24
24
|
"commander": "^12.0.0",
|
|
25
|
+
"ethers": "^6.9.0",
|
|
25
26
|
"inquirer": "^8.2.5",
|
|
26
27
|
"jose": "^6.1.3",
|
|
27
28
|
"ora": "^5.4.1"
|
|
@@ -29,8 +30,8 @@
|
|
|
29
30
|
"devDependencies": {
|
|
30
31
|
"@types/inquirer": "^9.0.7",
|
|
31
32
|
"@types/node": "^20.10.0",
|
|
32
|
-
"tsx": "^4.
|
|
33
|
-
"typescript": "^5.3
|
|
33
|
+
"tsx": "^4.21.0",
|
|
34
|
+
"typescript": "^5.9.3"
|
|
34
35
|
},
|
|
35
36
|
"engines": {
|
|
36
37
|
"node": ">=16.0.0"
|
package/src/commands/auth.ts
CHANGED
|
@@ -25,7 +25,7 @@ interface TokenVerificationResponse {
|
|
|
25
25
|
error?: string;
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
-
const API_BASE_URL = process.env.CODECRYPTO_API_URL || process.env.API_URL || '
|
|
28
|
+
const API_BASE_URL = process.env.CODECRYPTO_API_URL || process.env.API_URL || 'https://proyectos.codecrypto.academy';
|
|
29
29
|
const POLL_INTERVAL = 3000; // 3 segundos
|
|
30
30
|
const MAX_POLL_ATTEMPTS = 100; // MƔximo 5 minutos (100 * 3 segundos)
|
|
31
31
|
|
|
@@ -5,11 +5,12 @@ import { execSync } from 'child_process';
|
|
|
5
5
|
import * as fs from 'fs';
|
|
6
6
|
import * as path from 'path';
|
|
7
7
|
import * as os from 'os';
|
|
8
|
+
import { ethers } from 'ethers';
|
|
8
9
|
|
|
9
10
|
export const deployScCommand = new Command('deploy-sc')
|
|
10
11
|
.description('Deploy smart contract using Foundry')
|
|
11
12
|
.argument('<script-path>', 'Path to the Foundry deployment script')
|
|
12
|
-
.option('-u, --url <rpc-url>', 'RPC URL of the blockchain', 'https://besu1.codecrypto.academy')
|
|
13
|
+
.option('-u, --url <rpc-url>', 'RPC URL of the blockchain', 'https://besu1.proyectos.codecrypto.academy')
|
|
13
14
|
.option('-k, --private-key <key>', 'Private key for deployment (required unless using --anvil or --account)')
|
|
14
15
|
.option('--account <index>', 'Account index to use (for Anvil, use 0 for the default unlocked account)')
|
|
15
16
|
.option('--anvil', 'Force use of Anvil account 0 (ignores private-key)')
|
|
@@ -156,6 +157,44 @@ export const deployScCommand = new Command('deploy-sc')
|
|
|
156
157
|
forgeArgs.push('--slow');
|
|
157
158
|
}
|
|
158
159
|
|
|
160
|
+
// Validar saldo antes de desplegar (solo si se usa private-key)
|
|
161
|
+
if (options.privateKey && !options.anvil && options.account === undefined) {
|
|
162
|
+
const balanceSpinner = ora('Verificando saldo de la cuenta...').start();
|
|
163
|
+
try {
|
|
164
|
+
const provider = new ethers.JsonRpcProvider(options.url);
|
|
165
|
+
const wallet = new ethers.Wallet(options.privateKey, provider);
|
|
166
|
+
const address = wallet.address;
|
|
167
|
+
const balance = await provider.getBalance(address);
|
|
168
|
+
|
|
169
|
+
// Convertir a ETH (mĆnimo 1 ETH recomendado)
|
|
170
|
+
const balanceInEth = ethers.formatEther(balance);
|
|
171
|
+
const minBalance = ethers.parseEther('1.0');
|
|
172
|
+
|
|
173
|
+
balanceSpinner.succeed(`Saldo verificado: ${balanceInEth} ETH`);
|
|
174
|
+
|
|
175
|
+
if (balance < minBalance) {
|
|
176
|
+
console.error(chalk.red('\nā Error: Saldo insuficiente en la cuenta'));
|
|
177
|
+
console.error(chalk.red(` Dirección: ${address}`));
|
|
178
|
+
console.error(chalk.red(` Saldo actual: ${balanceInEth} ETH`));
|
|
179
|
+
console.error(chalk.red(` Saldo mĆnimo recomendado: 1.0 ETH`));
|
|
180
|
+
console.error(chalk.yellow('\nš” AsegĆŗrate de tener suficiente saldo para pagar las fees de gas'));
|
|
181
|
+
console.log(chalk.cyan('\nš° ObtĆ©n fondos del faucet:'));
|
|
182
|
+
console.log(chalk.cyan(` ${chalk.underline('https://faucet.codecrypto.academy')}`));
|
|
183
|
+
console.log(chalk.gray(` Visita el faucet y solicita fondos para tu dirección: ${address}\n`));
|
|
184
|
+
process.exit(1);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
console.log(chalk.green(` Dirección: ${chalk.cyan(address)}`));
|
|
188
|
+
console.log(chalk.green(` Saldo: ${chalk.cyan(balanceInEth)} ETH\n`));
|
|
189
|
+
} catch (error: any) {
|
|
190
|
+
balanceSpinner.warn(`No se pudo verificar el saldo: ${error.message}`);
|
|
191
|
+
console.log(chalk.yellow(' Continuando con el despliegue...'));
|
|
192
|
+
console.log(chalk.yellow(' AsegĆŗrate de tener suficiente saldo para las fees de gas'));
|
|
193
|
+
console.log(chalk.cyan('\nš° Si necesitas fondos, usa el faucet:'));
|
|
194
|
+
console.log(chalk.cyan(` ${chalk.underline('https://faucet.codecrypto.academy')}\n`));
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
159
198
|
// Ejecutar el script
|
|
160
199
|
const deploySpinner = ora('Desplegando smart contract...').start();
|
|
161
200
|
|
|
@@ -258,7 +297,8 @@ async function uploadDeploymentResults(config: {
|
|
|
258
297
|
}
|
|
259
298
|
|
|
260
299
|
const email = tokenData.email;
|
|
261
|
-
|
|
300
|
+
// URL especĆfica para subir smart contracts
|
|
301
|
+
const uploadServerUrl = process.env.CODECRYPTO_UPLOAD_URL || process.env.UPLOAD_SMART_CONTRACT_URL || 'https://proyectos.proyectos.codecrypto.academy';
|
|
262
302
|
const token = tokenData.token;
|
|
263
303
|
|
|
264
304
|
if (!email) {
|
|
@@ -323,7 +363,7 @@ async function uploadDeploymentResults(config: {
|
|
|
323
363
|
}
|
|
324
364
|
|
|
325
365
|
// 6. Hacer la llamada POST al endpoint
|
|
326
|
-
const apiUrl = `${
|
|
366
|
+
const apiUrl = `${uploadServerUrl}/api/uploadSmartContract`;
|
|
327
367
|
|
|
328
368
|
// Log de la petición (solo si debug estÔ activado)
|
|
329
369
|
if (config.debug) {
|
package/src/commands/doctor.ts
CHANGED
|
@@ -154,12 +154,79 @@ export const doctorCommand = new Command('doctor')
|
|
|
154
154
|
try {
|
|
155
155
|
const tokenData = JSON.parse(fs.readFileSync(tokenFilePath, 'utf-8'));
|
|
156
156
|
if (tokenData.token && tokenData.email) {
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
157
|
+
// Validar el token con el servidor
|
|
158
|
+
const serverUrl = tokenData.serverUrl || process.env.CODECRYPTO_API_URL || process.env.API_URL || 'https://proyectos.codecrypto.academy';
|
|
159
|
+
const token = String(tokenData.token).trim();
|
|
160
|
+
|
|
161
|
+
try {
|
|
162
|
+
const verifyUrl = `${serverUrl}/api/tokens/verify`;
|
|
163
|
+
const controller = new AbortController();
|
|
164
|
+
const timeoutId = setTimeout(() => controller.abort(), 10000); // 10 seconds timeout
|
|
165
|
+
|
|
166
|
+
const response = await fetch(verifyUrl, {
|
|
167
|
+
method: 'GET',
|
|
168
|
+
headers: {
|
|
169
|
+
'Authorization': `Bearer ${token}`,
|
|
170
|
+
},
|
|
171
|
+
signal: controller.signal,
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
clearTimeout(timeoutId);
|
|
175
|
+
|
|
176
|
+
if (response.ok) {
|
|
177
|
+
const responseData = await response.json();
|
|
178
|
+
tokenCheck.succeed(`Token valid for: ${tokenData.email}`);
|
|
179
|
+
checks.push({
|
|
180
|
+
name: 'CodeCrypto Token',
|
|
181
|
+
status: 'success',
|
|
182
|
+
message: `Token valid for: ${tokenData.email}`
|
|
183
|
+
});
|
|
184
|
+
} else {
|
|
185
|
+
const errorText = await response.text();
|
|
186
|
+
let errorMessage = 'Token validation failed';
|
|
187
|
+
try {
|
|
188
|
+
const errorJson = JSON.parse(errorText);
|
|
189
|
+
errorMessage = errorJson.error || errorJson.message || errorMessage;
|
|
190
|
+
} catch {
|
|
191
|
+
errorMessage = errorText || errorMessage;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
tokenCheck.fail(`Token validation failed: ${errorMessage}`);
|
|
195
|
+
checks.push({
|
|
196
|
+
name: 'CodeCrypto Token',
|
|
197
|
+
status: 'error',
|
|
198
|
+
message: `Token validation failed: ${errorMessage}`,
|
|
199
|
+
details: 'Run "codecrypto auth --force" to refresh your token'
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
} catch (fetchError: any) {
|
|
203
|
+
const errorMsg = fetchError.message || String(fetchError);
|
|
204
|
+
if (fetchError.name === 'AbortError' || errorMsg.includes('timeout')) {
|
|
205
|
+
tokenCheck.fail('Token validation timeout');
|
|
206
|
+
checks.push({
|
|
207
|
+
name: 'CodeCrypto Token',
|
|
208
|
+
status: 'error',
|
|
209
|
+
message: 'Token validation timeout',
|
|
210
|
+
details: 'Cannot reach server to validate token. Check your internet connection.'
|
|
211
|
+
});
|
|
212
|
+
} else if (errorMsg.includes('ECONNREFUSED') || errorMsg.includes('ENOTFOUND')) {
|
|
213
|
+
tokenCheck.fail('Cannot reach server to validate token');
|
|
214
|
+
checks.push({
|
|
215
|
+
name: 'CodeCrypto Token',
|
|
216
|
+
status: 'error',
|
|
217
|
+
message: 'Cannot reach server to validate token',
|
|
218
|
+
details: `Cannot reach ${serverUrl}. Check your network connection.`
|
|
219
|
+
});
|
|
220
|
+
} else {
|
|
221
|
+
tokenCheck.fail(`Token validation error: ${errorMsg}`);
|
|
222
|
+
checks.push({
|
|
223
|
+
name: 'CodeCrypto Token',
|
|
224
|
+
status: 'error',
|
|
225
|
+
message: `Token validation error: ${errorMsg}`,
|
|
226
|
+
details: 'Run "codecrypto auth --force" to refresh your token'
|
|
227
|
+
});
|
|
228
|
+
}
|
|
229
|
+
}
|
|
163
230
|
} else {
|
|
164
231
|
tokenCheck.fail('Token file exists but is invalid');
|
|
165
232
|
checks.push({
|
|
@@ -188,7 +255,69 @@ export const doctorCommand = new Command('doctor')
|
|
|
188
255
|
});
|
|
189
256
|
}
|
|
190
257
|
|
|
191
|
-
// 8. Check
|
|
258
|
+
// 8. Check server access (proyectos.codecrypto.academy)
|
|
259
|
+
const serverCheck = ora('Checking access to proyectos.codecrypto.academy...').start();
|
|
260
|
+
try {
|
|
261
|
+
const serverUrl = 'https://proyectos.codecrypto.academy';
|
|
262
|
+
const controller = new AbortController();
|
|
263
|
+
const timeoutId = setTimeout(() => controller.abort(), 10000); // 10 seconds timeout
|
|
264
|
+
|
|
265
|
+
const response = await fetch(serverUrl, {
|
|
266
|
+
method: 'GET',
|
|
267
|
+
signal: controller.signal,
|
|
268
|
+
headers: {
|
|
269
|
+
'User-Agent': 'CodeCrypto-CLI/1.0'
|
|
270
|
+
}
|
|
271
|
+
});
|
|
272
|
+
|
|
273
|
+
clearTimeout(timeoutId);
|
|
274
|
+
|
|
275
|
+
if (response.ok || response.status < 500) {
|
|
276
|
+
serverCheck.succeed(`Server accessible: ${serverUrl}`);
|
|
277
|
+
checks.push({
|
|
278
|
+
name: 'Server Access',
|
|
279
|
+
status: 'success',
|
|
280
|
+
message: `Server accessible: ${serverUrl} (status: ${response.status})`
|
|
281
|
+
});
|
|
282
|
+
} else {
|
|
283
|
+
serverCheck.fail(`Server returned error: ${response.status}`);
|
|
284
|
+
checks.push({
|
|
285
|
+
name: 'Server Access',
|
|
286
|
+
status: 'error',
|
|
287
|
+
message: `Server returned error: ${response.status}`,
|
|
288
|
+
details: `Check if ${serverUrl} is accessible from your network`
|
|
289
|
+
});
|
|
290
|
+
}
|
|
291
|
+
} catch (error: any) {
|
|
292
|
+
const errorMsg = error.message || String(error);
|
|
293
|
+
if (error.name === 'AbortError' || errorMsg.includes('timeout')) {
|
|
294
|
+
serverCheck.fail('Server connection timeout');
|
|
295
|
+
checks.push({
|
|
296
|
+
name: 'Server Access',
|
|
297
|
+
status: 'error',
|
|
298
|
+
message: 'Server connection timeout',
|
|
299
|
+
details: `Cannot reach https://proyectos.codecrypto.academy. Check your internet connection.`
|
|
300
|
+
});
|
|
301
|
+
} else if (errorMsg.includes('ECONNREFUSED') || errorMsg.includes('ENOTFOUND') || errorMsg.includes('getaddrinfo')) {
|
|
302
|
+
serverCheck.fail('Cannot resolve server address');
|
|
303
|
+
checks.push({
|
|
304
|
+
name: 'Server Access',
|
|
305
|
+
status: 'error',
|
|
306
|
+
message: 'Cannot resolve server address',
|
|
307
|
+
details: `Cannot reach https://proyectos.codecrypto.academy. Check DNS resolution and network connectivity.`
|
|
308
|
+
});
|
|
309
|
+
} else {
|
|
310
|
+
serverCheck.fail('Cannot access server');
|
|
311
|
+
checks.push({
|
|
312
|
+
name: 'Server Access',
|
|
313
|
+
status: 'error',
|
|
314
|
+
message: 'Cannot access server',
|
|
315
|
+
details: `Error: ${errorMsg}. Check if https://proyectos.codecrypto.academy is accessible.`
|
|
316
|
+
});
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
// 9. Check Docker certificates in token.json
|
|
192
321
|
const certCheck = ora('Checking Docker certificates in token.json...').start();
|
|
193
322
|
try {
|
|
194
323
|
if (fs.existsSync(tokenFilePath)) {
|
|
@@ -254,7 +383,7 @@ export const doctorCommand = new Command('doctor')
|
|
|
254
383
|
});
|
|
255
384
|
}
|
|
256
385
|
|
|
257
|
-
//
|
|
386
|
+
// 10. Check Git (optional but recommended)
|
|
258
387
|
const gitCheck = ora('Checking Git...').start();
|
|
259
388
|
try {
|
|
260
389
|
const gitVersion = execSync('git --version', { encoding: 'utf-8', stdio: 'pipe' }).trim();
|
|
@@ -279,7 +408,7 @@ export const doctorCommand = new Command('doctor')
|
|
|
279
408
|
// ============================================
|
|
280
409
|
console.log(chalk.cyan('\nš· Foundry / Smart Contracts Deployment Checks\n'));
|
|
281
410
|
|
|
282
|
-
//
|
|
411
|
+
// 11. Check Foundry (forge)
|
|
283
412
|
const forgeCheck = ora('Checking Foundry (forge)...').start();
|
|
284
413
|
try {
|
|
285
414
|
const forgeVersion = execSync('forge --version', { encoding: 'utf-8', stdio: 'pipe' }).trim();
|
|
@@ -299,7 +428,7 @@ export const doctorCommand = new Command('doctor')
|
|
|
299
428
|
});
|
|
300
429
|
}
|
|
301
430
|
|
|
302
|
-
//
|
|
431
|
+
// 12. Check cast
|
|
303
432
|
const castCheck = ora('Checking cast...').start();
|
|
304
433
|
try {
|
|
305
434
|
const castVersion = execSync('cast --version', { encoding: 'utf-8', stdio: 'pipe' }).trim();
|
|
@@ -319,7 +448,7 @@ export const doctorCommand = new Command('doctor')
|
|
|
319
448
|
});
|
|
320
449
|
}
|
|
321
450
|
|
|
322
|
-
//
|
|
451
|
+
// 13. Check anvil
|
|
323
452
|
const anvilCheck = ora('Checking anvil...').start();
|
|
324
453
|
try {
|
|
325
454
|
const anvilVersion = execSync('anvil --version', { encoding: 'utf-8', stdio: 'pipe' }).trim();
|
|
@@ -339,7 +468,7 @@ export const doctorCommand = new Command('doctor')
|
|
|
339
468
|
});
|
|
340
469
|
}
|
|
341
470
|
|
|
342
|
-
//
|
|
471
|
+
// 14. Check if Anvil is running on correct port and chain-id
|
|
343
472
|
const anvilRunningCheck = ora('Checking if Anvil is running (port 8545, chain-id 31337)...').start();
|
|
344
473
|
try {
|
|
345
474
|
// Try to get chain id from the RPC
|
|
@@ -402,7 +531,7 @@ export const doctorCommand = new Command('doctor')
|
|
|
402
531
|
}
|
|
403
532
|
}
|
|
404
533
|
|
|
405
|
-
//
|
|
534
|
+
// 15. Check Anvil account 0
|
|
406
535
|
const anvilAccountCheck = ora('Checking Anvil account 0...').start();
|
|
407
536
|
try {
|
|
408
537
|
const rpcUrl = 'http://localhost:8545';
|
|
@@ -427,6 +556,108 @@ export const doctorCommand = new Command('doctor')
|
|
|
427
556
|
});
|
|
428
557
|
}
|
|
429
558
|
|
|
559
|
+
// 16. Check Besu1 network access
|
|
560
|
+
const besu1Check = ora('Checking Besu1 network (https://besu1.proyectos.codecrypto.academy)...').start();
|
|
561
|
+
try {
|
|
562
|
+
const rpcUrl = 'https://besu1.proyectos.codecrypto.academy';
|
|
563
|
+
const chainIdResponse = execSync(
|
|
564
|
+
`cast chain-id --rpc-url ${rpcUrl}`,
|
|
565
|
+
{ encoding: 'utf-8', stdio: 'pipe', timeout: 10000 }
|
|
566
|
+
).trim();
|
|
567
|
+
|
|
568
|
+
let chainId: number;
|
|
569
|
+
if (chainIdResponse.startsWith('0x') || chainIdResponse.startsWith('0X')) {
|
|
570
|
+
chainId = parseInt(chainIdResponse, 16);
|
|
571
|
+
} else {
|
|
572
|
+
chainId = parseInt(chainIdResponse, 10);
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
besu1Check.succeed(`Besu1 network accessible (chain-id: ${chainId})`);
|
|
576
|
+
checks.push({
|
|
577
|
+
name: 'Besu1 Network',
|
|
578
|
+
status: 'success',
|
|
579
|
+
message: `Besu1 network accessible: ${rpcUrl} (chain-id: ${chainId})`
|
|
580
|
+
});
|
|
581
|
+
} catch (error: any) {
|
|
582
|
+
const errorMsg = error.message || String(error);
|
|
583
|
+
if (errorMsg.includes('ECONNREFUSED') || errorMsg.includes('Connection refused')) {
|
|
584
|
+
besu1Check.fail('Cannot connect to Besu1 network');
|
|
585
|
+
checks.push({
|
|
586
|
+
name: 'Besu1 Network',
|
|
587
|
+
status: 'error',
|
|
588
|
+
message: 'Cannot connect to Besu1 network',
|
|
589
|
+
details: 'Check if https://besu1.proyectos.codecrypto.academy is accessible from your network'
|
|
590
|
+
});
|
|
591
|
+
} else if (errorMsg.includes('timeout') || errorMsg.includes('ETIMEDOUT')) {
|
|
592
|
+
besu1Check.fail('Besu1 network connection timeout');
|
|
593
|
+
checks.push({
|
|
594
|
+
name: 'Besu1 Network',
|
|
595
|
+
status: 'error',
|
|
596
|
+
message: 'Besu1 network connection timeout',
|
|
597
|
+
details: 'Check your internet connection and network access to https://besu1.proyectos.codecrypto.academy'
|
|
598
|
+
});
|
|
599
|
+
} else {
|
|
600
|
+
besu1Check.fail('Cannot access Besu1 network');
|
|
601
|
+
checks.push({
|
|
602
|
+
name: 'Besu1 Network',
|
|
603
|
+
status: 'error',
|
|
604
|
+
message: 'Cannot access Besu1 network',
|
|
605
|
+
details: `Error: ${errorMsg}. Check if https://besu1.proyectos.codecrypto.academy is accessible.`
|
|
606
|
+
});
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
|
|
610
|
+
// 17. Check Besu2 network access
|
|
611
|
+
const besu2Check = ora('Checking Besu2 network (https://besu2.proyectos.codecrypto.academy)...').start();
|
|
612
|
+
try {
|
|
613
|
+
const rpcUrl = 'https://besu2.proyectos.codecrypto.academy';
|
|
614
|
+
const chainIdResponse = execSync(
|
|
615
|
+
`cast chain-id --rpc-url ${rpcUrl}`,
|
|
616
|
+
{ encoding: 'utf-8', stdio: 'pipe', timeout: 10000 }
|
|
617
|
+
).trim();
|
|
618
|
+
|
|
619
|
+
let chainId: number;
|
|
620
|
+
if (chainIdResponse.startsWith('0x') || chainIdResponse.startsWith('0X')) {
|
|
621
|
+
chainId = parseInt(chainIdResponse, 16);
|
|
622
|
+
} else {
|
|
623
|
+
chainId = parseInt(chainIdResponse, 10);
|
|
624
|
+
}
|
|
625
|
+
|
|
626
|
+
besu2Check.succeed(`Besu2 network accessible (chain-id: ${chainId})`);
|
|
627
|
+
checks.push({
|
|
628
|
+
name: 'Besu2 Network',
|
|
629
|
+
status: 'success',
|
|
630
|
+
message: `Besu2 network accessible: ${rpcUrl} (chain-id: ${chainId})`
|
|
631
|
+
});
|
|
632
|
+
} catch (error: any) {
|
|
633
|
+
const errorMsg = error.message || String(error);
|
|
634
|
+
if (errorMsg.includes('ECONNREFUSED') || errorMsg.includes('Connection refused')) {
|
|
635
|
+
besu2Check.fail('Cannot connect to Besu2 network');
|
|
636
|
+
checks.push({
|
|
637
|
+
name: 'Besu2 Network',
|
|
638
|
+
status: 'error',
|
|
639
|
+
message: 'Cannot connect to Besu2 network',
|
|
640
|
+
details: 'Check if https://besu2.proyectos.codecrypto.academy is accessible from your network'
|
|
641
|
+
});
|
|
642
|
+
} else if (errorMsg.includes('timeout') || errorMsg.includes('ETIMEDOUT')) {
|
|
643
|
+
besu2Check.fail('Besu2 network connection timeout');
|
|
644
|
+
checks.push({
|
|
645
|
+
name: 'Besu2 Network',
|
|
646
|
+
status: 'error',
|
|
647
|
+
message: 'Besu2 network connection timeout',
|
|
648
|
+
details: 'Check your internet connection and network access to https://besu2.proyectos.codecrypto.academy'
|
|
649
|
+
});
|
|
650
|
+
} else {
|
|
651
|
+
besu2Check.fail('Cannot access Besu2 network');
|
|
652
|
+
checks.push({
|
|
653
|
+
name: 'Besu2 Network',
|
|
654
|
+
status: 'error',
|
|
655
|
+
message: 'Cannot access Besu2 network',
|
|
656
|
+
details: `Error: ${errorMsg}. Check if https://besu2.proyectos.codecrypto.academy is accessible.`
|
|
657
|
+
});
|
|
658
|
+
}
|
|
659
|
+
}
|
|
660
|
+
|
|
430
661
|
// ============================================
|
|
431
662
|
// SUMMARY
|
|
432
663
|
// ============================================
|