@jellylegsai/aether-cli 1.9.2 → 2.0.2
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/IMPLEMENTATION_REPORT.md +319 -0
- package/commands/blockheight.js +230 -0
- package/commands/call.js +981 -0
- package/commands/claim.js +98 -72
- package/commands/deploy.js +959 -0
- package/commands/index.js +2 -0
- package/commands/init.js +33 -49
- package/commands/network-diagnostics.js +706 -0
- package/commands/network.js +412 -429
- package/commands/rewards.js +311 -266
- package/commands/sdk.js +791 -656
- package/commands/slot.js +3 -11
- package/commands/stake.js +581 -516
- package/commands/supply.js +483 -391
- package/commands/token-accounts.js +275 -0
- package/commands/transfer.js +3 -11
- package/commands/unstake.js +3 -11
- package/commands/validator-start.js +681 -323
- package/commands/validator.js +959 -0
- package/commands/validators.js +623 -626
- package/commands/version.js +240 -0
- package/commands/wallet.js +17 -24
- package/cycle-report-issue-116.txt +165 -0
- package/index.js +501 -602
- package/lib/ui.js +623 -0
- package/package.json +10 -3
- package/sdk/index.d.ts +546 -0
- package/sdk/index.js +130 -0
- package/sdk/package.json +2 -1
package/index.js
CHANGED
|
@@ -1,602 +1,501 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* aether-cli -
|
|
4
|
-
*
|
|
5
|
-
* Main entry point for the validator CLI tool.
|
|
6
|
-
* Provides onboarding, system checks, validator management, and
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
const
|
|
13
|
-
const
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
const {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
const
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
const {
|
|
23
|
-
const {
|
|
24
|
-
const {
|
|
25
|
-
const {
|
|
26
|
-
const {
|
|
27
|
-
const {
|
|
28
|
-
const {
|
|
29
|
-
const {
|
|
30
|
-
const {
|
|
31
|
-
const {
|
|
32
|
-
const {
|
|
33
|
-
const {
|
|
34
|
-
const {
|
|
35
|
-
const {
|
|
36
|
-
const {
|
|
37
|
-
const {
|
|
38
|
-
const {
|
|
39
|
-
const {
|
|
40
|
-
const {
|
|
41
|
-
const {
|
|
42
|
-
const {
|
|
43
|
-
const {
|
|
44
|
-
const {
|
|
45
|
-
const {
|
|
46
|
-
const
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
const
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
const
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
};
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
console.log(
|
|
88
|
-
|
|
89
|
-
console.log(
|
|
90
|
-
|
|
91
|
-
const
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
return;
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
if (answer === '
|
|
125
|
-
rl.close();
|
|
126
|
-
const {
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
},
|
|
182
|
-
monitor: {
|
|
183
|
-
description: 'Real-time validator dashboard (slot,
|
|
184
|
-
handler: () => {
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
},
|
|
205
|
-
stake: {
|
|
206
|
-
description: '
|
|
207
|
-
handler: () => {
|
|
208
|
-
const {
|
|
209
|
-
|
|
210
|
-
},
|
|
211
|
-
},
|
|
212
|
-
'stake-
|
|
213
|
-
description: '
|
|
214
|
-
handler: () => {
|
|
215
|
-
const {
|
|
216
|
-
|
|
217
|
-
},
|
|
218
|
-
},
|
|
219
|
-
|
|
220
|
-
description: '
|
|
221
|
-
handler:
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
},
|
|
243
|
-
|
|
244
|
-
description: '
|
|
245
|
-
handler:
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
},
|
|
269
|
-
|
|
270
|
-
description: '
|
|
271
|
-
handler: () => {
|
|
272
|
-
const {
|
|
273
|
-
|
|
274
|
-
},
|
|
275
|
-
},
|
|
276
|
-
|
|
277
|
-
description: '
|
|
278
|
-
handler:
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
},
|
|
327
|
-
|
|
328
|
-
description: '
|
|
329
|
-
handler:
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
},
|
|
339
|
-
|
|
340
|
-
description: '
|
|
341
|
-
handler:
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
},
|
|
367
|
-
|
|
368
|
-
description: '
|
|
369
|
-
handler:
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
},
|
|
375
|
-
|
|
376
|
-
description: '
|
|
377
|
-
handler:
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
description
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
}
|
|
441
|
-
}
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
}
|
|
485
|
-
}
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
}
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
process.argv = [process.argv[0], process.argv[1], 'install', '--help'];
|
|
503
|
-
installCommand();
|
|
504
|
-
},
|
|
505
|
-
},
|
|
506
|
-
help: {
|
|
507
|
-
description: 'Show this help message',
|
|
508
|
-
handler: showHelp,
|
|
509
|
-
},
|
|
510
|
-
version: {
|
|
511
|
-
description: 'Show version number',
|
|
512
|
-
handler: () => console.log(`aether-cli v${VERSION}`),
|
|
513
|
-
},
|
|
514
|
-
};
|
|
515
|
-
|
|
516
|
-
/**
|
|
517
|
-
* Display help message with ASCII art
|
|
518
|
-
*/
|
|
519
|
-
function showHelp() {
|
|
520
|
-
const header = `
|
|
521
|
-
███╗ ███╗██╗███████╗███████╗██╗ ██████╗ ███╗ ██╗
|
|
522
|
-
████╗ ████║██║██╔════╝██╔════╝██║██╔═══██╗████╗ ██║
|
|
523
|
-
██╔████╔██║██║███████╗███████╗██║██║ ██║██╔██╗ ██║
|
|
524
|
-
██║╚██╔╝██║██║╚════██║╚════██║██║██║ ██║██║╚██╗██║
|
|
525
|
-
██║ ╚═╝ ██║██║███████║███████║██║╚██████╔╝██║ ╚████║
|
|
526
|
-
╚═╝ ╚═╝╚═╝╚══════╝╚══════╝╚═╝ ╚═════╝ ╚═╝ ╚═══╝
|
|
527
|
-
|
|
528
|
-
Validator CLI v${VERSION}
|
|
529
|
-
`.trim();
|
|
530
|
-
|
|
531
|
-
console.log(header);
|
|
532
|
-
console.log('\nUsage: aether-cli <command> [options]\n');
|
|
533
|
-
console.log('Commands:');
|
|
534
|
-
Object.entries(COMMANDS).forEach(([cmd, info]) => {
|
|
535
|
-
if (info.hidden) return;
|
|
536
|
-
console.log(` ${cmd.padEnd(18)} ${info.description}`);
|
|
537
|
-
});
|
|
538
|
-
console.log('\nExamples:');
|
|
539
|
-
console.log(' aether-cli doctor # Check system requirements');
|
|
540
|
-
console.log(' aether-cli init # Start onboarding wizard');
|
|
541
|
-
console.log(' aether-cli monitor # Real-time validator dashboard');
|
|
542
|
-
console.log(' aether-cli validator start # Start validator node');
|
|
543
|
-
console.log(' aether-cli validator status # Check validator status');
|
|
544
|
-
console.log(' aether-cli wallet balance # Query AETH balance');
|
|
545
|
-
console.log(' aether-cli network # Network status, peers, slot info');
|
|
546
|
-
console.log(' aether-cli network --peers # Detailed peer list');
|
|
547
|
-
console.log(' aether-cli tx history # Show transaction history');
|
|
548
|
-
console.log(' aether-cli price # AETH/USD price check');
|
|
549
|
-
console.log(' aether-cli nft create # Create NFT with metadata');
|
|
550
|
-
console.log(' aether-cli nft list # List NFTs owned by wallet');
|
|
551
|
-
console.log(' aether-cli --version # Show version');
|
|
552
|
-
console.log('\nDocumentation: https://github.com/jelly-legs-ai/Jelly-legs-unsteady-workshop');
|
|
553
|
-
console.log('Spec: docs/MINING_VALIDATOR_TOOLS.md\n');
|
|
554
|
-
}
|
|
555
|
-
|
|
556
|
-
/**
|
|
557
|
-
* Parse command line arguments
|
|
558
|
-
*/
|
|
559
|
-
function parseArgs() {
|
|
560
|
-
const args = process.argv.slice(2);
|
|
561
|
-
|
|
562
|
-
// Handle version flag
|
|
563
|
-
if (args.includes('--version') || args.includes('-v') || args.includes('-V')) {
|
|
564
|
-
return 'version';
|
|
565
|
-
}
|
|
566
|
-
|
|
567
|
-
// No args → interactive menu
|
|
568
|
-
if (args.length === 0) {
|
|
569
|
-
return 'start';
|
|
570
|
-
}
|
|
571
|
-
|
|
572
|
-
// Handle multi-word commands (e.g., "validator start", "kyc generate")
|
|
573
|
-
if (args.length >= 2) {
|
|
574
|
-
const multiCmd = `${args[0]} ${args[1]}`;
|
|
575
|
-
if (COMMANDS[multiCmd]) {
|
|
576
|
-
return multiCmd;
|
|
577
|
-
}
|
|
578
|
-
}
|
|
579
|
-
|
|
580
|
-
// Handle single word commands
|
|
581
|
-
return args[0] || 'help';
|
|
582
|
-
}
|
|
583
|
-
|
|
584
|
-
/**
|
|
585
|
-
* Main CLI entry point
|
|
586
|
-
*/
|
|
587
|
-
function main() {
|
|
588
|
-
const command = parseArgs();
|
|
589
|
-
|
|
590
|
-
if (COMMANDS[command]) {
|
|
591
|
-
COMMANDS[command].handler();
|
|
592
|
-
} else {
|
|
593
|
-
console.error(`❌ Unknown command: ${command}`);
|
|
594
|
-
console.error('Run "aether-cli help" for usage.\n');
|
|
595
|
-
process.exit(1);
|
|
596
|
-
}
|
|
597
|
-
}
|
|
598
|
-
|
|
599
|
-
// Run CLI only if executed directly
|
|
600
|
-
if (require.main === module) {
|
|
601
|
-
main();
|
|
602
|
-
}
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* aether-cli - Aether Blockchain Command Line Interface
|
|
4
|
+
*
|
|
5
|
+
* Main entry point for the validator CLI tool.
|
|
6
|
+
* Provides onboarding, system checks, validator management, and blockchain operations.
|
|
7
|
+
*
|
|
8
|
+
* @version 2.0.0
|
|
9
|
+
* @author Jelly-legs AI Team
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
const readline = require('readline');
|
|
13
|
+
const path = require('path');
|
|
14
|
+
|
|
15
|
+
// Import UI framework for consistent branding
|
|
16
|
+
const { BRANDING, C, indicators, success, error, warning, info, code, key, value, formatHelp, drawBox } = require('./lib/ui');
|
|
17
|
+
|
|
18
|
+
// CLI version
|
|
19
|
+
const VERSION = '2.0.2';
|
|
20
|
+
|
|
21
|
+
// Command imports
|
|
22
|
+
const { doctorCommand } = require('./commands/doctor');
|
|
23
|
+
const { validatorStartCommand } = require('./commands/validator-start');
|
|
24
|
+
const { validatorStatus } = require('./commands/validator-status');
|
|
25
|
+
const { validatorInfo } = require('./commands/validator-info');
|
|
26
|
+
const { validatorCommand } = require('./commands/validator');
|
|
27
|
+
const { init } = require('./commands/init');
|
|
28
|
+
const { monitorLoop } = require('./commands/monitor');
|
|
29
|
+
const { logsCommand } = require('./commands/logs');
|
|
30
|
+
const { sdkCommand } = require('./commands/sdk');
|
|
31
|
+
const { snapshotCommand } = require('./commands/snapshot');
|
|
32
|
+
const { walletCommand } = require('./commands/wallet');
|
|
33
|
+
const { networkCommand } = require('./commands/network');
|
|
34
|
+
const { networkDiagnosticsCommand } = require('./commands/network-diagnostics');
|
|
35
|
+
const { validatorsCommand } = require('./commands/validators');
|
|
36
|
+
const { delegationsCommand } = require('./commands/delegations');
|
|
37
|
+
const { rewardsCommand } = require('./commands/rewards');
|
|
38
|
+
const { validatorRegisterCommand } = require('./commands/validator-register');
|
|
39
|
+
const { accountCommand } = require('./commands/account');
|
|
40
|
+
const { emergencyCommand } = require('./commands/emergency');
|
|
41
|
+
const { priceCommand } = require('./commands/price');
|
|
42
|
+
const { epochCommand } = require('./commands/epoch');
|
|
43
|
+
const { supplyCommand } = require('./commands/supply');
|
|
44
|
+
const { statusCommand } = require('./commands/status');
|
|
45
|
+
const { broadcastCommand } = require('./commands/broadcast');
|
|
46
|
+
const { apyCommand } = require('./commands/apy');
|
|
47
|
+
const { statsCommand } = require('./commands/stats');
|
|
48
|
+
const { txHistoryCommand } = require('./commands/tx-history');
|
|
49
|
+
const { feesCommand } = require('./commands/fees');
|
|
50
|
+
const { tpsCommand } = require('./commands/tps');
|
|
51
|
+
const { blockhashCommand } = require('./commands/blockhash');
|
|
52
|
+
const { sdkTestCommand } = require('./commands/sdk-test');
|
|
53
|
+
const { balanceCommand } = require('./commands/balance');
|
|
54
|
+
const { transferCommand } = require('./commands/transfer');
|
|
55
|
+
const { slotCommand } = require('./commands/slot');
|
|
56
|
+
const { configCommand } = require('./commands/config');
|
|
57
|
+
const { stakeCommand } = require('./commands/stake');
|
|
58
|
+
const { nftCommand } = require('./commands/nft');
|
|
59
|
+
const { installCommand } = require('./commands/install');
|
|
60
|
+
const { pingCommand } = require('./commands/ping');
|
|
61
|
+
const { claimCommand } = require('./commands/claim');
|
|
62
|
+
const { unstakeCommand } = require('./commands/unstake');
|
|
63
|
+
const { txCommand } = require('./commands/tx');
|
|
64
|
+
const { multisigCommand } = require('./commands/multisig');
|
|
65
|
+
const { deployCommand } = require('./commands/deploy');
|
|
66
|
+
const { callCommand } = require('./commands/call');
|
|
67
|
+
const { blockheightCommand } = require('./commands/blockheight');
|
|
68
|
+
const { versionCommand } = require('./commands/version');
|
|
69
|
+
const { tokenAccountsCommand } = require('./commands/token-accounts');
|
|
70
|
+
|
|
71
|
+
// Parse args early to support flags on commands
|
|
72
|
+
function getCommandArgs() {
|
|
73
|
+
return process.argv.slice(2);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Display the interactive main menu
|
|
78
|
+
*/
|
|
79
|
+
async function showMenu() {
|
|
80
|
+
const rl = readline.createInterface({
|
|
81
|
+
input: process.stdin,
|
|
82
|
+
output: process.stdout,
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
const prompt = (q) => new Promise((res) => rl.question(q, res));
|
|
86
|
+
|
|
87
|
+
console.log(BRANDING.header(VERSION));
|
|
88
|
+
|
|
89
|
+
console.log(` ${C.dim}Welcome to Aether CLI. What would you like to do?${C.reset}\n`);
|
|
90
|
+
|
|
91
|
+
const menuItems = [
|
|
92
|
+
{ num: '1', icon: indicators.bullet, label: 'Doctor', desc: 'Check system requirements', cmd: 'doctor' },
|
|
93
|
+
{ num: '2', icon: indicators.bullet, label: 'Start', desc: 'Begin validator onboarding', cmd: 'init' },
|
|
94
|
+
{ num: '3', icon: indicators.bullet, label: 'Monitor', desc: 'Watch live validator stats', cmd: 'monitor' },
|
|
95
|
+
{ num: '4', icon: indicators.bullet, label: 'Logs', desc: 'Tail validator logs', cmd: 'logs' },
|
|
96
|
+
{ num: '5', icon: indicators.bullet, label: 'SDK', desc: 'SDK tools and info', cmd: 'sdk' },
|
|
97
|
+
{ num: '6', icon: indicators.bullet, label: 'Network', desc: 'Network status', cmd: 'network' },
|
|
98
|
+
{ num: '7', icon: indicators.bullet, label: 'Help', desc: 'Show all commands', cmd: 'help' },
|
|
99
|
+
];
|
|
100
|
+
|
|
101
|
+
for (const item of menuItems) {
|
|
102
|
+
console.log(` ${C.cyan}${item.num})${C.reset} ${C.bright}${item.label}${C.reset} ${C.dim}${item.desc}${C.reset}`);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
console.log(`\n ${C.dim}Type a number or command name. Press Ctrl+C to exit.${C.reset}\n`);
|
|
106
|
+
|
|
107
|
+
const VALID_CHOICES = ['1', '2', '3', '4', '5', '6', '7', 'doctor', 'init', 'monitor', 'logs', 'sdk', 'network', 'help'];
|
|
108
|
+
|
|
109
|
+
while (true) {
|
|
110
|
+
const answer = (await prompt(`${C.cyan}>${C.reset} `)).trim().toLowerCase();
|
|
111
|
+
|
|
112
|
+
if (answer === '' || answer === '1' || answer === 'doctor') {
|
|
113
|
+
rl.close();
|
|
114
|
+
doctorCommand({ autoFix: false, tier: 'full' });
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
if (answer === '2' || answer === 'init' || answer === 'start') {
|
|
119
|
+
rl.close();
|
|
120
|
+
init();
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
if (answer === '3' || answer === 'monitor') {
|
|
125
|
+
rl.close();
|
|
126
|
+
const { main } = require('./commands/monitor');
|
|
127
|
+
main();
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
if (answer === '4' || answer === 'logs') {
|
|
132
|
+
rl.close();
|
|
133
|
+
logsCommand();
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
if (answer === '5' || answer === 'sdk') {
|
|
138
|
+
rl.close();
|
|
139
|
+
sdkCommand();
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
if (answer === '6' || answer === 'network') {
|
|
144
|
+
rl.close();
|
|
145
|
+
networkCommand();
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
if (answer === '7' || answer === 'help') {
|
|
150
|
+
showHelp();
|
|
151
|
+
console.log(` ${C.dim}Press Ctrl+C to exit or select an option above.${C.reset}\n`);
|
|
152
|
+
continue;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
console.log(`\n ${warning(`Unknown option: "${answer}". Type 1-7 or a command name.`)}\n`);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// Available commands
|
|
160
|
+
const COMMANDS = {
|
|
161
|
+
start: {
|
|
162
|
+
description: 'Launch interactive menu (default)',
|
|
163
|
+
handler: () => showMenu(),
|
|
164
|
+
},
|
|
165
|
+
doctor: {
|
|
166
|
+
description: 'Run system requirements checks (CPU/RAM/Disk/Network)',
|
|
167
|
+
handler: () => {
|
|
168
|
+
const args = getCommandArgs();
|
|
169
|
+
const autoFix = args.includes('--fix') || args.includes('-f');
|
|
170
|
+
let tier = 'full';
|
|
171
|
+
const tierIndex = args.findIndex(arg => arg === '--tier');
|
|
172
|
+
if (tierIndex !== -1 && args[tierIndex + 1]) {
|
|
173
|
+
tier = args[tierIndex + 1].toLowerCase();
|
|
174
|
+
}
|
|
175
|
+
doctorCommand({ autoFix, tier });
|
|
176
|
+
},
|
|
177
|
+
},
|
|
178
|
+
init: {
|
|
179
|
+
description: 'Start onboarding wizard (generate identity, wallet, connect)',
|
|
180
|
+
handler: init,
|
|
181
|
+
},
|
|
182
|
+
monitor: {
|
|
183
|
+
description: 'Real-time validator dashboard (slot, height, peers, TPS)',
|
|
184
|
+
handler: () => {
|
|
185
|
+
const { main } = require('./commands/monitor');
|
|
186
|
+
main();
|
|
187
|
+
},
|
|
188
|
+
},
|
|
189
|
+
logs: {
|
|
190
|
+
description: 'Tail validator logs with colour-coded output',
|
|
191
|
+
handler: logsCommand,
|
|
192
|
+
},
|
|
193
|
+
sdk: {
|
|
194
|
+
description: 'Aether SDK tools - direct blockchain RPC access',
|
|
195
|
+
handler: sdkCommand,
|
|
196
|
+
},
|
|
197
|
+
wallet: {
|
|
198
|
+
description: 'Wallet management - create, import, list, balance, transfer',
|
|
199
|
+
handler: walletCommand,
|
|
200
|
+
},
|
|
201
|
+
stake: {
|
|
202
|
+
description: 'Stake AETH to a validator - stake --validator <addr> --amount <aeth>',
|
|
203
|
+
handler: stakeCommand,
|
|
204
|
+
},
|
|
205
|
+
'stake-positions': {
|
|
206
|
+
description: 'Show current stake positions/delegations',
|
|
207
|
+
handler: () => {
|
|
208
|
+
const { stakePositionsCommand } = require('./commands/stake-positions');
|
|
209
|
+
stakePositionsCommand();
|
|
210
|
+
},
|
|
211
|
+
},
|
|
212
|
+
'stake-info': {
|
|
213
|
+
description: 'Get staking info for an address via chain RPC',
|
|
214
|
+
handler: () => {
|
|
215
|
+
const { stakeInfoCommand } = require('./commands/stake-info');
|
|
216
|
+
stakeInfoCommand();
|
|
217
|
+
},
|
|
218
|
+
},
|
|
219
|
+
unstake: {
|
|
220
|
+
description: 'Unstake AETH - deactivate a stake account',
|
|
221
|
+
handler: unstakeCommand,
|
|
222
|
+
},
|
|
223
|
+
claim: {
|
|
224
|
+
description: 'Claim accumulated staking rewards - claim --address <addr>',
|
|
225
|
+
handler: claimCommand,
|
|
226
|
+
},
|
|
227
|
+
transfer: {
|
|
228
|
+
description: 'Transfer AETH to another address - transfer --to <addr> --amount <aeth>',
|
|
229
|
+
handler: transferCommand,
|
|
230
|
+
},
|
|
231
|
+
'tx-history': {
|
|
232
|
+
description: 'Transaction history for an address',
|
|
233
|
+
handler: txHistoryCommand,
|
|
234
|
+
},
|
|
235
|
+
tx: {
|
|
236
|
+
description: 'Look up a transaction by signature - tx <sig> [--json] [--wait]',
|
|
237
|
+
handler: txCommand,
|
|
238
|
+
},
|
|
239
|
+
blockhash: {
|
|
240
|
+
description: 'Get the latest blockhash for transaction signing',
|
|
241
|
+
handler: blockhashCommand,
|
|
242
|
+
},
|
|
243
|
+
balance: {
|
|
244
|
+
description: 'Query account balance - balance [address] [--json]',
|
|
245
|
+
handler: balanceCommand,
|
|
246
|
+
},
|
|
247
|
+
network: {
|
|
248
|
+
description: 'Aether network status - slot, height, peers, TPS',
|
|
249
|
+
handler: networkCommand,
|
|
250
|
+
},
|
|
251
|
+
validator: {
|
|
252
|
+
description: 'Validator node management - status, info, start, stop, register, logs',
|
|
253
|
+
handler: () => {
|
|
254
|
+
validatorCommand();
|
|
255
|
+
},
|
|
256
|
+
},
|
|
257
|
+
delegations: {
|
|
258
|
+
description: 'List/claim stake delegations',
|
|
259
|
+
handler: delegationsCommand,
|
|
260
|
+
},
|
|
261
|
+
rewards: {
|
|
262
|
+
description: 'View staking rewards - list | summary | pending | claim | compound',
|
|
263
|
+
handler: rewardsCommand,
|
|
264
|
+
},
|
|
265
|
+
snapshot: {
|
|
266
|
+
description: 'Node sync status, snapshot slot info',
|
|
267
|
+
handler: snapshotCommand,
|
|
268
|
+
},
|
|
269
|
+
info: {
|
|
270
|
+
description: 'Validator info snapshot - identity, sync, peers, stake',
|
|
271
|
+
handler: () => {
|
|
272
|
+
const { infoCommand } = require('./commands/info');
|
|
273
|
+
infoCommand();
|
|
274
|
+
},
|
|
275
|
+
},
|
|
276
|
+
account: {
|
|
277
|
+
description: 'Query on-chain account data - account --address <addr> [--json]',
|
|
278
|
+
handler: accountCommand,
|
|
279
|
+
},
|
|
280
|
+
epoch: {
|
|
281
|
+
description: 'Aether epoch info - current epoch, slot, time remaining, APY',
|
|
282
|
+
handler: epochCommand,
|
|
283
|
+
},
|
|
284
|
+
supply: {
|
|
285
|
+
description: 'Aether token supply - total, circulating, staked, burned',
|
|
286
|
+
handler: supplyCommand,
|
|
287
|
+
},
|
|
288
|
+
status: {
|
|
289
|
+
description: 'Full dashboard - epoch, network, supply, validator info',
|
|
290
|
+
handler: statusCommand,
|
|
291
|
+
},
|
|
292
|
+
validators: {
|
|
293
|
+
description: 'Validator network management - validators list|info|top [--tier] [--json]',
|
|
294
|
+
handler: validatorsCommand,
|
|
295
|
+
},
|
|
296
|
+
'validator-info': {
|
|
297
|
+
description: 'Get detailed info for a specific validator',
|
|
298
|
+
handler: () => {
|
|
299
|
+
const { validatorInfoCommand } = require('./commands/validator-info');
|
|
300
|
+
validatorInfoCommand();
|
|
301
|
+
},
|
|
302
|
+
},
|
|
303
|
+
stats: {
|
|
304
|
+
description: 'Wallet stats dashboard - balance, stake, recent txs',
|
|
305
|
+
handler: statsCommand,
|
|
306
|
+
},
|
|
307
|
+
price: {
|
|
308
|
+
description: 'AETH/USD price - price [--pair AETH/USD] [--json]',
|
|
309
|
+
handler: priceCommand,
|
|
310
|
+
},
|
|
311
|
+
broadcast: {
|
|
312
|
+
description: 'Broadcast a signed transaction - broadcast --tx <sig> [--json]',
|
|
313
|
+
handler: broadcastCommand,
|
|
314
|
+
},
|
|
315
|
+
apy: {
|
|
316
|
+
description: 'Validator APY estimator',
|
|
317
|
+
handler: apyCommand,
|
|
318
|
+
},
|
|
319
|
+
ping: {
|
|
320
|
+
description: 'Ping RPC endpoint - measure latency, check node health',
|
|
321
|
+
handler: pingCommand,
|
|
322
|
+
},
|
|
323
|
+
'network-diagnostics': {
|
|
324
|
+
description: 'Network diagnostics with RPC failover',
|
|
325
|
+
handler: networkDiagnosticsCommand,
|
|
326
|
+
},
|
|
327
|
+
emergency: {
|
|
328
|
+
description: 'Emergency response & network alerts',
|
|
329
|
+
handler: emergencyCommand,
|
|
330
|
+
},
|
|
331
|
+
fees: {
|
|
332
|
+
description: 'Network fee estimates - fees [--json] [--verbose] [--rpc <url>]',
|
|
333
|
+
handler: feesCommand,
|
|
334
|
+
},
|
|
335
|
+
tps: {
|
|
336
|
+
description: 'Transactions per second monitor - tps [--monitor] [--interval 2] [--json]',
|
|
337
|
+
handler: tpsCommand,
|
|
338
|
+
},
|
|
339
|
+
slot: {
|
|
340
|
+
description: 'Get current slot number - slot [--json] [--rpc <url>]',
|
|
341
|
+
handler: slotCommand,
|
|
342
|
+
},
|
|
343
|
+
blockheight: {
|
|
344
|
+
description: 'Get current block height - blockheight [--json] [--rpc <url>] [--compare]',
|
|
345
|
+
handler: blockheightCommand,
|
|
346
|
+
},
|
|
347
|
+
'token-accounts': {
|
|
348
|
+
description: 'Get SPL token accounts for wallet - token-accounts [address] [--json]',
|
|
349
|
+
handler: tokenAccountsCommand,
|
|
350
|
+
},
|
|
351
|
+
version: {
|
|
352
|
+
description: 'Get node version info - version [--json] [--cli]',
|
|
353
|
+
handler: versionCommand,
|
|
354
|
+
},
|
|
355
|
+
multisig: {
|
|
356
|
+
description: 'Multi-signature wallet management',
|
|
357
|
+
handler: multisigCommand,
|
|
358
|
+
},
|
|
359
|
+
register: {
|
|
360
|
+
description: 'Register validator with network',
|
|
361
|
+
handler: validatorRegisterCommand,
|
|
362
|
+
},
|
|
363
|
+
'sdk-test': {
|
|
364
|
+
description: 'Test SDK with real RPC calls - sdk-test [--rpc <url>] [--quick] [--json]',
|
|
365
|
+
handler: sdkTestCommand,
|
|
366
|
+
},
|
|
367
|
+
config: {
|
|
368
|
+
description: 'Configuration management - config set/get/list/validate/init',
|
|
369
|
+
handler: configCommand,
|
|
370
|
+
},
|
|
371
|
+
nft: {
|
|
372
|
+
description: 'NFT management - create|list|transfer|info|update',
|
|
373
|
+
handler: nftCommand,
|
|
374
|
+
},
|
|
375
|
+
deploy: {
|
|
376
|
+
description: 'Deploy smart contracts - deploy <file> [--name <name>] [--upgradeable]',
|
|
377
|
+
handler: deployCommand,
|
|
378
|
+
},
|
|
379
|
+
call: {
|
|
380
|
+
description: 'Call smart contract functions - call <program-id> <function> [args...] [--query|--wallet]',
|
|
381
|
+
handler: callCommand,
|
|
382
|
+
},
|
|
383
|
+
'validator-setup': {
|
|
384
|
+
description: 'Setup validator prerequisites (alias for validator start)',
|
|
385
|
+
handler: () => {
|
|
386
|
+
const { validatorStartCommand } = require('./commands/validator-start');
|
|
387
|
+
validatorStartCommand();
|
|
388
|
+
},
|
|
389
|
+
},
|
|
390
|
+
install: {
|
|
391
|
+
description: 'Install or upgrade aether-cli',
|
|
392
|
+
handler: installCommand,
|
|
393
|
+
},
|
|
394
|
+
help: {
|
|
395
|
+
description: 'Show this help message',
|
|
396
|
+
handler: showHelp,
|
|
397
|
+
},
|
|
398
|
+
'cli-version': {
|
|
399
|
+
description: 'Show CLI version number',
|
|
400
|
+
handler: () => {
|
|
401
|
+
console.log(BRANDING.header(VERSION));
|
|
402
|
+
console.log(` ${C.dim}SDK-powered blockchain CLI for Aether validators${C.reset}\n`);
|
|
403
|
+
},
|
|
404
|
+
},
|
|
405
|
+
};
|
|
406
|
+
|
|
407
|
+
/**
|
|
408
|
+
* Display help message with consistent branding
|
|
409
|
+
*/
|
|
410
|
+
function showHelp() {
|
|
411
|
+
console.log(BRANDING.header(VERSION));
|
|
412
|
+
|
|
413
|
+
console.log(`\n ${C.bright}AETHER CLI${C.reset} — ${C.dim}Decentralized Infrastructure for the Future${C.reset}\n`);
|
|
414
|
+
|
|
415
|
+
// Group commands by category
|
|
416
|
+
const categories = {
|
|
417
|
+
'Wallet & Accounts': ['wallet', 'balance', 'transfer', 'tx', 'tx-history', 'account', 'stats', 'token-accounts'],
|
|
418
|
+
'Staking': ['stake', 'unstake', 'stake-positions', 'stake-info', 'delegations', 'rewards', 'claim'],
|
|
419
|
+
'Validator': ['init', 'validator', 'validator-info', 'register', 'validators', 'monitor', 'logs'],
|
|
420
|
+
'Network': ['network', 'network-diagnostics', 'ping', 'epoch', 'slot', 'blockheight', 'tps', 'fees', 'supply', 'version'],
|
|
421
|
+
'SDK & Tools': ['sdk', 'sdk-test', 'snapshot', 'info', 'status', 'blockhash', 'broadcast', 'price', 'apy', 'deploy'],
|
|
422
|
+
'Advanced': ['nft', 'multisig', 'emergency', 'config', 'doctor', 'install', 'call'],
|
|
423
|
+
};
|
|
424
|
+
|
|
425
|
+
for (const [category, cmds] of Object.entries(categories)) {
|
|
426
|
+
console.log(` ${C.cyan}◆ ${category}${C.reset}`);
|
|
427
|
+
for (const cmd of cmds) {
|
|
428
|
+
const cmdInfo = COMMANDS[cmd];
|
|
429
|
+
if (cmdInfo) {
|
|
430
|
+
console.log(` ${code(cmd.padEnd(18))} ${C.dim}${cmdInfo.description}${C.reset}`);
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
console.log();
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
console.log(` ${C.cyan}◆ Quick Start${C.reset}\n`);
|
|
437
|
+
console.log(` ${C.dim}$${C.reset} ${code('aether doctor')} ${C.dim}# Check system requirements${C.reset}`);
|
|
438
|
+
console.log(` ${C.dim}$${C.reset} ${code('aether init')} ${C.dim}# Start validator onboarding${C.reset}`);
|
|
439
|
+
console.log(` ${C.dim}$${C.reset} ${code('aether wallet create')} ${C.dim}# Create a new wallet${C.reset}`);
|
|
440
|
+
console.log(` ${C.dim}$${C.reset} ${code('aether network')} ${C.dim}# Check network status${C.reset}`);
|
|
441
|
+
console.log(` ${C.dim}$${C.reset} ${code('aether sdk getSlot')} ${C.dim}# Query current slot via SDK${C.reset}`);
|
|
442
|
+
console.log();
|
|
443
|
+
|
|
444
|
+
console.log(` ${C.dim}Documentation: ${C.cyan}https://github.com/jelly-legs-ai/Jelly-legs-unsteady-workshop${C.reset}\n`);
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
/**
|
|
448
|
+
* Parse command line arguments
|
|
449
|
+
*/
|
|
450
|
+
function parseArgs() {
|
|
451
|
+
const args = process.argv.slice(2);
|
|
452
|
+
|
|
453
|
+
// Handle version flags
|
|
454
|
+
if (args.includes('--version') || args.includes('-v') || args.includes('-V')) {
|
|
455
|
+
return 'cli-version';
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
// No args → interactive menu
|
|
459
|
+
if (args.length === 0) {
|
|
460
|
+
return 'start';
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
// Handle multi-word commands (e.g., "validator start")
|
|
464
|
+
if (args.length >= 2) {
|
|
465
|
+
const multiCmd = `${args[0]} ${args[1]}`;
|
|
466
|
+
if (COMMANDS[multiCmd]) {
|
|
467
|
+
return multiCmd;
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
// Handle single word commands
|
|
472
|
+
return args[0] || 'help';
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
/**
|
|
476
|
+
* Main CLI entry point
|
|
477
|
+
*/
|
|
478
|
+
function main() {
|
|
479
|
+
const command = parseArgs();
|
|
480
|
+
|
|
481
|
+
if (COMMANDS[command]) {
|
|
482
|
+
try {
|
|
483
|
+
COMMANDS[command].handler();
|
|
484
|
+
} catch (err) {
|
|
485
|
+
console.error(`\n ${error(`Command failed: ${err.message}`)}\n`);
|
|
486
|
+
process.exit(1);
|
|
487
|
+
}
|
|
488
|
+
} else {
|
|
489
|
+
console.error(`\n ${error(`Unknown command: ${command}`)}`);
|
|
490
|
+
console.log(` ${C.dim}Run "aether help" to see available commands.${C.reset}\n`);
|
|
491
|
+
process.exit(1);
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
// Run CLI only if executed directly
|
|
496
|
+
if (require.main === module) {
|
|
497
|
+
main();
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
// Export for module use
|
|
501
|
+
module.exports = { main, showHelp, COMMANDS, VERSION };
|