@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
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* aether-cli - Stake Info Command
|
|
4
|
+
* Get staking information for an address using real chain RPC calls.
|
|
5
|
+
* All calls go through @jellylegsai/aether-sdk → AetherClient → real HTTP RPC.
|
|
6
|
+
*
|
|
7
|
+
* Usage:
|
|
8
|
+
* aether stake-info <address> Show stake info for address
|
|
9
|
+
* aether stake-info <address> --json JSON output
|
|
10
|
+
* aether stake-info <address> --rpc <url> Custom RPC endpoint
|
|
11
|
+
*
|
|
12
|
+
* SDK wired to: GET /v1/slot, GET /v1/account/<addr>, GET /v1/blockheight
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
const path = require('path');
|
|
16
|
+
const sdkPath = path.join(__dirname, '..', 'sdk', 'index.js');
|
|
17
|
+
const { AetherClient } = require(sdkPath);
|
|
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
|
+
// ---------------------------------------------------------------------------
|
|
32
|
+
// Argument parsing
|
|
33
|
+
// ---------------------------------------------------------------------------
|
|
34
|
+
|
|
35
|
+
function parseArgs() {
|
|
36
|
+
const args = process.argv.slice(2);
|
|
37
|
+
const result = { address: null, json: false, rpc: null };
|
|
38
|
+
|
|
39
|
+
for (let i = 0; i < args.length; i++) {
|
|
40
|
+
if (!args[i].startsWith('-') && !result.address) {
|
|
41
|
+
result.address = args[i];
|
|
42
|
+
} else if (args[i] === '--json' || args[i] === '-j') {
|
|
43
|
+
result.json = true;
|
|
44
|
+
} else if ((args[i] === '--rpc' || args[i] === '-r') && args[i + 1]) {
|
|
45
|
+
result.rpc = args[++i];
|
|
46
|
+
} else if (args[i] === '--help' || args[i] === '-h') {
|
|
47
|
+
result.help = true;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return result;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function getDefaultRpc() {
|
|
54
|
+
return process.env.AETHER_RPC || 'http://127.0.0.1:8899';
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// ---------------------------------------------------------------------------
|
|
58
|
+
// Main
|
|
59
|
+
// ---------------------------------------------------------------------------
|
|
60
|
+
|
|
61
|
+
async function stakeInfoCommand() {
|
|
62
|
+
const opts = parseArgs();
|
|
63
|
+
|
|
64
|
+
if (opts.help || !opts.address) {
|
|
65
|
+
console.log(`
|
|
66
|
+
${C.bright}${C.cyan}aether-cli stake-info${C.reset} — Get stake/account info for an address
|
|
67
|
+
|
|
68
|
+
${C.bright}USAGE${C.reset}
|
|
69
|
+
aether stake-info <address> [--json] [--rpc <url>]
|
|
70
|
+
|
|
71
|
+
${C.bright}OPTIONS${C.reset}
|
|
72
|
+
--json, -j Output raw JSON
|
|
73
|
+
--rpc <url> RPC endpoint (default: AETHER_RPC or localhost:8899)
|
|
74
|
+
--help, -h Show this help
|
|
75
|
+
|
|
76
|
+
${C.bright}SDK METHODS USED${C.reset}
|
|
77
|
+
client.getSlot() → GET /v1/slot
|
|
78
|
+
client.getAccountInfo(addr) → GET /v1/account/<addr>
|
|
79
|
+
client.getBlockHeight() → GET /v1/blockheight
|
|
80
|
+
|
|
81
|
+
${C.bright}EXAMPLE${C.reset}
|
|
82
|
+
aether stake-info ATH3abc...def
|
|
83
|
+
`);
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const rpcUrl = opts.rpc || getDefaultRpc();
|
|
88
|
+
const client = new AetherClient({ rpcUrl });
|
|
89
|
+
|
|
90
|
+
try {
|
|
91
|
+
// Real chain RPC calls — all parallel for speed
|
|
92
|
+
const [slot, accountInfo, blockHeight] = await Promise.all([
|
|
93
|
+
client.getSlot().catch(() => null),
|
|
94
|
+
client.getAccountInfo(opts.address).catch(() => null),
|
|
95
|
+
client.getBlockHeight().catch(() => null),
|
|
96
|
+
]);
|
|
97
|
+
|
|
98
|
+
const balance = accountInfo?.lamports != null
|
|
99
|
+
? (accountInfo.lamports / 1e9).toFixed(4) + ' AETH'
|
|
100
|
+
: 'unavailable';
|
|
101
|
+
const owner = accountInfo?.owner || 'unknown';
|
|
102
|
+
const executable = accountInfo?.executable ? 'yes' : 'no';
|
|
103
|
+
|
|
104
|
+
if (opts.json) {
|
|
105
|
+
console.log(JSON.stringify({
|
|
106
|
+
address: opts.address,
|
|
107
|
+
slot: slot ?? null,
|
|
108
|
+
block_height: blockHeight ?? null,
|
|
109
|
+
account: {
|
|
110
|
+
lamports: accountInfo?.lamports ?? null,
|
|
111
|
+
balance_aeth: accountInfo?.lamports != null ? (accountInfo.lamports / 1e9).toFixed(4) : null,
|
|
112
|
+
owner: accountInfo?.owner ?? null,
|
|
113
|
+
executable: accountInfo?.executable ?? false,
|
|
114
|
+
rent_epoch: accountInfo?.rent_epoch ?? null,
|
|
115
|
+
},
|
|
116
|
+
rpc: rpcUrl,
|
|
117
|
+
timestamp: new Date().toISOString(),
|
|
118
|
+
}, null, 2));
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
console.log(`\n${C.bright}${C.cyan}── Aether Stake Info ─────────────────────────────────${C.reset}\n`);
|
|
123
|
+
console.log(` ${C.dim}Address:${C.reset} ${opts.address}`);
|
|
124
|
+
console.log(` ${C.dim}Balance:${C.reset} ${C.green}${balance}${C.reset}`);
|
|
125
|
+
console.log(` ${C.dim}Owner:${C.reset} ${owner}`);
|
|
126
|
+
console.log(` ${C.dim}Executable:${C.reset} ${executable}`);
|
|
127
|
+
console.log(` ${C.dim}Slot:${C.reset} ${slot ?? 'unavailable'}`);
|
|
128
|
+
console.log(` ${C.dim}Block Height:${C.reset} ${blockHeight ?? 'unavailable'}`);
|
|
129
|
+
console.log(` ${C.dim}RPC:${C.reset} ${rpcUrl}\n`);
|
|
130
|
+
console.log(` ${C.green}? Real chain RPC calls completed${C.reset}\n`);
|
|
131
|
+
} catch (error) {
|
|
132
|
+
console.log(` ${C.red}? Error: ${error.message}${C.reset}\n`);
|
|
133
|
+
process.exit(1);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
stakeInfoCommand();
|
|
138
|
+
|
|
139
|
+
module.exports = { stakeInfoCommand };
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* aether-cli stake-positions
|
|
4
|
+
*
|
|
5
|
+
* Query and display current stake positions/delegations for a wallet.
|
|
6
|
+
* Shows validator, amount, status, and accumulated rewards.
|
|
7
|
+
*
|
|
8
|
+
* Usage:
|
|
9
|
+
* aether stake-positions --address <addr> [--json]
|
|
10
|
+
* aether wallet stake-positions --address <addr> [--json]
|
|
11
|
+
*
|
|
12
|
+
* Examples:
|
|
13
|
+
* aether stake-positions --address ATHxxx
|
|
14
|
+
* aether wallet stake-positions --address ATHxxx --json
|
|
15
|
+
*
|
|
16
|
+
* SDK wired to: GET /v1/slot, GET /v1/stake/<address>, GET /v1/account/<addr>
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
const path = require('path');
|
|
20
|
+
|
|
21
|
+
// Import SDK — all network calls go through @jellylegsai/aether-sdk
|
|
22
|
+
const sdkPath = path.join(__dirname, '..', 'sdk', 'index.js');
|
|
23
|
+
const aether = require(sdkPath);
|
|
24
|
+
|
|
25
|
+
// ANSI colours
|
|
26
|
+
const C = {
|
|
27
|
+
reset: '\x1b[0m',
|
|
28
|
+
bright: '\x1b[1m',
|
|
29
|
+
dim: '\x1b[2m',
|
|
30
|
+
red: '\x1b[31m',
|
|
31
|
+
green: '\x1b[32m',
|
|
32
|
+
yellow: '\x1b[33m',
|
|
33
|
+
cyan: '\x1b[36m',
|
|
34
|
+
magenta: '\x1b[35m',
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
const CLI_VERSION = '1.0.1';
|
|
38
|
+
|
|
39
|
+
// ---------------------------------------------------------------------------
|
|
40
|
+
// Config
|
|
41
|
+
// ---------------------------------------------------------------------------
|
|
42
|
+
|
|
43
|
+
function getDefaultRpc() {
|
|
44
|
+
return process.env.AETHER_RPC || aether.DEFAULT_RPC_URL || 'http://127.0.0.1:8899';
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function createClient(rpcUrl) {
|
|
48
|
+
return new aether.AetherClient({ rpcUrl });
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// ---------------------------------------------------------------------------
|
|
52
|
+
// Argument parsing
|
|
53
|
+
// ---------------------------------------------------------------------------
|
|
54
|
+
|
|
55
|
+
function parseArgs() {
|
|
56
|
+
const args = process.argv.slice(2);
|
|
57
|
+
const result = { address: null, json: false };
|
|
58
|
+
|
|
59
|
+
for (let i = 0; i < args.length; i++) {
|
|
60
|
+
if ((args[i] === '--address' || args[i] === '-a') && args[i + 1]) {
|
|
61
|
+
result.address = args[++i];
|
|
62
|
+
} else if (args[i] === '--json' || args[i] === '--json-output') {
|
|
63
|
+
result.json = true;
|
|
64
|
+
} else if (args[i] === '--rpc' && args[i + 1]) {
|
|
65
|
+
result.rpc = args[++i];
|
|
66
|
+
} else if (args[i] === '--help' || args[i] === '-h') {
|
|
67
|
+
result.help = true;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
return result;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// ---------------------------------------------------------------------------
|
|
75
|
+
// Balance formatting
|
|
76
|
+
// ---------------------------------------------------------------------------
|
|
77
|
+
|
|
78
|
+
function formatAether(lamports) {
|
|
79
|
+
const aeth = (lamports || 0) / 1e9;
|
|
80
|
+
return aeth.toLocaleString(undefined, { minimumFractionDigits: 4, maximumFractionDigits: 4 }) + ' AETH';
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// ---------------------------------------------------------------------------
|
|
84
|
+
// Main
|
|
85
|
+
// ---------------------------------------------------------------------------
|
|
86
|
+
|
|
87
|
+
async function stakePositionsCommand() {
|
|
88
|
+
const opts = parseArgs();
|
|
89
|
+
|
|
90
|
+
if (opts.help) {
|
|
91
|
+
console.log(`
|
|
92
|
+
${C.bright}${C.cyan}stake-positions${C.reset} — Query active stake delegations for a wallet
|
|
93
|
+
|
|
94
|
+
${C.bright}USAGE${C.reset}
|
|
95
|
+
aether stake-positions --address <addr> [--json] [--rpc <url>]
|
|
96
|
+
|
|
97
|
+
${C.bright}OPTIONS${C.reset}
|
|
98
|
+
--address <addr> Wallet address (ATH...)
|
|
99
|
+
--json Output raw JSON
|
|
100
|
+
--rpc <url> RPC endpoint (default: AETHER_RPC or localhost:8899)
|
|
101
|
+
--help Show this help
|
|
102
|
+
|
|
103
|
+
${C.bright}SDK METHODS USED${C.reset}
|
|
104
|
+
client.getSlot() → GET /v1/slot
|
|
105
|
+
client.getStakePositions() → GET /v1/stake/<address>
|
|
106
|
+
client.getAccountInfo() → GET /v1/account/<addr>
|
|
107
|
+
|
|
108
|
+
${C.bright}EXAMPLES${C.reset}
|
|
109
|
+
aether stake-positions --address ATH3abc...
|
|
110
|
+
aether stake-positions --address ATH3abc... --json
|
|
111
|
+
`);
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
if (!opts.address) {
|
|
116
|
+
console.log(` ${C.red}✗ Missing --address${C.reset}\n`);
|
|
117
|
+
console.log(` Usage: aether stake-positions --address <addr> [--json]\n`);
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
const rpcUrl = opts.rpc || getDefaultRpc();
|
|
122
|
+
const client = createClient(rpcUrl);
|
|
123
|
+
const address = opts.address;
|
|
124
|
+
const rawAddr = address.startsWith('ATH') ? address.slice(3) : address;
|
|
125
|
+
|
|
126
|
+
if (!opts.json) {
|
|
127
|
+
console.log(`\n${C.bright}${C.cyan}── Stake Positions ──────────────────────────────────────${C.reset}\n`);
|
|
128
|
+
console.log(` ${C.dim}Wallet:${C.reset} ${address}`);
|
|
129
|
+
console.log(` ${C.dim}RPC: ${C.reset} ${rpcUrl}\n`);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
try {
|
|
133
|
+
// Verify chain connectivity via SDK (real RPC call)
|
|
134
|
+
const slot = await client.getSlot().catch(() => null);
|
|
135
|
+
|
|
136
|
+
// Fetch stake positions via SDK (real RPC call to GET /v1/stake/<address>)
|
|
137
|
+
const stakeAccounts = await client.getStakePositions(rawAddr);
|
|
138
|
+
|
|
139
|
+
if (opts.json) {
|
|
140
|
+
const totalLamports = stakeAccounts.reduce((sum, acc) => sum + (acc.stake_lamports || acc.lamports || 0), 0);
|
|
141
|
+
console.log(JSON.stringify({
|
|
142
|
+
wallet_address: address,
|
|
143
|
+
slot,
|
|
144
|
+
stake_accounts: stakeAccounts.map(acc => ({
|
|
145
|
+
stake_account: acc.pubkey || acc.publicKey || acc.account || 'unknown',
|
|
146
|
+
validator: acc.validator || acc.delegate || acc.validator_address || 'unknown',
|
|
147
|
+
stake_lamports: acc.stake_lamports || acc.lamports || 0,
|
|
148
|
+
stake_aeth: ((acc.stake_lamports || acc.lamports || 0) / 1e9).toFixed(4),
|
|
149
|
+
status: acc.status || acc.state || 'active',
|
|
150
|
+
updated_epoch: acc.epoch || acc.last_update_epoch || null,
|
|
151
|
+
})),
|
|
152
|
+
total_staked_lamports: totalLamports,
|
|
153
|
+
total_staked_aeth: (totalLamports / 1e9).toFixed(4),
|
|
154
|
+
count: stakeAccounts.length,
|
|
155
|
+
rpc: rpcUrl,
|
|
156
|
+
cli_version: CLI_VERSION,
|
|
157
|
+
fetched_at: new Date().toISOString(),
|
|
158
|
+
}, null, 2));
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
if (!stakeAccounts || stakeAccounts.length === 0) {
|
|
163
|
+
console.log(` ${C.yellow}? No active stake positions found.${C.reset}`);
|
|
164
|
+
console.log(` ${C.dim} Stake AETH with: ${C.cyan}aether stake --validator <addr> --amount <aeth>${C.reset}\n`);
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
let totalStaked = 0;
|
|
169
|
+
console.log(` ${C.bright}Stake Positions (${stakeAccounts.length})${C.reset}\n`);
|
|
170
|
+
|
|
171
|
+
for (const acc of stakeAccounts) {
|
|
172
|
+
const stakeAcct = acc.pubkey || acc.publicKey || acc.account || 'unknown';
|
|
173
|
+
const validator = acc.validator || acc.delegate || acc.validator_address || 'unknown';
|
|
174
|
+
const lamports = acc.stake_lamports || acc.lamports || 0;
|
|
175
|
+
const status = (acc.status || acc.state || 'active').toLowerCase();
|
|
176
|
+
const epoch = acc.epoch || acc.last_update_epoch || null;
|
|
177
|
+
|
|
178
|
+
totalStaked += lamports;
|
|
179
|
+
|
|
180
|
+
const statusColor = status === 'active' ? C.green : status === 'deactivating' ? C.yellow : C.dim;
|
|
181
|
+
const shortAcct = stakeAcct.length > 20 ? stakeAcct.slice(0, 8) + '.' + stakeAcct.slice(-8) : stakeAcct;
|
|
182
|
+
const shortVal = validator.length > 20 ? validator.slice(0, 8) + '.' + validator.slice(-8) : validator;
|
|
183
|
+
const aeth = (lamports / 1e9).toFixed(4);
|
|
184
|
+
|
|
185
|
+
console.log(` ${C.dim}┌─${C.bright}${statusColor} ${status.toUpperCase()}${C.reset}`);
|
|
186
|
+
console.log(` │ ${C.dim}Stake acct:${C.reset} ${shortAcct}`);
|
|
187
|
+
console.log(` │ ${C.dim}Validator:${C.reset} ${shortVal}`);
|
|
188
|
+
console.log(` │ ${C.dim}Staked:${C.reset} ${C.bright}${aeth} AETH${C.reset} (${lamports.toLocaleString()} lamports)`);
|
|
189
|
+
if (epoch) console.log(` │ ${C.dim}Epoch:${C.reset} ${C.bright}#${epoch}${C.reset}`);
|
|
190
|
+
console.log(` ${C.dim}└${C.reset}\n`);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
console.log(` ${C.dim}────────────────────────────────────────${C.reset}`);
|
|
194
|
+
console.log(` ${C.bright}Total Staked:${C.reset} ${C.green}${formatAether(totalStaked)}${C.reset}\n`);
|
|
195
|
+
|
|
196
|
+
} catch (err) {
|
|
197
|
+
console.log(` ${C.red}? Failed to fetch stake positions:${C.reset} ${err.message}\n`);
|
|
198
|
+
console.log(` ${C.dim} Set custom RPC: AETHER_RPC=https://your-rpc-url${C.reset}\n`);
|
|
199
|
+
process.exit(1);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
stakePositionsCommand();
|
|
204
|
+
|
|
205
|
+
module.exports = { stakePositionsCommand };
|