aether-hub 1.2.6 → 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/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 -508
- 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 +54 -6
- package/package.json +1 -3
package/commands/tps.js
ADDED
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* aether-cli tps
|
|
4
|
+
*
|
|
5
|
+
* Monitor real-time transactions per second (TPS) on the Aether blockchain.
|
|
6
|
+
* Uses @jellylegsai/aether-sdk for real RPC calls to /v1/tps endpoint.
|
|
7
|
+
*
|
|
8
|
+
* Usage:
|
|
9
|
+
* aether tps Show current TPS
|
|
10
|
+
* aether tps --monitor Continuous monitoring (updates every 2s)
|
|
11
|
+
* aether tps --interval <sec> Custom interval for monitoring (default: 2)
|
|
12
|
+
* aether tps --json JSON output for scripting
|
|
13
|
+
* aether tps --rpc <url> Custom RPC endpoint
|
|
14
|
+
*
|
|
15
|
+
* Examples:
|
|
16
|
+
* aether tps # Single TPS reading
|
|
17
|
+
* aether tps --monitor # Live monitoring dashboard
|
|
18
|
+
* aether tps --monitor --interval 1 # Update every second
|
|
19
|
+
* aether tps --json # JSON for alerting/monitoring
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
const path = require('path');
|
|
23
|
+
const sdkPath = path.join(__dirname, '..', 'sdk', 'index.js');
|
|
24
|
+
const aether = require(sdkPath);
|
|
25
|
+
|
|
26
|
+
// ANSI colours
|
|
27
|
+
const C = {
|
|
28
|
+
reset: '\x1b[0m',
|
|
29
|
+
bright: '\x1b[1m',
|
|
30
|
+
dim: '\x1b[2m',
|
|
31
|
+
red: '\x1b[31m',
|
|
32
|
+
green: '\x1b[32m',
|
|
33
|
+
yellow: '\x1b[33m',
|
|
34
|
+
cyan: '\x1b[36m',
|
|
35
|
+
magenta: '\x1b[35m',
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
const CLI_VERSION = '1.0.0';
|
|
39
|
+
|
|
40
|
+
// ---------------------------------------------------------------------------
|
|
41
|
+
// Helpers
|
|
42
|
+
// ---------------------------------------------------------------------------
|
|
43
|
+
|
|
44
|
+
function getDefaultRpc() {
|
|
45
|
+
return process.env.AETHER_RPC || aether.DEFAULT_RPC_URL || 'http://127.0.0.1:8899';
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function createClient(rpc) {
|
|
49
|
+
return new aether.AetherClient({ rpcUrl: rpc });
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function tpsColor(tps) {
|
|
53
|
+
if (tps === null || tps === undefined) return C.red;
|
|
54
|
+
if (tps >= 1000) return C.green;
|
|
55
|
+
if (tps >= 100) return C.cyan;
|
|
56
|
+
if (tps >= 10) return C.yellow;
|
|
57
|
+
return C.red;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function tpsLabel(tps) {
|
|
61
|
+
if (tps === null || tps === undefined) return '✗ unreachable';
|
|
62
|
+
if (tps >= 1000) return `● ${tps.toLocaleString()} TPS (excellent)`;
|
|
63
|
+
if (tps >= 100) return `● ${tps.toLocaleString()} TPS (good)`;
|
|
64
|
+
if (tps >= 10) return `○ ${tps.toLocaleString()} TPS (fair)`;
|
|
65
|
+
return `○ ${tps.toLocaleString()} TPS (low)`;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// ---------------------------------------------------------------------------
|
|
69
|
+
// Single TPS reading
|
|
70
|
+
// ---------------------------------------------------------------------------
|
|
71
|
+
|
|
72
|
+
async function getTpsOnce(rpcUrl) {
|
|
73
|
+
const client = createClient(rpcUrl);
|
|
74
|
+
const start = Date.now();
|
|
75
|
+
let tps = null;
|
|
76
|
+
let error = null;
|
|
77
|
+
let latencyMs = null;
|
|
78
|
+
|
|
79
|
+
try {
|
|
80
|
+
// Real RPC call: GET /v1/tps
|
|
81
|
+
tps = await client.getTPS();
|
|
82
|
+
latencyMs = Date.now() - start;
|
|
83
|
+
} catch (err) {
|
|
84
|
+
latencyMs = Date.now() - start;
|
|
85
|
+
error = err.message;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
return { tps, error, latencyMs, rpcUrl, timestamp: new Date() };
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// ---------------------------------------------------------------------------
|
|
92
|
+
// Continuous monitoring
|
|
93
|
+
// ---------------------------------------------------------------------------
|
|
94
|
+
|
|
95
|
+
async function monitorTps(rpcUrl, intervalSec) {
|
|
96
|
+
console.log(`\n${C.bright}${C.cyan}── Aether TPS Monitor ───────────────────────────────────${C.reset}`);
|
|
97
|
+
console.log(` ${C.dim}RPC: ${rpcUrl}${C.reset}`);
|
|
98
|
+
console.log(` ${C.dim}Interval: ${intervalSec}s${C.reset}`);
|
|
99
|
+
console.log(` ${C.dim}Press Ctrl+C to stop${C.reset}\n`);
|
|
100
|
+
|
|
101
|
+
const history = [];
|
|
102
|
+
const maxHistory = 20;
|
|
103
|
+
|
|
104
|
+
process.on('SIGINT', () => {
|
|
105
|
+
console.log(`\n${C.dim}Monitoring stopped.${C.reset}`);
|
|
106
|
+
if (history.length > 1) {
|
|
107
|
+
const tpsValues = history.map(h => h.tps).filter(t => t !== null);
|
|
108
|
+
if (tpsValues.length > 0) {
|
|
109
|
+
const avg = Math.round(tpsValues.reduce((a, b) => a + b, 0) / tpsValues.length);
|
|
110
|
+
const min = Math.min(...tpsValues);
|
|
111
|
+
const max = Math.max(...tpsValues);
|
|
112
|
+
console.log(` ${C.bright}Summary:${C.reset} avg=${avg} min=${min} max=${max} samples=${history.length}`);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
console.log();
|
|
116
|
+
process.exit(0);
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
while (true) {
|
|
120
|
+
const result = await getTpsOnce(rpcUrl);
|
|
121
|
+
history.push(result);
|
|
122
|
+
if (history.length > maxHistory) history.shift();
|
|
123
|
+
|
|
124
|
+
// Clear line and print
|
|
125
|
+
process.stdout.write('\x1b[2K\r');
|
|
126
|
+
|
|
127
|
+
const tc = tpsColor(result.tps);
|
|
128
|
+
const barLen = result.tps !== null ? Math.min(30, Math.floor(result.tps / 50)) : 0;
|
|
129
|
+
const bar = tc + '█'.repeat(barLen) + C.dim + '░'.repeat(30 - barLen) + C.reset;
|
|
130
|
+
|
|
131
|
+
const slotInfo = result.tps !== null ? ` ${C.dim}RPC latency: ${result.latencyMs}ms${C.reset}` : '';
|
|
132
|
+
|
|
133
|
+
console.log(` ${tc}${bar}${C.reset} ${tpsLabel(result.tps)}${C.reset}${slotInfo}`);
|
|
134
|
+
|
|
135
|
+
// Show trend
|
|
136
|
+
if (history.length >= 3) {
|
|
137
|
+
const recent = history.slice(-3).map(h => h.tps).filter(t => t !== null);
|
|
138
|
+
if (recent.length >= 2) {
|
|
139
|
+
const trend = recent[recent.length - 1] - recent[0];
|
|
140
|
+
const arrow = trend > 0 ? C.green + '▲' : trend < 0 ? C.red + '▼' : C.dim + '─';
|
|
141
|
+
console.log(` ${C.dim}Trend: ${arrow} ${Math.abs(trend)} TPS${C.reset}`);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
await new Promise(resolve => setTimeout(resolve, intervalSec * 1000));
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// ---------------------------------------------------------------------------
|
|
150
|
+
// Main command
|
|
151
|
+
// ---------------------------------------------------------------------------
|
|
152
|
+
|
|
153
|
+
async function tpsCommand() {
|
|
154
|
+
const args = process.argv.slice(2);
|
|
155
|
+
const asJson = args.includes('--json') || args.includes('-j');
|
|
156
|
+
const isMonitor = args.includes('--monitor') || args.includes('-m');
|
|
157
|
+
const rpcIdx = args.findIndex(a => a === '--rpc' || a === '-r');
|
|
158
|
+
const rpcUrl = rpcIdx !== -1 && args[rpcIdx + 1] ? args[rpcIdx + 1] : getDefaultRpc();
|
|
159
|
+
|
|
160
|
+
const intervalIdx = args.findIndex(a => a === '--interval' || a === '-i');
|
|
161
|
+
const intervalSec = intervalIdx !== -1 && args[intervalIdx + 1]
|
|
162
|
+
? Math.max(1, parseInt(args[intervalIdx + 1], 10) || 2)
|
|
163
|
+
: 2;
|
|
164
|
+
|
|
165
|
+
if (isMonitor) {
|
|
166
|
+
await monitorTps(rpcUrl, intervalSec);
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// Single reading
|
|
171
|
+
const result = await getTpsOnce(rpcUrl);
|
|
172
|
+
|
|
173
|
+
if (asJson) {
|
|
174
|
+
console.log(JSON.stringify({
|
|
175
|
+
rpc: rpcUrl,
|
|
176
|
+
tps: result.tps,
|
|
177
|
+
online: result.tps !== null,
|
|
178
|
+
latency_ms: result.latencyMs,
|
|
179
|
+
error: result.error || null,
|
|
180
|
+
timestamp: result.timestamp.toISOString(),
|
|
181
|
+
cli_version: CLI_VERSION,
|
|
182
|
+
}, null, 2));
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
console.log(`\n${C.bright}${C.cyan}── Aether Network TPS ─────────────────────────────────${C.reset}\n`);
|
|
187
|
+
|
|
188
|
+
const tc = tpsColor(result.tps);
|
|
189
|
+
const barLen = result.tps !== null ? Math.min(40, Math.floor(result.tps / 50)) : 0;
|
|
190
|
+
const bar = tc + '█'.repeat(barLen) + C.dim + '░'.repeat(40 - barLen) + C.reset;
|
|
191
|
+
|
|
192
|
+
console.log(` ${C.dim}RPC:${C.reset} ${rpcUrl}`);
|
|
193
|
+
console.log(` ${C.dim}Latency:${C.reset} ${result.latencyMs}ms`);
|
|
194
|
+
console.log();
|
|
195
|
+
console.log(` ${C.bright}${tc}${tpsLabel(result.tps)}${C.reset}`);
|
|
196
|
+
console.log();
|
|
197
|
+
console.log(` ${bar}`);
|
|
198
|
+
console.log();
|
|
199
|
+
|
|
200
|
+
if (result.error) {
|
|
201
|
+
console.log(` ${C.red}✗ ${result.error}${C.reset}`);
|
|
202
|
+
console.log();
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
// Context info
|
|
206
|
+
if (result.tps !== null) {
|
|
207
|
+
console.log(` ${C.dim}Network Health:${C.reset}`);
|
|
208
|
+
if (result.tps >= 1000) {
|
|
209
|
+
console.log(` ${C.green}● Network is handling high throughput${C.reset}`);
|
|
210
|
+
} else if (result.tps >= 100) {
|
|
211
|
+
console.log(` ${C.cyan}● Network operating normally${C.reset}`);
|
|
212
|
+
} else if (result.tps >= 10) {
|
|
213
|
+
console.log(` ${C.yellow}○ Network has low activity${C.reset}`);
|
|
214
|
+
} else {
|
|
215
|
+
console.log(` ${C.red}○ Network is idle or experiencing issues${C.reset}`);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
console.log();
|
|
220
|
+
console.log(` ${C.dim}Run ${C.cyan}aether tps --monitor${C.reset}${C.dim} for live tracking.${C.reset}\n`);
|
|
221
|
+
|
|
222
|
+
if (result.tps === null) {
|
|
223
|
+
process.exit(1);
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
// ---------------------------------------------------------------------------
|
|
228
|
+
// Entry point
|
|
229
|
+
// ---------------------------------------------------------------------------
|
|
230
|
+
|
|
231
|
+
module.exports = { tpsCommand };
|
|
232
|
+
|
|
233
|
+
if (require.main === module) {
|
|
234
|
+
tpsCommand().catch(err => {
|
|
235
|
+
console.error(`\n${C.red}TPS command failed:${C.reset} ${err.message}\n`);
|
|
236
|
+
process.exit(1);
|
|
237
|
+
});
|
|
238
|
+
}
|