UNPKG

@stoar/cli

Version:

CLI tool for STOAR - decentralized file storage on Arweave

112 lines 5.22 kB
import { Command } from 'commander'; import { output, createSpinner, formatBytes, createTable } from '../utils/output.js'; import { wrapCommand } from '../utils/error.js'; import { getArweave } from '../utils/arweave.js'; import { fetchAndParseBundle } from '../utils/bundle.js'; export const infoCommand = new Command('info') .description('Get information about a file or transaction') .argument('<txId>', 'Transaction ID to get info for') .action(wrapCommand(async (txId, options, command) => { const globalOptions = command.parent?.opts() || {}; const spinner = createSpinner(`Fetching transaction ${txId}...`); spinner.start(); try { // Get Arweave instance const Arweave = await getArweave(); const arweave = Arweave.init({ host: 'arweave.net', port: 443, protocol: 'https' }); // Get transaction const tx = await arweave.transactions.get(txId); const status = await arweave.transactions.getStatus(txId); spinner.stop(); // Extract tags const tags = {}; tx.get('tags').forEach((tag) => { const key = tag.get('name', { decode: true, string: true }); const value = tag.get('value', { decode: true, string: true }); tags[key] = value; }); const txInfo = { id: txId, owner: await arweave.wallets.ownerToAddress(tx.owner), size: formatBytes(parseInt(tx.data_size)), reward: `${arweave.ar.winstonToAr(tx.reward)} AR`, timestamp: new Date().toISOString(), // Approximate status: status.status === 200 ? 'Confirmed' : `Pending (${status.status})`, confirmations: status.confirmed?.number_of_confirmations || 0, blockHeight: status.confirmed?.block_height || 'N/A', tags, url: `https://arweave.net/${txId}` }; if (globalOptions.json) { output(txInfo, globalOptions); } else { console.log('\nTransaction Information:'); console.log('========================'); console.log(`ID: ${txInfo.id}`); console.log(`Owner: ${txInfo.owner}`); console.log(`Size: ${txInfo.size}`); console.log(`Cost: ${txInfo.reward}`); console.log(`Status: ${txInfo.status}`); console.log(`Confirmations: ${txInfo.confirmations}`); console.log(`Block Height: ${txInfo.blockHeight}`); console.log(`URL: ${txInfo.url}`); if (Object.keys(tags).length > 0) { console.log('\nTags:'); const table = createTable(['Key', 'Value']); Object.entries(tags).forEach(([key, value]) => { table.push([key, value]); }); console.log(table.toString()); } // Check if this is a bundle transaction if (tags['Bundle-Format'] && tags['Bundle-Version']) { console.log('\n📦 This is a bundle transaction!'); console.log('Fetching bundle contents...\n'); try { const bundleInfo = await fetchAndParseBundle(txId); console.log(`Bundle contains ${bundleInfo.totalItems} data items:\n`); const bundleTable = createTable(['#', 'Item ID', 'File Name', 'Size', 'Type']); bundleInfo.items.forEach((item, index) => { bundleTable.push([ (index + 1).toString(), item.id.substring(0, 12) + '...', item.fileName || 'Unknown', formatBytes(item.size), item.contentType || 'Unknown' ]); }); console.log(bundleTable.toString()); // Show individual item details if verbose if (globalOptions.verbose) { console.log('\nDetailed Item Information:'); bundleInfo.items.forEach((item, index) => { console.log(`\n--- Item ${index + 1} ---`); console.log(`ID: ${item.id}`); console.log(`Owner: ${item.owner}`); console.log(`Size: ${formatBytes(item.size)}`); if (Object.keys(item.tags).length > 0) { console.log('Tags:'); Object.entries(item.tags).forEach(([k, v]) => { console.log(` ${k}: ${v}`); }); } }); } } catch (bundleError) { console.log('⚠️ Failed to parse bundle contents:', bundleError instanceof Error ? bundleError.message : String(bundleError)); } } } } catch (error) { spinner.stop(); throw error; } })); //# sourceMappingURL=info.js.map