The buyer-side webapp Purchase button needs allow_fiat to know
whether to surface the fiat method, and fiat_currency for the
conversion-preview label. Without these in the published Nostr
event, the buyer would either have to REST-fetch the LNbits event
again (defeats the inventory-sync goal) or guess.
Same backwards-compat reasoning as the four counter tags — tags
are AIO additions outside the NIP-52 spec; unknown tags are
ignored by spec-compliant clients.
- tickets_allow_fiat: "true" when the organizer enabled the fiat
toggle. Omitted otherwise so the on-the-wire payload stays
small for the common Lightning-only case.
- tickets_fiat_currency: only emitted when allow_fiat is on
(otherwise it'd be ambiguous what the value represents).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Inventory sync over Nostr, mirroring how nostrmarket republishes
kind 30018 product events when stock changes. Connected webapp /
other-client subscriptions pick up the new state via their existing
relay subscription — no REST polling needed.
build_nip52_event grows four AIO custom tags on every published
kind 31922/31923 event:
- tickets_available — current remaining (omitted when amount_tickets
is 0, the schema's "unlimited" sentinel, so clients can tell the
difference between unlimited and sold-out)
- tickets_sold — running count, always emitted (clients derive
original_capacity = available + sold for progress bars)
- tickets_price — price_per_ticket (0 means free)
- tickets_currency — the currency string
Tags are AIO additions outside the NIP-52 spec; spec-compliant
clients MUST ignore unknown tags so this stays backwards-compatible.
set_ticket_paid calls publish_or_delete_nostr_event after the
counter update so the new state lands on relays. The whole sequence
(counter update + republish) is wrapped in a per-event-id asyncio
lock to address the existing # todo: lock and to ensure two paid
invoices for the same event can't reorder the published state.
Failures inside the Nostr publish are logged + swallowed by the
existing wrapper, so a relay outage can never break the payment
flow.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The webapp My Tickets view + the owned-ticket badges in the
activities feed both rely on this endpoint to enumerate a buyer's
tickets across all events. The CRUD function already existed
(`get_tickets_by_user_id`); just expose it.
Auth: Bearer access token (the same shape the webapp already sends
to other LNbits endpoints). The path param must match the token-
bound user.id — users can only enumerate their own tickets, not
anyone else's by ID-guessing.
Returns full `Ticket` rows rather than `PublicTicket` because the
owner needs the payment_hash (for the QR) + the `extra` envelope
(for refund / promo / notification state) in My Tickets.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>