aether-hub 1.2.6 → 1.2.8
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/commands/account.js +280 -304
- package/commands/apy.js +480 -480
- package/commands/balance.js +276 -0
- package/commands/blockhash.js +181 -0
- package/commands/broadcast.js +323 -323
- package/commands/claim.js +292 -0
- package/commands/delegations.js +45 -95
- package/commands/emergency.js +667 -657
- package/commands/epoch.js +275 -357
- package/commands/fees.js +276 -0
- package/commands/info.js +495 -536
- package/commands/monitor.js +431 -431
- package/commands/multisig.js +726 -726
- package/commands/network.js +429 -503
- package/commands/ping.js +266 -320
- package/commands/price.js +253 -253
- package/commands/sdk-test.js +477 -0
- package/commands/sdk.js +537 -537
- package/commands/slot.js +155 -0
- package/commands/snapshot.js +509 -509
- package/commands/stake-info.js +139 -0
- package/commands/stake-positions.js +31 -46
- package/commands/stats.js +418 -418
- package/commands/status.js +326 -370
- package/commands/supply.js +37 -83
- package/commands/tps.js +238 -0
- package/commands/transfer.js +495 -0
- package/commands/tx-history.js +65 -227
- package/commands/validator-info.js +10 -4
- package/commands/validator-start.js +1 -1
- package/commands/validator-status.js +32 -73
- package/commands/validators.js +36 -75
- package/commands/wallet.js +8 -29
- package/index.js +65 -8
- package/package.json +1 -3
package/commands/validators.js
CHANGED
|
@@ -13,10 +13,15 @@
|
|
|
13
13
|
* aether validators list --sort stake Sort by stake (default: score)
|
|
14
14
|
*
|
|
15
15
|
* Requires AETHER_RPC env var (default: http://127.0.0.1:8899)
|
|
16
|
+
*
|
|
17
|
+
* SDK wired to: GET /v1/validators, GET /v1/epoch, GET /v1/supply
|
|
16
18
|
*/
|
|
17
19
|
|
|
18
|
-
const
|
|
19
|
-
|
|
20
|
+
const path = require('path');
|
|
21
|
+
|
|
22
|
+
// Import SDK for real blockchain RPC calls
|
|
23
|
+
const sdkPath = path.join(__dirname, '..', 'sdk', 'index.js');
|
|
24
|
+
const aether = require(sdkPath);
|
|
20
25
|
|
|
21
26
|
// ANSI colours
|
|
22
27
|
const C = {
|
|
@@ -31,56 +36,12 @@ const C = {
|
|
|
31
36
|
magenta: '\x1b[35m',
|
|
32
37
|
};
|
|
33
38
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
// ---------------------------------------------------------------------------
|
|
37
|
-
// HTTP helpers
|
|
38
|
-
// ---------------------------------------------------------------------------
|
|
39
|
-
|
|
40
|
-
function httpRequest(rpcUrl, path) {
|
|
41
|
-
return new Promise((resolve, reject) => {
|
|
42
|
-
const url = new URL(path, rpcUrl);
|
|
43
|
-
const lib = url.protocol === 'https:' ? https : http;
|
|
44
|
-
const req = lib.request({
|
|
45
|
-
hostname: url.hostname,
|
|
46
|
-
port: url.port || (url.protocol === 'https:' ? 443 : 80),
|
|
47
|
-
path: url.pathname + url.search,
|
|
48
|
-
method: 'GET',
|
|
49
|
-
timeout: 8000,
|
|
50
|
-
headers: { 'Content-Type': 'application/json' },
|
|
51
|
-
}, (res) => {
|
|
52
|
-
let data = '';
|
|
53
|
-
res.on('data', (chunk) => data += chunk);
|
|
54
|
-
res.on('end', () => { try { resolve(JSON.parse(data)); } catch { resolve({ raw: data }); } });
|
|
55
|
-
});
|
|
56
|
-
req.on('error', reject);
|
|
57
|
-
req.on('timeout', () => { req.destroy(); reject(new Error('Request timeout')); });
|
|
58
|
-
req.end();
|
|
59
|
-
});
|
|
39
|
+
function getDefaultRpc() {
|
|
40
|
+
return process.env.AETHER_RPC || aether.DEFAULT_RPC_URL || 'http://127.0.0.1:8899';
|
|
60
41
|
}
|
|
61
42
|
|
|
62
|
-
function
|
|
63
|
-
return new
|
|
64
|
-
const url = new URL(path, rpcUrl);
|
|
65
|
-
const lib = url.protocol === 'https:' ? https : http;
|
|
66
|
-
const bodyStr = JSON.stringify(body);
|
|
67
|
-
const req = lib.request({
|
|
68
|
-
hostname: url.hostname,
|
|
69
|
-
port: url.port || (url.protocol === 'https:' ? 443 : 80),
|
|
70
|
-
path: url.pathname + url.search,
|
|
71
|
-
method: 'POST',
|
|
72
|
-
timeout: 8000,
|
|
73
|
-
headers: { 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(bodyStr) },
|
|
74
|
-
}, (res) => {
|
|
75
|
-
let data = '';
|
|
76
|
-
res.on('data', (chunk) => data += chunk);
|
|
77
|
-
res.on('end', () => { try { resolve(JSON.parse(data)); } catch { resolve(data); } });
|
|
78
|
-
});
|
|
79
|
-
req.on('error', reject);
|
|
80
|
-
req.on('timeout', () => { req.destroy(); reject(new Error('Request timeout')); });
|
|
81
|
-
req.write(bodyStr);
|
|
82
|
-
req.end();
|
|
83
|
-
});
|
|
43
|
+
function createClient(rpcUrl) {
|
|
44
|
+
return new aether.AetherClient({ rpcUrl });
|
|
84
45
|
}
|
|
85
46
|
|
|
86
47
|
// ---------------------------------------------------------------------------
|
|
@@ -90,7 +51,7 @@ function httpPost(rpcUrl, path, body) {
|
|
|
90
51
|
function parseArgs() {
|
|
91
52
|
const args = process.argv.slice(3); // [node, index.js, validators, list, ...]
|
|
92
53
|
const opts = {
|
|
93
|
-
rpc:
|
|
54
|
+
rpc: getDefaultRpc(),
|
|
94
55
|
subcmd: 'list',
|
|
95
56
|
tier: null,
|
|
96
57
|
asJson: false,
|
|
@@ -137,6 +98,7 @@ function parseArgs() {
|
|
|
137
98
|
}
|
|
138
99
|
|
|
139
100
|
function showHelp() {
|
|
101
|
+
const defaultRpc = getDefaultRpc();
|
|
140
102
|
console.log(`
|
|
141
103
|
${C.bright}${C.cyan}aether-cli validators${C.reset} - List and inspect Aether validators
|
|
142
104
|
|
|
@@ -148,17 +110,22 @@ ${C.bright}Options (list):${C.reset}
|
|
|
148
110
|
-t, --tier <type> Filter by tier: full, lite, observer
|
|
149
111
|
-s, --sort <field> Sort by: stake, score, apy, uptime, name (default: score)
|
|
150
112
|
-l, --limit <n> Max validators to show (default: 100, max: 500)
|
|
151
|
-
-r, --rpc <url> RPC endpoint (default: ${
|
|
113
|
+
-r, --rpc <url> RPC endpoint (default: ${defaultRpc} or $AETHER_RPC)
|
|
152
114
|
-j, --json Output raw JSON (for scripting)
|
|
153
115
|
-h, --help Show this help message
|
|
154
116
|
|
|
155
117
|
${C.bright}Options (rank):${C.reset}
|
|
156
118
|
-t, --tier <type> Filter by tier: full, lite, observer
|
|
157
119
|
-l, --limit <n> Max validators to show (default: 50, max: 200)
|
|
158
|
-
-r, --rpc <url> RPC endpoint (default: ${
|
|
120
|
+
-r, --rpc <url> RPC endpoint (default: ${defaultRpc} or $AETHER_RPC)
|
|
159
121
|
-j, --json Output raw JSON (for scripting)
|
|
160
122
|
-h, --help Show this help message
|
|
161
123
|
|
|
124
|
+
${C.bright}SDK Methods Used:${C.reset}
|
|
125
|
+
client.getValidators() → GET /v1/validators
|
|
126
|
+
client.getEpochInfo() → GET /v1/epoch
|
|
127
|
+
client.getSupply() → GET /v1/supply
|
|
128
|
+
|
|
162
129
|
${C.bright}Examples:${C.reset}
|
|
163
130
|
aether validators list # All validators, sorted by score
|
|
164
131
|
aether validators list --tier full # Full validators only
|
|
@@ -173,46 +140,40 @@ ${C.bright}Examples:${C.reset}
|
|
|
173
140
|
}
|
|
174
141
|
|
|
175
142
|
// ---------------------------------------------------------------------------
|
|
176
|
-
// Data fetchers
|
|
143
|
+
// Data fetchers using SDK - Real blockchain RPC calls
|
|
177
144
|
// ---------------------------------------------------------------------------
|
|
178
145
|
|
|
179
|
-
/** Fetch all validators from the network */
|
|
146
|
+
/** Fetch all validators from the network using SDK */
|
|
180
147
|
async function fetchValidators(rpc) {
|
|
181
148
|
try {
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
if (res.validators && Array.isArray(res.validators)) return res.validators;
|
|
187
|
-
if (res.accounts && Array.isArray(res.accounts)) return res.accounts;
|
|
188
|
-
}
|
|
189
|
-
// Fallback: POST to a validators query endpoint
|
|
190
|
-
const res2 = await httpPost(rpc, '/v1/validators', {});
|
|
191
|
-
if (res2 && !res2.error) {
|
|
192
|
-
if (Array.isArray(res2)) return res2;
|
|
193
|
-
if (res2.validators && Array.isArray(res2.validators)) return res2.validators;
|
|
194
|
-
}
|
|
195
|
-
return [];
|
|
149
|
+
const client = createClient(rpc);
|
|
150
|
+
// SDK getValidators() → GET /v1/validators
|
|
151
|
+
const result = await client.getValidators();
|
|
152
|
+
return Array.isArray(result) ? result : [];
|
|
196
153
|
} catch {
|
|
197
154
|
return [];
|
|
198
155
|
}
|
|
199
156
|
}
|
|
200
157
|
|
|
201
|
-
/** Fetch epoch info for APY calculations */
|
|
158
|
+
/** Fetch epoch info for APY calculations using SDK */
|
|
202
159
|
async function fetchEpochInfo(rpc) {
|
|
203
160
|
try {
|
|
204
|
-
const
|
|
205
|
-
|
|
161
|
+
const client = createClient(rpc);
|
|
162
|
+
// SDK getEpochInfo() → GET /v1/epoch
|
|
163
|
+
const result = await client.getEpochInfo();
|
|
164
|
+
return result || null;
|
|
206
165
|
} catch {
|
|
207
166
|
return null;
|
|
208
167
|
}
|
|
209
168
|
}
|
|
210
169
|
|
|
211
|
-
/** Fetch network-wide stake totals for APY estimation */
|
|
170
|
+
/** Fetch network-wide stake totals for APY estimation using SDK */
|
|
212
171
|
async function fetchSupply(rpc) {
|
|
213
172
|
try {
|
|
214
|
-
const
|
|
215
|
-
|
|
173
|
+
const client = createClient(rpc);
|
|
174
|
+
// SDK getSupply() → GET /v1/supply
|
|
175
|
+
const result = await client.getSupply();
|
|
176
|
+
return result || null;
|
|
216
177
|
} catch {
|
|
217
178
|
return null;
|
|
218
179
|
}
|
package/commands/wallet.js
CHANGED
|
@@ -19,6 +19,9 @@ const bip39 = require('bip39');
|
|
|
19
19
|
const nacl = require('tweetnacl');
|
|
20
20
|
const bs58 = require('bs58').default;
|
|
21
21
|
|
|
22
|
+
// Import SDK for blockchain RPC calls
|
|
23
|
+
const aether = require('../sdk');
|
|
24
|
+
|
|
22
25
|
// ANSI colours
|
|
23
26
|
const C = {
|
|
24
27
|
reset: '\x1b[0m',
|
|
@@ -541,37 +544,11 @@ async function connectWallet(rl) {
|
|
|
541
544
|
|
|
542
545
|
// ---------------------------------------------------------------------------
|
|
543
546
|
// BALANCE
|
|
544
|
-
// Query chain RPC GET /v1/account/<addr> for real AETH balance
|
|
547
|
+
// Query chain RPC GET /v1/account/<addr> for real AETH balance using SDK
|
|
545
548
|
// ---------------------------------------------------------------------------
|
|
546
549
|
|
|
547
550
|
function getDefaultRpc() {
|
|
548
|
-
return process.env.AETHER_RPC || 'http://127.0.0.1:8899';
|
|
549
|
-
}
|
|
550
|
-
|
|
551
|
-
/**
|
|
552
|
-
* Make HTTP GET request to the RPC endpoint
|
|
553
|
-
*/
|
|
554
|
-
function httpRequest(rpcUrl, path) {
|
|
555
|
-
return new Promise((resolve, reject) => {
|
|
556
|
-
const url = new URL(path, rpcUrl);
|
|
557
|
-
const lib = url.protocol === 'https:' ? require('https') : require('http');
|
|
558
|
-
const req = lib.request({
|
|
559
|
-
hostname: url.hostname,
|
|
560
|
-
port: url.port || (url.protocol === 'https:' ? 443 : 80),
|
|
561
|
-
path: url.pathname + url.search,
|
|
562
|
-
method: 'GET',
|
|
563
|
-
headers: { 'Content-Type': 'application/json' },
|
|
564
|
-
}, (res) => {
|
|
565
|
-
let data = '';
|
|
566
|
-
res.on('data', (chunk) => data += chunk);
|
|
567
|
-
res.on('end', () => {
|
|
568
|
-
try { resolve(JSON.parse(data)); }
|
|
569
|
-
catch { resolve(data); }
|
|
570
|
-
});
|
|
571
|
-
});
|
|
572
|
-
req.on('error', reject);
|
|
573
|
-
req.end();
|
|
574
|
-
});
|
|
551
|
+
return process.env.AETHER_RPC || aether.DEFAULT_RPC_URL || 'http://127.0.0.1:8899';
|
|
575
552
|
}
|
|
576
553
|
|
|
577
554
|
/**
|
|
@@ -612,9 +589,11 @@ async function balanceWallet(rl) {
|
|
|
612
589
|
console.log();
|
|
613
590
|
|
|
614
591
|
try {
|
|
592
|
+
// Use SDK for real blockchain RPC call
|
|
593
|
+
const client = new aether.AetherClient({ rpcUrl });
|
|
615
594
|
// Strip ATH prefix if present for API call
|
|
616
595
|
const rawAddr = address.startsWith('ATH') ? address.slice(3) : address;
|
|
617
|
-
const account = await
|
|
596
|
+
const account = await client.getAccountInfo(rawAddr);
|
|
618
597
|
|
|
619
598
|
if (!account || account.error) {
|
|
620
599
|
console.log(` ${C.yellow}⚠ Account not found on chain or RPC error.${C.reset}`);
|
package/index.js
CHANGED
|
@@ -30,6 +30,13 @@ const { broadcastCommand } = require('./commands/broadcast');
|
|
|
30
30
|
const { apyCommand } = require('./commands/apy');
|
|
31
31
|
const { statsCommand } = require('./commands/stats');
|
|
32
32
|
const { txHistoryCommand } = require('./commands/tx-history');
|
|
33
|
+
const { feesCommand } = require('./commands/fees');
|
|
34
|
+
const { tpsCommand } = require('./commands/tps');
|
|
35
|
+
const { blockhashCommand } = require('./commands/blockhash');
|
|
36
|
+
const { sdkTestCommand } = require('./commands/sdk-test');
|
|
37
|
+
const { balanceCommand } = require('./commands/balance');
|
|
38
|
+
const { transferCommand } = require('./commands/transfer');
|
|
39
|
+
const { slotCommand } = require('./commands/slot');
|
|
33
40
|
const readline = require('readline');
|
|
34
41
|
|
|
35
42
|
// CLI version
|
|
@@ -204,6 +211,13 @@ const COMMANDS = {
|
|
|
204
211
|
stakePositionsCommand();
|
|
205
212
|
},
|
|
206
213
|
},
|
|
214
|
+
'stake-info': {
|
|
215
|
+
description: 'Get staking info for an address via real chain RPC — aether stake-info <address>',
|
|
216
|
+
handler: () => {
|
|
217
|
+
const { stakeInfoCommand } = require('./commands/stake-info');
|
|
218
|
+
stakeInfoCommand();
|
|
219
|
+
},
|
|
220
|
+
},
|
|
207
221
|
unstake: {
|
|
208
222
|
description: 'Unstake AETH — deactivate a stake account — aether unstake --account <stakeAcct> [--amount <aeth>]',
|
|
209
223
|
handler: () => {
|
|
@@ -227,11 +241,7 @@ const COMMANDS = {
|
|
|
227
241
|
transfer: {
|
|
228
242
|
description: 'Transfer AETH to another address — aether transfer --to <addr> --amount <aeth>',
|
|
229
243
|
handler: () => {
|
|
230
|
-
|
|
231
|
-
const originalArgv = process.argv;
|
|
232
|
-
process.argv = [...originalArgv.slice(0, 2), 'wallet', 'transfer', ...originalArgv.slice(3)];
|
|
233
|
-
walletCommand();
|
|
234
|
-
process.argv = originalArgv;
|
|
244
|
+
transferCommand();
|
|
235
245
|
},
|
|
236
246
|
},
|
|
237
247
|
tx: {
|
|
@@ -246,6 +256,20 @@ const COMMANDS = {
|
|
|
246
256
|
txHistoryCommand();
|
|
247
257
|
},
|
|
248
258
|
},
|
|
259
|
+
blockhash: {
|
|
260
|
+
description: 'Get the latest blockhash from the chain (required for signing TXs) — aether blockhash [--json] [--watch]',
|
|
261
|
+
handler: () => {
|
|
262
|
+
const { blockhashCommand } = require('./commands/blockhash');
|
|
263
|
+
blockhashCommand();
|
|
264
|
+
},
|
|
265
|
+
},
|
|
266
|
+
balance: {
|
|
267
|
+
description: 'Query account balance — aether balance [address] [--json] [--lamports] [--rpc <url>]',
|
|
268
|
+
handler: () => {
|
|
269
|
+
const { balanceCommand } = require('./commands/balance');
|
|
270
|
+
balanceCommand();
|
|
271
|
+
},
|
|
272
|
+
},
|
|
249
273
|
network: {
|
|
250
274
|
description: 'Aether network status — slot, block height, peers, TPS, epoch info',
|
|
251
275
|
handler: () => {
|
|
@@ -394,6 +418,37 @@ const COMMANDS = {
|
|
|
394
418
|
emergencyCommand();
|
|
395
419
|
},
|
|
396
420
|
},
|
|
421
|
+
fees: {
|
|
422
|
+
description: 'Network fee estimates — aether fees [--json] [--verbose] [--rpc <url>]',
|
|
423
|
+
handler: () => {
|
|
424
|
+
feesCommand();
|
|
425
|
+
},
|
|
426
|
+
},
|
|
427
|
+
tps: {
|
|
428
|
+
description: 'Transactions per second monitor — aether tps [--monitor] [--interval 2] [--json]',
|
|
429
|
+
handler: () => {
|
|
430
|
+
tpsCommand();
|
|
431
|
+
},
|
|
432
|
+
},
|
|
433
|
+
slot: {
|
|
434
|
+
description: 'Get current slot number — aether slot [--json] [--rpc <url>]',
|
|
435
|
+
handler: () => {
|
|
436
|
+
slotCommand();
|
|
437
|
+
},
|
|
438
|
+
},
|
|
439
|
+
claim: {
|
|
440
|
+
description: 'Claim accumulated staking rewards — aether claim --address <addr> [--json] [--dry-run]',
|
|
441
|
+
handler: () => {
|
|
442
|
+
const { claimCommand } = require('./commands/claim');
|
|
443
|
+
claimCommand();
|
|
444
|
+
},
|
|
445
|
+
},
|
|
446
|
+
'sdk-test': {
|
|
447
|
+
description: 'Test SDK with real RPC calls — aether sdk-test [--rpc <url>] [--quick] [--json]',
|
|
448
|
+
handler: () => {
|
|
449
|
+
sdkTestCommand();
|
|
450
|
+
},
|
|
451
|
+
},
|
|
397
452
|
help: {
|
|
398
453
|
description: 'Show this help message',
|
|
399
454
|
handler: showHelp,
|
|
@@ -448,7 +503,7 @@ function parseArgs() {
|
|
|
448
503
|
const args = process.argv.slice(2);
|
|
449
504
|
|
|
450
505
|
// Handle version flag
|
|
451
|
-
if (args.includes('--version') || args.includes('-v')) {
|
|
506
|
+
if (args.includes('--version') || args.includes('-v') || args.includes('-V')) {
|
|
452
507
|
return 'version';
|
|
453
508
|
}
|
|
454
509
|
|
|
@@ -484,5 +539,7 @@ function main() {
|
|
|
484
539
|
}
|
|
485
540
|
}
|
|
486
541
|
|
|
487
|
-
// Run CLI
|
|
488
|
-
main
|
|
542
|
+
// Run CLI only if executed directly
|
|
543
|
+
if (require.main === module) {
|
|
544
|
+
main();
|
|
545
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "aether-hub",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.8",
|
|
4
4
|
"description": "AeTHer Validator CLI — tiered validators (Full/Lite/Observer), system checks, onboarding, and node management",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"bin": {
|
|
@@ -18,8 +18,6 @@
|
|
|
18
18
|
"test": "node test/doctor.test.js",
|
|
19
19
|
"start": "node index.js",
|
|
20
20
|
"doctor": "node index.js doctor",
|
|
21
|
-
"price": "node index.js price",
|
|
22
|
-
"build": "node -e \"require('./commands/price'); require('./commands/account'); require('./commands/emergency')\" && echo \"Build OK\"",
|
|
23
21
|
"postinstall": "node -e \"console.log('\\n\\n [Aether] aether-hub installed!\\n\\n Run: aether start\\n Docs: https://github.com/jelly-legs-ai/Jelly-legs-unsteady-workshop\\n')\""
|
|
24
22
|
},
|
|
25
23
|
"keywords": [
|