Skip to content

Pure TypeScript BOLT12 library (bolt12-utils)#30

Open
vincenzopalazzo wants to merge 22 commits into
rustyrussell:masterfrom
vincenzopalazzo:vincenzopalazzo/bolt12-ts-pure-js
Open

Pure TypeScript BOLT12 library (bolt12-utils)#30
vincenzopalazzo wants to merge 22 commits into
rustyrussell:masterfrom
vincenzopalazzo:vincenzopalazzo/bolt12-ts-pure-js

Conversation

@vincenzopalazzo
Copy link
Copy Markdown
Contributor

Summary

Complete rewrite of the JS/TypeScript BOLT12 library as a pure TypeScript implementation with zero native dependencies. Published as bolt12-utils on npm.

  • Pure TypeScript — only @noble/curves (secp256k1/schnorr) and @noble/hashes (SHA-256), no Node.js Buffer
  • All 82 test vectors passing — 53 offer decode/validate, 7 payer proof, 22 generated type smoke tests
  • Auto-generated types from spec — new tools/generate-ts.ts replaces the broken Python generator (which fails on modern spec's sciddir_or_pubkey type). Covers all 4 message types: offer, invoice_request, invoice, invoice_error
  • Spec CSV updatedlightning-rfc submodule pointed to latest lightning/bolts master, CSVs regenerated
  • Payer proof support — experimental create + verify for lnp messages (BOLT12 PR #1295)
  • Interactive playgroundvincenzopalazzo.github.io/bolt12 with live decoder, TLV inspector, and runnable code examples
  • Google TypeScript Style Guide applied, hand-written fields.ts preserved but @deprecated

Changes

Area Details
js/src/ Pure TS library: bech32, TLV, bigsize, merkle, offer validation, payer proofs, generated types
js/test/ 3 test suites (offers, payer proofs, generated types)
js/README.md Full API documentation with examples and type reference
tools/generate-ts.ts TypeScript code generator replacing broken generate-code.py
specs/ Regenerated CSVs from latest lightning/bolts
website/ Interactive decoder + educational content for GitHub Pages
Removed Old python/, javascript/, bolt12/ directories (superseded)

Maintenance

I will maintain the bolt12-utils npm package and keep the generated types in sync with the BOLT12 spec as it evolves.

Test plan

  • cd js && npm test — all 82 tests pass
  • npm run build — TypeScript compiles cleanly
  • npm run generate — types regenerate from spec CSV
  • npm run build:web — browser bundle builds
  • npm pack — 49.6 kB, 51 files

🤖 Generated with Claude Code

vincenzopalazzo and others added 20 commits March 17, 2026 16:58
Replace the outdated JavaScript implementation (bip-schnorr, js-sha256)
with a modern TypeScript library using only audited pure-JS dependencies
(@noble/curves, @noble/hashes). Passes all 53 official test vectors from
lightning/bolts offers-test.json including valid offers, malformed input
rejection, and semantic validation.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Vanilla JS/HTML/CSS single-page website that:
- Interactive decoder: paste any lno offer, see color-coded TLV fields
  with hover-to-inspect detail panel (inspired by bolt11.org)
- Educational sections: BOLT11 vs BOLT12 comparison, message flow diagram,
  offer fields reference table, key concepts (blinded paths, TLV encoding,
  Merkle signatures, bech32)
- Learning resources with links to the spec, bolt12.org, LDK, Optech
- Uses the bolt12-decoder library bundled via esbuild for browser

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Implements parsing, merkle reconstruction, and signature verification
for payer proofs (lnp prefix). Includes 13 tests covering all validation
paths.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Update decoder to handle all BOLT12 message types (offers, invoice
requests, invoices, payer proofs). Add GitHub Actions workflow to
deploy the website/ directory to GitHub Pages on push to master.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add a Usage section with copy-able code snippets showing how to decode
offers, parse TLV streams, verify signatures, and use payer proofs.
Includes a "Run" button that decodes a sample offer live in the browser.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Each code snippet now executes automatically on page load using the
bundled bolt12 library, with the real output rendered directly below.
No "Run" button needed - results are visible immediately.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add a split-pane editor/output playground (like TypeScript Playground).
Users can edit code on the left and see live results on the right.
Three example tabs: Decode Offer, TLV Parsing, Validate. Code runs
via the bundled bolt12 library. Supports Ctrl+Enter and Tab indenting.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
decodeOffer() now returns named fields directly:
  const { description, amount, issuer_id, offer_id } = decodeOffer(str);

Adds fields.ts with OfferFields interface and extractOfferFields().
Updates playground examples to showcase the destructured API.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace Buffer.from().toString('hex') in merkle.ts and
payer_proof.ts with pure JS byte comparison, fixing
"ReferenceError: Buffer is not defined" in the browser.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Implement createPayerProof() that generates BOLT12 payer proofs from
invoices, preimages, and payer secret keys. Fix merkle tree algorithm
to use LnNonce (matching LDK) instead of LnAll, and use recursive
DFS tree traversal for correct missing_hashes ordering.

All 7 test vectors pass (3 basic, 3 with notes, 1 invalid preimage).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add documentation section explaining BOLT12 payer proofs with
selective disclosure flow diagram and TLV field reference table.
Add interactive playground tab demonstrating createPayerProof API.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
New tab demonstrates decoding and verifying a payer proof,
showing disclosed fields, omitted markers, and payer info.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
These earlier implementations have been superseded by the pure
TypeScript rewrite in js/. Updated README, Makefile, and TODO
to reflect the new project structure.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…CSVs

Update the lightning-rfc submodule from rustyrussell/lightning-rfc
(guilt/offers branch) to the official lightning/bolts master.

Regenerate all spec CSV files from the latest BOLT markdown:
- bolt12.csv: new spec field name prefixes (offer_, invreq_, invoice_),
  new fields (invreq_paths, invreq_bip_353_name, invoice_amount),
  updated blinded_payinfo with htlc_minimum/maximum_msat
- bolt4.csv: updated onion routing types
- bolt1.csv: updated messaging types

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
New tools/generate-ts.ts replaces the broken Python generate-code.py
(which fails on the latest spec's sciddir_or_pubkey type).

The generator parses CSV spec files directly and produces:
- TypeScript interfaces (OfferFields, InvoiceRequestFields, InvoiceFields,
  InvoiceErrorFields, BlindedPayinfo, FallbackAddress)
- CONSTANT_CASE TLV type constants for all message types
- KNOWN_*_TYPES sets for validation
- TLV name lookup maps
- Field extractor functions (extractOfferFields, etc.)

Generated code uses pure Uint8Array (no Node.js Buffer), matching
the existing codebase conventions. Complex subtypes (blinded_path,
fallback_address) are stored as raw bytes for custom parser handling.

Output marked with @fileoverview and @generated JSDoc tags.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Export all generated types, constants, and extractors from index.ts
  (GeneratedOfferFields, InvoiceRequestFields, InvoiceFields, etc.)
- Add 'generate' npm script: npm run generate
- Add generated-test.ts with 22 smoke tests verifying constants,
  lookup tables, extractor parity with hand-written code, and
  spec-compliant field naming
- Update test script to run all 3 test suites (82 total tests)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Style guide (google.github.io/styleguide/tsguide.html):
- Always use braces for control structures (utils, offer, bech32,
  fields, payer_proof)
- Replace catch(e: any) with catch(e: unknown) + type narrowing
  in payer_proof.ts

Deprecation:
- Mark fields.ts module, OfferFields, Chain, and extractOfferFields
  with @deprecated JSDoc tags pointing to generated.ts replacements
- Add migration guidance in deprecation messages

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add files, repository, keywords, author fields and prepublishOnly script.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add comprehensive README with full API reference, examples, and type docs
- Rename package from bolt12-decoder to bolt12-utils
- Add BIP21/321 donation URI with taproot, ARK, and BOLT12 offer (lno= param)
- Update website install hint to bolt12-utils

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@vincenzopalazzo vincenzopalazzo force-pushed the vincenzopalazzo/bolt12-ts-pure-js branch from 5fbc135 to f0b7a59 Compare March 17, 2026 15:59
vincenzopalazzo and others added 2 commits March 17, 2026 17:02
- Remove old node-test (Node 10-15), python-tests (3.6-3.9), and
  BOLT quote tests jobs — all referenced deleted python/ and javascript/ dirs
- Add TypeScript test matrix (Node 18, 20, 22)
- Add generated types drift check (regenerate + git diff)
- Update actions to v4 (checkout, setup-node)
- Update Makefile to use npm instead of make -C js
- Clean up pages workflow branch list

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add verification tests mirroring ocean-ln's verify_offer_payment logic:
- Test 1: Valid CLN offer + invoice + preimage (full verification passes)
- Test 2/3: Phoenix wallet offer with blinded paths (verification correctly
  rejects due to payment hash mismatch with mismatched preimage)

The verification flow exercises decoding offers and invoices, extracting
signing pubkeys (including fallback from blinded paths), comparing offer
IDs, verifying invoice signatures, and checking proof-of-payment via
SHA256(preimage) == payment_hash.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
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