@jellylegsai/aether-cli 1.9.1 → 2.0.1
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 +88 -86
- 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 -595
- package/lib/ui.js +623 -0
- package/package.json +83 -76
- package/sdk/index.d.ts +546 -0
- package/sdk/index.js +130 -0
- package/sdk/package.json +2 -1
package/commands/claim.js
CHANGED
|
@@ -30,20 +30,12 @@ const nacl = require('tweetnacl');
|
|
|
30
30
|
const sdkPath = path.join(__dirname, '..', 'sdk', 'index.js');
|
|
31
31
|
const aether = require(sdkPath);
|
|
32
32
|
|
|
33
|
-
//
|
|
34
|
-
const C
|
|
35
|
-
|
|
36
|
-
bright: '\x1b[1m',
|
|
37
|
-
dim: '\x1b[2m',
|
|
38
|
-
red: '\x1b[31m',
|
|
39
|
-
green: '\x1b[32m',
|
|
40
|
-
yellow: '\x1b[33m',
|
|
41
|
-
cyan: '\x1b[36m',
|
|
42
|
-
magenta: '\x1b[35m',
|
|
43
|
-
};
|
|
33
|
+
// Import UI framework for consistent branding
|
|
34
|
+
const { BRANDING, C, indicators, startSpinner, stopSpinner, drawBox, drawTable,
|
|
35
|
+
success, error, warning, info, code, highlight } = require('../lib/ui');
|
|
44
36
|
|
|
45
37
|
const DERIVATION_PATH = "m/44'/7777777'/0'/0'";
|
|
46
|
-
const CLI_VERSION = '
|
|
38
|
+
const CLI_VERSION = '2.0.0';
|
|
47
39
|
|
|
48
40
|
// ---------------------------------------------------------------------------
|
|
49
41
|
// SDK Client Setup
|
|
@@ -238,30 +230,30 @@ async function claimCommand() {
|
|
|
238
230
|
const rl = createRl();
|
|
239
231
|
|
|
240
232
|
if (opts.help) {
|
|
241
|
-
console.log(
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
--
|
|
249
|
-
--
|
|
250
|
-
--
|
|
251
|
-
--
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
${C.
|
|
255
|
-
client.
|
|
256
|
-
client.
|
|
257
|
-
client.
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
${C.
|
|
261
|
-
aether claim --address ATH3abc...
|
|
262
|
-
aether claim --address ATH3abc... --
|
|
263
|
-
|
|
264
|
-
|
|
233
|
+
console.log(BRANDING.commandBanner('claim', 'Claim accumulated staking rewards'));
|
|
234
|
+
|
|
235
|
+
console.log(`\n ${C.bright}USAGE${C.reset}`);
|
|
236
|
+
console.log(` ${code('aether claim --address <addr> [--json] [--rpc <url>] [--dry-run]')}`);
|
|
237
|
+
|
|
238
|
+
console.log(`\n ${C.bright}OPTIONS${C.reset}`);
|
|
239
|
+
console.log(` ${code('--address <addr>')} Wallet address (ATH...)`);
|
|
240
|
+
console.log(` ${code('--json')} Output raw JSON`);
|
|
241
|
+
console.log(` ${code('--rpc <url>')} RPC endpoint (default: AETHER_RPC or localhost:8899)`);
|
|
242
|
+
console.log(` ${code('--dry-run')} Preview claim without submitting transaction`);
|
|
243
|
+
console.log(` ${code('--help')} Show this help`);
|
|
244
|
+
|
|
245
|
+
console.log(`\n ${C.bright}SDK METHODS USED${C.reset}`);
|
|
246
|
+
console.log(` ${C.dim}client.getStakePositions(address) → GET /v1/stake/<addr>${C.reset}`);
|
|
247
|
+
console.log(` ${C.dim}client.getRewards(address) → GET /v1/rewards/<addr>${C.reset}`);
|
|
248
|
+
console.log(` ${C.dim}client.getSlot() → GET /v1/slot${C.reset}`);
|
|
249
|
+
console.log(` ${C.dim}client.sendTransaction(tx) → POST /v1/transaction${C.reset}`);
|
|
250
|
+
|
|
251
|
+
console.log(`\n ${C.bright}EXAMPLES${C.reset}`);
|
|
252
|
+
console.log(` ${C.dim}$${C.reset} ${code('aether claim --address ATH3abc...')}`);
|
|
253
|
+
console.log(` ${C.dim}$${C.reset} ${code('aether claim --address ATH3abc... --dry-run')}`);
|
|
254
|
+
console.log(` ${C.dim}$${C.reset} ${code('aether claim --address ATH3abc... --json')}`);
|
|
255
|
+
console.log();
|
|
256
|
+
|
|
265
257
|
rl.close();
|
|
266
258
|
return;
|
|
267
259
|
}
|
|
@@ -272,8 +264,8 @@ ${C.bright}EXAMPLES${C.reset}
|
|
|
272
264
|
if (config.defaultWallet) {
|
|
273
265
|
opts.address = config.defaultWallet;
|
|
274
266
|
} else {
|
|
275
|
-
console.log(
|
|
276
|
-
console.log(` Usage: aether claim --address <addr> [--json] [--dry-run]\n`);
|
|
267
|
+
console.log(`\n ${error('Missing --address')}\n`);
|
|
268
|
+
console.log(` Usage: ${code('aether claim --address <addr> [--json] [--dry-run]')}\n`);
|
|
277
269
|
rl.close();
|
|
278
270
|
return;
|
|
279
271
|
}
|
|
@@ -284,10 +276,10 @@ ${C.bright}EXAMPLES${C.reset}
|
|
|
284
276
|
const rawAddr = address.startsWith('ATH') ? address.slice(3) : address;
|
|
285
277
|
|
|
286
278
|
if (!opts.json) {
|
|
287
|
-
console.log(
|
|
288
|
-
console.log(
|
|
289
|
-
console.log(` ${C.
|
|
290
|
-
if (opts.dryRun) console.log(` ${
|
|
279
|
+
console.log(BRANDING.commandBanner('claim', 'Claim Staking Rewards'));
|
|
280
|
+
console.log(`\n ${C.cyan}Wallet:${C.reset} ${address}`);
|
|
281
|
+
console.log(` ${C.cyan}RPC:${C.reset} ${rpcUrl}`);
|
|
282
|
+
if (opts.dryRun) console.log(` ${warning('(dry-run mode - no transaction will be submitted)')}`);
|
|
291
283
|
console.log();
|
|
292
284
|
}
|
|
293
285
|
|
|
@@ -296,11 +288,15 @@ ${C.bright}EXAMPLES${C.reset}
|
|
|
296
288
|
const client = createClient(rpcUrl);
|
|
297
289
|
|
|
298
290
|
if (!opts.json) {
|
|
299
|
-
|
|
291
|
+
startSpinner('Fetching stake positions via SDK');
|
|
300
292
|
}
|
|
301
293
|
|
|
302
294
|
const stakeAccounts = await fetchWalletStakeAccounts(rpcUrl, address);
|
|
303
295
|
|
|
296
|
+
if (!opts.json) {
|
|
297
|
+
stopSpinner(true, 'Stake positions retrieved');
|
|
298
|
+
}
|
|
299
|
+
|
|
304
300
|
if (!stakeAccounts || stakeAccounts.length === 0) {
|
|
305
301
|
if (opts.json) {
|
|
306
302
|
console.log(JSON.stringify({
|
|
@@ -309,8 +305,8 @@ ${C.bright}EXAMPLES${C.reset}
|
|
|
309
305
|
suggestion: 'Stake AETH first with: aether stake --validator <addr> --amount <aeth>',
|
|
310
306
|
}, null, 2));
|
|
311
307
|
} else {
|
|
312
|
-
console.log(
|
|
313
|
-
console.log(` ${C.dim}
|
|
308
|
+
console.log(`\n ${warning('No active stake positions found.')}`);
|
|
309
|
+
console.log(` ${C.dim}Stake AETH with: ${code('aether stake --validator <addr> --amount <aeth>')}${C.reset}\n`);
|
|
314
310
|
}
|
|
315
311
|
rl.close();
|
|
316
312
|
return;
|
|
@@ -320,6 +316,10 @@ ${C.bright}EXAMPLES${C.reset}
|
|
|
320
316
|
let totalPendingRewards = BigInt(0);
|
|
321
317
|
const rewardBreakdown = [];
|
|
322
318
|
|
|
319
|
+
if (!opts.json) {
|
|
320
|
+
startSpinner('Fetching reward data');
|
|
321
|
+
}
|
|
322
|
+
|
|
323
323
|
for (const acc of stakeAccounts) {
|
|
324
324
|
// SDK call: getRewards for each stake account
|
|
325
325
|
const rewardData = await fetchStakeRewards(rpcUrl, acc.address);
|
|
@@ -339,17 +339,29 @@ ${C.bright}EXAMPLES${C.reset}
|
|
|
339
339
|
}
|
|
340
340
|
|
|
341
341
|
if (!opts.json) {
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
for (const pos of rewardBreakdown) {
|
|
345
|
-
const shortVal = shortPubkey(pos.validator);
|
|
346
|
-
const shortAcct = shortPubkey(pos.stakeAcct);
|
|
347
|
-
console.log(` ${C.dim}├─ ${C.reset}${shortAcct} → ${C.cyan}${shortVal}${C.reset}`);
|
|
348
|
-
console.log(` │ ${C.dim}Staked:${C.reset} ${formatAether(pos.stakeLamports)}`);
|
|
349
|
-
console.log(` │ ${C.green}Pending:${C.reset} ${pos.pendingFormatted}\n`);
|
|
350
|
-
}
|
|
342
|
+
stopSpinner(true, 'Reward data retrieved');
|
|
343
|
+
}
|
|
351
344
|
|
|
352
|
-
|
|
345
|
+
if (!opts.json) {
|
|
346
|
+
console.log(`\n ${C.bright}Stake Positions (${C.cyan}${stakeAccounts.length}${C.reset})\n`);
|
|
347
|
+
|
|
348
|
+
// Build table rows
|
|
349
|
+
const rows = rewardBreakdown.map(pos => {
|
|
350
|
+
return [
|
|
351
|
+
shortPubkey(pos.stakeAcct),
|
|
352
|
+
shortPubkey(pos.validator),
|
|
353
|
+
formatAether(pos.stakeLamports),
|
|
354
|
+
C.green + pos.pendingFormatted + C.reset
|
|
355
|
+
];
|
|
356
|
+
});
|
|
357
|
+
|
|
358
|
+
console.log(drawTable(
|
|
359
|
+
['Stake Account', 'Validator', 'Staked', 'Pending'],
|
|
360
|
+
rows,
|
|
361
|
+
{ borderStyle: 'single', headerColor: C.cyan + C.bright }
|
|
362
|
+
));
|
|
363
|
+
|
|
364
|
+
console.log(`\n ${C.dim}${'─'.repeat(50)}${C.reset}`);
|
|
353
365
|
console.log(` ${C.bright}Total Pending Rewards:${C.reset} ${C.green}${formatFlux(totalPendingRewards.toString())}${C.reset}\n`);
|
|
354
366
|
}
|
|
355
367
|
|
|
@@ -366,7 +378,7 @@ ${C.bright}EXAMPLES${C.reset}
|
|
|
366
378
|
sdk_version: CLI_VERSION,
|
|
367
379
|
}, null, 2));
|
|
368
380
|
} else {
|
|
369
|
-
console.log(` ${
|
|
381
|
+
console.log(` ${warning('Dry run - not submitting claim transaction')}\n`);
|
|
370
382
|
}
|
|
371
383
|
rl.close();
|
|
372
384
|
return;
|
|
@@ -375,15 +387,15 @@ ${C.bright}EXAMPLES${C.reset}
|
|
|
375
387
|
// Load wallet for signing
|
|
376
388
|
const wallet = loadWallet(address);
|
|
377
389
|
if (!wallet) {
|
|
378
|
-
console.log(
|
|
379
|
-
console.log(` ${C.dim}Import it: aether wallet import${C.reset}\n`);
|
|
390
|
+
console.log(`\n ${error('Wallet not found locally:')} ${address}`);
|
|
391
|
+
console.log(` ${C.dim}Import it: ${code('aether wallet import')}${C.reset}\n`);
|
|
380
392
|
rl.close();
|
|
381
393
|
return;
|
|
382
394
|
}
|
|
383
395
|
|
|
384
396
|
// Step: Submit claim transaction
|
|
385
397
|
if (!opts.json) {
|
|
386
|
-
console.log(` ${C.dim}Preparing claim transaction...${C.reset}`);
|
|
398
|
+
console.log(` ${C.dim}Preparing claim transaction...${C.reset}\n`);
|
|
387
399
|
}
|
|
388
400
|
|
|
389
401
|
// Ask for mnemonic
|
|
@@ -394,7 +406,7 @@ ${C.bright}EXAMPLES${C.reset}
|
|
|
394
406
|
try {
|
|
395
407
|
keyPair = deriveKeypair(mnemonic);
|
|
396
408
|
} catch (e) {
|
|
397
|
-
console.log(
|
|
409
|
+
console.log(`\n ${error('Failed to derive keypair:')} ${e.message}\n`);
|
|
398
410
|
rl.close();
|
|
399
411
|
return;
|
|
400
412
|
}
|
|
@@ -402,16 +414,24 @@ ${C.bright}EXAMPLES${C.reset}
|
|
|
402
414
|
// Verify derived address matches
|
|
403
415
|
const derivedAddress = formatAddress(keyPair.publicKey);
|
|
404
416
|
if (derivedAddress !== address) {
|
|
405
|
-
console.log(
|
|
406
|
-
console.log(` ${C.dim}
|
|
407
|
-
console.log(` ${C.dim}
|
|
417
|
+
console.log(`\n ${error('Passphrase mismatch.')}`);
|
|
418
|
+
console.log(` ${C.dim}Derived: ${derivedAddress}${C.reset}`);
|
|
419
|
+
console.log(` ${C.dim}Expected: ${address}${C.reset}`);
|
|
408
420
|
console.log(` ${C.dim}Check your passphrase and try again.${C.reset}\n`);
|
|
409
421
|
rl.close();
|
|
410
422
|
return;
|
|
411
423
|
}
|
|
412
424
|
|
|
413
425
|
// SDK call: get current slot
|
|
426
|
+
if (!opts.json) {
|
|
427
|
+
startSpinner('Getting current slot');
|
|
428
|
+
}
|
|
429
|
+
|
|
414
430
|
const currentSlot = await client.getSlot().catch(() => 0);
|
|
431
|
+
|
|
432
|
+
if (!opts.json) {
|
|
433
|
+
stopSpinner(true, 'Slot retrieved');
|
|
434
|
+
}
|
|
415
435
|
|
|
416
436
|
// Build claim transaction for SDK
|
|
417
437
|
const tx = {
|
|
@@ -433,12 +453,16 @@ ${C.bright}EXAMPLES${C.reset}
|
|
|
433
453
|
tx.signature = signTransaction(tx, keyPair.secretKey);
|
|
434
454
|
|
|
435
455
|
if (!opts.json) {
|
|
436
|
-
|
|
456
|
+
startSpinner('Submitting claim via SDK');
|
|
437
457
|
}
|
|
438
458
|
|
|
439
459
|
// SDK call: sendTransaction (REAL RPC POST /v1/transaction)
|
|
440
460
|
const result = await client.sendTransaction(tx);
|
|
441
461
|
|
|
462
|
+
if (!opts.json) {
|
|
463
|
+
stopSpinner(true, 'Transaction submitted');
|
|
464
|
+
}
|
|
465
|
+
|
|
442
466
|
if (opts.json) {
|
|
443
467
|
console.log(JSON.stringify({
|
|
444
468
|
wallet_address: address,
|
|
@@ -453,18 +477,19 @@ ${C.bright}EXAMPLES${C.reset}
|
|
|
453
477
|
}, null, 2));
|
|
454
478
|
} else {
|
|
455
479
|
if (result.error) {
|
|
456
|
-
console.log(
|
|
480
|
+
console.log(`\n ${error('Claim failed:')} ${result.error}\n`);
|
|
457
481
|
rl.close();
|
|
458
482
|
process.exit(1);
|
|
459
483
|
}
|
|
460
484
|
|
|
461
|
-
console.log(
|
|
462
|
-
console.log(
|
|
485
|
+
console.log();
|
|
486
|
+
console.log(BRANDING.successBanner('Rewards claimed!'));
|
|
487
|
+
console.log(`\n ${C.cyan}Amount:${C.reset} ${C.green}${formatFlux(result.claimed || totalPendingRewards.toString())}${C.reset}`);
|
|
463
488
|
if (result.signature || result.txid) {
|
|
464
|
-
console.log(` ${C.
|
|
489
|
+
console.log(` ${C.cyan}Tx:${C.reset} ${shortPubkey(result.signature || result.txid)}`);
|
|
465
490
|
}
|
|
466
|
-
console.log(` ${C.
|
|
467
|
-
console.log(` ${C.dim}
|
|
491
|
+
console.log(` ${C.cyan}Slot:${C.reset} ${result.slot || currentSlot}`);
|
|
492
|
+
console.log(` ${C.dim}SDK: sendTransaction()${C.reset}\n`);
|
|
468
493
|
}
|
|
469
494
|
|
|
470
495
|
rl.close();
|
|
@@ -473,8 +498,9 @@ ${C.bright}EXAMPLES${C.reset}
|
|
|
473
498
|
if (opts.json) {
|
|
474
499
|
console.log(JSON.stringify({ address, error: err.message, sdk_version: CLI_VERSION }, null, 2));
|
|
475
500
|
} else {
|
|
476
|
-
|
|
477
|
-
console.log(
|
|
501
|
+
stopSpinner(false, 'Failed');
|
|
502
|
+
console.log(`\n ${error('Failed to claim rewards:')} ${err.message}\n`);
|
|
503
|
+
console.log(` ${C.dim}Set custom RPC: AETHER_RPC=https://your-rpc-url${C.reset}\n`);
|
|
478
504
|
}
|
|
479
505
|
rl.close();
|
|
480
506
|
process.exit(1);
|