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.
@@ -9,10 +9,11 @@
9
9
  * aether delegations list --address <addr> List all stake delegations
10
10
  * aether delegations list --address <addr> --json JSON output
11
11
  * aether delegations claim --address <addr> --account <stakeAcct> [--json]
12
+ *
13
+ * SDK wired to: GET /v1/slot, GET /v1/account/<addr>, GET /v1/stake/<addr>
12
14
  */
13
15
 
14
- const http = require('http');
15
- const https = require('https');
16
+ const path = require('path');
16
17
  const readline = require('readline');
17
18
  const crypto = require('crypto');
18
19
  const bs58 = require('bs58').default;
@@ -32,18 +33,25 @@ const C = {
32
33
  };
33
34
 
34
35
  const DERIVATION_PATH = "m/44'/7777777'/0'/0'";
35
- const CLI_VERSION = '1.0.5';
36
+ const CLI_VERSION = '1.0.6';
37
+
38
+ // ---------------------------------------------------------------------------
39
+ // SDK Import
40
+ // ---------------------------------------------------------------------------
41
+
42
+ const sdkPath = path.join(__dirname, '..', 'sdk', 'index.js');
43
+ const aether = require(sdkPath);
36
44
 
37
45
  // ---------------------------------------------------------------------------
38
46
  // Paths & config
39
47
  // ---------------------------------------------------------------------------
40
48
 
41
49
  function getAetherDir() {
42
- return require('path').join(require('os').homedir(), '.aether');
50
+ return path.join(require('os').homedir(), '.aether');
43
51
  }
44
52
 
45
53
  function loadConfig() {
46
- const p = require('path').join(getAetherDir(), 'config.json');
54
+ const p = path.join(getAetherDir(), 'config.json');
47
55
  if (!require('fs').existsSync(p)) return { defaultWallet: null };
48
56
  try {
49
57
  return JSON.parse(require('fs').readFileSync(p, 'utf8'));
@@ -53,7 +61,7 @@ function loadConfig() {
53
61
  }
54
62
 
55
63
  function loadWallet(address) {
56
- const fp = require('path').join(getAetherDir(), 'wallets', `${address}.json`);
64
+ const fp = path.join(getAetherDir(), 'wallets', `${address}.json`);
57
65
  if (!require('fs').existsSync(fp)) return null;
58
66
  return JSON.parse(require('fs').readFileSync(fp, 'utf8'));
59
67
  }
@@ -75,57 +83,15 @@ function formatAddress(publicKey) {
75
83
  }
76
84
 
77
85
  // ---------------------------------------------------------------------------
78
- // HTTP helpers
86
+ // Config helpers
79
87
  // ---------------------------------------------------------------------------
80
88
 
81
- function httpRequest(rpcUrl, path) {
82
- return new Promise((resolve, reject) => {
83
- const url = new URL(path, rpcUrl);
84
- const lib = url.protocol === 'https:' ? https : http;
85
- const req = lib.request({
86
- hostname: url.hostname,
87
- port: url.port || (url.protocol === 'https:' ? 443 : 80),
88
- path: url.pathname + url.search,
89
- method: 'GET',
90
- timeout: 8000,
91
- headers: { 'Content-Type': 'application/json' },
92
- }, (res) => {
93
- let data = '';
94
- res.on('data', (chunk) => data += chunk);
95
- res.on('end', () => { try { resolve(JSON.parse(data)); } catch { resolve({ raw: data }); } });
96
- });
97
- req.on('error', reject);
98
- req.on('timeout', () => { req.destroy(); reject(new Error('Request timeout')); });
99
- req.end();
100
- });
101
- }
102
-
103
- function httpPost(rpcUrl, path, body) {
104
- return new Promise((resolve, reject) => {
105
- const url = new URL(path, rpcUrl);
106
- const lib = url.protocol === 'https:' ? https : http;
107
- const bodyStr = JSON.stringify(body);
108
- const req = lib.request({
109
- hostname: url.hostname,
110
- port: url.port || (url.protocol === 'https:' ? 443 : 80),
111
- path: url.pathname + url.search,
112
- method: 'POST',
113
- timeout: 8000,
114
- headers: { 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(bodyStr) },
115
- }, (res) => {
116
- let data = '';
117
- res.on('data', (chunk) => data += chunk);
118
- res.on('end', () => { try { resolve(JSON.parse(data)); } catch { resolve({ raw: data }); } });
119
- });
120
- req.on('error', reject);
121
- req.on('timeout', () => { req.destroy(); reject(new Error('Request timeout')); });
122
- req.write(bodyStr);
123
- req.end();
124
- });
89
+ function getDefaultRpc() {
90
+ return process.env.AETHER_RPC || aether.DEFAULT_RPC_URL || 'http://127.0.0.1:8899';
125
91
  }
126
92
 
127
- function getDefaultRpc() {
128
- return process.env.AETHER_RPC || 'http://127.0.0.1:8899';
93
+ function createClient(rpcUrl) {
94
+ return new aether.AetherClient({ rpcUrl });
129
95
  }
130
96
 
131
97
  function formatAether(lamports) {
@@ -159,7 +125,7 @@ async function askMnemonic(rl, prompt) {
159
125
  }
160
126
 
161
127
  // ---------------------------------------------------------------------------
162
- // LIST DELEGATIONS
128
+ // LIST DELEGATIONS — uses SDK
163
129
  // ---------------------------------------------------------------------------
164
130
 
165
131
  async function listDelegations(args) {
@@ -169,9 +135,9 @@ async function listDelegations(args) {
169
135
  let rpcUrl = getDefaultRpc();
170
136
 
171
137
  for (let i = 0; i < args.length; i++) {
172
- if ((args[i] === '--address' || args[i] === '-a') && args[i + 1]) address = args[i + 1];
138
+ if ((args[i] === '--address' || args[i] === '-a') && args[i + 1]) address = args[++i];
173
139
  else if (args[i] === '--json' || args[i] === '-j') asJson = true;
174
- else if ((args[i] === '--rpc' || args[i] === '-r') && args[i + 1]) rpcUrl = args[i + 1];
140
+ else if ((args[i] === '--rpc' || args[i] === '-r') && args[i + 1]) rpcUrl = args[++i];
175
141
  }
176
142
 
177
143
  if (!address) {
@@ -186,29 +152,15 @@ async function listDelegations(args) {
186
152
  return;
187
153
  }
188
154
 
189
- try {
190
- const rawAddr = address.startsWith('ATH') ? address.slice(3) : address;
191
-
192
- // Fetch account info for context
193
- const account = await httpRequest(rpcUrl, `/v1/account/${rawAddr}`);
155
+ const client = createClient(rpcUrl);
156
+ const rawAddr = address.startsWith('ATH') ? address.slice(3) : address;
194
157
 
195
- // Fetch stake accounts for this wallet
196
- // The RPC may return stake accounts via a dedicated endpoint or as program accounts
197
- let stakeAccounts = [];
198
- try {
199
- const res = await httpRequest(rpcUrl, `/v1/stake?address=${encodeURIComponent(rawAddr)}`);
200
- if (res && !res.error) {
201
- stakeAccounts = Array.isArray(res) ? res : (res.accounts || []);
202
- }
203
- } catch {
204
- // Fallback: try program account query
205
- try {
206
- const res2 = await httpRequest(rpcUrl, `/v1/program/STAKE/accounts?owner=${encodeURIComponent(rawAddr)}`);
207
- if (res2 && !res2.error) {
208
- stakeAccounts = Array.isArray(res2) ? res2 : (res2.accounts || []);
209
- }
210
- } catch { /* no stake accounts or RPC doesn't support this endpoint */ }
211
- }
158
+ try {
159
+ // Real chain RPC calls via SDK
160
+ const [account, stakeAccounts] = await Promise.all([
161
+ client.getAccountInfo(rawAddr).catch(() => null),
162
+ client.getStakePositions(rawAddr).catch(() => []),
163
+ ]);
212
164
 
213
165
  if (asJson) {
214
166
  console.log(JSON.stringify({
@@ -216,6 +168,7 @@ async function listDelegations(args) {
216
168
  rpc: rpcUrl,
217
169
  account: account && !account.error ? { lamports: account.lamports } : null,
218
170
  delegations: stakeAccounts,
171
+ cli_version: CLI_VERSION,
219
172
  fetched_at: new Date().toISOString(),
220
173
  }, null, 2));
221
174
  rl.close();
@@ -230,7 +183,7 @@ async function listDelegations(args) {
230
183
  }
231
184
  console.log();
232
185
 
233
- if (stakeAccounts.length === 0) {
186
+ if (!stakeAccounts || stakeAccounts.length === 0) {
234
187
  console.log(` ${C.dim}No stake delegations found for this wallet.${C.reset}`);
235
188
  console.log(` ${C.dim}Delegate with:${C.reset} ${C.cyan}aether stake --address ${address} --validator <val> --amount <aeth>${C.reset}\n`);
236
189
  rl.close();
@@ -282,7 +235,7 @@ async function listDelegations(args) {
282
235
  }
283
236
 
284
237
  // ---------------------------------------------------------------------------
285
- // CLAIM REWARDS
238
+ // CLAIM REWARDS — uses SDK for fetch, wallet for signing
286
239
  // ---------------------------------------------------------------------------
287
240
 
288
241
  async function claimRewards(args) {
@@ -294,10 +247,10 @@ async function claimRewards(args) {
294
247
  let rpcUrl = getDefaultRpc();
295
248
 
296
249
  for (let i = 0; i < args.length; i++) {
297
- if ((args[i] === '--address' || args[i] === '-a') && args[i + 1]) address = args[i + 1];
298
- else if ((args[i] === '--account' || args[i] === '-s') && args[i + 1]) stakeAccount = args[i + 1];
250
+ if ((args[i] === '--address' || args[i] === '-a') && args[i + 1]) address = args[++i];
251
+ else if ((args[i] === '--account' || args[i] === '-s') && args[i + 1]) stakeAccount = args[++i];
299
252
  else if (args[i] === '--json' || args[i] === '-j') asJson = true;
300
- else if ((args[i] === '--rpc' || args[i] === '-r') && args[i + 1]) rpcUrl = args[i + 1];
253
+ else if ((args[i] === '--rpc' || args[i] === '-r') && args[i + 1]) rpcUrl = args[++i];
301
254
  }
302
255
 
303
256
  if (!address) {
@@ -312,17 +265,14 @@ async function claimRewards(args) {
312
265
  return;
313
266
  }
314
267
 
268
+ const client = createClient(rpcUrl);
269
+
270
+ // If no stake account specified, fetch list via SDK
315
271
  if (!stakeAccount) {
316
- // Fetch list first to let user pick
317
- let stakeAccounts = [];
318
- try {
319
- const res = await httpRequest(rpcUrl, `/v1/stake?address=${encodeURIComponent(address.startsWith('ATH') ? address.slice(3) : address)}`);
320
- if (res && !res.error) {
321
- stakeAccounts = Array.isArray(res) ? res : (res.accounts || []);
322
- }
323
- } catch { /* noop */ }
272
+ const rawAddr = address.startsWith('ATH') ? address.slice(3) : address;
273
+ let stakeAccounts = await client.getStakePositions(rawAddr).catch(() => []);
324
274
 
325
- if (stakeAccounts.length === 0) {
275
+ if (!stakeAccounts || stakeAccounts.length === 0) {
326
276
  console.log(` ${C.red}✗ No stake accounts found.${C.reset} Use ${C.cyan}--account <stakeAcct>${C.reset} to specify one.\n`);
327
277
  rl.close();
328
278
  return;
@@ -366,7 +316,7 @@ async function claimRewards(args) {
366
316
 
367
317
  let keyPair;
368
318
  try {
369
- keyPair = deriveKeypair(mnemonic, DERIVATION_PATH);
319
+ keyPair = deriveKeypair(mnemonic);
370
320
  } catch (e) {
371
321
  console.log(` ${C.red}✗ Failed to derive keypair: ${e.message}${C.reset}\n`);
372
322
  rl.close();
@@ -404,10 +354,10 @@ async function claimRewards(args) {
404
354
  timestamp: Math.floor(Date.now() / 1000),
405
355
  };
406
356
 
407
- console.log(` ${C.dim}Submitting to ${rpcUrl}...${C.reset}`);
357
+ console.log(` ${C.dim}Submitting via SDK to ${rpcUrl}...${C.reset}`);
408
358
 
409
359
  try {
410
- const result = await httpPost(rpcUrl, '/v1/tx', tx);
360
+ const result = await client.sendTransaction(tx);
411
361
 
412
362
  if (result.error) {
413
363
  console.log(`\n ${C.red}✗ Claim failed:${C.reset} ${result.error}\n`);
@@ -651,7 +651,17 @@ async function main() {
651
651
  }
652
652
  }
653
653
 
654
- main().catch(err => {
655
- console.error(`\n${C.red}Error in emergency command:${C.reset}`, err.message, '\n');
656
- process.exit(1);
657
- });
654
+ // Exported emergency command handler for CLI integration
655
+ async function emergencyCommand() {
656
+ return main();
657
+ }
658
+
659
+ // Run if called directly
660
+ if (require.main === module) {
661
+ main().catch(err => {
662
+ console.error(`\n${C.red}Error in emergency command:${C.reset}`, err.message, '\n');
663
+ process.exit(1);
664
+ });
665
+ }
666
+
667
+ module.exports = { emergencyCommand };