aether-hub 1.0.5 → 1.0.6

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.
@@ -938,6 +938,149 @@ async function transferWallet(rl) {
938
938
  }
939
939
  }
940
940
 
941
+ // ---------------------------------------------------------------------------
942
+ // TX HISTORY
943
+ // Fetch and display recent transactions for an address
944
+ // ---------------------------------------------------------------------------
945
+
946
+ async function txHistory(rl) {
947
+ console.log(`\n${C.bright}${C.cyan}── Transaction History ────────────────────────────────────${C.reset}\n`);
948
+
949
+ const args = process.argv.slice(4);
950
+ let address = null;
951
+ let limit = 20;
952
+ let asJson = false;
953
+
954
+ const addrIdx = args.findIndex((a) => a === '--address' || a === '-a');
955
+ if (addrIdx !== -1 && args[addrIdx + 1]) {
956
+ address = args[addrIdx + 1];
957
+ }
958
+
959
+ const limitIdx = args.findIndex((a) => a === '--limit' || a === '-l');
960
+ if (limitIdx !== -1 && args[limitIdx + 1]) {
961
+ limit = parseInt(args[limitIdx + 1], 10);
962
+ if (isNaN(limit) || limit < 1 || limit > 100) {
963
+ console.log(` ${C.red}✗ --limit must be between 1 and 100.${C.reset}\n`);
964
+ return;
965
+ }
966
+ }
967
+
968
+ asJson = args.includes('--json') || args.includes('-j');
969
+
970
+ if (!address) {
971
+ const cfg = loadConfig();
972
+ address = cfg.defaultWallet;
973
+ }
974
+
975
+ if (!address) {
976
+ console.log(` ${C.red}✗ No wallet address specified and no default wallet set.${C.reset}`);
977
+ console.log(` ${C.dim}Usage: aether tx history --address <addr> [--limit 20] [--json]${C.reset}\n`);
978
+ return;
979
+ }
980
+
981
+ const rpcUrl = getDefaultRpc();
982
+ const rawAddr = address.startsWith('ATH') ? address.slice(3) : address;
983
+
984
+ if (!asJson) {
985
+ console.log(` ${C.green}★${C.reset} Address: ${C.bright}${address}${C.reset}`);
986
+ console.log(` ${C.dim} RPC: ${rpcUrl} Limit: ${limit}${C.reset}`);
987
+ console.log();
988
+ }
989
+
990
+ try {
991
+ // Fetch account info first (for context)
992
+ const account = await httpRequest(rpcUrl, `/v1/account/${rawAddr}`);
993
+
994
+ // Fetch transactions for this address
995
+ const txs = await httpRequest(rpcUrl, `/v1/tx?address=${encodeURIComponent(rawAddr)}&limit=${limit}`);
996
+
997
+ if (asJson) {
998
+ const out = {
999
+ address,
1000
+ rpc: rpcUrl,
1001
+ account: account && !account.error ? {
1002
+ lamports: account.lamports,
1003
+ owner: account.owner,
1004
+ } : null,
1005
+ transactions: txs && !txs.error ? (Array.isArray(txs) ? txs : txs.transactions || []) : [],
1006
+ fetched_at: new Date().toISOString(),
1007
+ };
1008
+ console.log(JSON.stringify(out, null, 2));
1009
+ return;
1010
+ }
1011
+
1012
+ if (!account || account.error) {
1013
+ console.log(` ${C.yellow}⚠ Account not found on chain.${C.reset}`);
1014
+ } else {
1015
+ console.log(` ${C.green}✓ Balance:${C.reset} ${C.bright}${formatAether(account.lamports || 0)}${C.reset}`);
1016
+ if (account.owner) {
1017
+ const ownerStr = Array.isArray(account.owner)
1018
+ ? 'ATH' + bs58.encode(Buffer.from(account.owner.slice(0, 32)))
1019
+ : account.owner;
1020
+ console.log(` ${C.dim} Owner: ${ownerStr}${C.reset}`);
1021
+ }
1022
+ console.log();
1023
+ }
1024
+
1025
+ if (!txs || txs.error) {
1026
+ console.log(` ${C.yellow}⚠ No transaction history available.${C.reset}`);
1027
+ console.log(` ${C.dim} RPC response: ${JSON.stringify(txs?.error || txs)}${C.reset}`);
1028
+ console.log(` ${C.dim} (New wallets with 0 txs will return empty results)${C.reset}\n`);
1029
+ return;
1030
+ }
1031
+
1032
+ const txList = Array.isArray(txs) ? txs : txs.transactions || [];
1033
+ console.log(` ${C.bright}Recent Transactions (${txList.length})${C.reset}\n`);
1034
+
1035
+ if (txList.length === 0) {
1036
+ console.log(` ${C.dim} No transactions found for this address.${C.reset}`);
1037
+ console.log(` ${C.dim} This is normal for new wallets.${C.reset}\n`);
1038
+ return;
1039
+ }
1040
+
1041
+ const typeColors = {
1042
+ Transfer: C.cyan,
1043
+ Stake: C.green,
1044
+ Unstake: C.yellow,
1045
+ ClaimRewards: C.magenta,
1046
+ CreateNFT: C.red,
1047
+ MintNFT: C.red,
1048
+ TransferNFT: C.cyan,
1049
+ UpdateMetadata: C.yellow,
1050
+ };
1051
+
1052
+ for (const tx of txList) {
1053
+ const txType = tx.tx_type || tx.type || 'Unknown';
1054
+ const color = typeColors[txType] || C.reset;
1055
+ const ts = tx.timestamp
1056
+ ? new Date(tx.timestamp * 1000).toISOString()
1057
+ : 'unknown';
1058
+ const sig = tx.signature || tx.id || tx.tx_signature || '—';
1059
+ const sigShort = sig.length > 20 ? sig.slice(0, 8) + '…' + sig.slice(-8) : sig;
1060
+
1061
+ console.log(` ${C.dim}┌─ ${ts}${C.reset}`);
1062
+ console.log(` │ ${C.bright}${color}${txType}${C.reset} ${C.dim}sig:${C.reset} ${sigShort}`);
1063
+ if (tx.payload && tx.payload.data) {
1064
+ const d = tx.payload.data;
1065
+ if (d.recipient) console.log(` │ ${C.dim} → to: ${d.recipient}${C.reset}`);
1066
+ if (d.amount) console.log(` │ ${C.dim} amount: ${formatAether(d.amount)}${C.reset}`);
1067
+ if (d.validator) console.log(` │ ${C.dim} validator: ${d.validator}${C.reset}`);
1068
+ if (d.stake_account) console.log(` │ ${C.dim} stake_acct: ${d.stake_account}${C.reset}`);
1069
+ }
1070
+ if (tx.fee !== undefined && tx.fee > 0) {
1071
+ console.log(` │ ${C.dim} fee: ${tx.fee} lamports${C.reset}`);
1072
+ }
1073
+ console.log(` ${C.dim}└${C.reset}`);
1074
+ console.log();
1075
+ }
1076
+ console.log();
1077
+ } catch (err) {
1078
+ console.log(` ${C.red}✗ Failed to fetch transaction history:${C.reset} ${err.message}`);
1079
+ console.log(` ${C.dim} Is your validator running? RPC: ${rpcUrl}${C.reset}`);
1080
+ console.log(` ${C.dim} Set custom RPC: AETHER_RPC=https://your-rpc-url${C.reset}\n`);
1081
+ }
1082
+ }
1083
+
941
1084
  // ---------------------------------------------------------------------------
942
1085
  // Main dispatcher
943
1086
  // ---------------------------------------------------------------------------
@@ -967,6 +1110,8 @@ async function walletCommand() {
967
1110
  await stakeWallet(rl);
968
1111
  } else if (subcmd === 'transfer') {
969
1112
  await transferWallet(rl);
1113
+ } else if (subcmd === 'history' || subcmd === 'tx') {
1114
+ await txHistory(rl);
970
1115
  } else {
971
1116
  console.log(`\n ${C.red}Unknown wallet subcommand:${C.reset} ${subcmd}`);
972
1117
  console.log(`\n Usage:`);
@@ -978,6 +1123,7 @@ async function walletCommand() {
978
1123
  console.log(` ${C.cyan}aether wallet balance${C.reset} Query chain balance for an address`);
979
1124
  console.log(` ${C.cyan}aether wallet stake${C.reset} Stake AETH to a validator`);
980
1125
  console.log(` ${C.cyan}aether wallet transfer${C.reset} Transfer AETH to another address`);
1126
+ console.log(` ${C.cyan}aether wallet history${C.reset} Show recent transactions for an address`);
981
1127
  console.log();
982
1128
  process.exit(1);
983
1129
  }
package/index.js CHANGED
@@ -182,6 +182,26 @@ const COMMANDS = {
182
182
  process.argv = originalArgv;
183
183
  },
184
184
  },
185
+ tx: {
186
+ description: 'Transaction history — aether tx history --address <addr> [--limit 20] [--json]',
187
+ handler: () => {
188
+ const { walletCommand } = require('./commands/wallet');
189
+ const originalArgv = process.argv;
190
+ process.argv = [...originalArgv.slice(0, 2), 'wallet', 'history', ...originalArgv.slice(3)];
191
+ walletCommand();
192
+ process.argv = originalArgv;
193
+ },
194
+ },
195
+ history: {
196
+ description: 'Transaction history for an address — alias for tx history',
197
+ handler: () => {
198
+ const { walletCommand } = require('./commands/wallet');
199
+ const originalArgv = process.argv;
200
+ process.argv = [...originalArgv.slice(0, 2), 'wallet', 'history', ...originalArgv.slice(3)];
201
+ walletCommand();
202
+ process.argv = originalArgv;
203
+ },
204
+ },
185
205
  validator: {
186
206
  description: 'Validator node management',
187
207
  handler: () => {
@@ -249,6 +269,8 @@ Validator CLI v${VERSION}
249
269
  console.log(' aether-cli monitor # Real-time validator dashboard');
250
270
  console.log(' aether-cli validator start # Start validator node');
251
271
  console.log(' aether-cli validator status # Check validator status');
272
+ console.log(' aether-cli wallet balance # Query AETH balance');
273
+ console.log(' aether-cli tx history # Show transaction history');
252
274
  console.log(' aether-cli --version # Show version');
253
275
  console.log('\nDocumentation: https://github.com/jelly-legs-ai/Jelly-legs-unsteady-workshop');
254
276
  console.log('Spec: docs/MINING_VALIDATOR_TOOLS.md\n');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "aether-hub",
3
- "version": "1.0.5",
3
+ "version": "1.0.6",
4
4
  "description": "AeTHer Validator CLI — tiered validators (Full/Lite/Observer), system checks, onboarding, and node management",
5
5
  "main": "index.js",
6
6
  "bin": {