mirror of
https://github.com/PR0M3TH3AN/bitvid.git
synced 2026-10-27 07:52:24 +00:00
zaps: foundation for the bitvid-native zap tally (#47) — schema + verify
First slice of docs/zap-tally-plan.md (decisions D1-D5 resolved in the doc): - ZAP_TALLY_KIND = 30081 (addressable, d=payment_hash → one canonical event per real payment) + NOTE_TYPES.ZAP_TALLY schema + buildZapTallyEvent (nostrEventSchemas.js). Video + profile pointers. - FEATURE_ZAP_TALLY flag (constants.js), default ON per D4. - zapReceiptValidator.js: extractBolt11Fields (payment_hash + description_hash from the existing bech32 walker), verifyPaymentPreimage (sha256(preimage)==payment_hash), verifyBitvidZapTally — the security core: proves the invoice was paid AND bound to this zap request (description-hash binding blocks reusing a leaked preimage for another video). Amount is bolt11-derived, never the tag; pointers come from the embedded zap request. - Schema-doc row for kind 30081. Tests: tests/zap-tally-verify.test.mjs (8) — preimage check, bech32 field round-trip, valid/bad-preimage/replay/zero-sats decisions, builder tag shape (video + profile). Lint + build green. No publishing or counting wired yet — next slices per the plan checklist. Co-Authored-By: Claude Fable 5 <[email protected]>
This commit is contained in:
1 parent
ce4904f1a4
commit
a6b2996f4e
6 files changed
+542
-16
No files matched your search
@@ -196,6 +196,7 @@ Video posts should treat `videoRootId` as the stable series identifier that rema
|
||||
| Legacy Direct Message (`NOTE_TYPES.LEGACY_DM`) | `4` | `['p', <recipient pubkey>]` | NIP-04 encrypted ciphertext |
|
||||
| Zap request (`NOTE_TYPES.ZAP_REQUEST`) | `9734` | `['p', <recipient pubkey>]` plus optional `['e', <event id>]`, `['a', <coordinate>]`, `['amount', <msats>]`, `['lnurl', <bech32>]`, and `['relays', ...]` for receipt publishing | Optional plaintext zap note |
|
||||
| Zap receipt (`NOTE_TYPES.ZAP_RECEIPT`) | `9735` | `['bolt11', <invoice>]`, `['description', <zap request JSON>]`, `['p', <recipient pubkey>]` plus optional `['e', <event id>]` and `['a', <coordinate>]` | Empty content; receipts are published by the recipient's LNURL server |
|
||||
| Zap tally (`NOTE_TYPES.ZAP_TALLY`) | `30081` (addressable, `d = payment_hash`) | `['d', <payment_hash>]`, `['p', <recipient>]`, optional `['e', <event id>]`/`['a', <coordinate>]`, `['amount', <msats>]`, `['bolt11', <invoice>]`, `['preimage', <hex>]`, `['description', <zap request JSON>]`, `['client', 'bitvid']`, `['t', 'zap']` | bitvid-native, payer-signed, **preimage-verified** stand-in for a 9735 when the recipient's wallet doesn't publish one. Verified via `sha256(preimage)==payment_hash` + `description_hash==sha256(zapRequest)`. Counted alongside 9735s (deduped by `payment_hash`). See `docs/zap-tally-plan.md`. |
|
||||
| HTTP Auth (`NOTE_TYPES.HTTP_AUTH`) | `27235` | `['u', <url>]`, `['method', <http method>]`, `['payload', <payload hash>]` | Optional plaintext content (NIP-98 recommends empty, but implementations may vary) |
|
||||
| Report (`NOTE_TYPES.REPORT`) | `1984` | `['e', <event id>, <report type>]`, `['p', <pubkey>, <report type>]`, and optional `['t', <report type>]` | Plaintext report reason |
|
||||
|
||||
|
||||
+21
-16
@@ -426,23 +426,28 @@ tallies simply stop being counted. No data migration.
|
||||
|
||||
---
|
||||
|
||||
## 10. Open decisions (need a call before/at build time)
|
||||
## 10. Decisions (RESOLVED 2026-07-04)
|
||||
|
||||
- **D1 — event kind.** Proposed `9736` (adjacent to the 9735 receipt, "bitvid zap
|
||||
tally"). Must confirm it's unassigned in the NIP kind registry; if risky, pick a
|
||||
clearly app-specific regular kind and reserve it in `docs/nostr-event-schemas.md`.
|
||||
Everything references `ZAP_TALLY_KIND` so the number is a one-line change.
|
||||
- **D2 — profile zaps in v1?** Video path is the ask; profile path is the same
|
||||
primitives + a channel-page badge. Ship video-only first, profile as a
|
||||
follow-up? (Recommended: yes, video-only v1.)
|
||||
- **D3 — publish relays.** Publish the tally to the user's write relays (same as
|
||||
video publishing) so bitvid clients querying those relays see it. Confirm the
|
||||
store queries a superset (it queries `client.relays`). Likely fine; verify.
|
||||
- **D4 — privacy default.** Default the feature flag off and add one line of UI
|
||||
copy ("your zap will be publicly attributed on bitvid") before default-on?
|
||||
- **D5 — chart Y-axis (§5.9).** Independent per-series scaling (each cumulative
|
||||
line filling the height — simplest, trend-focused, **recommended**) vs. a dual
|
||||
labeled Y-axis (left=views, right=sats — more precise, busier in a small modal).
|
||||
- **D1 — event kind → ADDRESSABLE `ZAP_TALLY_KIND = 30081`, `d = payment_hash`.**
|
||||
Chosen: a higher, app-specific kind in bitvid's own family (30078 video,
|
||||
30079 view, **30081** zap tally). Addressable (30000–39999) with the
|
||||
per-payment `payment_hash` as the `d` tag makes each real payment map to
|
||||
exactly ONE canonical event — relay-level idempotency; a re-publish replaces
|
||||
rather than duplicates. Still queried by its `#a`/`#e`/`#p` tags like a 9735.
|
||||
Reserve the kind in `docs/nostr-event-schemas.md`.
|
||||
- **D2 — scope → VIDEO + PROFILE zaps in v1.** Video path drives the badges/Most
|
||||
Zapped; profile path reuses the same primitives with a `p`-only pointer and a
|
||||
channel-page total (new small UI surface). Both ship in v1.
|
||||
- **D3 — publish relays → user's WRITE relays** (same path as video publishing).
|
||||
The store queries `client.relays` (a superset incl. write relays); verify at
|
||||
wiring time.
|
||||
- **D4 — publishing → ON BY DEFAULT.** `FEATURE_ZAP_TALLY` still exists for
|
||||
rollback but defaults **true**; every successful zap publishes a tally. Keep a
|
||||
short one-line disclosure in the zap UI ("zaps are publicly attributed on
|
||||
bitvid") since it's honest and cheap, but no opt-in gate.
|
||||
- **D5 — chart Y-axis → INDEPENDENT PER-SERIES scaling.** Each cumulative line
|
||||
fills the height against its own max; the legend names the two units. No dual
|
||||
labeled Y-axis.
|
||||
|
||||
---
|
||||
|
||||
|
||||
Reference in new issue
Block a user