Skip to content

feat: add the five verified recursive-endpoint wrappers - #6

Merged
jerryfane merged 8 commits into
mainfrom
feat/endpoint-coverage
Sep 9, 2026
Merged

jerryfane merged 8 commits into
mainfrom
feat/endpoint-coverage

Conversation

@jerryfane

Copy link
Copy Markdown
Owner

Completes the endpoint surface so consumers do not have to hand-build routes through request().

Routes verified live before wrapping

Checked against mainnet ordinals.com, not assumed from documentation:

Route Status Response
/r/inscription/<id> 200 {charms, content_type, content_length, delegate, fee, height, id, number, output, sat, ...}
/r/parents/<id> and /<page> 200 {ids, more, page_index}
/r/children/<id>/inscriptions 200 {children, more, page}
/r/undelegated-content/<id> 200 raw body, correct content type
/r/blockinfo/<height> 200 {average_fee, average_fee_rate, bits, chainwork, confirmations, ...}

Note the asymmetry that is now documented rather than smoothed over: parents paginate with page_index, children with page.

Bytes

3,004 → 3,582 B minified, +578 B, leaving 329 B under the 3,911 B live inscription body. That is below the +747 B first measured, because getInscriptionContent and getUndelegatedContent now share one fetchContent helper instead of duplicating the fetch, error check, mime read and base64 conversion.

Rough order-of-magnitude cost of the addition at 1 sat/vB: ~145 sats. That is an estimate from body bytes plus assumed envelope and commit overhead, not a dry-run quote.

Verification

node scripts/gate.mjs — all five stages pass: 12/12 tests on source, 12/12 against the minified artifact, byte budget 3,582 ≤ 3,911, and the real-Chromium inscription-path smoke.

Two new tests: one pinning all six wrapper routes including both pagination styles, and one proving getUndelegatedContent returns the inscription own bytes while getInscriptionContent follows the delegate — the whole point of having both.

Not included

No getSatInscriptionContent(sat, index): it needs a newer ord and support detection would mean treating 404s as version signals. request() still reaches it for anyone who wants it.

getInscription, getParents, getChildrenInscriptions, getUndelegatedContent and
getBlockInfo. Every route was checked against mainnet ordinals.com first.
getInscriptionContent and getUndelegatedContent share one fetchContent helper,
so the delegate-aware method costs bytes it would otherwise duplicate.
- getSatInscriptionContent(sat, index = -1) fetches /r/sat/<sat>/at/<index>/content
  in one request; route verified against mainnet ordinals.com
- every failure now throws "OrdJS <status> <endpoint>: <ord message>" with a
  .status property, instead of a bare status number, shared by both the JSON
  and content paths
- 3,897 B minified, still under the 3,911 B live inscription body
- OrdJS.decoderUrl makes the decoder inscription replaceable, so a candidate can
  be served locally and tested before anyone spends money inscribing it
- scripts/build-decoder.mjs builds vendor/cbor2-decoder.js from cbor2@2.3.0
  (MIT, notice retained) with a manifest recording bytes, sha256 and build command
- scripts/decoder-smoke.mjs decodes RFC 8949 Appendix A in Chromium through
  OrdJS.decoderUrl: 59/59 correct, versus 8 findings for the inscribed decoder
- the gate runs the decoder check whenever the candidate is present
- drop the unread isInitialized constructor field to stay inside the byte budget
- browser smoke takes --engine chromium|firefox|webkit|all and asserts the
  indexed-content route and the error contract as well; all three pass
- scripts/fee-estimate.mjs serialises the actual ord envelope, tapscript,
  reveal witness and a standard commit tx instead of dividing bytes by four
- the gate runs both, and CI installs all three engines
Findings fixed:
- /r/blockinfo/latest is a 400 on mainnet; drop it from the README, the source
  comment and the route test, which could only ever prove concatenation
- fee estimate mis-serialised the envelope header twice: the content-type tag is
  a data push (2 B, not OP_1) and ord uses text/javascript, not
  text/javascript;charset=utf-8
- the fee stage could not fail; it now checks its own invariants and a
  known-answer table for pushSize, and exits non-zero
- vendor/cbor2-decoder.json was never verified against its artifact; the new
  check-manifest stage compares bytes, sha256 and the retained MIT notice
- drop OrdJS.decoderUrl and restore isInitialized: the harness serves the
  candidate at the real /content path instead, so no inscribed byte pays for a
  test hook (3897 B, 14 B of headroom instead of 1)
- the decoder smoke now runs against the MINIFIED artifact and prints the
  measured migration table (integer-keyed maps, tags 0/1/23/24/32)
- README: 59/59 is 59 of 82 upstream entries; the migration claim was wrong;
  setup needs all three engines; --no-browser drops the decoder stage too
- document that getSatInscriptionContent throws where
  getSatLastInscriptionContent resolves null

Both mutants the reviewer slipped past the gate now fail it.
- the weight/vsize check was tautological (vsize*4 - (vsize*4 - weight) is
  always weight); replace it with the BIP 141 relation vsize = ceil(weight/4)
  plus a body-derived weight floor. Mutants that halve the weight or understate
  the vsize by 5 now fail the stage; previously both passed
- run the decoder manifest check outside the browser branch: artifact/manifest
  drift is an integrity failure and --no-browser must not skip it
- migration probe: use the literal CBOR hex instead of a sliced string, and
  describe wrapper objects by shape, since a minified library has no stable
  constructor names
- test fixture used a 65-character "block hash"; use the real 64-character
  hash of block 840000
The numbers were right but four gates could not detect them being wrong.

- fee estimate: pin known answers taken from the REAL reveal of the live v0.1.2
  inscription (3911 B body -> 3995 B tapscript, 4476 wu, 1119 vB), pin the
  commit tx at 154 vB / 616 wu, pin the 520-byte chunk boundary, and pin ord
  media-table content type for .js. Mutants that previously slipped now fail:
  content-type tag as OP_1, CHUNK=1000, charset content type, collapsed commit
- decoder smoke: assert decoded VALUES, not just shapes. A decoder returning
  Invalid Date for every tag 0/1 and rewriting tag 32 to another host passed
  every stage with a self-consistent manifest; it now fails
- gate: a missing decoder artifact silently removed both decoder stages while
  reporting success; manifest and artifact must now exist together
- drop the dead OrdJS.decoderUrl instruction from the shipped manifest, its
  generator and the smoke header: no such hook is inscribed
- refresh the stale stage inventory in the gate header
@jerryfane
jerryfane merged commit 3dcd6a0 into main Sep 9, 2026
1 check passed
@jerryfane
jerryfane deleted the feat/endpoint-coverage branch September 9, 2026 09:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant