deviant/scripts/scan-all-wallets-ft.mjs
Local Dev cdf197e751 docs(snapshots): 0282 chipnet A-H full FT redeem + consolidation to H
Operation ran today: swept every FT holding across A-H + gmx
(backed MBAs + non-state NBAs) back to BCH via implicit fungible-token
burn, consolidated into wallet H. 9 txs total, 51 covenant-state NFTs
preserved. H now at 2.6967 BCH (up from 1.86).

Also kept two new audit helpers from the operation:
  scripts/scan-all-wallets-ft.mjs    one-shot inventory across every
                                     .chipnet-keys-*.json
  scripts/inspect-h-utxos.mjs        classifies H's UTXOs
                                     (bch-only / ft / nft / hybrid)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-10-23 21:26:44 +03:00

58 lines
2.2 KiB
JavaScript

#!/usr/bin/env node
// Inventory FT holdings across every chipnet wallet (.chipnet-keys-*.json)
// Prints per-wallet BCH + per-category FT balances. Read-only.
import { readFileSync, readdirSync } from 'node:fs';
import { join } from 'node:path';
import { ElectrumNetworkProvider } from 'cashscript';
const ROOT = join(import.meta.dirname, '..');
const KEYS = readdirSync(ROOT).filter(f => /^\.chipnet-keys.*\.json$/.test(f)).sort();
const provider = new ElectrumNetworkProvider('chipnet');
const KNOWN = {};
try {
for (const p of ['ChipnetTests/.chipnet-asm-token.json',
'ChipnetTests/.chipnet-asm2-token.json',
'ChipnetTests/.chipnet-cap-token.json',
'ChipnetTests/.chipnet-t001-token.json']) {
const o = JSON.parse(readFileSync(join(ROOT, p), 'utf8'));
const cat = (o.tokenId || o.categoryId || '').toLowerCase();
if (cat) KNOWN[cat] = o.ticker || o.name || p.split('/').pop();
}
} catch {}
for (const k of KEYS) {
let j;
try { j = JSON.parse(readFileSync(join(ROOT, k), 'utf8')); } catch { continue; }
const addr = j.cashaddr || j.address || j.tokenaddr;
if (!addr) { console.log(`${k}: no address field`); continue; }
try {
const utxos = await provider.getUtxos(addr);
let bch = 0n;
const byCat = new Map();
for (const u of utxos) {
if (u.token) {
bch += BigInt(u.satoshis ?? 0);
const c = u.token.category.toLowerCase();
byCat.set(c, (byCat.get(c) ?? 0n) + BigInt(u.token.amount ?? 0));
} else {
bch += BigInt(u.satoshis ?? 0);
}
}
const bchStr = (Number(bch) / 1e8).toFixed(8);
const label = k.replace(/^\.chipnet-keys-?/, '').replace(/\.json$/, '') || '(default)';
console.log(`\n${label.padEnd(20)} ${addr.slice(0, 18)}...${addr.slice(-6)}`);
console.log(` BCH ${bchStr} (${utxos.length} UTXOs)`);
if (byCat.size === 0) {
console.log(` no FTs`);
} else {
for (const [cat, amt] of byCat) {
const name = KNOWN[cat] || cat.slice(0, 10) + '…';
console.log(` ${name.padEnd(14)} ${amt.toString()} units [${cat.slice(0, 12)}…]`);
}
}
} catch (e) {
console.log(`${k}: ERROR ${e.message?.slice(0, 80)}`);
}
}