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.
@@ -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 http = require('http');
19
- const https = require('https');
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
- const DEFAULT_RPC = process.env.AETHER_RPC || 'http://127.0.0.1:8899';
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 httpPost(rpcUrl, path, body) {
63
- return new Promise((resolve, reject) => {
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: DEFAULT_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: ${DEFAULT_RPC} or $AETHER_RPC)
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: ${DEFAULT_RPC} or $AETHER_RPC)
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
- // Try /v1/validators first (standard Aether RPC endpoint)
183
- const res = await httpRequest(rpc, '/v1/validators');
184
- if (res && !res.error) {
185
- if (Array.isArray(res)) return res;
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 res = await httpRequest(rpc, '/v1/epoch-info');
205
- return res;
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 res = await httpRequest(rpc, '/v1/supply');
215
- return res;
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
  }
@@ -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 httpRequest(rpcUrl, `/v1/account/${rawAddr}`);
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
- const { walletCommand } = require('./commands/wallet');
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
- const { walletCommand } = require('./commands/wallet');
240
- const originalArgv = process.argv;
241
- process.argv = [...originalArgv.slice(0, 2), 'wallet', 'history', ...originalArgv.slice(3)];
242
- walletCommand();
243
- process.argv = originalArgv;
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
- const { walletCommand } = require('./commands/wallet');
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 | rewards summary | rewards pending | rewards claim',
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.5",
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": [