aboutsummaryrefslogtreecommitdiffstats
path: root/lib/invoices.ts
Commit message (Collapse)AuthorAgeFilesLines
* bolt12: put the requested expiry and single-use on the offer itselfAdam Soltys6 days1-0/+9
| | | | | | | | The expiry was only stored on our invoice record, so CLN kept issuing invoices for the offer after it had expired. Pass it as absolute_expiry, and accept single_use to cap an offer at one payment. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* invoices: a supplied account must belong to the invoice's userAdam Soltys8 days1-1/+6
| | | | | | | | | | generate() took any existing account id as the credit target, so an invoice could carry one user's name while paying into someone else's account. A supplied aid now has to be in the invoice user's own account list; otherwise the invoice credits that user's main account. Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01KCxLg8s1g8yBwjRwPN4uJR
* invoices: don't let a supplied id overwrite another user's invoiceAdam Soltys2026-09-291-0/+11
| | | | | | | | | | | | generate() writes invoice:<id> wholesale with the caller's uid, and the old bolt11 pointer keeps resolving to that id, so passing someone else's invoice id re-pointed their invoice at the caller's account. Invoice ids aren't secret (LUD-21 verify URLs, invoice pages, receipts), so refuse an existing id that belongs to a different user, both in generate() and in POST /invoice for anonymous pay-page callers. Both fail with "invoice not found" so ids can't be probed for existence. Co-Authored-By: Claude Fable 5.1 <[email protected]>
* security: drop the admin endpoint surface and land pending hardeningAdam Soltys2026-09-131-0/+2
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Removes the admin-gated endpoints and the account flags they set, plus a batch of hardening that had accumulated uncommitted in the tree. These were deployed and verified together, so they land as one change. admin surface: - drop POST /hidepay, POST /unlimit and GET /users, their handlers, and the now-unused admin preValidation export - `unlimited` was only ever written, never read; `hidepay` only appeared in output projections. Both flags go, along with their whitelist, public-fields and type entries. request log: - redactBody now recurses. It only masked top-level keys, so a body that nests credentials one level down wrote them to the log in plaintext, and pin fields were not on the list at all. payments: - sendOnchain/build gate `aid` through requireAccount, so a caller can only spend from an account it owns - sendOnchain signs only a tx we composed, matched against a short-lived per-account build receipt - raise xpay retry_for to 60s; route-finding preferred a drained zero-fee hop and burned the whole budget on it. check()'s reversal window keeps its 2x margin. ecash / invoices / webhooks: - resolve a token's mint through the IP-pinning fetcher instead of plain fetch, closing an unauthenticated SSRF path into the internal network - reject non-positive amounts before the balance write - /sign requires the caller to own the address, rather than signing under any address the hot wallet controls - webhook delivery no longer disables TLS verification; the body carries the merchant's shared secret registration: - refuse a username the v3 registrar holds unless the caller's own nostr key is the holder (lib/names.ts) liquid: - honour the deposit kill switch at invoice generation and at credit elements image: - pin 23.3.4 and verify the release tarball checksum Co-Authored-By: Claude Opus 5 (1M context) <[email protected]> Claude-Session: https://claude.ai/code/session_0112TGi9GGNWqji1XQ5jZRzc
* mint/lightning: refuse caller-supplied invoices, tiered fees, log hygieneAdam Soltys2026-07-301-14/+11
| | | | | | | | | | | | | | | - invoices: reject caller-supplied bolt11/bolt12; the server always mints its own. Closes the invoice-registration path behind the shared-node credit and payment-hijack vectors. - lightning: skip mint-owned invoices (lbl* label) in the paid-invoice listener. - payments: lightning free-tier fee credit, withheld for flagged high-throughput (ln:nofree) accounts which pay an elevated rate; the failed-send reversal restores credit at the same rate. freezeCheck made crash-resilient. Lightning and bolt12 sends stay pending until the preimage settles. - payments (route): validate payment-request / invoice input types. - logging: collapse repeated xpay failure lines into one. Co-Authored-By: Claude Opus 4.8 <[email protected]>
* bolt12 zaps: pay offers, NWC pay/receive, per-user offers, NIP-44Adam Soltys2026-07-301-1/+38
| | | | | | | | | | | | | | | | - sendLightning fetches an invoice from lno1 offers (payer_note passthrough for NIP-177 zap intents) and pays it through the existing bolt12 path - NWC: new nwc#2 pay/receive methods (BIP-321 URIs, payer proofs stubbed until CLN 26.06 createproof), nip44_v2 alongside nip04 with per-request scheme detection, dual 23196/23197 notifications, 13194 refreshed when its content or encryption tag goes stale - standing per-user bolt12 offer via GET /offer; incoming bolt12 payments record invreq_payer_note as memo - parse/fetchinvoice routes handle offers; zap display parses kind 9736 receipts (amount tag + embedded intent) and drops a call to a sync() helper that never existed Co-Authored-By: Claude Fable 5 <[email protected]>
* preimages: support fiat prices, converted at invoice-creation timeAdam Soltys2026-07-141-6/+24
| | | | | | | | | | | | | | POST /preimages now accepts fiat + optional currency (defaults to the merchant's) as an alternative to a sat price. The fiat amount is stored per entry and converted to sats at the moment a usePreimage invoice is created, so the price tracks the exchange rate instead of freezing at upload time. The invoice also takes on the entry's currency and rate so receipts display the fiat price exactly as the merchant set it. If no rate is available for the entry's currency, the preimage is pushed back onto the queue and creation fails rather than issuing an any-amount invoice. Co-Authored-By: Claude Fable 5 <[email protected]>
* preimages: enforce a merchant-set price per preimage batchAdam Soltys2026-07-131-6/+27
| | | | | | | | | | | | | Invoice creation is unauthenticated, so buyers could name their own price for a queued preimage (create the usePreimage invoice with amount: 1). POST /preimages now takes an optional price (sats) that is stored per entry and overrides the requested amount when the preimage is consumed; omitting it keeps the old any-amount behavior. Also gate the stored-preimage reveal in credit() on the invoice being fully paid, since internal sends can settle partial amounts. Bare-hex entries queued before this change still parse (treated as priceless). Co-Authored-By: Claude Fable 5 <[email protected]>
* Merge remote-tracking branch 'origin/master'Adam Soltys2026-07-111-2/+37
|\ | | | | | | | | # Conflicts: # lib/payments.ts
| * invoices: sell merchant-supplied preimages via a usePreimage queueAdam Soltys2026-07-101-2/+37
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Merchants POST /preimages (auth) to pre-load 32-byte hex preimages into a FIFO queue; creating an invoice with usePreimage: true consumes the next one so the invoice's payment hash is sha256(preimage). Paying the invoice reveals the merchant-chosen secret to the buyer — via their own wallet on external settlements, and via GET /invoice/:id once settled — enabling backend-less digital download stores (encrypted files on static hosting, preimage + public string = decryption key). - GET /preimages lists the queue with payment hashes so the merchant can map files to future invoices; POST /preimages/delete clears it - empty queue fails invoice creation rather than issuing a random preimage the buyer would pay for but couldn't decrypt with - preimages cln rejects as already used are discarded and the next tried - consumed preimages persist at preimage:${payment_hash} (TTL = invoice expiry) and credit() prefers them as the settlement ref, so internal coinos-to-coinos payments reveal the real preimage instead of the sender's uid Co-Authored-By: Claude Fable 5 <[email protected]>
* | invoices: reject sub-300-sat on-chain invoice amountsAdam Soltys2026-07-101-0/+12
|/ | | | | | | | | | On-chain deposits below 300 sats are dropped by the dust filter in the confirm/credit path, so a specific-amount bitcoin/liquid invoice under that threshold can never be credited. Reject creating one at generation time and point the user at lightning. Any-amount (0) addresses are unaffected. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
* invoices: don't re-list an invoice id on update (dedupe :invoices)Adam Soltys2026-06-181-1/+7
| | | | | | | | | | | generate() unconditionally lPush'd the invoice id to `${aid}:invoices`, but it's also called from the update() handler (tip/webhook changes, and repeated bolt12 offer creation) re-using the existing id — so each update re-appended the same id and the user's :invoices accumulated duplicate entries, rendering the same offer/invoice multiple times. Only push when the id isn't already in the list (LPOS guard). Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
* health checkAdam Soltys2026-02-061-10/+1
|
* fix bolt12 invoicesAdam Soltys2025-09-191-1/+1
|
* sendinvoice supportAdam Soltys2025-09-181-10/+19
|
* handle 0 tipAdam Soltys2025-08-261-1/+2
|
* fix invoice updateAdam Soltys2025-08-211-3/+4
|
* add missing make_invoice fields (fixes #78)Adam Soltys2025-07-261-0/+3
|
* respect null tipsAdam Soltys2025-07-191-1/+1
|
* mark self-generated invoicesAdam Soltys2025-06-231-0/+3
|
* use getInvoice helperAdam Soltys2025-03-051-2/+2
|
* payment typesAdam Soltys2025-02-261-8/+9
|
* send zaps for internal paymentsAdam Soltys2025-01-171-3/+2
|
* default to blech32 for liquidAdam Soltys2025-01-151-1/+5
|
* sign endpointAdam Soltys2025-01-151-3/+4
|
* check for duplicate offersAdam Soltys2024-12-221-1/+3
|
* unique offer descriptionAdam Soltys2024-12-211-1/+1
|
* handle offersAdam Soltys2024-12-191-2/+2
|
* printer endpointAdam Soltys2024-12-181-8/+11
|
* ecash receiveAdam Soltys2024-11-221-0/+4
|
* wipAdam Soltys2024-11-211-0/+8
|
* set account idAdam Soltys2024-11-081-0/+1
|
* biome lintAdam Soltys2024-10-311-1/+3
|
* fix type logAdam Soltys2024-10-301-1/+1
|
* dedup locationsAdam Soltys2024-10-301-14/+14
|
* log invalid typeAdam Soltys2024-10-231-1/+1
|
* push to account invoicesAdam Soltys2024-09-251-1/+1
|
* reconcile onchain balanceAdam Soltys2024-09-241-1/+4
|
* reconcile on-chain balanceAdam Soltys2024-09-231-1/+4
|
* rename account idAdam Soltys2024-09-201-7/+7
|
* nwc make_invoiceAdam Soltys2024-09-191-2/+1
|
* add default account if missingAdam Soltys2024-09-131-2/+2
|
* default accountAdam Soltys2024-09-121-0/+2
|
* package rpcAdam Soltys2024-09-081-1/+1
|
* refactor rpc helper, accounts endpointsAdam Soltys2024-09-081-5/+2
|
* return expiryAdam Soltys2024-09-061-3/+5
|
* update sample configAdam Soltys2024-09-051-1/+10
|
* fx endpointAdam Soltys2024-09-041-6/+6
|
* fix some ts issuesAdam Soltys2024-08-261-1/+1
|
* typescriptAdam Soltys2024-08-261-0/+128