aether-hub 1.2.8 → 1.3.0

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/index.js CHANGED
@@ -40,7 +40,11 @@ const { slotCommand } = require('./commands/slot');
40
40
  const readline = require('readline');
41
41
 
42
42
  // CLI version
43
- const VERSION = '1.0.5';
43
+ const VERSION = '1.3.0';
44
+
45
+ // Import shared theme
46
+ const theme = require('./theme');
47
+ const { C, BANNERS, ICONS } = theme;
44
48
 
45
49
  // Parse args early to support flags on commands
46
50
  function getCommandArgs() {
@@ -66,21 +70,17 @@ async function showMenu() {
66
70
 
67
71
  const prompt = (q) => new Promise((res) => rl.question(q, res));
68
72
 
69
- console.log(
70
- TIER_COLORS.FULL + '\n ╔═══════════════════════════════════════════════╗\n' +
71
- ' ║ AETHER CHAIN — Validator Setup Wizard ║\n' +
72
- ' ╚═══════════════════════════════════════════════╝' + TIER_COLORS.reset + '\n'
73
- );
73
+ console.log(BANNERS.compact + '\n');
74
74
 
75
75
  console.log(' Welcome to AeTHer Chain. What would you like to do?\n');
76
- console.log(' ' + TIER_COLORS.FULL + '1)' + TIER_COLORS.reset + ' 🩺 Doctor — Check if your system meets requirements');
77
- console.log(' ' + TIER_COLORS.FULL + '2)' + TIER_COLORS.reset + ' 🚀 Start — Begin validator onboarding (recommended)');
78
- console.log(' ' + TIER_COLORS.FULL + '3)' + TIER_COLORS.reset + ' 📊 Monitor — Watch live validator stats');
79
- console.log(' ' + TIER_COLORS.FULL + '4)' + TIER_COLORS.reset + ' 📋 Logs — Tail and colourise validator logs');
80
- console.log(' ' + TIER_COLORS.FULL + '5)' + TIER_COLORS.reset + ' 📦 SDK — Get SDK links and install tools');
81
- console.log(' ' + TIER_COLORS.FULL + '6)' + TIER_COLORS.reset + ' 🌐 Network — Aether network status (slot, peers, TPS)');
82
- console.log(' ' + TIER_COLORS.FULL + '7)' + TIER_COLORS.reset + ' ❓ Help — Show all commands\n');
83
- console.log(' ' + TIER_COLORS.reset + ' Type a number or command name. Press Ctrl+C to exit.\n');
76
+ console.log(` ${C.cyan}1)${C.reset} ${ICONS.active} ${C.bright}Doctor${C.reset} — Check if your system meets requirements`);
77
+ console.log(` ${C.cyan}2)${C.reset} 🚀 ${C.bright}Start${C.reset} — Begin validator onboarding (recommended)`);
78
+ console.log(` ${C.cyan}3)${C.reset} 📊 ${C.bright}Monitor${C.reset} — Watch live validator stats`);
79
+ console.log(` ${C.cyan}4)${C.reset} 📋 ${C.bright}Logs${C.reset} — Tail and colourise validator logs`);
80
+ console.log(` ${C.cyan}5)${C.reset} 📦 ${C.bright}SDK${C.reset} — Get SDK links and install tools`);
81
+ console.log(` ${C.cyan}6)${C.reset} 🌐 ${C.bright}Network${C.reset} — Aether network status (slot, peers, TPS)`);
82
+ console.log(` ${C.cyan}7)${C.reset}${C.bright}Help${C.reset} — Show all commands\n`);
83
+ console.log(` ${C.dim}Type a number or command name. Press Ctrl+C to exit.\n`);
84
84
 
85
85
  const VALID_CHOICES = ['1', '2', '3', '4', '5', '6', '7', 'doctor', 'init', 'monitor', 'logs', 'sdk', 'network', 'help'];
86
86
 
@@ -463,37 +463,27 @@ const COMMANDS = {
463
463
  * Display help message with ASCII art
464
464
  */
465
465
  function showHelp() {
466
- const header = `
467
- ███╗ ███╗██╗███████╗███████╗██╗ ██████╗ ███╗ ██╗
468
- ████╗ ████║██║██╔════╝██╔════╝██║██╔═══██╗████╗ ██║
469
- ██╔████╔██║██║███████╗███████╗██║██║ ██║██╔██╗ ██║
470
- ██║╚██╔╝██║██║╚════██║╚════██║██║██║ ██║██║╚██╗██║
471
- ██║ ╚═╝ ██║██║███████║███████║██║╚██████╔╝██║ ╚████║
472
- ╚═╝ ╚═╝╚═╝╚══════╝╚══════╝╚═╝ ╚═════╝ ╚═╝ ╚═══╝
473
-
474
- Validator CLI v${VERSION}
475
- `.trim();
476
-
477
- console.log(header);
478
- console.log('\nUsage: aether-cli <command> [options]\n');
466
+ console.log(BANNERS.main);
467
+ console.log(`${C.bright}Validator CLI v${VERSION}${C.reset}\n`);
468
+ console.log(`Usage: aether <command> [options]\n`);
479
469
  console.log('Commands:');
480
470
  Object.entries(COMMANDS).forEach(([cmd, info]) => {
481
- console.log(` ${cmd.padEnd(18)} ${info.description}`);
471
+ console.log(` ${C.cyan}${cmd.padEnd(18)}${C.reset} ${info.description}`);
482
472
  });
483
473
  console.log('\nExamples:');
484
- console.log(' aether-cli doctor # Check system requirements');
485
- console.log(' aether-cli init # Start onboarding wizard');
486
- console.log(' aether-cli monitor # Real-time validator dashboard');
487
- console.log(' aether-cli validator start # Start validator node');
488
- console.log(' aether-cli validator status # Check validator status');
489
- console.log(' aether-cli wallet balance # Query AETH balance');
490
- console.log(' aether-cli network # Network status, peers, slot info');
491
- console.log(' aether-cli network --peers # Detailed peer list');
492
- console.log(' aether-cli tx history # Show transaction history');
493
- console.log(' aether-cli price # AETH/USD price check');
494
- console.log(' aether-cli --version # Show version');
495
- console.log('\nDocumentation: https://github.com/jelly-legs-ai/Jelly-legs-unsteady-workshop');
496
- console.log('Spec: docs/MINING_VALIDATOR_TOOLS.md\n');
474
+ console.log(` ${C.cyan}aether doctor${C.reset} # Check system requirements`);
475
+ console.log(` ${C.cyan}aether init${C.reset} # Start onboarding wizard`);
476
+ console.log(` ${C.cyan}aether monitor${C.reset} # Real-time validator dashboard`);
477
+ console.log(` ${C.cyan}aether validator start${C.reset} # Start validator node`);
478
+ console.log(` ${C.cyan}aether validator status${C.reset} # Check validator status`);
479
+ console.log(` ${C.cyan}aether wallet balance${C.reset} # Query AETH balance`);
480
+ console.log(` ${C.cyan}aether network${C.reset} # Network status, peers, slot info`);
481
+ console.log(` ${C.cyan}aether network --peers${C.reset} # Detailed peer list`);
482
+ console.log(` ${C.cyan}aether tx history${C.reset} # Show transaction history`);
483
+ console.log(` ${C.cyan}aether price${C.reset} # AETH/USD price check`);
484
+ console.log(` ${C.cyan}aether --version${C.reset} # Show version`);
485
+ console.log(`\n${C.dim}Documentation: https://github.com/jelly-legs-ai/Jelly-legs-unsteady-workshop${C.reset}`);
486
+ console.log(`${C.dim}Spec: docs/MINING_VALIDATOR_TOOLS.md\n`);
497
487
  }
498
488
 
499
489
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "aether-hub",
3
- "version": "1.2.8",
3
+ "version": "1.3.0",
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": {
@@ -9,7 +9,9 @@
9
9
  },
10
10
  "files": [
11
11
  "index.js",
12
+ "theme.js",
12
13
  "commands/",
14
+ "sdk/",
13
15
  "test/",
14
16
  "README.md",
15
17
  "LICENSE"
package/sdk/README.md ADDED
@@ -0,0 +1,210 @@
1
+ # @jellylegsai/aether-sdk
2
+
3
+ Official Aether Blockchain SDK for Node.js. Every function makes **REAL HTTP RPC calls** to the Aether blockchain at `http://127.0.0.1:8899`. No stubs, no mocks.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @jellylegsai/aether-sdk
9
+ ```
10
+
11
+ Or use locally from the `sdk/` folder in this repo:
12
+
13
+ ```javascript
14
+ const aether = require('./sdk');
15
+ ```
16
+
17
+ ## Quick Start
18
+
19
+ ```javascript
20
+ const aether = require('@jellylegsai/aether-sdk');
21
+
22
+ // Get current slot
23
+ const slot = await aether.getSlot();
24
+ console.log('Current slot:', slot);
25
+
26
+ // Get account balance
27
+ const balance = await aether.getBalance('ATH...');
28
+ console.log('Balance:', balance);
29
+
30
+ // Use custom RPC endpoint
31
+ const client = new aether.AetherClient({ rpcUrl: 'http://127.0.0.1:8899' });
32
+ const epoch = await client.getEpochInfo();
33
+ ```
34
+
35
+ ## SDK Architecture
36
+
37
+ - **`AetherClient`** — Full-featured blockchain client class. All methods make real HTTP calls.
38
+ - **Convenience functions** — Top-level exports for one-off queries using the default RPC.
39
+ - **Low-level RPC helpers** — `rpcGet` / `rpcPost` for custom requests.
40
+
41
+ Default RPC: `http://127.0.0.1:8899` (override via `AETHER_RPC` env or constructor option).
42
+
43
+ ## AetherClient
44
+
45
+ ```javascript
46
+ const aether = require('@jellylegsai/aether-sdk');
47
+
48
+ const client = new aether.AetherClient({
49
+ rpcUrl: 'http://127.0.0.1:8899', // default
50
+ timeoutMs: 10000, // default: 10s
51
+ });
52
+ ```
53
+
54
+ ## API Reference
55
+
56
+ ### Chain Queries
57
+
58
+ | Method | Returns | RPC Endpoint |
59
+ |--------|---------|--------------|
60
+ | `getSlot()` | `number` — current slot | `GET /v1/slot` |
61
+ | `getBlockHeight()` | `number` — block height | `GET /v1/blockheight` |
62
+ | `getEpochInfo()` | `object` — epoch + slot info | `GET /v1/epoch` |
63
+ | `getAccountInfo(address)` | `object` — lamports, owner, data | `GET /v1/account/:address` |
64
+ | `getBalance(address)` | `number` — lamports | `GET /v1/account/:address` |
65
+ | `getTransaction(signature)` | `object` — tx details | `GET /v1/transaction/:sig` |
66
+ | `getRecentTransactions(address, limit?)` | `array` — recent txs | `GET /v1/transactions/:address` |
67
+ | `getTokenAccounts(address)` | `array` — SPL token accounts | `GET /v1/tokens/:address` |
68
+ | `getStakeAccounts(address)` | `array` — stake accounts | `GET /v1/stake-accounts/:address` |
69
+ | `getStakePositions(address)` | `array` — delegations | `GET /v1/stake/:address` |
70
+ | `getRewards(address)` | `object` — staking rewards | `GET /v1/rewards/:address` |
71
+ | `getValidators()` | `array` — validator list | `GET /v1/validators` |
72
+ | `getValidatorAPY(validatorAddr)` | `object` — APY data | `GET /v1/validator/:addr/apy` |
73
+ | `getTPS()` | `number` — TPS | `GET /v1/tps` |
74
+ | `getSupply()` | `object` — total/circulating/non-circulating | `GET /v1/supply` |
75
+ | `getFees()` | `object` — fee estimates | `GET /v1/fees` |
76
+ | `getSlotProduction()` | `object` — slot production | `POST /v1/slot_production` |
77
+ | `getClusterPeers()` | `array` — peer list | `GET /v1/peers` |
78
+ | `getHealth()` | `string` — "ok" if healthy | `GET /v1/health` |
79
+ | `getVersion()` | `object` — node version | `GET /v1/version` |
80
+
81
+ ### Blockhash (required for signing)
82
+
83
+ | Method | Returns | RPC Endpoint |
84
+ |--------|---------|--------------|
85
+ | `getRecentBlockhash()` | `{ blockhash, lastValidBlockHeight }` | `GET /v1/recent-blockhash` |
86
+
87
+ ### Transaction Submission
88
+
89
+ | Method | Returns | RPC Endpoint |
90
+ |--------|---------|--------------|
91
+ | `sendTransaction(tx)` | `object` — receipt | `POST /v1/transaction` |
92
+
93
+ ### Transaction Builders (build + submit)
94
+
95
+ | Method | Description |
96
+ |--------|-------------|
97
+ | `transfer({ from, to, amount, nonce, signFn })` | Build + send a Transfer TX |
98
+ | `stake({ staker, validator, amount, signFn })` | Build + send a Stake TX |
99
+ | `unstake({ stakeAccount, amount, signFn })` | Build + send an Unstake TX |
100
+ | `claimRewards({ stakeAccount, signFn })` | Build + send a ClaimRewards TX |
101
+ | `createNFT({ creator, metadataUrl, royalties, signFn })` | Build + send a CreateNFT TX |
102
+ | `transferNFT({ from, nftId, to, signFn })` | Build + send a TransferNFT TX |
103
+ | `updateMetadata({ creator, nftId, metadataUrl, signFn })` | Build + send an UpdateMetadata TX |
104
+
105
+ Each builder fetches a fresh `blockhash` + current `slot` from the chain, then submits the signed transaction via `sendTransaction()`. All steps are real RPC calls.
106
+
107
+ ## Convenience Functions
108
+
109
+ ```javascript
110
+ // All of these use the default RPC (http://127.0.0.1:8899)
111
+ const slot = await aether.getSlot();
112
+ const balance = await aether.getBalance('ATH...');
113
+ const epoch = await aether.getEpoch();
114
+ const tps = await aether.getTPS();
115
+ const supply = await aether.getSupply();
116
+ const fees = await aether.getFees();
117
+ const validators = await aether.getValidators();
118
+ const peers = await aether.getPeers();
119
+ const health = await aether.getHealth();
120
+ const { blockhash } = await aether.getRecentBlockhash();
121
+ const tx = await aether.getTransaction('sig...');
122
+ const txs = await aether.getRecentTransactions('ATH...', 20);
123
+ const stakePos = await aether.getStakePositions('ATH...');
124
+ const rewards = await aether.getRewards('ATH...');
125
+ const tokenAccts = await aether.getTokenAccounts('ATH...');
126
+ const stakeAccts = await aether.getStakeAccounts('ATH...');
127
+ const apy = await aether.getValidatorAPY('validatorAddr');
128
+ const pingResult = await aether.ping(); // { ok, latency, rpc }
129
+ ```
130
+
131
+ ## Utilities
132
+
133
+ | Function | Description |
134
+ |----------|-------------|
135
+ | `createClient(options)` | Factory: create an `AetherClient` instance |
136
+ | `ping(rpcUrl?)` | Ping RPC, returns `{ ok, latency, rpc }` |
137
+ | `rpcGet(rpcUrl, path, timeout?)` | Low-level GET |
138
+ | `rpcPost(rpcUrl, path, body, timeout?)` | Low-level POST |
139
+ | `DEFAULT_RPC_URL` | `"http://127.0.0.1:8899"` |
140
+ | `DEFAULT_TIMEOUT_MS` | `10000` |
141
+
142
+ ## CLI Integration
143
+
144
+ The SDK is wired into these CLI commands in `aether-cli`:
145
+
146
+ | CLI Command | SDK Method Used |
147
+ |-------------|----------------|
148
+ | `aether status` | `getEpochInfo`, `getSupply`, `getSlot`, `getBlockHeight`, `getClusterPeers`, `getVersion`, `getStakePositions`, `getRewards` |
149
+ | `aether network` | `getSlot`, `getBlockHeight`, `getClusterPeers`, `getValidators`, `getEpochInfo`, `getSupply`, `getTPS` |
150
+ | `aether blockhash` | `getRecentBlockhash` |
151
+ | `aether fees` | `getFees`, `getRecentBlockhash` |
152
+ | `aether tps` | `getTPS`, `getSlot` |
153
+ | `aether account` | `getAccountInfo`, `getBalance`, `getRecentTransactions`, `getStakePositions`, `getTokenAccounts`, `getStakeAccounts` |
154
+
155
+ ## Configuration
156
+
157
+ ```bash
158
+ # Environment variable
159
+ export AETHER_RPC=http://127.0.0.1:8899
160
+
161
+ # Or per-call
162
+ const client = new aether.AetherClient({ rpcUrl: 'http://custom:8899' });
163
+ ```
164
+
165
+ ## Example: Full Dashboard
166
+
167
+ ```javascript
168
+ const aether = require('@jellylegsai/aether-sdk');
169
+
170
+ async function dashboard() {
171
+ const [slot, blockHeight, tps, supply, { blockhash }] = await Promise.all([
172
+ aether.getSlot(),
173
+ aether.getBlockHeight(),
174
+ aether.getTPS(),
175
+ aether.getSupply(),
176
+ aether.getRecentBlockhash(),
177
+ ]);
178
+
179
+ console.log('=== Aether Network Dashboard ===');
180
+ console.log(`Slot: ${slot}`);
181
+ console.log(`Block: ${blockHeight}`);
182
+ console.log(`TPS: ${tps}`);
183
+ console.log(`Total Supply: ${supply.total}`);
184
+ console.log(`Blockhash: ${blockhash}`);
185
+ }
186
+
187
+ dashboard();
188
+ ```
189
+
190
+ ## Example: Check Staking Rewards
191
+
192
+ ```javascript
193
+ const aether = require('@jellylegsai/aether-sdk');
194
+
195
+ async function checkRewards(walletAddress) {
196
+ const [stakePositions, rewards] = await Promise.all([
197
+ aether.getStakePositions(walletAddress),
198
+ aether.getRewards(walletAddress),
199
+ ]);
200
+
201
+ console.log(`Stake positions: ${stakePositions.length}`);
202
+ console.log(`Total rewards: ${rewards.total || rewards.amount} lamports`);
203
+ }
204
+
205
+ checkRewards('ATH...');
206
+ ```
207
+
208
+ ## License
209
+
210
+ MIT © Jelly-legs AI Team