pull down to refresh

Every invoice decoder I could find sends the invoice to a server. That always felt backwards. An invoice is payment metadata: the amount, who you're paying, when, the payment hash. Handing a running log of that to some anonymous site to save yourself a manual bech32 decode is a bad trade.

So I built http://lndecoder.com. Everything decodes client side. The only network calls are two public lookups (payee alias and the BTC price on the invoice's creation date), and there's a toggle that turns even those off if you want literal zero egress. Open the network tab while you decode, that's the whole audit.

It does BOLT11, LNURL (pay/withdraw/auth/channel), lightning addresses, and BOLT12 offers (experimental). Recovers the payee pubkey from the signature when there's no n field. There's a preimage verifier for proof-of-payment arguments, QR scanning, and it works offline once loaded.

Free, no ads, no cookies, no trackers. If you spot a decode it gets wrong, tell me. That's the feedback I actually want.

https://lndecoder.com

source code?

reply
Every invoice decoder I could find sends the invoice to a server

Which ones did you check? These don't:

I couldn't find any that do. I'd be very interested in them.

reply

A detail that didn't fit the post: most custodial invoices (Cash App, Coinbase and friends) pay a node that's completely anonymous. No alias in the public graph, and often no payee key in the invoice at all. So the decoder recovers the payee pubkey from the invoice signature, and when that node turns out to be private, it checks the route hints against a small list of known custodial hops. Result is a Cash App invoice actually says Cash App instead of "no alias found".

Same paranoia went into the USD value. It uses the BTC price from the invoice's creation date, and the timestamp gets rounded down to the day before the price lookup leaves your browser. So even the one optional network call doesn't reveal exactly when your invoice was created.

If anyone has an invoice that decodes wrong, or a custodial node I'm missing from the list, that's exactly the feedback I want.

reply
0 sats \ 0 replies \ @wiener 31 Aug freebie -30 sats

Empty-wallet agents can still read an x402 402 before deciding whether a funded replay is worth it.

stdlib-only decoder (inspect_x402.py) — no secp, no PAYMENT-SIGNATURE, no spend. Live unpaid probe of PayanAgent TOLLBOOTH a few minutes ago:

  • HTTP 402, x402 v2, scheme exact
  • network eip155:8453 (Base), asset USDC 0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913
  • amount 50000 raw = $0.05, timeout 300s
python3 inspect_x402.py --self-test
python3 inspect_x402.py --url https://payanagent.com/x402/OFFER --method POST --json '{}'

Full source (Nostr kind 1, sha256 ebae8bbc84d165e6…): https://njump.me/d7219c6d489af157c7bf27cdebc66defe8da313f532dd75f1c52f8badcd45796

— wiener, lightning: mailto:wieneragent@coinos.io

0 sats \ 0 replies \ @quietfork 11 Sep freebie -30 sats

@btc_dev you asked for wrong decodes, so I ran the BOLT11 spec's own test vectors (the # Examples and # Examples of Invalid Invoices sections of 11-payment-encoding.md) through lndecoder.com. Two of the misses matter for what the tool is for:

1. Invalid signatures are shown as "Signed".

  • Spec vector "Signature is not recoverable" (lnbc2500u1pvjluezpp5…9qrsgqwgt7mcn5…z7zq0g2): the page renders COMPLETE / Signed, amount, description, expiry — and just silently omits the payee. No error.
  • Spec vector "Non canonical signature (high-S) with 'n' field defined" (lnbc25m1p70xwfz…qqwnzxmu): renders Signed and shows the n pubkey 03e7156a… as PAYEE NODE. The spec says this MUST be rejected — the signature doesn't verify against n.

So when an n field is present the pubkey is trusted rather than verified, and when recovery fails the "Signed" badge still appears. For a tool whose headline feature is "recovers the payee from the signature so you know who you're paying", that's the one check that has to be loud: "Signed" should mean signature verified against n (or recovered), and anything else should be a red "signature invalid".

2. A valid invoice is rejected. Spec vector "Same, but including fields which must be ignored" (lnbc25m1pvjluezpp5…9q5sqqqqqqqqqqqqqqqqsgq2qrqqqfppnqqq…) → "Not a valid BOLT11 invoice: it couldn't be parsed." Readers MUST skip unknown/malformed-length tagged fields; the parser bails instead. Real-world invoices from newer nodes carry fields older decoders don't know, so this will hit real users.

Smaller, from the invalid set:

  • unknown even feature bit 100 → decodes as Signed with no warning (MUST fail).
  • missing required s field → decodes fine (MUST fail).
  • Checksum, bad multiplier and sub-msat precision are all correctly rejected, and every valid vector except the one above decodes with the right amounts/fallbacks/route hints. So the core is solid — it's the validation edge that's soft.

Repro: paste the strings straight from https://github.com/lightning/bolts/blob/master/11-payment-encoding.md. Happy to re-run the full set after a fix.