aether-hub 1.2.5 → 1.2.7
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 +10 -34
- 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/emergency.js +657 -657
- package/commands/epoch.js +12 -94
- package/commands/fees.js +276 -0
- package/commands/info.js +38 -79
- package/commands/network.js +34 -108
- package/commands/ping.js +11 -65
- package/commands/price.js +253 -253
- package/commands/rewards.js +187 -4
- package/commands/sdk-test.js +477 -0
- package/commands/stake-info.js +139 -0
- package/commands/status.js +113 -157
- package/commands/supply.js +34 -82
- package/commands/tps.js +238 -0
- package/commands/transfer.js +495 -0
- package/commands/tx-history.js +462 -0
- 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 +5 -29
- package/index.js +64 -17
- 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
|
@@ -541,37 +541,11 @@ async function connectWallet(rl) {
|
|
|
541
541
|
|
|
542
542
|
// ---------------------------------------------------------------------------
|
|
543
543
|
// BALANCE
|
|
544
|
-
// Query chain RPC GET /v1/account/<addr> for real AETH balance
|
|
544
|
+
// Query chain RPC GET /v1/account/<addr> for real AETH balance using SDK
|
|
545
545
|
// ---------------------------------------------------------------------------
|
|
546
546
|
|
|
547
547
|
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
|
-
});
|
|
548
|
+
return process.env.AETHER_RPC || aether.DEFAULT_RPC_URL || 'http://127.0.0.1:8899';
|
|
575
549
|
}
|
|
576
550
|
|
|
577
551
|
/**
|
|
@@ -612,9 +586,11 @@ async function balanceWallet(rl) {
|
|
|
612
586
|
console.log();
|
|
613
587
|
|
|
614
588
|
try {
|
|
589
|
+
// Use SDK for real blockchain RPC call
|
|
590
|
+
const client = new aether.AetherClient({ rpcUrl });
|
|
615
591
|
// Strip ATH prefix if present for API call
|
|
616
592
|
const rawAddr = address.startsWith('ATH') ? address.slice(3) : address;
|
|
617
|
-
const account = await
|
|
593
|
+
const account = await client.getAccountInfo(rawAddr);
|
|
618
594
|
|
|
619
595
|
if (!account || account.error) {
|
|
620
596
|
console.log(` ${C.yellow}⚠ Account not found on chain or RPC error.${C.reset}`);
|
package/index.js
CHANGED
|
@@ -29,6 +29,13 @@ const { statusCommand } = require('./commands/status');
|
|
|
29
29
|
const { broadcastCommand } = require('./commands/broadcast');
|
|
30
30
|
const { apyCommand } = require('./commands/apy');
|
|
31
31
|
const { statsCommand } = require('./commands/stats');
|
|
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');
|
|
32
39
|
const readline = require('readline');
|
|
33
40
|
|
|
34
41
|
// CLI version
|
|
@@ -203,6 +210,13 @@ const COMMANDS = {
|
|
|
203
210
|
stakePositionsCommand();
|
|
204
211
|
},
|
|
205
212
|
},
|
|
213
|
+
'stake-info': {
|
|
214
|
+
description: 'Get staking info for an address via real chain RPC — aether stake-info <address>',
|
|
215
|
+
handler: () => {
|
|
216
|
+
const { stakeInfoCommand } = require('./commands/stake-info');
|
|
217
|
+
stakeInfoCommand();
|
|
218
|
+
},
|
|
219
|
+
},
|
|
206
220
|
unstake: {
|
|
207
221
|
description: 'Unstake AETH — deactivate a stake account — aether unstake --account <stakeAcct> [--amount <aeth>]',
|
|
208
222
|
handler: () => {
|
|
@@ -226,21 +240,33 @@ const COMMANDS = {
|
|
|
226
240
|
transfer: {
|
|
227
241
|
description: 'Transfer AETH to another address — aether transfer --to <addr> --amount <aeth>',
|
|
228
242
|
handler: () => {
|
|
229
|
-
|
|
230
|
-
const originalArgv = process.argv;
|
|
231
|
-
process.argv = [...originalArgv.slice(0, 2), 'wallet', 'transfer', ...originalArgv.slice(3)];
|
|
232
|
-
walletCommand();
|
|
233
|
-
process.argv = originalArgv;
|
|
243
|
+
transferCommand();
|
|
234
244
|
},
|
|
235
245
|
},
|
|
236
246
|
tx: {
|
|
237
247
|
description: 'Transaction history — aether tx history --address <addr> [--limit 20] [--json]',
|
|
238
248
|
handler: () => {
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
249
|
+
txHistoryCommand();
|
|
250
|
+
},
|
|
251
|
+
},
|
|
252
|
+
'tx-history': {
|
|
253
|
+
description: 'Transaction history for an address — aether tx-history --address <addr> [--limit 20] [--json]',
|
|
254
|
+
handler: () => {
|
|
255
|
+
txHistoryCommand();
|
|
256
|
+
},
|
|
257
|
+
},
|
|
258
|
+
blockhash: {
|
|
259
|
+
description: 'Get the latest blockhash from the chain (required for signing TXs) — aether blockhash [--json] [--watch]',
|
|
260
|
+
handler: () => {
|
|
261
|
+
const { blockhashCommand } = require('./commands/blockhash');
|
|
262
|
+
blockhashCommand();
|
|
263
|
+
},
|
|
264
|
+
},
|
|
265
|
+
balance: {
|
|
266
|
+
description: 'Query account balance — aether balance [address] [--json] [--lamports] [--rpc <url>]',
|
|
267
|
+
handler: () => {
|
|
268
|
+
const { balanceCommand } = require('./commands/balance');
|
|
269
|
+
balanceCommand();
|
|
244
270
|
},
|
|
245
271
|
},
|
|
246
272
|
network: {
|
|
@@ -253,11 +279,7 @@ const COMMANDS = {
|
|
|
253
279
|
history: {
|
|
254
280
|
description: 'Transaction history for an address — alias for tx history',
|
|
255
281
|
handler: () => {
|
|
256
|
-
|
|
257
|
-
const originalArgv = process.argv;
|
|
258
|
-
process.argv = [...originalArgv.slice(0, 2), 'wallet', 'history', ...originalArgv.slice(3)];
|
|
259
|
-
walletCommand();
|
|
260
|
-
process.argv = originalArgv;
|
|
282
|
+
txHistoryCommand();
|
|
261
283
|
},
|
|
262
284
|
},
|
|
263
285
|
validator: {
|
|
@@ -300,7 +322,7 @@ const COMMANDS = {
|
|
|
300
322
|
},
|
|
301
323
|
},
|
|
302
324
|
rewards: {
|
|
303
|
-
description: 'View staking rewards — aether rewards list |
|
|
325
|
+
description: 'View staking rewards — aether rewards list | summary | pending | claim | compound',
|
|
304
326
|
handler: () => {
|
|
305
327
|
rewardsCommand();
|
|
306
328
|
},
|
|
@@ -395,6 +417,31 @@ const COMMANDS = {
|
|
|
395
417
|
emergencyCommand();
|
|
396
418
|
},
|
|
397
419
|
},
|
|
420
|
+
fees: {
|
|
421
|
+
description: 'Network fee estimates — aether fees [--json] [--verbose] [--rpc <url>]',
|
|
422
|
+
handler: () => {
|
|
423
|
+
feesCommand();
|
|
424
|
+
},
|
|
425
|
+
},
|
|
426
|
+
tps: {
|
|
427
|
+
description: 'Transactions per second monitor — aether tps [--monitor] [--interval 2] [--json]',
|
|
428
|
+
handler: () => {
|
|
429
|
+
tpsCommand();
|
|
430
|
+
},
|
|
431
|
+
},
|
|
432
|
+
claim: {
|
|
433
|
+
description: 'Claim accumulated staking rewards — aether claim --address <addr> [--json] [--dry-run]',
|
|
434
|
+
handler: () => {
|
|
435
|
+
const { claimCommand } = require('./commands/claim');
|
|
436
|
+
claimCommand();
|
|
437
|
+
},
|
|
438
|
+
},
|
|
439
|
+
'sdk-test': {
|
|
440
|
+
description: 'Test SDK with real RPC calls — aether sdk-test [--rpc <url>] [--quick] [--json]',
|
|
441
|
+
handler: () => {
|
|
442
|
+
sdkTestCommand();
|
|
443
|
+
},
|
|
444
|
+
},
|
|
398
445
|
help: {
|
|
399
446
|
description: 'Show this help message',
|
|
400
447
|
handler: showHelp,
|
|
@@ -449,7 +496,7 @@ function parseArgs() {
|
|
|
449
496
|
const args = process.argv.slice(2);
|
|
450
497
|
|
|
451
498
|
// Handle version flag
|
|
452
|
-
if (args.includes('--version') || args.includes('-v')) {
|
|
499
|
+
if (args.includes('--version') || args.includes('-v') || args.includes('-V')) {
|
|
453
500
|
return 'version';
|
|
454
501
|
}
|
|
455
502
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "aether-hub",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.7",
|
|
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": [
|