feat(nostr): NIP-99 menu listings, NIP-01 profile, NIP-17 stub

nostr/event.py
  Bare NIP-01 NostrEvent with canonical id computation.

nostr/nostr_client.py
  Bidirectional WebSocket client (lifted from events ext, kept
  local). Connects to nostrclient ext's internal relay endpoint,
  dedups by event id (LRU 1000).

nostr_publisher.py
  Builders for:
    * kind 0    — restaurant profile (NIP-01 metadata)
    * kind 30402 — menu item (NIP-99 classified listing,
                              parameterized replaceable by item.id)
    * kind 5    — deletion request (NIP-09)
  Schnorr signing via coincurve (BIP-340).

  Menu listings carry structured price tags (["price", n, currency]),
  status (active|sold) so customers see sold-out items, and 't' tags
  for category, dietary, allergens (allergen:<x>) and ingredients
  (ingr:<x>) so webapps can filter without parsing markdown.

  Restaurants can sign with their own keypair (per-restaurant Nostr
  identity) or fall back to the LNbits Account keypair.

nostr_sync.py
  Subscribes to:
    * kind 30402 #t=menu — backfill 200 + live (echo confirmation
      for now; foreign-menu indexing deferred until we settle on a
      federated cache table).
    * kind 1059 — NIP-17 gift-wrapped DMs, only when
      settings.nostr_orders_enabled. Decryption stubbed (needs
      NIP-44 v2 unwrap); REST stays the supported transport
      until that's wired up. _place_order_from_dm is complete and
      ready for the decryption hook.
This commit is contained in:
Padreug 2026-04-29 23:42:01 +02:00
commit b155548036
5 changed files with 601 additions and 0 deletions

0
nostr/__init__.py Normal file
View file