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.
- package/commands/wallet.js +146 -0
- package/index.js +22 -0
- package/package.json +1 -1
package/commands/wallet.js
CHANGED
|
@@ -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');
|