jaelis-node 1.1.0 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -76,6 +76,7 @@ program
76
76
  .option('--rpc-host <host>', 'RPC server host', '0.0.0.0')
77
77
  .option('--no-rpc', 'Disable RPC server')
78
78
  .option('--sync-mode <mode>', 'Sync mode: full, light, archive', 'full')
79
+ .option('--reward-recipient <address>', 'Wallet address to receive node rewards (ANY chain format!)')
79
80
  .action(async (options) => {
80
81
  console.log(chalk.cyan(BANNER));
81
82
  console.log(chalk.green('Starting JAELIS Node...'));
@@ -94,6 +95,9 @@ program
94
95
  console.log(chalk.gray(` P2P Port: ${options.p2pPort}`));
95
96
  console.log(chalk.gray(` Data Dir: ${options.dataDir}`));
96
97
  console.log(chalk.gray(` Sync Mode: ${options.syncMode}`));
98
+ if (options.rewardRecipient) {
99
+ console.log(chalk.gray(` Rewards To: ${options.rewardRecipient}`));
100
+ }
97
101
  console.log();
98
102
 
99
103
  const spinner = ora('Initializing node...').start();
@@ -111,7 +115,8 @@ program
111
115
  dataDir: options.dataDir,
112
116
  syncMode: options.syncMode,
113
117
  enableRpc: options.rpc,
114
- bootstrapNodes: network.bootstrapNodes
118
+ bootstrapNodes: network.bootstrapNodes,
119
+ rewardRecipient: options.rewardRecipient // Like Geth's --suggested-fee-recipient
115
120
  });
116
121
 
117
122
  spinner.text = 'Connecting to network...';
@@ -311,5 +316,201 @@ program
311
316
  console.log(chalk.cyan('Website: https://jaelis.io'));
312
317
  });
313
318
 
319
+ // ═══════════════════════════════════════════════════════════════════════════
320
+ // WALLET COMMANDS - Manage node wallet configuration
321
+ // Like Geth's account management, but supports ANY chain address!
322
+ // NO STAKING REQUIRED - JAELIS doesn't hold your funds!
323
+ // ═══════════════════════════════════════════════════════════════════════════
324
+
325
+ // WALLET SET-RECIPIENT - Set reward recipient address (like Geth --suggested-fee-recipient)
326
+ program
327
+ .command('wallet:set-recipient <address>')
328
+ .description('Set the wallet address to receive node rewards (accepts ANY chain format!)')
329
+ .option('-d, --data-dir <path>', 'Data directory', './jaelis-data')
330
+ .action((address, options) => {
331
+ console.log(chalk.cyan('Setting reward recipient...'));
332
+ console.log();
333
+
334
+ try {
335
+ const { NodeWalletConfig, validateAddress } = require('../lib/index.js');
336
+
337
+ // Validate address format
338
+ const validation = validateAddress(address);
339
+ if (!validation.valid) {
340
+ console.log(chalk.red('✗ Invalid address format'));
341
+ console.log(chalk.gray(' Supported formats:'));
342
+ console.log(chalk.gray(' • EVM (Ethereum, Polygon, etc.): 0x...'));
343
+ console.log(chalk.gray(' • Solana: base58 address'));
344
+ console.log(chalk.gray(' • Bitcoin: 1..., 3..., or bc1...'));
345
+ console.log(chalk.gray(' • TON: base64url address'));
346
+ console.log(chalk.gray(' • Move (Aptos/Sui): 0x... (64 chars)'));
347
+ process.exit(1);
348
+ }
349
+
350
+ const walletConfig = new NodeWalletConfig(options.dataDir);
351
+ walletConfig.load();
352
+ const result = walletConfig.setRewardRecipient(address);
353
+
354
+ console.log(chalk.green('✓ Reward recipient set successfully!'));
355
+ console.log();
356
+ console.log(chalk.white(' Address: ') + chalk.cyan(result.originalFormat));
357
+ console.log(chalk.white(' Type: ') + chalk.gray(result.typeName));
358
+ console.log();
359
+ console.log(chalk.gray(' Node rewards will be sent to this address.'));
360
+ console.log(chalk.gray(' NO STAKING REQUIRED - you keep your own funds!'));
361
+
362
+ } catch (error) {
363
+ console.log(chalk.red('✗ Failed to set recipient'));
364
+ console.log(chalk.gray(error.message));
365
+ process.exit(1);
366
+ }
367
+ });
368
+
369
+ // WALLET ADD - Add an additional wallet
370
+ program
371
+ .command('wallet:add <name> <address>')
372
+ .description('Add a wallet to this node (accepts ANY chain format!)')
373
+ .option('-d, --data-dir <path>', 'Data directory', './jaelis-data')
374
+ .option('-p, --purpose <purpose>', 'Wallet purpose (general, validator, development)', 'general')
375
+ .action((name, address, options) => {
376
+ console.log(chalk.cyan('Adding wallet...'));
377
+ console.log();
378
+
379
+ try {
380
+ const { NodeWalletConfig, validateAddress } = require('../lib/index.js');
381
+
382
+ const validation = validateAddress(address);
383
+ if (!validation.valid) {
384
+ console.log(chalk.red('✗ Invalid address format'));
385
+ process.exit(1);
386
+ }
387
+
388
+ const walletConfig = new NodeWalletConfig(options.dataDir);
389
+ walletConfig.load();
390
+ const result = walletConfig.addWallet(name, address, { purpose: options.purpose });
391
+
392
+ console.log(chalk.green('✓ Wallet added successfully!'));
393
+ console.log();
394
+ console.log(chalk.white(' Name: ') + chalk.cyan(result.name));
395
+ console.log(chalk.white(' Address: ') + chalk.gray(result.originalFormat));
396
+ console.log(chalk.white(' Type: ') + chalk.gray(result.typeName));
397
+ console.log(chalk.white(' Purpose: ') + chalk.gray(result.purpose));
398
+
399
+ } catch (error) {
400
+ console.log(chalk.red('✗ Failed to add wallet'));
401
+ console.log(chalk.gray(error.message));
402
+ process.exit(1);
403
+ }
404
+ });
405
+
406
+ // WALLET REMOVE - Remove a wallet
407
+ program
408
+ .command('wallet:remove <name-or-address>')
409
+ .description('Remove a wallet from this node')
410
+ .option('-d, --data-dir <path>', 'Data directory', './jaelis-data')
411
+ .action((nameOrAddress, options) => {
412
+ console.log(chalk.cyan('Removing wallet...'));
413
+ console.log();
414
+
415
+ try {
416
+ const { NodeWalletConfig } = require('../lib/index.js');
417
+
418
+ const walletConfig = new NodeWalletConfig(options.dataDir);
419
+ walletConfig.load();
420
+ const result = walletConfig.removeWallet(nameOrAddress);
421
+
422
+ console.log(chalk.green('✓ Wallet removed!'));
423
+ console.log(chalk.gray(` Removed: ${result.name} (${result.originalFormat})`));
424
+
425
+ } catch (error) {
426
+ console.log(chalk.red('✗ Failed to remove wallet'));
427
+ console.log(chalk.gray(error.message));
428
+ process.exit(1);
429
+ }
430
+ });
431
+
432
+ // WALLET LIST - List all wallets
433
+ program
434
+ .command('wallet:list')
435
+ .description('List all configured wallets')
436
+ .option('-d, --data-dir <path>', 'Data directory', './jaelis-data')
437
+ .action((options) => {
438
+ console.log(chalk.cyan('Node Wallet Configuration'));
439
+ console.log();
440
+
441
+ try {
442
+ const { NodeWalletConfig } = require('../lib/index.js');
443
+
444
+ const walletConfig = new NodeWalletConfig(options.dataDir);
445
+ const config = walletConfig.listWallets();
446
+
447
+ // Show reward recipient
448
+ if (config.rewardRecipient) {
449
+ console.log(chalk.white('Reward Recipient:'));
450
+ console.log(chalk.green(` ★ ${config.rewardRecipient.originalFormat}`));
451
+ console.log(chalk.gray(` Type: ${config.rewardRecipient.typeName}`));
452
+ console.log();
453
+ } else {
454
+ console.log(chalk.yellow('⚠ No reward recipient set!'));
455
+ console.log(chalk.gray(' Run: jaelis-node wallet:set-recipient <your-address>'));
456
+ console.log();
457
+ }
458
+
459
+ // Show additional wallets
460
+ if (config.wallets && config.wallets.length > 0) {
461
+ console.log(chalk.white('Additional Wallets:'));
462
+ config.wallets.forEach((wallet, i) => {
463
+ console.log(chalk.cyan(` ${i + 1}. ${wallet.name}`));
464
+ console.log(chalk.gray(` Address: ${wallet.originalFormat}`));
465
+ console.log(chalk.gray(` Type: ${wallet.typeName}`));
466
+ console.log(chalk.gray(` Purpose: ${wallet.purpose}`));
467
+ });
468
+ } else {
469
+ console.log(chalk.gray('No additional wallets configured.'));
470
+ }
471
+
472
+ console.log();
473
+ console.log(chalk.gray('Supported address formats:'));
474
+ console.log(chalk.gray(' • EVM (Ethereum, Polygon, Arbitrum, Base, etc.)'));
475
+ console.log(chalk.gray(' • Solana (base58)'));
476
+ console.log(chalk.gray(' • Bitcoin (Legacy & SegWit)'));
477
+ console.log(chalk.gray(' • TON'));
478
+ console.log(chalk.gray(' • Move (Aptos/Sui)'));
479
+
480
+ } catch (error) {
481
+ console.log(chalk.red('Failed to list wallets'));
482
+ console.log(chalk.gray(error.message));
483
+ }
484
+ });
485
+
486
+ // WALLET IDENTITY - Show or generate node identity
487
+ program
488
+ .command('wallet:identity')
489
+ .description('Show or generate the node identity (like Solana identity keypair)')
490
+ .option('-d, --data-dir <path>', 'Data directory', './jaelis-data')
491
+ .action((options) => {
492
+ console.log(chalk.cyan('Node Identity'));
493
+ console.log();
494
+
495
+ try {
496
+ const { NodeWalletConfig } = require('../lib/index.js');
497
+
498
+ const walletConfig = new NodeWalletConfig(options.dataDir);
499
+ walletConfig.load();
500
+ const identity = walletConfig.getNodeIdentity();
501
+
502
+ console.log(chalk.white('Node Identity:'));
503
+ console.log(chalk.green(` Public Key: ${identity.publicKey}`));
504
+ console.log(chalk.gray(` Created: ${new Date(identity.createdAt).toISOString()}`));
505
+ console.log();
506
+ console.log(chalk.gray('This identity is used to identify your node on the network.'));
507
+ console.log(chalk.gray('It is NOT a wallet - use wallet:set-recipient for rewards.'));
508
+
509
+ } catch (error) {
510
+ console.log(chalk.red('Failed to get node identity'));
511
+ console.log(chalk.gray(error.message));
512
+ }
513
+ });
514
+
314
515
  // Parse and execute
315
516
  program.parse();