@jellylegsai/aether-cli 1.9.2 → 2.0.1
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/IMPLEMENTATION_REPORT.md +319 -0
- package/commands/blockheight.js +230 -0
- package/commands/call.js +981 -0
- package/commands/claim.js +98 -72
- package/commands/deploy.js +959 -0
- package/commands/index.js +2 -0
- package/commands/init.js +33 -49
- package/commands/network-diagnostics.js +706 -0
- package/commands/network.js +412 -429
- package/commands/rewards.js +311 -266
- package/commands/sdk.js +791 -656
- package/commands/slot.js +3 -11
- package/commands/stake.js +581 -516
- package/commands/supply.js +483 -391
- package/commands/token-accounts.js +275 -0
- package/commands/transfer.js +3 -11
- package/commands/unstake.js +3 -11
- package/commands/validator-start.js +681 -323
- package/commands/validator.js +959 -0
- package/commands/validators.js +623 -626
- package/commands/version.js +240 -0
- package/commands/wallet.js +17 -24
- package/cycle-report-issue-116.txt +165 -0
- package/index.js +501 -602
- package/lib/ui.js +623 -0
- package/package.json +10 -3
- package/sdk/index.d.ts +546 -0
- package/sdk/index.js +130 -0
- package/sdk/package.json +2 -1
package/commands/sdk.js
CHANGED
|
@@ -1,656 +1,791 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
* aether
|
|
11
|
-
* aether
|
|
12
|
-
* aether
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
*
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
}
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
});
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
}
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* aether-cli sdk
|
|
4
|
+
*
|
|
5
|
+
* Direct SDK access for developers - query any SDK method from the command line.
|
|
6
|
+
* Makes REAL HTTP RPC calls to the Aether blockchain.
|
|
7
|
+
* No stubs, no mocks - every function makes actual RPC calls.
|
|
8
|
+
*
|
|
9
|
+
* Usage:
|
|
10
|
+
* aether sdk getSlot Get current slot
|
|
11
|
+
* aether sdk getBalance <address> Get account balance
|
|
12
|
+
* aether sdk getAccountInfo <address> Get full account info
|
|
13
|
+
* aether sdk getEpochInfo Get epoch information
|
|
14
|
+
* aether sdk getBlockHeight Get block height
|
|
15
|
+
* aether sdk getTransaction <signature> Get transaction by signature
|
|
16
|
+
* aether sdk getStakePositions <address> Get stake positions
|
|
17
|
+
* aether sdk getRewards <address> Get rewards info
|
|
18
|
+
* aether sdk getValidators List validators
|
|
19
|
+
* aether sdk getSupply Get token supply
|
|
20
|
+
* aether sdk getTPS Get transactions per second
|
|
21
|
+
* aether sdk getHealth Check node health
|
|
22
|
+
* aether sdk getVersion Get node version
|
|
23
|
+
* aether sdk getRecentBlockhash Get recent blockhash
|
|
24
|
+
* aether sdk getSlotProduction Get slot production stats
|
|
25
|
+
* aether sdk getClusterPeers Get peer nodes
|
|
26
|
+
* aether sdk getFees Get fee schedule
|
|
27
|
+
* aether sdk getNFT <id> Get NFT details
|
|
28
|
+
* aether sdk getNFTHoldings <address> Get NFT holdings
|
|
29
|
+
* aether sdk getRecentTransactions <addr> Get recent transactions
|
|
30
|
+
* aether sdk ping Ping RPC endpoint
|
|
31
|
+
* aether sdk --rpc <url> Use specific RPC endpoint
|
|
32
|
+
* aether sdk --json Output JSON format
|
|
33
|
+
* aether sdk --list List all available SDK methods
|
|
34
|
+
*
|
|
35
|
+
* SDK Methods Used:
|
|
36
|
+
* - All methods from @jellylegsai/aether-sdk
|
|
37
|
+
* - Real HTTP RPC calls to http://127.0.0.1:8899
|
|
38
|
+
*/
|
|
39
|
+
|
|
40
|
+
const path = require('path');
|
|
41
|
+
const readline = require('readline');
|
|
42
|
+
|
|
43
|
+
// Import SDK - REAL blockchain RPC calls
|
|
44
|
+
const sdkPath = path.join(__dirname, '..', 'sdk', 'index.js');
|
|
45
|
+
const aether = require(sdkPath);
|
|
46
|
+
|
|
47
|
+
// ANSI colours
|
|
48
|
+
const C = {
|
|
49
|
+
reset: '\x1b[0m',
|
|
50
|
+
bright: '\x1b[1m',
|
|
51
|
+
dim: '\x1b[2m',
|
|
52
|
+
red: '\x1b[31m',
|
|
53
|
+
green: '\x1b[32m',
|
|
54
|
+
yellow: '\x1b[33m',
|
|
55
|
+
cyan: '\x1b[36m',
|
|
56
|
+
magenta: '\x1b[35m',
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
const CLI_VERSION = '1.2.0';
|
|
60
|
+
|
|
61
|
+
// ============================================================================
|
|
62
|
+
// SDK Client Setup
|
|
63
|
+
// ============================================================================
|
|
64
|
+
|
|
65
|
+
function getDefaultRpc() {
|
|
66
|
+
return process.env.AETHER_RPC || aether.DEFAULT_RPC_URL || 'http://127.0.0.1:8899';
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function createClient(rpcUrl) {
|
|
70
|
+
return new aether.AetherClient({ rpcUrl });
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// ============================================================================
|
|
74
|
+
// Format Helpers
|
|
75
|
+
// ============================================================================
|
|
76
|
+
|
|
77
|
+
function formatAether(lamports) {
|
|
78
|
+
if (!lamports || lamports === '0') return '0 AETH';
|
|
79
|
+
const aeth = Number(lamports) / 1e9;
|
|
80
|
+
return aeth.toFixed(4).replace(/\.?0+$/, '') + ' AETH';
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function formatNumber(n) {
|
|
84
|
+
if (n === null || n === undefined) return 'N/A';
|
|
85
|
+
return n.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',');
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function shortAddress(addr) {
|
|
89
|
+
if (!addr || addr.length < 16) return addr || 'unknown';
|
|
90
|
+
return addr.slice(0, 8) + '...' + addr.slice(-8);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// ============================================================================
|
|
94
|
+
// SDK Method Definitions
|
|
95
|
+
// ============================================================================
|
|
96
|
+
|
|
97
|
+
const SDK_METHODS = {
|
|
98
|
+
// Core chain queries
|
|
99
|
+
getSlot: {
|
|
100
|
+
desc: 'Get current slot number',
|
|
101
|
+
args: [],
|
|
102
|
+
returns: 'slot number',
|
|
103
|
+
example: 'aether sdk getSlot',
|
|
104
|
+
},
|
|
105
|
+
getBlockHeight: {
|
|
106
|
+
desc: 'Get current block height',
|
|
107
|
+
args: [],
|
|
108
|
+
returns: 'block height',
|
|
109
|
+
example: 'aether sdk getBlockHeight',
|
|
110
|
+
},
|
|
111
|
+
getEpochInfo: {
|
|
112
|
+
desc: 'Get epoch information',
|
|
113
|
+
args: [],
|
|
114
|
+
returns: 'epoch data',
|
|
115
|
+
example: 'aether sdk getEpochInfo',
|
|
116
|
+
},
|
|
117
|
+
getHealth: {
|
|
118
|
+
desc: 'Check node health',
|
|
119
|
+
args: [],
|
|
120
|
+
returns: 'health status',
|
|
121
|
+
example: 'aether sdk getHealth',
|
|
122
|
+
},
|
|
123
|
+
getVersion: {
|
|
124
|
+
desc: 'Get node version',
|
|
125
|
+
args: [],
|
|
126
|
+
returns: 'version info',
|
|
127
|
+
example: 'aether sdk getVersion',
|
|
128
|
+
},
|
|
129
|
+
getTPS: {
|
|
130
|
+
desc: 'Get transactions per second',
|
|
131
|
+
args: [],
|
|
132
|
+
returns: 'TPS number',
|
|
133
|
+
example: 'aether sdk getTPS',
|
|
134
|
+
},
|
|
135
|
+
getSupply: {
|
|
136
|
+
desc: 'Get token supply info',
|
|
137
|
+
args: [],
|
|
138
|
+
returns: 'supply data',
|
|
139
|
+
example: 'aether sdk getSupply',
|
|
140
|
+
},
|
|
141
|
+
getFees: {
|
|
142
|
+
desc: 'Get fee schedule',
|
|
143
|
+
args: [],
|
|
144
|
+
returns: 'fee info',
|
|
145
|
+
example: 'aether sdk getFees',
|
|
146
|
+
},
|
|
147
|
+
getRecentBlockhash: {
|
|
148
|
+
desc: 'Get recent blockhash',
|
|
149
|
+
args: [],
|
|
150
|
+
returns: 'blockhash',
|
|
151
|
+
example: 'aether sdk getRecentBlockhash',
|
|
152
|
+
},
|
|
153
|
+
getSlotProduction: {
|
|
154
|
+
desc: 'Get slot production stats',
|
|
155
|
+
args: [],
|
|
156
|
+
returns: 'production stats',
|
|
157
|
+
example: 'aether sdk getSlotProduction',
|
|
158
|
+
},
|
|
159
|
+
getClusterPeers: {
|
|
160
|
+
desc: 'Get cluster peers',
|
|
161
|
+
args: [],
|
|
162
|
+
returns: 'peers list',
|
|
163
|
+
example: 'aether sdk getClusterPeers',
|
|
164
|
+
},
|
|
165
|
+
getValidators: {
|
|
166
|
+
desc: 'Get validators list',
|
|
167
|
+
args: [],
|
|
168
|
+
returns: 'validators',
|
|
169
|
+
example: 'aether sdk getValidators',
|
|
170
|
+
},
|
|
171
|
+
|
|
172
|
+
// Account queries
|
|
173
|
+
getAccountInfo: {
|
|
174
|
+
desc: 'Get account info',
|
|
175
|
+
args: ['address'],
|
|
176
|
+
returns: 'account data',
|
|
177
|
+
example: 'aether sdk getAccountInfo ATHxxx...',
|
|
178
|
+
},
|
|
179
|
+
getBalance: {
|
|
180
|
+
desc: 'Get account balance',
|
|
181
|
+
args: ['address'],
|
|
182
|
+
returns: 'balance in lamports',
|
|
183
|
+
example: 'aether sdk getBalance ATHxxx...',
|
|
184
|
+
},
|
|
185
|
+
getStakePositions: {
|
|
186
|
+
desc: 'Get stake positions',
|
|
187
|
+
args: ['address'],
|
|
188
|
+
returns: 'stake positions',
|
|
189
|
+
example: 'aether sdk getStakePositions ATHxxx...',
|
|
190
|
+
},
|
|
191
|
+
getRewards: {
|
|
192
|
+
desc: 'Get rewards info',
|
|
193
|
+
args: ['address'],
|
|
194
|
+
returns: 'rewards data',
|
|
195
|
+
example: 'aether sdk getRewards ATHxxx...',
|
|
196
|
+
},
|
|
197
|
+
getStakeAccounts: {
|
|
198
|
+
desc: 'Get all stake accounts',
|
|
199
|
+
args: ['address'],
|
|
200
|
+
returns: 'stake accounts',
|
|
201
|
+
example: 'aether sdk getStakeAccounts ATHxxx...',
|
|
202
|
+
},
|
|
203
|
+
getTokenAccounts: {
|
|
204
|
+
desc: 'Get token accounts',
|
|
205
|
+
args: ['address'],
|
|
206
|
+
returns: 'token accounts',
|
|
207
|
+
example: 'aether sdk getTokenAccounts ATHxxx...',
|
|
208
|
+
},
|
|
209
|
+
getNFTHoldings: {
|
|
210
|
+
desc: 'Get NFT holdings',
|
|
211
|
+
args: ['address'],
|
|
212
|
+
returns: 'NFT holdings',
|
|
213
|
+
example: 'aether sdk getNFTHoldings ATHxxx...',
|
|
214
|
+
},
|
|
215
|
+
getNFTsByCreator: {
|
|
216
|
+
desc: 'Get NFTs by creator',
|
|
217
|
+
args: ['address'],
|
|
218
|
+
returns: 'NFTs list',
|
|
219
|
+
example: 'aether sdk getNFTsByCreator ATHxxx...',
|
|
220
|
+
},
|
|
221
|
+
|
|
222
|
+
// Transaction queries
|
|
223
|
+
getTransaction: {
|
|
224
|
+
desc: 'Get transaction by signature',
|
|
225
|
+
args: ['signature'],
|
|
226
|
+
returns: 'transaction data',
|
|
227
|
+
example: 'aether sdk getTransaction SIGxxx...',
|
|
228
|
+
},
|
|
229
|
+
getRecentTransactions: {
|
|
230
|
+
desc: 'Get recent transactions',
|
|
231
|
+
args: ['address', 'limit?'],
|
|
232
|
+
returns: 'transactions list',
|
|
233
|
+
example: 'aether sdk getRecentTransactions ATHxxx...',
|
|
234
|
+
},
|
|
235
|
+
getTransactionHistory: {
|
|
236
|
+
desc: 'Get full tx history with details',
|
|
237
|
+
args: ['address', 'limit?'],
|
|
238
|
+
returns: 'tx history',
|
|
239
|
+
example: 'aether sdk getTransactionHistory ATHxxx...',
|
|
240
|
+
},
|
|
241
|
+
|
|
242
|
+
// NFT queries
|
|
243
|
+
getNFT: {
|
|
244
|
+
desc: 'Get NFT details',
|
|
245
|
+
args: ['id'],
|
|
246
|
+
returns: 'NFT data',
|
|
247
|
+
example: 'aether sdk getNFT <id>',
|
|
248
|
+
},
|
|
249
|
+
|
|
250
|
+
// Utilities
|
|
251
|
+
ping: {
|
|
252
|
+
desc: 'Ping RPC endpoint',
|
|
253
|
+
args: ['url?'],
|
|
254
|
+
returns: 'ping result',
|
|
255
|
+
example: 'aether sdk ping',
|
|
256
|
+
},
|
|
257
|
+
};
|
|
258
|
+
|
|
259
|
+
// ============================================================================
|
|
260
|
+
// Argument Parsing
|
|
261
|
+
// ============================================================================
|
|
262
|
+
|
|
263
|
+
function parseArgs() {
|
|
264
|
+
const args = process.argv.slice(2);
|
|
265
|
+
const opts = {
|
|
266
|
+
method: null,
|
|
267
|
+
args: [],
|
|
268
|
+
rpc: getDefaultRpc(),
|
|
269
|
+
json: false,
|
|
270
|
+
list: false,
|
|
271
|
+
help: false,
|
|
272
|
+
};
|
|
273
|
+
|
|
274
|
+
// Check for --list
|
|
275
|
+
if (args.includes('--list') || args.includes('-l')) {
|
|
276
|
+
opts.list = true;
|
|
277
|
+
return opts;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
// Check for --help
|
|
281
|
+
if (args.includes('--help') || args.includes('-h')) {
|
|
282
|
+
opts.help = true;
|
|
283
|
+
return opts;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
// Parse method and arguments
|
|
287
|
+
for (let i = 0; i < args.length; i++) {
|
|
288
|
+
const arg = args[i];
|
|
289
|
+
|
|
290
|
+
if (arg === '--rpc' || arg === '-r') {
|
|
291
|
+
opts.rpc = args[++i];
|
|
292
|
+
} else if (arg === '--json' || arg === '-j') {
|
|
293
|
+
opts.json = true;
|
|
294
|
+
} else if (arg === '--list' || arg === '-l') {
|
|
295
|
+
opts.list = true;
|
|
296
|
+
} else if (arg === '--help' || arg === '-h') {
|
|
297
|
+
opts.help = true;
|
|
298
|
+
} else if (!opts.method && !arg.startsWith('-')) {
|
|
299
|
+
// First non-flag argument is the method
|
|
300
|
+
opts.method = arg;
|
|
301
|
+
} else if (opts.method && !arg.startsWith('-')) {
|
|
302
|
+
// Subsequent non-flag arguments are method args
|
|
303
|
+
opts.args.push(arg);
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
return opts;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
function showHelp() {
|
|
311
|
+
console.log(`
|
|
312
|
+
${C.bright}${C.cyan}aether-cli sdk${C.reset} - Direct SDK access for developers
|
|
313
|
+
|
|
314
|
+
${C.bright}USAGE${C.reset}
|
|
315
|
+
aether sdk <method> [args...] [options]
|
|
316
|
+
|
|
317
|
+
${C.bright}CORE CHAIN QUERIES${C.reset}
|
|
318
|
+
getSlot Get current slot number
|
|
319
|
+
getBlockHeight Get current block height
|
|
320
|
+
getEpochInfo Get epoch information
|
|
321
|
+
getHealth Check node health
|
|
322
|
+
getVersion Get node version info
|
|
323
|
+
getTPS Get transactions per second
|
|
324
|
+
getSupply Get token supply
|
|
325
|
+
getFees Get fee schedule
|
|
326
|
+
getRecentBlockhash Get recent blockhash
|
|
327
|
+
getSlotProduction Get slot production stats
|
|
328
|
+
getClusterPeers Get cluster peer nodes
|
|
329
|
+
getValidators List validators
|
|
330
|
+
|
|
331
|
+
${C.bright}ACCOUNT QUERIES${C.reset}
|
|
332
|
+
getAccountInfo <address> Get account info
|
|
333
|
+
getBalance <address> Get balance in lamports
|
|
334
|
+
getStakePositions <address> Get stake positions
|
|
335
|
+
getRewards <address> Get rewards info
|
|
336
|
+
getStakeAccounts <address> Get all stake accounts
|
|
337
|
+
getTokenAccounts <address> Get token accounts
|
|
338
|
+
getNFTHoldings <address> Get NFT holdings
|
|
339
|
+
getNFTsByCreator <address> Get NFTs by creator
|
|
340
|
+
|
|
341
|
+
${C.bright}TRANSACTION QUERIES${C.reset}
|
|
342
|
+
getTransaction <signature> Get transaction by signature
|
|
343
|
+
getRecentTransactions <addr> Get recent transactions
|
|
344
|
+
getTransactionHistory <addr> Get tx history with details
|
|
345
|
+
|
|
346
|
+
${C.bright}NFT QUERIES${C.reset}
|
|
347
|
+
getNFT <id> Get NFT details
|
|
348
|
+
|
|
349
|
+
${C.bright}UTILITIES${C.reset}
|
|
350
|
+
ping [url] Ping RPC endpoint
|
|
351
|
+
--list List all SDK methods
|
|
352
|
+
|
|
353
|
+
${C.bright}OPTIONS${C.reset}
|
|
354
|
+
--rpc <url> RPC endpoint (default: ${getDefaultRpc()})
|
|
355
|
+
--json Output as JSON
|
|
356
|
+
--help Show this help
|
|
357
|
+
|
|
358
|
+
${C.bright}EXAMPLES${C.reset}
|
|
359
|
+
aether sdk getSlot
|
|
360
|
+
aether sdk getBalance ATH3abc...
|
|
361
|
+
aether sdk getAccountInfo ATH3abc... --json
|
|
362
|
+
aether sdk getValidators --json
|
|
363
|
+
aether sdk getStakePositions ATH3abc...
|
|
364
|
+
aether sdk ping --rpc http://custom-rpc:8899
|
|
365
|
+
AETHER_RPC=https://rpc.aether.network aether sdk getEpochInfo
|
|
366
|
+
`);
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
function showMethodList() {
|
|
370
|
+
console.log(`\n${C.bright}${C.cyan}══ Available SDK Methods ══${C.reset}\n`);
|
|
371
|
+
|
|
372
|
+
const categories = {
|
|
373
|
+
'Core Chain': ['getSlot', 'getBlockHeight', 'getEpochInfo', 'getHealth', 'getVersion', 'getTPS', 'getSupply', 'getFees', 'getRecentBlockhash', 'getSlotProduction', 'getClusterPeers', 'getValidators'],
|
|
374
|
+
'Account': ['getAccountInfo', 'getBalance', 'getStakePositions', 'getRewards', 'getStakeAccounts', 'getTokenAccounts', 'getNFTHoldings', 'getNFTsByCreator'],
|
|
375
|
+
'Transaction': ['getTransaction', 'getRecentTransactions', 'getTransactionHistory'],
|
|
376
|
+
'NFT': ['getNFT'],
|
|
377
|
+
'Utility': ['ping'],
|
|
378
|
+
};
|
|
379
|
+
|
|
380
|
+
for (const [category, methods] of Object.entries(categories)) {
|
|
381
|
+
console.log(`\n${C.bright}${C.cyan}${category}${C.reset}`);
|
|
382
|
+
for (const method of methods) {
|
|
383
|
+
const info = SDK_METHODS[method];
|
|
384
|
+
if (info) {
|
|
385
|
+
const argsStr = info.args.length > 0 ? ` <${info.args.join('> <')}>` : '';
|
|
386
|
+
console.log(` ${C.green}${method.padEnd(25)}${C.reset} ${C.dim}${info.desc}${C.reset}`);
|
|
387
|
+
console.log(` ${C.dim}Usage: ${info.example}${C.reset}`);
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
console.log(`\n${C.dim}All methods make REAL RPC calls to ${getDefaultRpc()}${C.reset}\n`);
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
// ============================================================================
|
|
396
|
+
// SDK Method Execution
|
|
397
|
+
// ============================================================================
|
|
398
|
+
|
|
399
|
+
async function executeMethod(opts) {
|
|
400
|
+
const { method, args, rpc, json } = opts;
|
|
401
|
+
|
|
402
|
+
if (!method) {
|
|
403
|
+
throw new Error('No method specified. Use --list to see available methods.');
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
// Validate method exists
|
|
407
|
+
if (!SDK_METHODS[method]) {
|
|
408
|
+
throw new Error(`Unknown method: ${method}. Use --list to see available methods.`);
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
const client = createClient(rpc);
|
|
412
|
+
const methodInfo = SDK_METHODS[method];
|
|
413
|
+
|
|
414
|
+
// Validate required arguments
|
|
415
|
+
if (methodInfo.args.length > args.length) {
|
|
416
|
+
throw new Error(`Method ${method} requires ${methodInfo.args.length} argument(s): ${methodInfo.args.join(', ')}`);
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
// Execute the method
|
|
420
|
+
let result;
|
|
421
|
+
|
|
422
|
+
switch (method) {
|
|
423
|
+
// Core chain queries
|
|
424
|
+
case 'getSlot':
|
|
425
|
+
result = await client.getSlot();
|
|
426
|
+
break;
|
|
427
|
+
case 'getBlockHeight':
|
|
428
|
+
result = await client.getBlockHeight();
|
|
429
|
+
break;
|
|
430
|
+
case 'getEpochInfo':
|
|
431
|
+
result = await client.getEpochInfo();
|
|
432
|
+
break;
|
|
433
|
+
case 'getHealth':
|
|
434
|
+
result = await client.getHealth();
|
|
435
|
+
break;
|
|
436
|
+
case 'getVersion':
|
|
437
|
+
result = await client.getVersion();
|
|
438
|
+
break;
|
|
439
|
+
case 'getTPS':
|
|
440
|
+
result = await client.getTPS();
|
|
441
|
+
break;
|
|
442
|
+
case 'getSupply':
|
|
443
|
+
result = await client.getSupply();
|
|
444
|
+
break;
|
|
445
|
+
case 'getFees':
|
|
446
|
+
result = await client.getFees();
|
|
447
|
+
break;
|
|
448
|
+
case 'getRecentBlockhash':
|
|
449
|
+
result = await client.getRecentBlockhash();
|
|
450
|
+
break;
|
|
451
|
+
case 'getSlotProduction':
|
|
452
|
+
result = await client.getSlotProduction();
|
|
453
|
+
break;
|
|
454
|
+
case 'getClusterPeers':
|
|
455
|
+
result = await client.getClusterPeers();
|
|
456
|
+
break;
|
|
457
|
+
case 'getValidators':
|
|
458
|
+
result = await client.getValidators();
|
|
459
|
+
break;
|
|
460
|
+
|
|
461
|
+
// Account queries
|
|
462
|
+
case 'getAccountInfo':
|
|
463
|
+
result = await client.getAccountInfo(args[0]);
|
|
464
|
+
break;
|
|
465
|
+
case 'getBalance':
|
|
466
|
+
result = await client.getBalance(args[0]);
|
|
467
|
+
break;
|
|
468
|
+
case 'getStakePositions':
|
|
469
|
+
result = await client.getStakePositions(args[0]);
|
|
470
|
+
break;
|
|
471
|
+
case 'getRewards':
|
|
472
|
+
result = await client.getRewards(args[0]);
|
|
473
|
+
break;
|
|
474
|
+
case 'getStakeAccounts':
|
|
475
|
+
result = await client.getStakeAccounts(args[0]);
|
|
476
|
+
break;
|
|
477
|
+
case 'getTokenAccounts':
|
|
478
|
+
result = await client.getTokenAccounts(args[0]);
|
|
479
|
+
break;
|
|
480
|
+
case 'getNFTHoldings':
|
|
481
|
+
result = await client.getNFTHoldings(args[0]);
|
|
482
|
+
break;
|
|
483
|
+
case 'getNFTsByCreator':
|
|
484
|
+
result = await client.getNFTsByCreator(args[0]);
|
|
485
|
+
break;
|
|
486
|
+
|
|
487
|
+
// Transaction queries
|
|
488
|
+
case 'getTransaction':
|
|
489
|
+
result = await client.getTransaction(args[0]);
|
|
490
|
+
break;
|
|
491
|
+
case 'getRecentTransactions':
|
|
492
|
+
result = await client.getRecentTransactions(args[0], parseInt(args[1]) || 20);
|
|
493
|
+
break;
|
|
494
|
+
case 'getTransactionHistory':
|
|
495
|
+
result = await client.getTransactionHistory(args[0], parseInt(args[1]) || 20);
|
|
496
|
+
break;
|
|
497
|
+
|
|
498
|
+
// NFT queries
|
|
499
|
+
case 'getNFT':
|
|
500
|
+
result = await client.getNFT(args[0]);
|
|
501
|
+
break;
|
|
502
|
+
|
|
503
|
+
// Utilities
|
|
504
|
+
case 'ping':
|
|
505
|
+
result = await aether.ping(args[0] || rpc);
|
|
506
|
+
break;
|
|
507
|
+
|
|
508
|
+
default:
|
|
509
|
+
throw new Error(`Method ${method} not implemented in CLI`);
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
// Output result
|
|
513
|
+
if (json) {
|
|
514
|
+
console.log(JSON.stringify({
|
|
515
|
+
method,
|
|
516
|
+
args,
|
|
517
|
+
rpc,
|
|
518
|
+
result,
|
|
519
|
+
timestamp: new Date().toISOString(),
|
|
520
|
+
cli_version: CLI_VERSION,
|
|
521
|
+
}, null, 2));
|
|
522
|
+
} else {
|
|
523
|
+
// Pretty output
|
|
524
|
+
console.log(`\n${C.bright}${C.cyan}══ SDK Result: ${method} ══${C.reset}\n`);
|
|
525
|
+
console.log(` ${C.dim}RPC:${C.reset} ${rpc}`);
|
|
526
|
+
console.log(` ${C.dim}Method:${C.reset} ${method}`);
|
|
527
|
+
if (args.length > 0) {
|
|
528
|
+
console.log(` ${C.dim}Args:${C.reset} ${args.join(' ')}`);
|
|
529
|
+
}
|
|
530
|
+
console.log();
|
|
531
|
+
|
|
532
|
+
// Format result based on type
|
|
533
|
+
if (typeof result === 'object') {
|
|
534
|
+
// Special formatting for specific methods
|
|
535
|
+
if (method === 'getBalance') {
|
|
536
|
+
console.log(` ${C.green}Balance:${C.reset} ${formatNumber(result)} lamports`);
|
|
537
|
+
console.log(` ${C.green}Formatted:${C.reset} ${formatAether(result)}`);
|
|
538
|
+
} else if (method === 'getSlot' || method === 'getBlockHeight') {
|
|
539
|
+
console.log(` ${C.green}Result:${C.reset} ${formatNumber(result)}`);
|
|
540
|
+
} else if (method === 'getTPS') {
|
|
541
|
+
console.log(` ${C.green}TPS:${C.reset} ${result}`);
|
|
542
|
+
} else if (method === 'getHealth') {
|
|
543
|
+
const status = result === 'ok' ? C.green : C.yellow;
|
|
544
|
+
console.log(` ${C.green}Status:${C.reset} ${status}${result}${C.reset}`);
|
|
545
|
+
} else {
|
|
546
|
+
// Generic object output
|
|
547
|
+
console.log(` ${C.green}Result:${C.reset}`);
|
|
548
|
+
console.log(JSON.stringify(result, null, 2).split('\n').map(l => ` ${C.dim}${l}${C.reset}`).join('\n'));
|
|
549
|
+
}
|
|
550
|
+
} else if (Array.isArray(result)) {
|
|
551
|
+
console.log(` ${C.green}Count:${C.reset} ${result.length}`);
|
|
552
|
+
if (result.length === 0) {
|
|
553
|
+
console.log(` ${C.dim}(empty array)${C.reset}`);
|
|
554
|
+
} else {
|
|
555
|
+
// Show first few items
|
|
556
|
+
const preview = result.slice(0, 3);
|
|
557
|
+
preview.forEach((item, i) => {
|
|
558
|
+
if (typeof item === 'object') {
|
|
559
|
+
const id = item.pubkey || item.address || item.signature || item.id || `Item ${i + 1}`;
|
|
560
|
+
console.log(` ${C.dim}[${i}]${C.reset} ${shortAddress(id)}`);
|
|
561
|
+
} else {
|
|
562
|
+
console.log(` ${C.dim}[${i}]${C.reset} ${item}`);
|
|
563
|
+
}
|
|
564
|
+
});
|
|
565
|
+
if (result.length > 3) {
|
|
566
|
+
console.log(` ${C.dim}... and ${result.length - 3} more${C.reset}`);
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
} else {
|
|
570
|
+
console.log(` ${C.green}Result:${C.reset} ${result}`);
|
|
571
|
+
}
|
|
572
|
+
console.log();
|
|
573
|
+
console.log(` ${C.dim}SDK: @jellylegsai/aether-sdk v${CLI_VERSION}${C.reset}`);
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
return result;
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
// ============================================================================
|
|
580
|
+
// Interactive Mode
|
|
581
|
+
// ============================================================================
|
|
582
|
+
|
|
583
|
+
async function interactiveMode() {
|
|
584
|
+
const rl = readline.createInterface({
|
|
585
|
+
input: process.stdin,
|
|
586
|
+
output: process.stdout,
|
|
587
|
+
});
|
|
588
|
+
|
|
589
|
+
console.log(`\n${C.bright}${C.cyan}══ Aether SDK Interactive Mode ══${C.reset}\n`);
|
|
590
|
+
console.log(`${C.dim}Type a method name or 'help' for usage, 'exit' to quit.${C.reset}\n`);
|
|
591
|
+
|
|
592
|
+
const ask = () => {
|
|
593
|
+
return new Promise((resolve) => {
|
|
594
|
+
rl.question(`${C.cyan}sdk>${C.reset} `, (answer) => {
|
|
595
|
+
resolve(answer.trim());
|
|
596
|
+
});
|
|
597
|
+
});
|
|
598
|
+
};
|
|
599
|
+
|
|
600
|
+
while (true) {
|
|
601
|
+
const input = await ask();
|
|
602
|
+
|
|
603
|
+
if (input === 'exit' || input === 'quit') {
|
|
604
|
+
console.log(`${C.dim}Goodbye!${C.reset}\n`);
|
|
605
|
+
rl.close();
|
|
606
|
+
break;
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
if (input === 'help' || input === '?') {
|
|
610
|
+
showMethodList();
|
|
611
|
+
continue;
|
|
612
|
+
}
|
|
613
|
+
|
|
614
|
+
if (input === 'list' || input === 'ls') {
|
|
615
|
+
showMethodList();
|
|
616
|
+
continue;
|
|
617
|
+
}
|
|
618
|
+
|
|
619
|
+
if (!input) continue;
|
|
620
|
+
|
|
621
|
+
// Parse input as command
|
|
622
|
+
const parts = input.split(/\s+/);
|
|
623
|
+
const method = parts[0];
|
|
624
|
+
const args = parts.slice(1);
|
|
625
|
+
|
|
626
|
+
if (!SDK_METHODS[method]) {
|
|
627
|
+
console.log(`${C.red}✗ Unknown method: ${method}${C.reset}`);
|
|
628
|
+
console.log(`${C.dim}Use 'list' to see available methods${C.reset}\n`);
|
|
629
|
+
continue;
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
// Execute the method
|
|
633
|
+
try {
|
|
634
|
+
const client = createClient(getDefaultRpc());
|
|
635
|
+
let result;
|
|
636
|
+
|
|
637
|
+
switch (method) {
|
|
638
|
+
case 'getSlot':
|
|
639
|
+
result = await client.getSlot();
|
|
640
|
+
break;
|
|
641
|
+
case 'getBlockHeight':
|
|
642
|
+
result = await client.getBlockHeight();
|
|
643
|
+
break;
|
|
644
|
+
case 'getEpochInfo':
|
|
645
|
+
result = await client.getEpochInfo();
|
|
646
|
+
break;
|
|
647
|
+
case 'getHealth':
|
|
648
|
+
result = await client.getHealth();
|
|
649
|
+
break;
|
|
650
|
+
case 'getVersion':
|
|
651
|
+
result = await client.getVersion();
|
|
652
|
+
break;
|
|
653
|
+
case 'getTPS':
|
|
654
|
+
result = await client.getTPS();
|
|
655
|
+
break;
|
|
656
|
+
case 'getSupply':
|
|
657
|
+
result = await client.getSupply();
|
|
658
|
+
break;
|
|
659
|
+
case 'getFees':
|
|
660
|
+
result = await client.getFees();
|
|
661
|
+
break;
|
|
662
|
+
case 'getRecentBlockhash':
|
|
663
|
+
result = await client.getRecentBlockhash();
|
|
664
|
+
break;
|
|
665
|
+
case 'getSlotProduction':
|
|
666
|
+
result = await client.getSlotProduction();
|
|
667
|
+
break;
|
|
668
|
+
case 'getClusterPeers':
|
|
669
|
+
result = await client.getClusterPeers();
|
|
670
|
+
break;
|
|
671
|
+
case 'getValidators':
|
|
672
|
+
result = await client.getValidators();
|
|
673
|
+
break;
|
|
674
|
+
case 'getAccountInfo':
|
|
675
|
+
result = await client.getAccountInfo(args[0]);
|
|
676
|
+
break;
|
|
677
|
+
case 'getBalance':
|
|
678
|
+
result = await client.getBalance(args[0]);
|
|
679
|
+
break;
|
|
680
|
+
case 'getStakePositions':
|
|
681
|
+
result = await client.getStakePositions(args[0]);
|
|
682
|
+
break;
|
|
683
|
+
case 'getRewards':
|
|
684
|
+
result = await client.getRewards(args[0]);
|
|
685
|
+
break;
|
|
686
|
+
case 'getStakeAccounts':
|
|
687
|
+
result = await client.getStakeAccounts(args[0]);
|
|
688
|
+
break;
|
|
689
|
+
case 'getTokenAccounts':
|
|
690
|
+
result = await client.getTokenAccounts(args[0]);
|
|
691
|
+
break;
|
|
692
|
+
case 'getNFTHoldings':
|
|
693
|
+
result = await client.getNFTHoldings(args[0]);
|
|
694
|
+
break;
|
|
695
|
+
case 'getNFTsByCreator':
|
|
696
|
+
result = await client.getNFTsByCreator(args[0]);
|
|
697
|
+
break;
|
|
698
|
+
case 'getTransaction':
|
|
699
|
+
result = await client.getTransaction(args[0]);
|
|
700
|
+
break;
|
|
701
|
+
case 'getRecentTransactions':
|
|
702
|
+
result = await client.getRecentTransactions(args[0], parseInt(args[1]) || 20);
|
|
703
|
+
break;
|
|
704
|
+
case 'getTransactionHistory':
|
|
705
|
+
result = await client.getTransactionHistory(args[0], parseInt(args[1]) || 20);
|
|
706
|
+
break;
|
|
707
|
+
case 'getNFT':
|
|
708
|
+
result = await client.getNFT(args[0]);
|
|
709
|
+
break;
|
|
710
|
+
case 'ping':
|
|
711
|
+
result = await aether.ping(args[0] || getDefaultRpc());
|
|
712
|
+
break;
|
|
713
|
+
default:
|
|
714
|
+
throw new Error(`Method ${method} not implemented`);
|
|
715
|
+
}
|
|
716
|
+
|
|
717
|
+
// Show result
|
|
718
|
+
if (typeof result === 'object') {
|
|
719
|
+
if (method === 'getBalance') {
|
|
720
|
+
console.log(` ${C.green}Balance:${C.reset} ${formatNumber(result)} lamports (${formatAether(result)})`);
|
|
721
|
+
} else if (method === 'getSlot' || method === 'getBlockHeight') {
|
|
722
|
+
console.log(` ${C.green}Result:${C.reset} ${formatNumber(result)}`);
|
|
723
|
+
} else if (method === 'getTPS') {
|
|
724
|
+
console.log(` ${C.green}TPS:${C.reset} ${result}`);
|
|
725
|
+
} else if (method === 'getHealth') {
|
|
726
|
+
const status = result === 'ok' ? `${C.green}OK${C.reset}` : `${C.yellow}${result}${C.reset}`;
|
|
727
|
+
console.log(` ${C.green}Status:${C.reset} ${status}`);
|
|
728
|
+
} else if (Array.isArray(result)) {
|
|
729
|
+
console.log(` ${C.green}Count:${C.reset} ${result.length}`);
|
|
730
|
+
result.slice(0, 5).forEach((item, i) => {
|
|
731
|
+
const id = item.pubkey || item.address || item.signature || item.id || `Item ${i + 1}`;
|
|
732
|
+
console.log(` ${C.dim}[${i}]${C.reset} ${shortAddress(id)}`);
|
|
733
|
+
});
|
|
734
|
+
if (result.length > 5) {
|
|
735
|
+
console.log(` ${C.dim}... and ${result.length - 5} more${C.reset}`);
|
|
736
|
+
}
|
|
737
|
+
} else {
|
|
738
|
+
console.log(` ${C.green}Result:${C.reset}`);
|
|
739
|
+
console.log(JSON.stringify(result, null, 2).split('\n').map(l => ` ${C.dim}${l}${C.reset}`).join('\n'));
|
|
740
|
+
}
|
|
741
|
+
} else {
|
|
742
|
+
console.log(` ${C.green}Result:${C.reset} ${result}`);
|
|
743
|
+
}
|
|
744
|
+
console.log();
|
|
745
|
+
|
|
746
|
+
} catch (err) {
|
|
747
|
+
console.log(`${C.red}✗ Error: ${err.message}${C.reset}\n`);
|
|
748
|
+
}
|
|
749
|
+
}
|
|
750
|
+
}
|
|
751
|
+
|
|
752
|
+
// ============================================================================
|
|
753
|
+
// Main Entry Point
|
|
754
|
+
// ============================================================================
|
|
755
|
+
|
|
756
|
+
async function sdkCommand() {
|
|
757
|
+
const opts = parseArgs();
|
|
758
|
+
|
|
759
|
+
if (opts.help) {
|
|
760
|
+
showHelp();
|
|
761
|
+
return;
|
|
762
|
+
}
|
|
763
|
+
|
|
764
|
+
if (opts.list) {
|
|
765
|
+
showMethodList();
|
|
766
|
+
return;
|
|
767
|
+
}
|
|
768
|
+
|
|
769
|
+
if (!opts.method) {
|
|
770
|
+
// Interactive mode if no method specified
|
|
771
|
+
await interactiveMode();
|
|
772
|
+
return;
|
|
773
|
+
}
|
|
774
|
+
|
|
775
|
+
try {
|
|
776
|
+
await executeMethod(opts);
|
|
777
|
+
} catch (err) {
|
|
778
|
+
console.error(`\n${C.red}✗ SDK command failed:${C.reset} ${err.message}\n`);
|
|
779
|
+
console.error(`${C.dim}Run ${C.cyan}aether sdk --list${C.reset}${C.dim} to see available methods${C.reset}\n`);
|
|
780
|
+
process.exit(1);
|
|
781
|
+
}
|
|
782
|
+
}
|
|
783
|
+
|
|
784
|
+
module.exports = { sdkCommand };
|
|
785
|
+
|
|
786
|
+
if (require.main === module) {
|
|
787
|
+
sdkCommand().catch(err => {
|
|
788
|
+
console.error(`${C.red}✗ SDK command failed:${C.reset} ${err.message}`);
|
|
789
|
+
process.exit(1);
|
|
790
|
+
});
|
|
791
|
+
}
|