H14 (NWC double-pay): after the 15s pay() timeout, useNWC now polls
lookupInvoice to confirm settlement before reporting failure; if the status
stays unknown it throws a coded error (PAYMENT_STATUS_UNKNOWN) and the callers
that used to fall through to another rail (useZaps, usePurchasePro,
PlatformFeePayment) now STOP and tell the user to check their wallet — no
automatic second payment.
H1 (spot claim): claim-from now stores the ORIGINAL COORDINATE
(30818:pubkey:d) rather than an ambiguous bare pubkey; SkateSpot parses
claimedFrom/claimReason; a claimed listing shows a 'Claimed listing' notice so
the duplicate is understandable. NIP.md updated. Full reader-side supersede is
documented as the remaining design item (a wrong rule could hide real spots).
So Local relays are used and Blocked relays are excluded EVERYWHERE, not just in
the NPool routers:
- useListingReports, useSellerInfo, useSkateRelays (read+write), useZaps
(NIP-57 relays tag), usePurchasePro, CollectionDetailPage, CrewForm,
useDirectMessages write fallback
- AppProvider's empty-relays defaults check is the only intentional direct reader
- AGENTS.md updated
Gate: 101 tests, 0 errors/warnings, boot smoke green.
Audit of the wallet/zap flow surfaced a real money-path bug in ZapDialog's
Cashu branch:
• One-click Cashu zap never worked. The Cashu payment branch only ran
`if (... && invoice)`, but no invoice exists on the first click — so
selecting "Cashu" and tapping Zap silently fell through to the Lightning
flow (generating an invoice / paying via NWC-WebLN) and the user's Cashu
balance was never used. Now the Cashu path generates the recipient's
amount-verified zap invoice and melts it from the Cashu wallet in a single
click.
To support this cleanly, useZaps now exposes `generateZapInvoice()` —
builds + signs the NIP-57 request, fetches the LNURL invoice, and runs the
same `assertInvoiceAmount` security check the Lightning rail uses — WITHOUT
auto-paying. The Lightning `zap()` path was refactored to use it too, so
both rails share one verified-invoice codepath.
• Custom-amount balance guard bypassed. The insufficient-balance warning and
the disabled Send state only checked `typeof amount === 'number'`, but the
custom-amount input stores a string — so a typed amount over the Cashu
balance slipped past both. Both now coerce to a number first.
• Smarter defaults: when the dialog opens and the user has Cashu funds but no
connected Lightning wallet, Cashu is pre-selected and the "connect a wallet"
setup nag is skipped (they can already pay).
• Removed a dead `useLightningOperations` import.
Also audited mobile layout (Layout.tsx — mature, safe-area-aware, no changes
needed) and ZapCrewDialog (uses the separate useCrewZap splitter, no Cashu
option, no bug).
Bumps to 1.2.21 (Android versionCode 10221 auto-derived).
Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
Fixes the audit findings:
HIGH-1 (NWC/WebLN auto-pay of unverified invoices): add assertInvoiceAmount and
call it before every programmatic payment in useZaps, useCrewZap, and
SpamFeePayment. A malicious LNURL/Lightning-address server can no longer return
an inflated invoice and drain the wallet — amount is decoded from bolt11 and must
match the intended sats (±1 sat), amountless invoices are rejected.
HIGH-2 (forgeable trust signals):
- useSasquatchPro: Pro is granted ONLY by a zap receipt AUTHORED by the
platform's Lightning provider, embedding a user-signed zap request that tags
the platform, with a real paid amount >= smallest tier. The self-signed
kind:32671 receipt is now advisory only and never grants access (closed the
"self-grant permanent Pro" hole).
- useFeaturedVerification: a listing is 'verified' only when the matching 9735 is
authored by the provider pubkey (not any self-published receipt).
- useCrewGoal: tally only invoice-backed (bolt11) zaps; the forgeable amount tag
is no longer summed, so goal progress can't be inflated with fake receipts.
Bump to 1.2.14.
Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
Newer nostr-tools removed nip57.getSatoshisAmountFromBolt11, breaking
useZaps and useCrewGoal. Add src/lib/bolt11.ts (getSatoshisFromBolt11)
that parses the sat amount straight from the invoice's human-readable
prefix — no external dependency, immune to nostr-tools API churn — and
use it in both hooks.
Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
The clean node_modules reinstall pulled newer @nostrify/* and nostr-tools
minors whose nip57.makeZapRequest signature changed (event param became a
required full NostrEvent), breaking tsc in useZaps and usePurchasePro.
Build the kind:9734 zap request events directly per NIP-57 instead of
relying on nip57.makeZapRequest, so we're decoupled from that helper's
changing type signature. Preserves correct target tagging:
- addressable events → 'a' tag (kind:pubkey:dTag)
- other events → 'e' tag (event id)
- profile-only (pro purchase) → no event tag, keeps pro-tier/pro-expiry.
Pin @nostrify/nostrify, @nostrify/react and nostr-tools so the tree
stays reproducible.
Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
The entire skate-spots codebase was accidentally copied into src/src/ and
public/public/ instead of src/ and public/ directly. This left the real
src/ directory as blank MKStack template stubs, explaining why the landing
page showed the default template instead of SkateSpots.
Changes made:
- Copied all files from src/src/ up to src/ (App.tsx, AppRouter.tsx, main.tsx,
all pages, components, hooks, contexts, lib, i18n, test)
- Copied all files from public/public/ up to public/ (images, manifest, etc.)
- Deleted src/src/ and public/public/ nested directories
- Removed HelloWorld.tsx template stub from pages/
- Retained the previously fixed index.css (Tailwind v3 directives)
Full skate-spots feature set is now active:
- All 30+ routes (map, events, spots, coaches, marketplace, wallet, etc.)
- NWCProvider, LanguageProvider, PWAInstallPrompt, AmberCallbackHandler
- Skate community relays (goskatespots.nostr1.com, wotr.relatr.xyz, etc.)
- Outfit Variable font, Amber pre-check in main.tsx
- All hooks (useSkateSpots, useCoaches, useZaps, etc.)
- i18n support (en/es)
Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>