@jellylegsai/aether-cli 1.8.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/LICENSE +21 -0
- package/README.md +110 -0
- package/aether-cli-1.0.0.tgz +0 -0
- package/aether-cli-1.8.0.tgz +0 -0
- package/aether-hub-1.0.5.tgz +0 -0
- package/aether-hub-1.1.8.tgz +0 -0
- package/aether-hub-1.2.1.tgz +0 -0
- package/commands/account.js +280 -0
- package/commands/apy.js +499 -0
- package/commands/balance.js +241 -0
- package/commands/blockhash.js +181 -0
- package/commands/broadcast.js +387 -0
- package/commands/claim.js +490 -0
- package/commands/config.js +851 -0
- package/commands/delegations.js +582 -0
- package/commands/doctor.js +769 -0
- package/commands/emergency.js +667 -0
- package/commands/epoch.js +275 -0
- package/commands/fees.js +276 -0
- package/commands/index.js +78 -0
- package/commands/info.js +495 -0
- package/commands/init.js +816 -0
- package/commands/install.js +666 -0
- package/commands/kyc.js +272 -0
- package/commands/logs.js +315 -0
- package/commands/monitor.js +431 -0
- package/commands/multisig.js +701 -0
- package/commands/network.js +429 -0
- package/commands/nft.js +857 -0
- package/commands/ping.js +266 -0
- package/commands/price.js +253 -0
- package/commands/rewards.js +931 -0
- package/commands/sdk-test.js +477 -0
- package/commands/sdk.js +656 -0
- package/commands/slot.js +155 -0
- package/commands/snapshot.js +470 -0
- package/commands/stake-info.js +139 -0
- package/commands/stake-positions.js +205 -0
- package/commands/stake.js +516 -0
- package/commands/stats.js +396 -0
- package/commands/status.js +327 -0
- package/commands/supply.js +391 -0
- package/commands/tps.js +238 -0
- package/commands/transfer.js +495 -0
- package/commands/tx-history.js +346 -0
- package/commands/unstake.js +597 -0
- package/commands/validator-info.js +657 -0
- package/commands/validator-register.js +593 -0
- package/commands/validator-start.js +323 -0
- package/commands/validator-status.js +227 -0
- package/commands/validators.js +626 -0
- package/commands/wallet.js +1570 -0
- package/index.js +593 -0
- package/lib/errors.js +398 -0
- package/package.json +76 -0
- package/sdk/README.md +210 -0
- package/sdk/index.js +1639 -0
- package/sdk/package.json +34 -0
- package/sdk/rpc.js +254 -0
- package/sdk/test.js +85 -0
- package/test/doctor.test.js +76 -0
- package/validator-identity.json +4 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Jelly-legs AI Team
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
# aether-cli
|
|
2
|
+
|
|
3
|
+
AeTHer Validator Command Line Interface for system validation, onboarding, and node management.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
# Install globally via npm
|
|
9
|
+
npm install -g aether-cli
|
|
10
|
+
|
|
11
|
+
# Or install from repo
|
|
12
|
+
git clone https://github.com/jelly-legs-ai/Jelly-legs-unsteady-workshop.git
|
|
13
|
+
cd Jelly-legs-unsteady-workshop/aether-cli
|
|
14
|
+
npm install
|
|
15
|
+
npm link
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Quick Start
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
# Check system requirements
|
|
22
|
+
aether-cli doctor
|
|
23
|
+
|
|
24
|
+
# Start onboarding wizard
|
|
25
|
+
aether-cli init
|
|
26
|
+
|
|
27
|
+
# Generate KYC link
|
|
28
|
+
aether-cli kyc generate
|
|
29
|
+
|
|
30
|
+
# Manage validator
|
|
31
|
+
aether-cli validator start
|
|
32
|
+
aether-cli validator status
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Commands
|
|
36
|
+
|
|
37
|
+
| Command | Description |
|
|
38
|
+
|---------|-------------|
|
|
39
|
+
| `aether-cli doctor` | Run system requirements checks (CPU/RAM/Disk/Network/Firewall) |
|
|
40
|
+
| `aether-cli init` | Start onboarding wizard |
|
|
41
|
+
| `aether-cli kyc generate` | Generate pre-filled KYC link with pubkey, node ID, signature |
|
|
42
|
+
| `aether-cli validator start` | Start validator node |
|
|
43
|
+
| `aether-cli validator stop` | Stop validator node |
|
|
44
|
+
| `aether-cli validator status` | Check validator status |
|
|
45
|
+
| `aether-cli help` | Show help message |
|
|
46
|
+
| `aether-cli --version` | Show version number |
|
|
47
|
+
|
|
48
|
+
## System Requirements
|
|
49
|
+
|
|
50
|
+
The `doctor` command validates:
|
|
51
|
+
|
|
52
|
+
- **CPU**: 8+ cores (physical)
|
|
53
|
+
- **RAM**: 32GB+ total, 28GB+ available
|
|
54
|
+
- **Disk**: 512GB+ SSD with 340GB+ free
|
|
55
|
+
- **Network**: 100Mbps+ connection
|
|
56
|
+
- **Firewall**: Ports 3030 (P2P), 8899 (RPC), 22 (SSH) accessible
|
|
57
|
+
|
|
58
|
+
## Example Output
|
|
59
|
+
|
|
60
|
+
```
|
|
61
|
+
$ aether-cli doctor
|
|
62
|
+
|
|
63
|
+
███╗ ███╗██╗███████╗███████╗██╗ ██████╗ ███╗ ██╗
|
|
64
|
+
████╗ ████║██║██╔════╝██╔════╝██║██╔═══██╗████╗ ██║
|
|
65
|
+
...
|
|
66
|
+
|
|
67
|
+
Validator System Check
|
|
68
|
+
v1.0.0
|
|
69
|
+
2026-03-24
|
|
70
|
+
|
|
71
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
72
|
+
|
|
73
|
+
Running system checks...
|
|
74
|
+
|
|
75
|
+
CPU
|
|
76
|
+
Model: Intel Xeon E5-2680 v4
|
|
77
|
+
Cores: 16 (8 physical)
|
|
78
|
+
Frequency: 2.4 GHz
|
|
79
|
+
✅ PASS (required: 4+ cores minimum)
|
|
80
|
+
|
|
81
|
+
Memory
|
|
82
|
+
Total: 32 GB DDR4
|
|
83
|
+
Available: 28 GB
|
|
84
|
+
✅ PASS (required: 8 GB minimum)
|
|
85
|
+
|
|
86
|
+
...
|
|
87
|
+
|
|
88
|
+
SUMMARY: All checks passed! ✅
|
|
89
|
+
|
|
90
|
+
Your system is ready to run an AeTHer validator.
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
## Development
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
# Run doctor command
|
|
97
|
+
npm run doctor
|
|
98
|
+
|
|
99
|
+
# Run tests
|
|
100
|
+
npm test
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
## License
|
|
104
|
+
|
|
105
|
+
MIT - Jelly-legs AI Team
|
|
106
|
+
|
|
107
|
+
## Links
|
|
108
|
+
|
|
109
|
+
- Repository: https://github.com/jelly-legs-ai/Jelly-legs-unsteady-workshop
|
|
110
|
+
- Documentation: docs/MINING_VALIDATOR_TOOLS.md
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,280 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* aether-cli account
|
|
4
|
+
*
|
|
5
|
+
* Query detailed on-chain account data for any address.
|
|
6
|
+
* Shows lamports, owner, executable, rent epoch, and program-owned account keys.
|
|
7
|
+
*
|
|
8
|
+
* Usage:
|
|
9
|
+
* aether account --address <addr> Full account dump
|
|
10
|
+
* aether account --address <addr> --json JSON output for scripting
|
|
11
|
+
* aether account --address <addr> --data Show raw account data as base64/hex
|
|
12
|
+
*
|
|
13
|
+
* Uses @jellylegsai/aether-sdk for real blockchain RPC calls to http://127.0.0.1:8899
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
const path = require('path');
|
|
17
|
+
const bs58 = require('bs58').default;
|
|
18
|
+
|
|
19
|
+
// ANSI colours
|
|
20
|
+
const C = {
|
|
21
|
+
reset: '\x1b[0m',
|
|
22
|
+
bright: '\x1b[1m',
|
|
23
|
+
dim: '\x1b[2m',
|
|
24
|
+
red: '\x1b[31m',
|
|
25
|
+
green: '\x1b[32m',
|
|
26
|
+
yellow: '\x1b[33m',
|
|
27
|
+
cyan: '\x1b[36m',
|
|
28
|
+
magenta: '\x1b[35m',
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
// Import SDK for real blockchain RPC calls
|
|
32
|
+
const sdkPath = path.join(__dirname, '..', 'sdk', 'index.js');
|
|
33
|
+
const aether = require(sdkPath);
|
|
34
|
+
|
|
35
|
+
function getDefaultRpc() {
|
|
36
|
+
return process.env.AETHER_RPC || aether.DEFAULT_RPC_URL || 'http://127.0.0.1:8899';
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function formatAether(lamports) {
|
|
40
|
+
const aeth = lamports / 1e9;
|
|
41
|
+
if (aeth === 0) return '0 AETH';
|
|
42
|
+
return aeth.toFixed(4).replace(/\.?0+$/, '') + ' AETH';
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// ---------------------------------------------------------------------------
|
|
46
|
+
// Parse args
|
|
47
|
+
// ---------------------------------------------------------------------------
|
|
48
|
+
|
|
49
|
+
function parseArgs() {
|
|
50
|
+
return process.argv.slice(2); // [node, account.js, ...]
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function findArg(args, ...flags) {
|
|
54
|
+
for (const flag of flags) {
|
|
55
|
+
const idx = args.indexOf(flag);
|
|
56
|
+
if (idx !== -1 && args[idx + 1] && !args[idx + 1].startsWith('-')) {
|
|
57
|
+
return { value: args[idx + 1], idx };
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
return null;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function parseBoolArg(args, ...flags) {
|
|
64
|
+
return flags.some(f => args.includes(f));
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// ---------------------------------------------------------------------------
|
|
68
|
+
// Format helpers
|
|
69
|
+
// ---------------------------------------------------------------------------
|
|
70
|
+
|
|
71
|
+
function formatPubkey(key) {
|
|
72
|
+
if (!key) return '—';
|
|
73
|
+
if (Array.isArray(key)) {
|
|
74
|
+
// base64-like or raw bytes → treat as public key bytes
|
|
75
|
+
if (key.length === 32) return 'ATH' + bs58.encode(Buffer.from(key.slice(0, 32)));
|
|
76
|
+
return 'ATH' + bs58.encode(Buffer.from(key));
|
|
77
|
+
}
|
|
78
|
+
if (typeof key === 'string') {
|
|
79
|
+
if (key.startsWith('ATH')) return key;
|
|
80
|
+
// Assume base58
|
|
81
|
+
try { return 'ATH' + bs58.encode(bs58.decode(key)); }
|
|
82
|
+
catch { return key.substring(0, 16) + '...'; }
|
|
83
|
+
}
|
|
84
|
+
return String(key).substring(0, 16);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function base64ToHex(b64) {
|
|
88
|
+
try {
|
|
89
|
+
const buf = Buffer.from(b64, 'base64');
|
|
90
|
+
return buf.toString('hex');
|
|
91
|
+
} catch {
|
|
92
|
+
return b64;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function formatData(data) {
|
|
97
|
+
if (!data) return null;
|
|
98
|
+
if (typeof data === 'string') return data;
|
|
99
|
+
if (Array.isArray(data)) {
|
|
100
|
+
// raw bytes → hex
|
|
101
|
+
return Buffer.from(data).toString('hex');
|
|
102
|
+
}
|
|
103
|
+
return JSON.stringify(data);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// ---------------------------------------------------------------------------
|
|
107
|
+
// Main account query
|
|
108
|
+
// ---------------------------------------------------------------------------
|
|
109
|
+
|
|
110
|
+
async function accountCommand() {
|
|
111
|
+
const args = parseArgs();
|
|
112
|
+
|
|
113
|
+
// Parse flags
|
|
114
|
+
const addrArg = findArg(args, '--address', '-a');
|
|
115
|
+
const asJson = parseBoolArg(args, '--json', '-j');
|
|
116
|
+
const showData = parseBoolArg(args, '--data', '-d');
|
|
117
|
+
const rpcArg = findArg(args, '--rpc', '-r');
|
|
118
|
+
const rpcUrl = rpcArg ? rpcArg.value : getDefaultRpc();
|
|
119
|
+
|
|
120
|
+
if (!addrArg) {
|
|
121
|
+
console.log(`\n ${C.red}✗ Missing --address flag.${C.reset}`);
|
|
122
|
+
console.log(`\n ${C.cyan}Usage:${C.reset}`);
|
|
123
|
+
console.log(` ${C.cyan}aether account --address <addr>${C.reset} Show account details`);
|
|
124
|
+
console.log(` ${C.cyan}aether account --address <addr> --json${C.reset} JSON output`);
|
|
125
|
+
console.log(` ${C.cyan}aether account --address <addr> --data${C.reset} Show raw account data`);
|
|
126
|
+
console.log(` ${C.cyan}aether account --address <addr> --rpc <url>${C.reset} Use custom RPC\n`);
|
|
127
|
+
process.exit(1);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
const rawAddress = addrArg.value;
|
|
131
|
+
const address = rawAddress.startsWith('ATH') ? rawAddress : rawAddress;
|
|
132
|
+
const apiAddress = rawAddress.startsWith('ATH') ? rawAddress.slice(3) : rawAddress;
|
|
133
|
+
|
|
134
|
+
if (!asJson) {
|
|
135
|
+
console.log(`\n${C.bright}${C.cyan}── Account Info ──────────────────────────────────────────${C.reset}\n`);
|
|
136
|
+
console.log(` ${C.green}★${C.reset} Address: ${C.bright}${address}${C.reset}`);
|
|
137
|
+
console.log(` ${C.dim} RPC: ${rpcUrl}${C.reset}`);
|
|
138
|
+
console.log();
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
try {
|
|
142
|
+
// Use SDK for real blockchain RPC call
|
|
143
|
+
const client = new aether.AetherClient({ rpcUrl: rpcUrl });
|
|
144
|
+
const account = await client.getAccountInfo(apiAddress);
|
|
145
|
+
|
|
146
|
+
if (!account || account.error) {
|
|
147
|
+
if (asJson) {
|
|
148
|
+
console.log(JSON.stringify({ address, error: account?.error || 'Account not found' }, null, 2));
|
|
149
|
+
} else {
|
|
150
|
+
console.log(` ${C.yellow}⚠ Account not found on chain or RPC error.${C.reset}`);
|
|
151
|
+
console.log(` ${C.dim} This is normal for addresses with no on-chain account.${C.reset}`);
|
|
152
|
+
console.log(` ${C.dim} RPC response: ${JSON.stringify(account?.error || account)}${C.reset}\n`);
|
|
153
|
+
}
|
|
154
|
+
process.exit(1);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
const lamports = account.lamports || account.lamports === 0 ? account.lamports : 0;
|
|
158
|
+
const owner = account.owner || null;
|
|
159
|
+
const executable = account.executable || false;
|
|
160
|
+
const rentEpoch = account.rent_epoch;
|
|
161
|
+
const data = account.data;
|
|
162
|
+
const dataLen = data ? (Array.isArray(data) ? data.length : typeof data === 'string' ? data.length : 0) : 0;
|
|
163
|
+
|
|
164
|
+
if (asJson) {
|
|
165
|
+
let ownerStr = null;
|
|
166
|
+
if (owner) {
|
|
167
|
+
if (Array.isArray(owner)) {
|
|
168
|
+
ownerStr = 'ATH' + bs58.encode(Buffer.from(owner.slice(0, 32)));
|
|
169
|
+
} else if (typeof owner === 'string') {
|
|
170
|
+
ownerStr = owner.startsWith('ATH') ? owner : 'ATH' + bs58.encode(bs58.decode(owner));
|
|
171
|
+
} else {
|
|
172
|
+
ownerStr = String(owner);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
console.log(JSON.stringify({
|
|
177
|
+
address,
|
|
178
|
+
rpc: rpcUrl,
|
|
179
|
+
lamports,
|
|
180
|
+
lamports_formatted: formatAether(lamports),
|
|
181
|
+
owner: ownerStr,
|
|
182
|
+
executable,
|
|
183
|
+
rent_epoch: rentEpoch,
|
|
184
|
+
data_size: dataLen,
|
|
185
|
+
data: showData ? formatData(data) : null,
|
|
186
|
+
fetched_at: new Date().toISOString(),
|
|
187
|
+
}, null, 2));
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
// Human-readable output
|
|
192
|
+
console.log(` ${C.green}✓${C.reset} Found on chain`);
|
|
193
|
+
console.log(` ${C.dim}────────────────────────────────────────${C.reset}`);
|
|
194
|
+
console.log(` ${C.dim} Balance:${C.reset} ${C.bright}${formatAether(lamports)}${C.reset} (${lamports.toLocaleString()} lamports)`);
|
|
195
|
+
|
|
196
|
+
if (owner) {
|
|
197
|
+
let ownerStr;
|
|
198
|
+
if (Array.isArray(owner)) {
|
|
199
|
+
ownerStr = 'ATH' + bs58.encode(Buffer.from(owner.slice(0, 32)));
|
|
200
|
+
} else if (typeof owner === 'string') {
|
|
201
|
+
ownerStr = owner.startsWith('ATH') ? owner : 'ATH' + bs58.encode(bs58.decode(owner));
|
|
202
|
+
} else {
|
|
203
|
+
ownerStr = String(owner);
|
|
204
|
+
}
|
|
205
|
+
console.log(` ${C.dim} Owner:${C.reset} ${C.cyan}${ownerStr}${C.reset}`);
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
console.log(` ${C.dim} Executable:${C.reset} ${C.bright}${(executable ? 'Yes' : 'No')}${C.reset}`);
|
|
209
|
+
if (rentEpoch !== undefined) {
|
|
210
|
+
console.log(` ${C.dim} Rent epoch:${C.reset} ${rentEpoch}`);
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
if (dataLen > 0) {
|
|
214
|
+
console.log(` ${C.dim} Data size:${C.reset} ${C.bright}${dataLen} bytes${C.reset}`);
|
|
215
|
+
} else {
|
|
216
|
+
console.log(` ${C.dim} Data size:${C.reset} 0 bytes`);
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
if (showData && data) {
|
|
220
|
+
console.log();
|
|
221
|
+
console.log(` ${C.dim} Raw data (hex):${C.reset}`);
|
|
222
|
+
const hex = formatData(data);
|
|
223
|
+
// Pretty-print in 32-byte chunks
|
|
224
|
+
const chunks = hex.match(/.{1,64}/g) || [];
|
|
225
|
+
for (let i = 0; i < chunks.length; i++) {
|
|
226
|
+
const offset = (i * 32).toString(16).padStart(8, '0');
|
|
227
|
+
console.log(` ${C.dim}${offset}:${C.reset} ${chunks[i]}`);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
console.log();
|
|
232
|
+
console.log(` ${C.dim}────────────────────────────────────────${C.reset}`);
|
|
233
|
+
|
|
234
|
+
// Additional context: try to determine account type
|
|
235
|
+
let accountType = 'Unknown';
|
|
236
|
+
if (owner) {
|
|
237
|
+
const ownerStr = Array.isArray(owner)
|
|
238
|
+
? bs58.encode(Buffer.from(owner.slice(0, 32)))
|
|
239
|
+
: (typeof owner === 'string' && !owner.startsWith('ATH') ? owner : '');
|
|
240
|
+
// Known program IDs (these are common Aether program identifiers)
|
|
241
|
+
const knownPrograms = {
|
|
242
|
+
'STAKE': 'Stake Program',
|
|
243
|
+
'SYSTEM': 'System Program',
|
|
244
|
+
'VOTE': 'Vote Program',
|
|
245
|
+
'TOKEN': 'Token Program',
|
|
246
|
+
'MEMO': 'Memo Program',
|
|
247
|
+
};
|
|
248
|
+
const prog = knownPrograms[ownerStr.toUpperCase()];
|
|
249
|
+
if (prog) accountType = prog;
|
|
250
|
+
else if (executable) accountType = 'Executable Program';
|
|
251
|
+
else if (dataLen === 0) accountType = 'Empty Account (no data)';
|
|
252
|
+
else accountType = 'Data Account';
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
console.log(` ${C.dim} Account type:${C.reset} ${C.bright}${accountType}${C.reset}`);
|
|
256
|
+
console.log();
|
|
257
|
+
console.log(` ${C.dim} Fetch via API:${C.reset} GET ${rpcUrl}/v1/account/${apiAddress}`);
|
|
258
|
+
console.log();
|
|
259
|
+
|
|
260
|
+
} catch (err) {
|
|
261
|
+
if (asJson) {
|
|
262
|
+
console.log(JSON.stringify({ address, error: err.message }, null, 2));
|
|
263
|
+
} else {
|
|
264
|
+
console.log(` ${C.red}✗ Failed to fetch account:${C.reset} ${err.message}`);
|
|
265
|
+
console.log(` ${C.dim} Is your validator running? RPC: ${rpcUrl}${C.reset}`);
|
|
266
|
+
console.log(` ${C.dim} Set custom RPC: AETHER_RPC=https://your-rpc-url${C.reset}\n`);
|
|
267
|
+
}
|
|
268
|
+
process.exit(1);
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
// ---------------------------------------------------------------------------
|
|
273
|
+
// Export & run
|
|
274
|
+
// ---------------------------------------------------------------------------
|
|
275
|
+
|
|
276
|
+
module.exports = { accountCommand };
|
|
277
|
+
|
|
278
|
+
if (require.main === module) {
|
|
279
|
+
accountCommand();
|
|
280
|
+
}
|