Phase 1 of the docs-by-domain reorg. Every snapshot now carries YAML frontmatter (domain + summary + tags); the auto-guess was hand-corrected against the full index (T6/interchain -> cross-chain, CDP/MBA/stablecoin -> fiatm, CitizenToken/Ballot -> governance, etc.). No file renamed/moved. build-snapshot-index.mjs now reads the frontmatter and emits a greppable INDEX.md: a top Quick-find table (No | domain | tags | summary) plus per-domain sections with summary + tags. 224/224 tagged, 8 domains, zero uncategorised. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
5.4 KiB
| domain | summary | tags |
|---|---|---|
| infra | chipnet scripts delegate to the wallet library | wallet |
Snapshot 0029: chipnet scripts delegate to the wallet library
Captured 2026-05-22
TL;DR
Step 1 of the post-finalization plan. The chipnet PoC scripts now have a
chain-connected bridge to DeviantWallet: a runtime adapter layer
(src/wallet/runtime.ts) plus three library-delegating scripts
(chipnet-lib-balances, chipnet-lib-send, chipnet-lib-swap) that
replace inlined TransactionBuilder logic with plan*() / execute*()
calls. This converts the 129+-swap chipnet evidence into a regression
guarantee for the library API.
6 new tests pass; 156 total in the unit suite, zero failures.
What landed
src/wallet/runtime.ts — the chain-connected adapter layer
The orchestrator (wallet.ts) takes three injected dependencies. This
module satisfies all three against cashscript + mainnet-js + libauth:
class ElectrumUtxoSource implements UtxoSource // wraps NetworkProvider
function makeBroadcaster(ctx): Broadcaster // wraps shell-runtime.broadcast
function cashaddrToLockingBytecode(addr): Uint8Array // libauth address decode
Plus the glue that turns chipnet artifacts into library inputs:
function tokenFileToTierA(file: ChipnetTokenFile): TokenTierA
function connectWallet(options): DeviantWallet // assembles all of the above
connectWallet is the one-call factory: give it a registry, a network (or
provider), a private key, and the wallet's addresses, and it returns a
chain-ready DeviantWallet with addressToLockingBytecode pre-wired.
Dependency boundary: like shell-runtime.ts, this module imports the
heavy chain libraries. Pure consumers (tests, server-side planners) must
not import it — they stay on wallet/index.ts.
UTXO normalisation: ElectrumUtxoSource coerces provider UTXOs into
the library's Utxo shape — satoshis and token amounts to bigint
regardless of whether the provider returned numbers, strings, or bigints.
This was the silent footgun in the original scripts (scattered
BigInt(u.satoshis) calls); now it's centralised and tested.
Three library-delegating scripts
| Script | Replaces | Delegates to |
|---|---|---|
chipnet-lib-balances.mjs |
chipnet-balances.mjs |
wallet.getBalance() |
chipnet-lib-send.mjs |
chipnet-asm-send.mjs |
planTierASend → executeTierASend |
chipnet-lib-swap.mjs |
chipnet-asm-swap.mjs |
planSwap → executeSwap |
Each follows the production two-phase pattern: build the plan, print its
confirmationMessage + warnings, refuse non-canonical operations, then
execute on consent. The swap script no longer computes the source amount
by hand — planSwap's ceilDiv derives it, so any TARGET_AMOUNT works
(the original required clean integer rate ratios).
The new scripts run via node --import tsx (they import the TS library);
npm aliases chipnet:lib-balances / chipnet:lib-send / chipnet:lib-swap.
Why new -lib scripts instead of editing the originals
The originals are the validated evidence (snapshots 0008/0013–0016/0025).
Editing them in place would destroy the baseline before the replacements
are confirmed on-chain. The -lib variants run side-by-side; once a user
confirms them against funded chipnet keys, the originals can be retired.
Verification
- Type-check clean (only the pre-existing
tokenId.tserror). - Token-file mapping verified against the real
.chipnet-asm-token.json—tokenFileToTierAproduces a validTokenTierA(ticker ASM, rate 100, feeBps 100, categoryId round-trips, registry accepts it). - 6 new unit tests cover
tokenFileToTierA(default + explicit ticker/numeric fields),cashaddrToLockingBytecode(P2PKH decode matches the file'sfounderLockingBytecodeHex; token-aware address yields identical bytecode; malformed input throws), andElectrumUtxoSourcenormalisation (number/string/bigint satoshis → bigint). - Full import graph resolves through tsx — the scripts parse and their module graph loads up to the network boundary.
Not yet done: an actual on-chain broadcast through the new scripts.
That requires funded chipnet keys + network access — the user runs
npm run chipnet:lib-swap (etc.) to close the loop. The structural
refactor and everything short of the live broadcast is verified.
Next slices
- SQLite registry backing — drop-in for
InMemoryTokenRegistry. ← next src/verify/discover.ts— chain-side bytecode cross-check.- Phase 3 — Architecture A wallet integration / consolidation.
Files this snapshot
A src/wallet/runtime.ts (adapter layer + connectWallet)
A scripts/chipnet-lib-balances.mjs (getBalance via library)
A scripts/chipnet-lib-send.mjs (tier-A send via library)
A scripts/chipnet-lib-swap.mjs (swap via library)
A test/unit/wallet/runtime.test.ts (6 tests)
M package.json (3 npm aliases)
A snapshots/0029-chipnet-scripts-on-library.md (this file)
Cumulative state
156 unit tests passing. 6 new this snapshot. Zero regressions.
The library is now reachable from the chipnet harness through a single
connectWallet() call. The remaining post-finalization work (SQLite
storage, chain-side discover, Phase-3 consolidation) builds on this bridge.