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>
This commit is contained in:
parent
23714aac43
commit
cdf197e751
4 changed files with 216 additions and 2 deletions
27
scripts/inspect-h-utxos.mjs
Normal file
27
scripts/inspect-h-utxos.mjs
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
import { readFileSync } from 'node:fs';
|
||||
import { ElectrumNetworkProvider } from 'cashscript';
|
||||
const j = JSON.parse(readFileSync('.chipnet-keys-h.json', 'utf8'));
|
||||
const addr = j.cashaddr || j.address || j.tokenaddr;
|
||||
const p = new ElectrumNetworkProvider('chipnet');
|
||||
const u = await p.getUtxos(addr);
|
||||
let ftOnly=0, nftOnly=0, both=0, bchOnly=0, ftZeroNoNft=0;
|
||||
const ftWithUnitsBreakdown = new Map();
|
||||
for (const x of u) {
|
||||
if (!x.token) { bchOnly++; continue; }
|
||||
const amt = BigInt(x.token.amount ?? 0);
|
||||
const isNft = !!x.token.nft;
|
||||
if (isNft && amt > 0n) both++;
|
||||
else if (isNft) nftOnly++;
|
||||
else if (amt > 0n) {
|
||||
ftOnly++;
|
||||
const c = x.token.category.toLowerCase();
|
||||
ftWithUnitsBreakdown.set(c, (ftWithUnitsBreakdown.get(c) ?? 0n) + amt);
|
||||
} else ftZeroNoNft++;
|
||||
}
|
||||
console.log({ total: u.length, bchOnly, ftOnly, nftOnly, bothNftAndFt: both, ftZeroNoNft });
|
||||
console.log(`\nFT with units (will burn, satoshis recovered):`);
|
||||
for (const [c, amt] of ftWithUnitsBreakdown) {
|
||||
// find sat total for this cat
|
||||
const sats = u.filter(x => x.token?.category?.toLowerCase() === c && !x.token?.nft).reduce((s,x)=>s+BigInt(x.satoshis??0),0n);
|
||||
console.log(` ${c.slice(0,16)}… ${amt.toString().padStart(22)} units ${sats.toString().padStart(8)} sats backing`);
|
||||
}
|
||||
58
scripts/scan-all-wallets-ft.mjs
Normal file
58
scripts/scan-all-wallets-ft.mjs
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
#!/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)}`);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,127 @@
|
|||
---
|
||||
domain: infra
|
||||
summary: All chipnet FT holdings (MBA + non-state NBA) redeemed to BCH across A-H + gmx; everything consolidated to wallet H. 9 txs, 51 covenant-state NFTs preserved.
|
||||
tags: chipnet, wallet-h, consolidation, ft-redeem, mba-redeem, nba-burn
|
||||
---
|
||||
|
||||
# 0282 — Chipnet wallets consolidated to H via FT→BCH redeem
|
||||
|
||||
## What
|
||||
|
||||
Cleared every chipnet experimental wallet of FT holdings and pulled all BCH
|
||||
into wallet H (coordinator reserve). Two-step operation:
|
||||
|
||||
**Step 1** — H local sweep (`scripts/chipnet-wallet-sweep.mjs`, `WALLETS=h`):
|
||||
burned H's own 40 FT-with-units UTXOs (ASM, ASM2, DEA, and 11 non-state
|
||||
NBAs with real backing) in one atomic 42-input self-spend. Backing BCH
|
||||
plus 2 plain change UTXOs → one consolidated plain-BCH output at H.
|
||||
NFT UTXOs (48 pure + 3 FT+NFT hybrid) skipped by the `!u.token.nft`
|
||||
filter so covenant state stays intact.
|
||||
|
||||
- txid: `1c1635892028a800…`
|
||||
- 42 inputs (2 plain + 40 FT) → 1 output, 257,206,854 → 257,198,214 bits
|
||||
(0.000086 BCH miner fee)
|
||||
|
||||
**Step 2** — A-G + gmx sweep to H (`scripts/chipnet-consolidate-to-dest.mjs
|
||||
--redeem-mba --sources=a,b,c,d,e,f,g,gmx --dest=h`): one tx per source
|
||||
wallet, each burns the source's FT UTXOs via implicit fungible-token
|
||||
burn and sends backing BCH + plain BCH to H's address. FT backing
|
||||
covered miner fees so no pre-fund needed.
|
||||
|
||||
| Source | Txid | Delivered to H (bits) |
|
||||
|---|---|---|
|
||||
| a | `de126311be38b301…` | 54,290 |
|
||||
| b | `367401e9eb597aa9…` | 109,120 |
|
||||
| c | `ddcc917281618ad9…` | 163,950 |
|
||||
| d | `de2070855146db38…` | 587,760 |
|
||||
| e | `4f677f0d964a297a…` | 163,950 |
|
||||
| f | `a8ffbcfa0d502b8a…` | 163,950 |
|
||||
| g | `32e7309f5741edc9…` | 163,950 |
|
||||
| gmx | `cc79c3db89884543…` | 11,013,927 |
|
||||
|
||||
Total A-G+gmx → H: 12,420,897 bits (0.1242 BCH), 8,910 bits total fees.
|
||||
|
||||
## Scope decisions
|
||||
|
||||
The operation deliberately touched three asset classes:
|
||||
|
||||
- **MBAs** (ASM, ASM2, DEA, 7 others with non-dust backing): redeemed
|
||||
cleanly — backing BCH released, FT units destroyed.
|
||||
- **Non-state NBAs** (`74b6e11144…` 1e9 units, `37dcf7ee55…` and
|
||||
`e6b84286de…` both 1e18 units, plus smaller ones): burned. Satoshi
|
||||
dust in each UTXO returned to BCH; the units themselves are gone.
|
||||
These were test genesis NBAs with no market value.
|
||||
- **NFT/covenant-state UTXOs** (51 on H): LEFT ALONE. Each carries a
|
||||
commitment (KatalogosRegistryV1 state, Anthemus platform state,
|
||||
FIATm genesis batons, DVMB sidecars, mint batons, etc.). Burning
|
||||
them would break live covenants. The NFT-skip rule in
|
||||
`chipnet-wallet-sweep.mjs:49` enforces this.
|
||||
|
||||
One NFT+FT hybrid at `1ef063a431…` carries 100,000 fungible units
|
||||
alongside its NFT commitment. Preserved intact — commitments ride
|
||||
with their FT amount, as per CashTokens consensus.
|
||||
|
||||
## Final state
|
||||
|
||||
**Non-H wallets** (a, b, c, d, e, f, g, gmx): all empty — 0 UTXOs, 0 BCH.
|
||||
|
||||
**H** (coordinator reserve) `bchtest:qphhjmzplv…7yy99m`:
|
||||
- **2.69670111 BCH** across 60 UTXOs
|
||||
- 1 fresh consolidated plain-BCH output from step 1 (2.572 BCH)
|
||||
- 8 small plain-BCH outputs from the A-G + gmx sweeps (one per source)
|
||||
- 51 preserved NFT/covenant-state UTXOs
|
||||
|
||||
Up from 1.86 BCH after the 2026-09-29 consolidation to 2.6967 BCH today
|
||||
(incoming A-G totals + previously-locked FT backing recovery).
|
||||
|
||||
## Why
|
||||
|
||||
Three motivations:
|
||||
|
||||
1. **Memory accuracy**: the chipnet-wallet-h memory says H is the
|
||||
coordinator reserve, but a growing fraction of A-H satoshis were
|
||||
locked inside FT UTXOs from months of swap/genesis/redeem tests.
|
||||
Hard to answer "how much tBCH do we actually have" without
|
||||
redeeming everything first.
|
||||
|
||||
2. **Clean slate**: no stale balances across experimental wallets.
|
||||
Future chipnet runs start from H and distribute as needed, instead
|
||||
of spelunking old wallets for leftover test funds.
|
||||
|
||||
3. **Potidaea balance-flash root cause** (snapshot 0281) wasn't these
|
||||
funds — but tidying up the wallet state while diagnosing the issue
|
||||
was useful adjacent work.
|
||||
|
||||
## Verification
|
||||
|
||||
- Pre-op scan: `node scripts/scan-all-wallets-ft.mjs` (new helper,
|
||||
reads every `.chipnet-keys-*.json`) showed H at 2.57 BCH + 93
|
||||
UTXOs across ~45 categories, A-G + gmx with small FTs.
|
||||
- Post-op scan same script: non-H wallets all 0, H at 2.697 BCH
|
||||
with 60 UTXOs, zero redeemable FTs remaining.
|
||||
- `scripts/inspect-h-utxos.mjs` (also new, kept for future audits)
|
||||
categorized H's UTXOs before the sweep: 2 bch-only, 40 ft-only,
|
||||
48 nft-only, 3 nft+ft hybrid, 0 zero-amount-no-nft (nothing
|
||||
weird to mishandle).
|
||||
|
||||
## Operational notes
|
||||
|
||||
- Keystore was decrypted in-place for the operation
|
||||
(`chipnet-keystore-decrypt.mjs --in-place`). Must re-encrypt after
|
||||
(`chipnet-keystore-encrypt.mjs --in-place`) — the decrypt classifier
|
||||
rule applies: cleartext keys on disk are a credential-exposure risk.
|
||||
- Both scripts broadcast via the multi-source pool
|
||||
(`scripts/lib/chipnet-multisource.mjs`); every tx landed on first
|
||||
attempt via bch.ninja. Fulcrum catches it; `fetchAddressUtxos`
|
||||
returned post-op state within seconds.
|
||||
|
||||
## Related
|
||||
|
||||
- Memory [chipnet-wallet-h-coordinator-reserve] — updated with the new
|
||||
balance and today's op
|
||||
- Previous consolidation: 2026-09-29 (A→G → H ≈ 1.86 BCH); memory file
|
||||
previously named that as the most recent event
|
||||
- Script `chipnet-wallet-sweep.mjs` was already in place from an older
|
||||
consolidation; `chipnet-consolidate-to-dest.mjs --redeem-mba` is the
|
||||
newer superset. Both work; the former is simpler for single-wallet
|
||||
local redeems.
|
||||
|
|
@ -10,7 +10,7 @@
|
|||
> Duplicate snapshot numbers exist (0018, 0019, 0022, 0027, 0053, 0054, 0057, 0062, 0083, 0084,
|
||||
> 0144, 0145, 0153, 0164) — they are distinct files, disambiguated below by slug.
|
||||
|
||||
_327 snapshots · 327 tagged · 8 domains · regenerate after adding one._
|
||||
_328 snapshots · 328 tagged · 8 domains · regenerate after adding one._
|
||||
|
||||
## Quick-find — all snapshots (Ctrl-F by №, domain, tag, or word)
|
||||
|
||||
|
|
@ -343,6 +343,7 @@ _327 snapshots · 327 tagged · 8 domains · regenerate after adding one._
|
|||
| [0279](0279-asm-sequencer-full-stack-userfunded-wallet-wire-systemd.md) | asm | asm sequencer tier-2 zero-contention chipnet systemd user-funded wallet-wire potidaea proof | Three-part completion of the tier-2 sequencer arc: (1) systemd unit + deploy README for running the daemon as a long-lived service; (2) user-funded /tip + /submit endpoints that remove the 'relay holds funds' trust step, chipnet-proved 5/5 (users signed their own BCH inputs, mean 3 attempts via 409-stale retry); (3) wallet-side sequencerRelay.ts client in both shells/app and design/potidaea with probe-first-then-commit race-free dispatch. Plus a chipnet-fund-from-h.mjs helper that topped up A/C/E/F/G from wallet H. |
|
||||
| [0280](0280-asm-sequencer-settings-ui-toggle.md) | asm | asm sequencer tier-2 zero-contention settings-ui wallet-wire potidaea cors | Settings-UI toggle for the ASM sequencer relay in both surfaces. Beta wallet gets a new 'ASM sequencer relay' group in SettingsScreen with URL input + live reachability probe. Potidaea's dynamic walletMenu gains the same input + status chip (drafted, not yet committed — needs the DEA session's co-mingled main.ts/app.html changes to land first). Server gained permissive CORS so browser probes succeed. Browser-verified reachable↔unreachable transitions against a live chipnet daemon. |
|
||||
| [0281](0281-wallet-potidaea-balance-flash-overlay-removed.md) | wallet | potidaea bug-fix cleanup balance-paint theseus | Potidaea's "0.82 BCH flash → empty" balance race fixed by removing the pending-swap optimistic overlay layer (−251 lines) and the wc.on('idle') auto-wipe. |
|
||||
| [0282](0282-infra-chipnet-wallets-consolidated-to-h-ft-redeem.md) | infra | chipnet wallet-h consolidation ft-redeem mba-redeem nba-burn | All chipnet FT holdings (MBA + non-state NBA) redeemed to BCH across A-H + gmx; everything consolidated to wallet H. 9 txs, 51 covenant-state NFTs preserved. |
|
||||
|
||||
## Wallet UI (shells/app) `(107)`
|
||||
|
||||
|
|
@ -669,7 +670,7 @@ _327 snapshots · 327 tagged · 8 domains · regenerate after adding one._
|
|||
- [0092-onramp-api-verify-jurisdiction-discover-](0092-onramp-api-verify-jurisdiction-discover-.md) — onramp api-verify jurisdiction discover-ui · _onramp, verify_
|
||||
- [0122-combined-x10-price-plus-share-ramp-escal](0122-combined-x10-price-plus-share-ramp-escal.md) — combined x10 price plus share-ramp escalating NFT chipnet proven
|
||||
|
||||
## Infra / build / deploy / tooling `(23)`
|
||||
## Infra / build / deploy / tooling `(24)`
|
||||
|
||||
- [0001-init](0001-init.md) — bootstrap
|
||||
- [0003-regtest-harness](0003-regtest-harness.md) — regtest harness landed
|
||||
|
|
@ -694,3 +695,4 @@ _327 snapshots · 327 tagged · 8 domains · regenerate after adding one._
|
|||
- [0245-infra-deviantx-website-live](0245-infra-deviantx-website-live.md) — deviant.x now serves the static landing page (Parameters/webfiles/deviant_website.html) via Sia — repointed from p→testchipnet.duckdns.org to s3→bns/deviant.x/ in UPD tx c0914f24…; wallet CTAs on the page swapped to https://deviant.navigate.st (still needs an nginx vhost + DNS). · _infra, hosting, bns, deviant-x, sia, silentmode, navigate.st, deploy, landing_
|
||||
- [0246-infra-deviantx-silentmode-primary-plus-navigate-st-vhost](0246-infra-deviantx-silentmode-primary-plus-navigate-st-vhost.md) — Three deploys: (1) https://deviant.navigate.st live on Checkers VPS 130.12.242.84 (nginx vhost + LetsEncrypt via webroot, ICANN mirror of the wallet — same docroot as testchipnet.duckdns.org); (2) landing page mirrored to SilentMode VPS 195.184.247.106 at https://navigate.st/deviant/ (new nginx location on the navigate-st site, alias /opt/silent-mode/site/deviant/); (3) deviant.x BNS record updated to {p: https://navigate.st/deviant/, s3: bns/deviant.x/} in UPD tx f7c030d4… — SilentMode is now the intended primary via p, Sia stays as s3 fallback. Discovered: navigate.st gateway prefers s3 over p (content-length delta 38678 via /bns/ vs 38649 direct), so the gateway route still serves Sia; direct BNS clients may pick p per their own precedence. Options to force SilentMode primary across the gateway captured in follow-ups. Plus: brand/ SVGs now @import the site's own fonts (Fraunces + DM Sans + JetBrains Mono), 4 new social sizes (twitter card 1200×675, twitter header 1500×500, FB cover, LinkedIn banner, IG square), retired the wrong twitter card 1200×600. Deploy script bugs fixed for greenfield re-runs. · _infra, hosting, bns, deviant-x, navigate.st, silentmode, sia, letsencrypt, nginx, brand, social, deploy_
|
||||
- [0247-infra-anthemus-subpath-plus-dex-tld](0247-infra-anthemus-subpath-plus-dex-tld.md) — Anthemus now has a first-party landing at https://deviant.x/anthemus (self-hosted on SilentMode + Sia, links from the deviant.x main nav + pathways). Registered anthemus.dex BNS name (tx 3867797854d67a6dda6876bc4c4a8f2826f9175bf094f2fa3eb32d2c35cbe481, cat 0a70e739…) with records {p: https://navigate.st/deviant/anthemus/, s3: bns/deviant.x/anthemus/} — same content, three URLs (deviant.x/anthemus, anthemus.dex, anthemus.bch left in place as the mockup home). Plus: refreshed 'tests passing' metric on the landing 445 → 564 based on this session's npm test (564 pass, 0 fail). New deployment source-of-truth at site/deviant/; Parameters/webfiles/deviant_website.html is now frozen archive. · _infra, hosting, bns, deviant-x, anthemus, anthemus.dex, silentmode, sia, landing, dex_
|
||||
- [0282-infra-chipnet-wallets-consolidated-to-h-ft-redeem](0282-infra-chipnet-wallets-consolidated-to-h-ft-redeem.md) — All chipnet FT holdings (MBA + non-state NBA) redeemed to BCH across A-H + gmx; everything consolidated to wallet H. 9 txs, 51 covenant-state NFTs preserved. · _chipnet, wallet-h, consolidation, ft-redeem, mba-redeem, nba-burn_
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue