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.
@@ -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
  }
@@ -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 httpRequest(rpcUrl, `/v1/account/${rawAddr}`);
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
- const { walletCommand } = require('./commands/wallet');
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.6",
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": [