65f7179557
CRITICAL fixes: - Stop passing mint URLs as relay URLs in initNDK (protocol mismatch) - Add unit tests for buildTransactionHistory (dedup, fallback, sort) HIGH fixes: - Restore .claude entry in .gitignore - Add warning logging for skipped malformed proof tags in nutzap parsing - Add error handling + 30s timeout to NDK initialization - Add unit tests for formatCSV and escapeField - Export escapeField for testability Also: add test script to package.json, include test/ in tsconfig Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
87 lines
2.3 KiB
TypeScript
87 lines
2.3 KiB
TypeScript
import { initNDK } from "./ndk.js";
|
|
import {
|
|
fetchWalletData,
|
|
fetchTokenEvents,
|
|
fetchHistoryEvents,
|
|
fetchNutzapEvents,
|
|
fetchNutzapRedemptions,
|
|
buildTransactionHistory,
|
|
} from "./events.js";
|
|
import { formatCSV } from "./csv.js";
|
|
|
|
function usage(): never {
|
|
console.error(`Usage: NOSTR_SECRET_KEY=<hex|nsec> bun run src/index.ts [--mints <url1,url2,...>]
|
|
|
|
Options:
|
|
--mints Comma-separated list of additional mint URLs to include
|
|
|
|
Environment:
|
|
NOSTR_SECRET_KEY Required. Nostr private key in hex or nsec format.`);
|
|
process.exit(1);
|
|
}
|
|
|
|
async function main() {
|
|
const secretKey = process.env.NOSTR_SECRET_KEY;
|
|
if (!secretKey) {
|
|
console.error("Error: NOSTR_SECRET_KEY environment variable is required");
|
|
usage();
|
|
}
|
|
|
|
// Parse --mints flag
|
|
const args = process.argv.slice(2);
|
|
const mintsIdx = args.indexOf("--mints");
|
|
const extraMints =
|
|
mintsIdx !== -1 && args[mintsIdx + 1]
|
|
? args[mintsIdx + 1].split(",").filter(Boolean)
|
|
: [];
|
|
|
|
// Initialize NDK (don't pass mints as relays — they use different protocols)
|
|
const { ndk, signer, user } = await initNDK(secretKey);
|
|
|
|
// Fetch wallet data first (need mints for context)
|
|
const walletData = await fetchWalletData(ndk, user, signer);
|
|
const allMints = [...new Set([...walletData.mints, ...extraMints])];
|
|
if (allMints.length > 0) {
|
|
console.error(`Discovered mints: ${allMints.join(", ")}`);
|
|
}
|
|
|
|
// Fetch all events in parallel
|
|
const [tokens, history, nutzaps, redemptions] = await Promise.all([
|
|
fetchTokenEvents(ndk, user, signer),
|
|
fetchHistoryEvents(ndk, user, signer),
|
|
fetchNutzapEvents(ndk, user),
|
|
fetchNutzapRedemptions(ndk, user, signer),
|
|
]);
|
|
|
|
// Build unified transaction history
|
|
const records = buildTransactionHistory(
|
|
walletData,
|
|
tokens,
|
|
history,
|
|
nutzaps,
|
|
redemptions
|
|
);
|
|
|
|
console.error(`Total transactions: ${records.length}`);
|
|
|
|
// Output CSV to stdout
|
|
const csv = formatCSV(records);
|
|
process.stdout.write(csv + "\n");
|
|
|
|
// Clean shutdown
|
|
// NDK doesn't have a disconnect method that returns a promise reliably,
|
|
// so we just exit after output
|
|
process.exit(0);
|
|
}
|
|
|
|
// Handle SIGINT
|
|
process.on("SIGINT", () => {
|
|
console.error("\nInterrupted.");
|
|
process.exit(1);
|
|
});
|
|
|
|
main().catch((err) => {
|
|
console.error(`Error: ${err instanceof Error ? err.message : err}`);
|
|
process.exit(1);
|
|
});
|