← Back to Whitepapers

TXEX / forge-media-extract

On-chain media ETL — extract + transform media stored on BSV, on our own metal

NODEZEROINSIDE.


0. Abstract

txex is a bun-native CLI + TypeScript library that extracts and transforms media (images, video, audio) stored on the BSV blockchain, then hands us clean files. It reads the four on-chain file protocols — B://, BCAT, 1Sat Ordinals, and ORDFS Streams — reassembles chunked and streamed content, traces a marketplace outpoint back to its inscription origin, and pipes the bytes through Sharp (images) and FFmpeg (video/audio) for resize / crop / format-convert / thumbnail / trim. It is pure read + transform: no broadcast, no keys, no signing — the safest possible chain tool. We adopted it from b-open-io (MIT, © 2025) under the Babbage rule: take the mechanism, run it entirely on family metal, reject the hosted default. It is wrapped by the family skill forge-media-extract. It is the media ETL that is meant to feed our on-chain content surfaces (Kate chain-gallery, FORGEPATH, ORDFS renders) — not a viewer.

BUILT and proven by running (2026-07-05): txex@0.0.4 is installed and executes a real extraction from live chain. DESIGN/VISION (honestly flagged): the sovereign fetch-source swap (Tera-Z SPV instead of GorillaPool) and the content-pipeline wiring (Kate/FORGEPATH/ORDFS) are not yet in the code path. Both are detailed in §7–§8.


1. Why txex exists

On-chain media does not arrive as a file. It arrives as an inscription envelope, or a BitCom OP_RETURN payload, or a metadata transaction pointing at a list of chunk transactions that must be fetched and concatenated in order, or a chain of 1-sat ordinal transfers that must be walked. A gallery, a render pipeline, or a FORGEPATH content surface needs a file — a .webp, an .mp4, a thumbnail at the right dimensions. Between the chain and the file sits an ETL problem: Extract the envelope, Transform the bytes, Load them where the surface can use them.

txex is that ETL. It is deliberately narrow: it does not render, it does not display, it does not sign, it does not broadcast. It reads bytes that already exist on chain and turns them into files on disk. That narrowness is the whole safety argument (§6).


2. What it extracts — the four protocols (BUILT)

Each protocol is a real parser under src/protocols/. txex auto-detects the protocol from the output's locking script (detectProtocol() in extract.ts), in order of specificity:

Protocol Prefix / pattern Shape Source
1Sat Ordinals OP_FALSE OP_IF "ord" … OP_ENDIF inscription envelope: content + MIME protocols/ordinals.ts
BCAT metadata 15DHF…h4Up + chunks 1ChD…qpJL metadata tx lists N chunk txids; reassembled protocols/bcat.ts
B:// 19Hxig…doAut single OP_RETURN: data + media type + encoding + filename protocols/b.ts
ORDFS Stream content-type ordfs/stream continuation chunks across ordinal transfers, followed until type changes protocols/stream.ts

Two hard cases are handled in code:


3. What it transforms (BUILT)

Once the bytes are in hand, txex pipes them through local processors. Both are present on this metal (/usr/bin/ffmpeg confirmed; Sharp is a package dependency):

A transform is content-addressed: the transform options are hashed (hashConfig) so a given (outpoint × transform) result is cached and reused (§5).


4. The one command (usage)

txex <txid_vout>                        # extract media at an outpoint (vout 0 if omitted)
txex <txid_vout> -o out.webp -w 1200    # resize to 1200px wide, WebP
txex <txid_vout> --thumbnail 00:00:05   # grab a video frame at 5s
txex <collection_outpoint> -l 50 -c 5   # download up to 50 collection items, 5 in parallel
txex info <txid_vout>                   # metadata only — protocol, MIME, size, sats (no extract)
txex color <txid_vout>                  # dominant color + palette + BlurHash
txex cache                              # manage the two-tier cache

It is also importable as a fully-typed library (extract(), extractData(), setStorageProvider()), which is the seam we would use to wire it into a pipeline (§8).


5. Caching + storage — the sovereign seam (BUILT seam, DESIGN swap)

txex has a two-tier cache: raw transactions (tx: namespace) and transformed outputs (tfm: namespace). The important architectural fact for us is the StorageProvider interface (storage.ts):

This is a genuine sovereign seam and it is real code. What is NOT yet done: we have not written a family StorageProvider (Redis / forge-storage). Today it runs on the FS default, which is sovereign-adequate. A custom provider is DESIGN (§8).

Config is read from .txexrc / txex.config.json (cwd then $HOME) via config.ts.


6. Sovereignty posture — pure read, and where it fetches (honest)

The safety core (BUILT, verified in source): txex has no signing path and no broadcast path. Grepping the source confirms the only network egress is fetch() against a transaction indexer to read bytes. There are no keys, no wallet, no createAction, nothing that can spend or publish. Per the manifest and skill: "Pure read/transform — no broadcast, no keys. Safe." Confirmed.

The fetch source (the honest caveat): the raw-transaction provider is providers/junglebus.ts, and its base URL is hardcoded:

const JUNGLEBUS_BASE = "https://junglebus.gorillapool.io";

Every extraction — including the proven run in §9 — currently fetches from GorillaPool's JungleBus, a public BSV indexer. That is an acceptable read fallback (no keys cross it; it is bytes-in only), and it is what the manifest calls "reads via public BSV indexers as fallback." But the manifest's aspiration — "prefer our Tera-Z SPV / txstore where configurable" — is NOT met by the current code: there is no config knob that repoints the fetch at Tera-Z. The StorageProvider swap covers the cache layer, not the fetch layer. Pointing txex at our own metal for the source-of-truth read is a code edit we have not made. This is the single most important build-vs-vision gap in this tool, and it is called out plainly so no future session mistakes the aspiration for the state.


7. Built vs. Vision — the honest ledger

Claim State Evidence
txex@0.0.4 installed, runs on our metal BUILT ~/.bun/bin/txex, --version0.0.4, --help full CLI
Real extraction from live chain BUILT — proven by running §9: info e17d…a584_0 → ORD, image/png, 2.6 KB, 1 sat
B:// · BCAT · 1Sat Ordinals · ORDFS Stream parsers BUILT src/protocols/{b,bcat,ordinals,stream}.ts
BCAT parallel reassembly; ordinal origin tracing BUILT extract.ts extractBCAT; ordinal.ts findOrigin
Sharp image transforms; FFmpeg video/audio transforms BUILT CLI flags; ffmpeg present; transform.ts / video.ts
Two-tier cache; FS default (no Cloudflare) BUILT cache.ts, storage.ts; default ~/.txex/cache
Pure read — no keys, no broadcast BUILT — verified in source only fetch() reads; no signing/wallet code
StorageProvider swap seam (Redis / our storage) SEAM BUILT; family provider NOT written setStorageProvider() exists; no forge-storage impl
Prefer Tera-Z SPV / our txstore for the fetch DESIGN / VISION JUNGLEBUS_BASE hardcoded to GorillaPool; no config knob
Feeds Kate gallery / FORGEPATH :7800 / ORDFS renders DESIGN / VISION manifest primary_use_cases; no pipeline glue on disk
Composes with bsv_mcp_bopen (Uno Satoj) + forge_claw WORKFLOW / VISION manifest composes_with; a pairing pattern, not wired code

8. Sequencing (what "done" would take)


9. Proven by running (2026-07-05)

Protocol: ORD Media Type: image/png Size: 2.6 KB Satoshis: 1

Fetched over GorillaPool JungleBus (/v1/transaction/get/…/bin, HTTP 200, 0.61s). This is a real 1Sat Ordinal PNG inscription, read and identified by txex on our metal — the extract path works end to end.
- Local processors present: /usr/bin/ffmpeg confirmed; Sharp is a resolved dependency in node_modules/txex.

Total: install + version + full-CLI + one live on-chain extraction + local processors present = the read/identify path is proven; the transform path is dependency-present and CLI-exposed.


10. Facts

This paper is family-internal — NOT for public fire. It maps a vendored MIT tool's real state, separates BUILT from VISION honestly, and is not chain-stamped (scar #5: external code + aspiration must not be dressed as canon). If a public account of the media-ETL surface is ever wanted, author a public-safe paper separately.

NODEZEROINSIDE. ∞.