aether-hub 1.2.7 → 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.
- package/commands/account.js +280 -280
- package/commands/apy.js +480 -480
- package/commands/balance.js +276 -276
- package/commands/claim.js +292 -292
- package/commands/delegations.js +45 -95
- package/commands/emergency.js +14 -4
- package/commands/epoch.js +275 -275
- package/commands/fees.js +276 -276
- package/commands/info.js +495 -495
- package/commands/monitor.js +431 -431
- package/commands/multisig.js +726 -726
- package/commands/network.js +429 -429
- package/commands/ping.js +266 -266
- package/commands/sdk-test.js +477 -477
- package/commands/sdk.js +537 -537
- package/commands/slot.js +155 -0
- package/commands/snapshot.js +509 -509
- package/commands/stake-positions.js +31 -46
- package/commands/stats.js +418 -418
- package/commands/status.js +326 -326
- package/commands/supply.js +3 -1
- package/commands/tps.js +238 -238
- package/commands/tx-history.js +346 -462
- package/commands/wallet.js +3 -0
- package/index.js +11 -2
- package/package.json +1 -1
package/commands/balance.js
CHANGED
|
@@ -1,276 +1,276 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* aether-cli balance
|
|
4
|
-
*
|
|
5
|
-
* Query account balance from the Aether blockchain — real HTTP RPC calls,
|
|
6
|
-
* real data. No stubs, no mocks.
|
|
7
|
-
*
|
|
8
|
-
* Usage:
|
|
9
|
-
* aether balance <address> Query balance for an address
|
|
10
|
-
* aether balance Query default wallet balance
|
|
11
|
-
* aether balance --json JSON output for scripting
|
|
12
|
-
* aether balance --rpc <url> Query a specific RPC endpoint
|
|
13
|
-
* aether balance --lamports Show balance in lamports (not AETH)
|
|
14
|
-
*
|
|
15
|
-
* Requires AETHER_RPC env var (default: http://127.0.0.1:8899)
|
|
16
|
-
* SDK: @jellylegsai/aether-sdk — makes REAL HTTP RPC calls to the chain
|
|
17
|
-
*/
|
|
18
|
-
|
|
19
|
-
const os = require('os');
|
|
20
|
-
const path = require('path');
|
|
21
|
-
|
|
22
|
-
// ANSI colours
|
|
23
|
-
const C = {
|
|
24
|
-
reset: '\x1b[0m',
|
|
25
|
-
bright: '\x1b[1m',
|
|
26
|
-
dim: '\x1b[2m',
|
|
27
|
-
red: '\x1b[31m',
|
|
28
|
-
green: '\x1b[32m',
|
|
29
|
-
yellow: '\x1b[33m',
|
|
30
|
-
cyan: '\x1b[36m',
|
|
31
|
-
magenta: '\x1b[35m',
|
|
32
|
-
};
|
|
33
|
-
|
|
34
|
-
// Import SDK — REAL blockchain RPC calls to http://127.0.0.1:8899
|
|
35
|
-
const sdkPath = path.join(__dirname, '..', 'sdk', 'index.js');
|
|
36
|
-
const aether = require(sdkPath);
|
|
37
|
-
|
|
38
|
-
const DEFAULT_RPC = process.env.AETHER_RPC || aether.DEFAULT_RPC_URL || 'http://127.0.0.1:8899';
|
|
39
|
-
const CLI_VERSION = '1.0.0';
|
|
40
|
-
|
|
41
|
-
// ---------------------------------------------------------------------------
|
|
42
|
-
// Helpers
|
|
43
|
-
// ---------------------------------------------------------------------------
|
|
44
|
-
|
|
45
|
-
function getDefaultRpc() {
|
|
46
|
-
return process.env.AETHER_RPC || aether.DEFAULT_RPC_URL || 'http://127.0.0.1:8899';
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
function createClient(rpc) {
|
|
50
|
-
return new aether.AetherClient({ rpcUrl: rpc });
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
function lamportsToAeth(lamports) {
|
|
54
|
-
return (Number(lamports) / 1e9).toFixed(6);
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
function loadConfig() {
|
|
58
|
-
const fs = require('fs');
|
|
59
|
-
const aetherDir = path.join(os.homedir(), '.aether');
|
|
60
|
-
const cfgPath = path.join(aetherDir, 'config.json');
|
|
61
|
-
if (!fs.existsSync(cfgPath)) return { defaultWallet: null };
|
|
62
|
-
try { return JSON.parse(fs.readFileSync(cfgPath, 'utf8')); }
|
|
63
|
-
catch { return { defaultWallet: null }; }
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
function shortenAddress(addr) {
|
|
67
|
-
if (!addr) return 'unknown';
|
|
68
|
-
if (addr.length <= 10) return addr;
|
|
69
|
-
return `${addr.substring(0, 6)}...${addr.substring(addr.length - 4)}`;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
// ---------------------------------------------------------------------------
|
|
73
|
-
// Argument parsing
|
|
74
|
-
// ---------------------------------------------------------------------------
|
|
75
|
-
|
|
76
|
-
function parseArgs() {
|
|
77
|
-
const args = process.argv.slice(2);
|
|
78
|
-
const options = {
|
|
79
|
-
rpc: getDefaultRpc(),
|
|
80
|
-
address: null,
|
|
81
|
-
asJson: false,
|
|
82
|
-
showLamports: false,
|
|
83
|
-
};
|
|
84
|
-
|
|
85
|
-
for (let i = 0; i < args.length; i++) {
|
|
86
|
-
const arg = args[i];
|
|
87
|
-
if (arg === '--rpc' || arg === '-r') {
|
|
88
|
-
options.rpc = args[++i];
|
|
89
|
-
} else if (arg === '--json' || arg === '-j') {
|
|
90
|
-
options.asJson = true;
|
|
91
|
-
} else if (arg === '--lamports' || arg === '-l') {
|
|
92
|
-
options.showLamports = true;
|
|
93
|
-
} else if (arg === '--help' || arg === '-h') {
|
|
94
|
-
showHelp();
|
|
95
|
-
process.exit(0);
|
|
96
|
-
} else if (!arg.startsWith('-') && !options.address) {
|
|
97
|
-
options.address = arg;
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
// If no address provided, try to load default wallet
|
|
102
|
-
if (!options.address) {
|
|
103
|
-
const config = loadConfig();
|
|
104
|
-
if (config.defaultWallet) {
|
|
105
|
-
options.address = config.defaultWallet;
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
return options;
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
function showHelp() {
|
|
113
|
-
console.log(`
|
|
114
|
-
${C.bright}${C.cyan}aether-cli balance${C.reset} - Query Account Balance
|
|
115
|
-
|
|
116
|
-
${C.bright}Usage:${C.reset}
|
|
117
|
-
aether balance [address] [options]
|
|
118
|
-
|
|
119
|
-
${C.bright}Arguments:${C.reset}
|
|
120
|
-
address Account public key (base58). If omitted, uses default wallet.
|
|
121
|
-
|
|
122
|
-
${C.bright}Options:${C.reset}
|
|
123
|
-
--rpc <url> Query a specific RPC endpoint (default: ${DEFAULT_RPC})
|
|
124
|
-
--json, -j Output raw JSON for scripting
|
|
125
|
-
--lamports, -l Show balance in lamports (not AETH)
|
|
126
|
-
--help, -h Show this help message
|
|
127
|
-
|
|
128
|
-
${C.bright}Description:${C.reset}
|
|
129
|
-
Queries the Aether blockchain for an account's balance.
|
|
130
|
-
Every call makes a REAL HTTP RPC request to the configured
|
|
131
|
-
Aether node — no caching, no stubs, no mocks.
|
|
132
|
-
|
|
133
|
-
RPC Endpoint: GET /v1/account/<address>
|
|
134
|
-
|
|
135
|
-
${C.bright}Examples:${C.reset}
|
|
136
|
-
aether balance # Default wallet
|
|
137
|
-
aether balance 8xPt...3nQ # Specific address
|
|
138
|
-
aether balance --json # JSON output
|
|
139
|
-
aether balance --lamports # Show lamports
|
|
140
|
-
AETHER_RPC=https://my-node:8899 aether balance
|
|
141
|
-
`);
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
// ---------------------------------------------------------------------------
|
|
145
|
-
// Balance query - REAL RPC call via SDK
|
|
146
|
-
// ---------------------------------------------------------------------------
|
|
147
|
-
|
|
148
|
-
async function fetchBalance(rpc, address) {
|
|
149
|
-
const client = createClient(rpc);
|
|
150
|
-
|
|
151
|
-
// Real RPC call: GET /v1/account/<address>
|
|
152
|
-
const account = await client.getAccountInfo(address);
|
|
153
|
-
|
|
154
|
-
return {
|
|
155
|
-
address,
|
|
156
|
-
lamports: account.lamports !== undefined ? account.lamports : 0,
|
|
157
|
-
owner: account.owner || null,
|
|
158
|
-
executable: account.executable || false,
|
|
159
|
-
rentEpoch: account.rent_epoch !== undefined ? account.rent_epoch : null,
|
|
160
|
-
};
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
// ---------------------------------------------------------------------------
|
|
164
|
-
// Output formatters
|
|
165
|
-
// ---------------------------------------------------------------------------
|
|
166
|
-
|
|
167
|
-
function printBalance(data, options) {
|
|
168
|
-
const { address, lamports, owner, executable, rentEpoch } = data;
|
|
169
|
-
const { showLamports, rpc } = options;
|
|
170
|
-
|
|
171
|
-
const aeth = lamportsToAeth(lamports);
|
|
172
|
-
|
|
173
|
-
console.log(`\n${C.bright}${C.cyan}── Aether Account Balance ───────────────────────────────${C.reset}\n`);
|
|
174
|
-
console.log(` ${C.bright}Address:${C.reset} ${C.magenta}${address}${C.reset}`);
|
|
175
|
-
|
|
176
|
-
if (showLamports) {
|
|
177
|
-
console.log(` ${C.bright}Balance:${C.reset} ${C.green}${lamports.toLocaleString()} lamports${C.reset}`);
|
|
178
|
-
} else {
|
|
179
|
-
console.log(` ${C.bright}Balance:${C.reset} ${C.green}${aeth} AETH${C.reset}`);
|
|
180
|
-
console.log(` ${C.dim} (${lamports.toLocaleString()} lamports)${C.reset}`);
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
if (owner) {
|
|
184
|
-
console.log(` ${C.bright}Owner:${C.reset} ${C.dim}${shortenAddress(owner)}${C.reset}`);
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
if (executable !== undefined) {
|
|
188
|
-
const execStr = executable ? `${C.yellow}yes${C.reset}` : `${C.dim}no${C.reset}`;
|
|
189
|
-
console.log(` ${C.bright}Executable:${C.reset} ${execStr}`);
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
if (rentEpoch !== null) {
|
|
193
|
-
console.log(` ${C.bright}Rent Epoch:${C.reset} ${C.dim}${rentEpoch}${C.reset}`);
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
console.log(` ${C.dim}RPC: ${rpc}${C.reset}\n`);
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
function printJson(data, rpc) {
|
|
200
|
-
console.log(JSON.stringify({
|
|
201
|
-
address: data.address,
|
|
202
|
-
lamports: data.lamports,
|
|
203
|
-
aeth: lamportsToAeth(data.lamports),
|
|
204
|
-
owner: data.owner,
|
|
205
|
-
executable: data.executable,
|
|
206
|
-
rentEpoch: data.rentEpoch,
|
|
207
|
-
rpc,
|
|
208
|
-
cli_version: CLI_VERSION,
|
|
209
|
-
timestamp: new Date().toISOString(),
|
|
210
|
-
}, null, 2));
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
// ---------------------------------------------------------------------------
|
|
214
|
-
// Main
|
|
215
|
-
// ---------------------------------------------------------------------------
|
|
216
|
-
|
|
217
|
-
async function balanceCommand() {
|
|
218
|
-
const options = parseArgs();
|
|
219
|
-
const { rpc, address, asJson } = options;
|
|
220
|
-
|
|
221
|
-
// Validate address
|
|
222
|
-
if (!address) {
|
|
223
|
-
if (asJson) {
|
|
224
|
-
console.log(JSON.stringify({
|
|
225
|
-
error: 'No address provided and no default wallet configured',
|
|
226
|
-
hint: 'Run "aether init" to set up a wallet, or provide an address',
|
|
227
|
-
}));
|
|
228
|
-
} else {
|
|
229
|
-
console.log(`\n${C.red}✗ No address provided${C.reset}`);
|
|
230
|
-
console.log(` ${C.dim}Provide an address or run "aether init" to set up a default wallet.${C.reset}`);
|
|
231
|
-
console.log(` ${C.dim}Usage: aether balance <address>${C.reset}\n`);
|
|
232
|
-
}
|
|
233
|
-
process.exit(1);
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
if (!asJson) {
|
|
237
|
-
console.log(`${C.dim}Querying balance for ${C.cyan}${shortenAddress(address)}${C.dim}...${C.reset}`);
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
try {
|
|
241
|
-
// Real blockchain RPC call
|
|
242
|
-
const data = await fetchBalance(rpc, address);
|
|
243
|
-
|
|
244
|
-
if (asJson) {
|
|
245
|
-
printJson(data, rpc);
|
|
246
|
-
} else {
|
|
247
|
-
printBalance(data, options);
|
|
248
|
-
}
|
|
249
|
-
} catch (err) {
|
|
250
|
-
if (asJson) {
|
|
251
|
-
console.log(JSON.stringify({
|
|
252
|
-
error: err.message,
|
|
253
|
-
address,
|
|
254
|
-
rpc,
|
|
255
|
-
}));
|
|
256
|
-
} else {
|
|
257
|
-
console.log(`\n${C.red}✗ Failed to fetch balance: ${err.message}${C.reset}`);
|
|
258
|
-
console.log(` ${C.dim}Address: ${address}${C.reset}`);
|
|
259
|
-
console.log(` ${C.dim}RPC: ${rpc}${C.reset}\n`);
|
|
260
|
-
}
|
|
261
|
-
process.exit(1);
|
|
262
|
-
}
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
// ---------------------------------------------------------------------------
|
|
266
|
-
// Exports
|
|
267
|
-
// ---------------------------------------------------------------------------
|
|
268
|
-
|
|
269
|
-
module.exports = { balanceCommand };
|
|
270
|
-
|
|
271
|
-
if (require.main === module) {
|
|
272
|
-
balanceCommand().catch(err => {
|
|
273
|
-
console.error(`${C.red}✗ Balance command failed: ${err.message}${C.reset}`);
|
|
274
|
-
process.exit(1);
|
|
275
|
-
});
|
|
276
|
-
}
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* aether-cli balance
|
|
4
|
+
*
|
|
5
|
+
* Query account balance from the Aether blockchain — real HTTP RPC calls,
|
|
6
|
+
* real data. No stubs, no mocks.
|
|
7
|
+
*
|
|
8
|
+
* Usage:
|
|
9
|
+
* aether balance <address> Query balance for an address
|
|
10
|
+
* aether balance Query default wallet balance
|
|
11
|
+
* aether balance --json JSON output for scripting
|
|
12
|
+
* aether balance --rpc <url> Query a specific RPC endpoint
|
|
13
|
+
* aether balance --lamports Show balance in lamports (not AETH)
|
|
14
|
+
*
|
|
15
|
+
* Requires AETHER_RPC env var (default: http://127.0.0.1:8899)
|
|
16
|
+
* SDK: @jellylegsai/aether-sdk — makes REAL HTTP RPC calls to the chain
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
const os = require('os');
|
|
20
|
+
const path = require('path');
|
|
21
|
+
|
|
22
|
+
// ANSI colours
|
|
23
|
+
const C = {
|
|
24
|
+
reset: '\x1b[0m',
|
|
25
|
+
bright: '\x1b[1m',
|
|
26
|
+
dim: '\x1b[2m',
|
|
27
|
+
red: '\x1b[31m',
|
|
28
|
+
green: '\x1b[32m',
|
|
29
|
+
yellow: '\x1b[33m',
|
|
30
|
+
cyan: '\x1b[36m',
|
|
31
|
+
magenta: '\x1b[35m',
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
// Import SDK — REAL blockchain RPC calls to http://127.0.0.1:8899
|
|
35
|
+
const sdkPath = path.join(__dirname, '..', 'sdk', 'index.js');
|
|
36
|
+
const aether = require(sdkPath);
|
|
37
|
+
|
|
38
|
+
const DEFAULT_RPC = process.env.AETHER_RPC || aether.DEFAULT_RPC_URL || 'http://127.0.0.1:8899';
|
|
39
|
+
const CLI_VERSION = '1.0.0';
|
|
40
|
+
|
|
41
|
+
// ---------------------------------------------------------------------------
|
|
42
|
+
// Helpers
|
|
43
|
+
// ---------------------------------------------------------------------------
|
|
44
|
+
|
|
45
|
+
function getDefaultRpc() {
|
|
46
|
+
return process.env.AETHER_RPC || aether.DEFAULT_RPC_URL || 'http://127.0.0.1:8899';
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function createClient(rpc) {
|
|
50
|
+
return new aether.AetherClient({ rpcUrl: rpc });
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function lamportsToAeth(lamports) {
|
|
54
|
+
return (Number(lamports) / 1e9).toFixed(6);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function loadConfig() {
|
|
58
|
+
const fs = require('fs');
|
|
59
|
+
const aetherDir = path.join(os.homedir(), '.aether');
|
|
60
|
+
const cfgPath = path.join(aetherDir, 'config.json');
|
|
61
|
+
if (!fs.existsSync(cfgPath)) return { defaultWallet: null };
|
|
62
|
+
try { return JSON.parse(fs.readFileSync(cfgPath, 'utf8')); }
|
|
63
|
+
catch { return { defaultWallet: null }; }
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function shortenAddress(addr) {
|
|
67
|
+
if (!addr) return 'unknown';
|
|
68
|
+
if (addr.length <= 10) return addr;
|
|
69
|
+
return `${addr.substring(0, 6)}...${addr.substring(addr.length - 4)}`;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// ---------------------------------------------------------------------------
|
|
73
|
+
// Argument parsing
|
|
74
|
+
// ---------------------------------------------------------------------------
|
|
75
|
+
|
|
76
|
+
function parseArgs() {
|
|
77
|
+
const args = process.argv.slice(2);
|
|
78
|
+
const options = {
|
|
79
|
+
rpc: getDefaultRpc(),
|
|
80
|
+
address: null,
|
|
81
|
+
asJson: false,
|
|
82
|
+
showLamports: false,
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
for (let i = 0; i < args.length; i++) {
|
|
86
|
+
const arg = args[i];
|
|
87
|
+
if (arg === '--rpc' || arg === '-r') {
|
|
88
|
+
options.rpc = args[++i];
|
|
89
|
+
} else if (arg === '--json' || arg === '-j') {
|
|
90
|
+
options.asJson = true;
|
|
91
|
+
} else if (arg === '--lamports' || arg === '-l') {
|
|
92
|
+
options.showLamports = true;
|
|
93
|
+
} else if (arg === '--help' || arg === '-h') {
|
|
94
|
+
showHelp();
|
|
95
|
+
process.exit(0);
|
|
96
|
+
} else if (!arg.startsWith('-') && !options.address) {
|
|
97
|
+
options.address = arg;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// If no address provided, try to load default wallet
|
|
102
|
+
if (!options.address) {
|
|
103
|
+
const config = loadConfig();
|
|
104
|
+
if (config.defaultWallet) {
|
|
105
|
+
options.address = config.defaultWallet;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
return options;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
function showHelp() {
|
|
113
|
+
console.log(`
|
|
114
|
+
${C.bright}${C.cyan}aether-cli balance${C.reset} - Query Account Balance
|
|
115
|
+
|
|
116
|
+
${C.bright}Usage:${C.reset}
|
|
117
|
+
aether balance [address] [options]
|
|
118
|
+
|
|
119
|
+
${C.bright}Arguments:${C.reset}
|
|
120
|
+
address Account public key (base58). If omitted, uses default wallet.
|
|
121
|
+
|
|
122
|
+
${C.bright}Options:${C.reset}
|
|
123
|
+
--rpc <url> Query a specific RPC endpoint (default: ${DEFAULT_RPC})
|
|
124
|
+
--json, -j Output raw JSON for scripting
|
|
125
|
+
--lamports, -l Show balance in lamports (not AETH)
|
|
126
|
+
--help, -h Show this help message
|
|
127
|
+
|
|
128
|
+
${C.bright}Description:${C.reset}
|
|
129
|
+
Queries the Aether blockchain for an account's balance.
|
|
130
|
+
Every call makes a REAL HTTP RPC request to the configured
|
|
131
|
+
Aether node — no caching, no stubs, no mocks.
|
|
132
|
+
|
|
133
|
+
RPC Endpoint: GET /v1/account/<address>
|
|
134
|
+
|
|
135
|
+
${C.bright}Examples:${C.reset}
|
|
136
|
+
aether balance # Default wallet
|
|
137
|
+
aether balance 8xPt...3nQ # Specific address
|
|
138
|
+
aether balance --json # JSON output
|
|
139
|
+
aether balance --lamports # Show lamports
|
|
140
|
+
AETHER_RPC=https://my-node:8899 aether balance
|
|
141
|
+
`);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// ---------------------------------------------------------------------------
|
|
145
|
+
// Balance query - REAL RPC call via SDK
|
|
146
|
+
// ---------------------------------------------------------------------------
|
|
147
|
+
|
|
148
|
+
async function fetchBalance(rpc, address) {
|
|
149
|
+
const client = createClient(rpc);
|
|
150
|
+
|
|
151
|
+
// Real RPC call: GET /v1/account/<address>
|
|
152
|
+
const account = await client.getAccountInfo(address);
|
|
153
|
+
|
|
154
|
+
return {
|
|
155
|
+
address,
|
|
156
|
+
lamports: account.lamports !== undefined ? account.lamports : 0,
|
|
157
|
+
owner: account.owner || null,
|
|
158
|
+
executable: account.executable || false,
|
|
159
|
+
rentEpoch: account.rent_epoch !== undefined ? account.rent_epoch : null,
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// ---------------------------------------------------------------------------
|
|
164
|
+
// Output formatters
|
|
165
|
+
// ---------------------------------------------------------------------------
|
|
166
|
+
|
|
167
|
+
function printBalance(data, options) {
|
|
168
|
+
const { address, lamports, owner, executable, rentEpoch } = data;
|
|
169
|
+
const { showLamports, rpc } = options;
|
|
170
|
+
|
|
171
|
+
const aeth = lamportsToAeth(lamports);
|
|
172
|
+
|
|
173
|
+
console.log(`\n${C.bright}${C.cyan}── Aether Account Balance ───────────────────────────────${C.reset}\n`);
|
|
174
|
+
console.log(` ${C.bright}Address:${C.reset} ${C.magenta}${address}${C.reset}`);
|
|
175
|
+
|
|
176
|
+
if (showLamports) {
|
|
177
|
+
console.log(` ${C.bright}Balance:${C.reset} ${C.green}${lamports.toLocaleString()} lamports${C.reset}`);
|
|
178
|
+
} else {
|
|
179
|
+
console.log(` ${C.bright}Balance:${C.reset} ${C.green}${aeth} AETH${C.reset}`);
|
|
180
|
+
console.log(` ${C.dim} (${lamports.toLocaleString()} lamports)${C.reset}`);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
if (owner) {
|
|
184
|
+
console.log(` ${C.bright}Owner:${C.reset} ${C.dim}${shortenAddress(owner)}${C.reset}`);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
if (executable !== undefined) {
|
|
188
|
+
const execStr = executable ? `${C.yellow}yes${C.reset}` : `${C.dim}no${C.reset}`;
|
|
189
|
+
console.log(` ${C.bright}Executable:${C.reset} ${execStr}`);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
if (rentEpoch !== null) {
|
|
193
|
+
console.log(` ${C.bright}Rent Epoch:${C.reset} ${C.dim}${rentEpoch}${C.reset}`);
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
console.log(` ${C.dim}RPC: ${rpc}${C.reset}\n`);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
function printJson(data, rpc) {
|
|
200
|
+
console.log(JSON.stringify({
|
|
201
|
+
address: data.address,
|
|
202
|
+
lamports: data.lamports,
|
|
203
|
+
aeth: lamportsToAeth(data.lamports),
|
|
204
|
+
owner: data.owner,
|
|
205
|
+
executable: data.executable,
|
|
206
|
+
rentEpoch: data.rentEpoch,
|
|
207
|
+
rpc,
|
|
208
|
+
cli_version: CLI_VERSION,
|
|
209
|
+
timestamp: new Date().toISOString(),
|
|
210
|
+
}, null, 2));
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// ---------------------------------------------------------------------------
|
|
214
|
+
// Main
|
|
215
|
+
// ---------------------------------------------------------------------------
|
|
216
|
+
|
|
217
|
+
async function balanceCommand() {
|
|
218
|
+
const options = parseArgs();
|
|
219
|
+
const { rpc, address, asJson } = options;
|
|
220
|
+
|
|
221
|
+
// Validate address
|
|
222
|
+
if (!address) {
|
|
223
|
+
if (asJson) {
|
|
224
|
+
console.log(JSON.stringify({
|
|
225
|
+
error: 'No address provided and no default wallet configured',
|
|
226
|
+
hint: 'Run "aether init" to set up a wallet, or provide an address',
|
|
227
|
+
}));
|
|
228
|
+
} else {
|
|
229
|
+
console.log(`\n${C.red}✗ No address provided${C.reset}`);
|
|
230
|
+
console.log(` ${C.dim}Provide an address or run "aether init" to set up a default wallet.${C.reset}`);
|
|
231
|
+
console.log(` ${C.dim}Usage: aether balance <address>${C.reset}\n`);
|
|
232
|
+
}
|
|
233
|
+
process.exit(1);
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
if (!asJson) {
|
|
237
|
+
console.log(`${C.dim}Querying balance for ${C.cyan}${shortenAddress(address)}${C.dim}...${C.reset}`);
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
try {
|
|
241
|
+
// Real blockchain RPC call
|
|
242
|
+
const data = await fetchBalance(rpc, address);
|
|
243
|
+
|
|
244
|
+
if (asJson) {
|
|
245
|
+
printJson(data, rpc);
|
|
246
|
+
} else {
|
|
247
|
+
printBalance(data, options);
|
|
248
|
+
}
|
|
249
|
+
} catch (err) {
|
|
250
|
+
if (asJson) {
|
|
251
|
+
console.log(JSON.stringify({
|
|
252
|
+
error: err.message,
|
|
253
|
+
address,
|
|
254
|
+
rpc,
|
|
255
|
+
}));
|
|
256
|
+
} else {
|
|
257
|
+
console.log(`\n${C.red}✗ Failed to fetch balance: ${err.message}${C.reset}`);
|
|
258
|
+
console.log(` ${C.dim}Address: ${address}${C.reset}`);
|
|
259
|
+
console.log(` ${C.dim}RPC: ${rpc}${C.reset}\n`);
|
|
260
|
+
}
|
|
261
|
+
process.exit(1);
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
// ---------------------------------------------------------------------------
|
|
266
|
+
// Exports
|
|
267
|
+
// ---------------------------------------------------------------------------
|
|
268
|
+
|
|
269
|
+
module.exports = { balanceCommand };
|
|
270
|
+
|
|
271
|
+
if (require.main === module) {
|
|
272
|
+
balanceCommand().catch(err => {
|
|
273
|
+
console.error(`${C.red}✗ Balance command failed: ${err.message}${C.reset}`);
|
|
274
|
+
process.exit(1);
|
|
275
|
+
});
|
|
276
|
+
}
|