mirror of
https://github.com/aljazceru/awesome-nostr.git
synced 2026-09-14 02:55:07 +00:00
grantless: make zap chips clickable on GitHub
GitHub's sanitizer strips lightning: links entirely (verified via the GitHub markdown render API), so chips now use a self-hosted https form: [⚡ zap](https://nostr.net/grant/?zap=addr@host) - GitHub visitors get a working link to the grant page, which auto-opens the zap dialog (QR / copy / open wallet / connect-wallet path) - nostr.net decodes the address locally from the query string; the full in-page zap flow is unchanged; raw lightning: chips still parse (back-compat) - README addresses are human-readable again (trivial to audit); the getalby.com redirect helper is dead (404) so nothing depends on it - zap-core: lnurlDecode (checksum-verified bech32) + tests; 27 pass
This commit is contained in:
+3
-3
@@ -17,13 +17,13 @@ The insight: the list **is** the funding platform. Turn entries into zappable en
|
||||
Keep the existing format, add optional standardized chips at the end of an entry:
|
||||
|
||||
```markdown
|
||||
- [Amethyst](https://www.amethyst.social/) - Android-only app [⚡ zap](lightning:vitor@amethyst.social) [donate](https://geyser.fund/project/xyz)
|
||||
- [Damus](https://damus.io/) - The OG nostr client for iOS [⚡ zap](lightning:jb55@damus.io)
|
||||
- [Amethyst](https://www.amethyst.social/) - Android-only app [⚡ zap](https://nostr.net/grant/?zap=vitor@amethyst.social) [donate](https://geyser.fund/project/xyz)
|
||||
- [Damus](https://damus.io/) - The OG nostr client for iOS [⚡ zap](https://nostr.net/grant/?zap=jb55@damus.io)
|
||||
```
|
||||
|
||||
Rules:
|
||||
|
||||
- **`[⚡ zap](lightning:...)`** — a `lightning:` URI holding an LN address (or LNURL). This is what makes an entry *zappable*. Parsed with `/\[⚡\s*zap\]\(lightning:([^)\s]+)\)/i`.
|
||||
- **`[⚡ zap](https://nostr.net/grant/?zap=jb55@damus.io)`** — an https redirect helper carrying the bech32-encoded LNURL-pay endpoint of the project's lightning address. GitHub's sanitizer **strips raw `lightning:` links entirely** (verified via the GitHub markdown render API), so chips must use this https form to stay clickable on GitHub — clicking offers to open the user's wallet (or shows a QR). On nostr.net the chip is decoded **locally** (`zapCore.lnurlDecode`) back into the address and zapped in-page; the helper is never in the zap path itself. Raw `lightning:` chips are still recognized by the parser for back-compat.
|
||||
- **`[donate](https://...)`** — optional external funding link (Geyser, OpenSats, Patreon, whatever). Rendered as a second chip. No one-size-fits-all: the project picks.
|
||||
- Everything else about entries stays exactly as it is. GitHub renders the chips as normal links, so the README stays perfectly readable on GitHub too.
|
||||
- Adding/changing a zap address happens via PR — same review flow as today. That's the "grantless" model: anyone can walk in, but the curator merges.
|
||||
|
||||
@@ -6,23 +6,23 @@ nostr.net services [start.nostr.net](https://start.nostr.net) || [relay.nostr.ne
|
||||
## Most popular
|
||||
|
||||
### Apps
|
||||
- [Zapstore](https://zapstore.dev/) - A truly open app store [⚡ zap](lightning:zapstore@rizful.com)
|
||||
- [Hivetalk](https://honey.hivetalk.org/) - Nostr + Lightning Video Conferencing [⚡ zap](lightning:bitkarrot@primal.net)
|
||||
- [Zapstore](https://zapstore.dev/) - A truly open app store [⚡ zap](https://nostr.net/grant/?zap=zapstore@rizful.com)
|
||||
- [Hivetalk](https://honey.hivetalk.org/) - Nostr + Lightning Video Conferencing [⚡ zap](https://nostr.net/grant/?zap=bitkarrot@primal.net)
|
||||
|
||||
### Mobile clients
|
||||
- [Damus](https://damus.io/) - iOS, Android and Desktop client [⚡ zap](lightning:damus@sendsats.lol)
|
||||
- [Wisp](https://wisp.mobile/) - Android-only app [⚡ zap](lightning:utxo@rizful.com)
|
||||
- [Amethyst](https://www.amethyst.social/) - Android-only app [⚡ zap](lightning:vitor@vitorpamplona.com)
|
||||
- [Primal](https://primal.net/downloads) - iOS and Android apps [⚡ zap](lightning:miljan@primal.net)
|
||||
- [YakiHonne](https://yakihonne.com/yakihonne-mobile-app) - iOS and Android app [⚡ zap](lightning:yakihonne@getalby.com)
|
||||
- [Damus](https://damus.io/) - iOS, Android and Desktop client [⚡ zap](https://nostr.net/grant/?zap=damus@sendsats.lol)
|
||||
- [Wisp](https://wisp.mobile/) - Android-only app [⚡ zap](https://nostr.net/grant/?zap=utxo@rizful.com)
|
||||
- [Amethyst](https://www.amethyst.social/) - Android-only app [⚡ zap](https://nostr.net/grant/?zap=vitor@vitorpamplona.com)
|
||||
- [Primal](https://primal.net/downloads) - iOS and Android apps [⚡ zap](https://nostr.net/grant/?zap=miljan@primal.net)
|
||||
- [YakiHonne](https://yakihonne.com/yakihonne-mobile-app) - iOS and Android app [⚡ zap](https://nostr.net/grant/?zap=yakihonne@getalby.com)
|
||||
|
||||
### Web clients
|
||||
- [primal.net](https://primal.net/) [⚡ zap](lightning:miljan@primal.net)
|
||||
- [nostria](https://nostria.app/) [⚡ zap](lightning:sondreb@rizful.com)
|
||||
- [coracle.social](https://coracle.social/) [⚡ zap](lightning:hodlbod@getalby.com)
|
||||
- [YakiHonne](https://yakihonne.com) [⚡ zap](lightning:yakihonne@getalby.com)
|
||||
- [Ditto](https://ditto.pub) [⚡ zap](lightning:alex@alexgleason.me)
|
||||
- [Jumble@Imwald](https://jumble.imwald.eu/) [⚡ zap](lightning:stellainforest@cake.cash)
|
||||
- [primal.net](https://primal.net/) [⚡ zap](https://nostr.net/grant/?zap=miljan@primal.net)
|
||||
- [nostria](https://nostria.app/) [⚡ zap](https://nostr.net/grant/?zap=sondreb@rizful.com)
|
||||
- [coracle.social](https://coracle.social/) [⚡ zap](https://nostr.net/grant/?zap=hodlbod@getalby.com)
|
||||
- [YakiHonne](https://yakihonne.com) [⚡ zap](https://nostr.net/grant/?zap=yakihonne@getalby.com)
|
||||
- [Ditto](https://ditto.pub) [⚡ zap](https://nostr.net/grant/?zap=alex@alexgleason.me)
|
||||
- [Jumble@Imwald](https://jumble.imwald.eu/) [⚡ zap](https://nostr.net/grant/?zap=stellainforest@cake.cash)
|
||||
|
||||
## Protocol
|
||||
|
||||
@@ -32,7 +32,7 @@ nostr.net services [start.nostr.net](https://start.nostr.net) || [relay.nostr.ne
|
||||
- [Nostr: Solucionando la censura de una vez por todas](https://estudiobitcoin.com/nostr-solucionando-la-censura-de-una-vez-por-todas/)
|
||||
- [nostr.how](https://nostr.how) - A comprehensive non-technical beginners guide to Nostr. Available in several languages.
|
||||
- [nostr.com](https://nostr.com) - nostr getting started guide
|
||||
- [nostrich.love](https://nostrich.love/) - a normie-friendly introduction and quick start guide. [⚡ zap](lightning:nostrich@wallet.yakihonne.com)
|
||||
- [nostrich.love](https://nostrich.love/) - a normie-friendly introduction and quick start guide. [⚡ zap](https://nostr.net/grant/?zap=nostrich@wallet.yakihonne.com)
|
||||
- [NostrHub](https://nostrhub.io) - Your HUB for all things Nostr. Discover NIPs and publish your own Custom NIPs, Community forum, Nostr app directory, Nostr app GitHub repositories, DVMs, and more.
|
||||
- [nostr](https://github.com/nostr-protocol/nostr) - Overview and FAQ
|
||||
- [data-vending-machines](https://github.com/nostr-protocol/data-vending-machines) - DVM documentation and kind registry
|
||||
@@ -40,7 +40,7 @@ nostr.net services [start.nostr.net](https://start.nostr.net) || [relay.nostr.ne
|
||||
- [tinkering with nostr without any client](https://medium.com/@p2w34/tinkering-with-the-nostr-protocol-will-it-take-twitter-over-74c4bf0fea66)
|
||||
- [UseNostr](https://usenostr.org) - A small guide for anyone who wants to learn more about how nostr works and what it can do.
|
||||
- [Building Nostr](https://building-nostr.coracle.social/) - A guide for developers building on Nostr (PDF/EPUB available).
|
||||
- [persian nostr book](https://github.com/kehiy/persian-nostr-book) - a book written in the Persian language about nostr, containing nips translation. [⚡ zap](lightning:kehiy@walletofsatoshi.com)
|
||||
- [persian nostr book](https://github.com/kehiy/persian-nostr-book) - a book written in the Persian language about nostr, containing nips translation. [⚡ zap](https://nostr.net/grant/?zap=kehiy@walletofsatoshi.com)
|
||||
- [NosTracker](https://marcodpt.github.io/nostracker/) [](https://github.com/marcodpt/nostracker) - Information about NIP support for clients, relays, tools and libraries. Like a caniuse but for NIPs.
|
||||
- [Grow Nostr Initiative](https://grownostr.org) - Empowering the future of decentralized social communication through community initiatives, education, and outreach.
|
||||
- [Marmot Protocol](https://github.com/marmot-protocol/marmot) - A messaging protocol specification for efficient end-to-end encrypted group messaging using Nostr's decentralized identity & relay network combined with the MLS Protocol.
|
||||
@@ -70,7 +70,7 @@ of the public instances.
|
||||
- [210Maxi](https://github.com/dezh-tech/ddsr/tree/main/210maxi) - A nostr relay that only accepts 210 character events (NIP-B1).
|
||||
- [Denostr](https://github.com/guakamoli/denostr) - Deno based, cloud native nostr implemention.
|
||||
- [Ephemerelay](https://gitlab.com/soapbox-pub/ephemerelay) - An in-memory Nostr relay that doesn't store data.
|
||||
- [Fenrir-s](https://github.com/rushmi0/Fenrir-s) - a Nostr Relay written in Kotlin with PostgreSQL backend and GraalVM support. [⚡ zap](lightning:parkinghot99@walletofsatoshi.com)
|
||||
- [Fenrir-s](https://github.com/rushmi0/Fenrir-s) - a Nostr Relay written in Kotlin with PostgreSQL backend and GraalVM support. [⚡ zap](https://nostr.net/grant/?zap=parkinghot99@walletofsatoshi.com)
|
||||
- [gnost-relay](https://github.com/barkyq/gnost-relay)  - nostr relay written in go backed by PostgreSQL database.
|
||||
- [grain](https://github.com/0ceanslim/grain) - A highly configurable, multipurpose relay written in Go, Storing Events in a MongoDB.
|
||||
- [HAVEN](https://github.com/bitvora/haven) - Four relays in one + Blossom Media Server for a modern, sovereign and personal Nostr experience.
|
||||
@@ -94,7 +94,7 @@ of the public instances.
|
||||
- [Nostr client and relay](https://github.com/pedro-vicente/nostr_client_relay) - C++ engine that allows building Nostr applications for command line, desktop or web.
|
||||
- [nostrcheck-server](https://github.com/quentintaranpino/nostrcheck-server) - A server with relay, File Hosting, Nostr Address, Lightning Redirects, NWC and WoT.
|
||||
- [nostr_relay](https://code.pobblelabs.org/fossil/nostr_relay/) - a nostr relay written in Python, backed by SQLite
|
||||
- [nostr-filter-relay](https://github.com/atrifat/nostr-filter-relay) - A nostr relay docker image package which filter content based on content type (SFW/NSFW), user type, language, hate speech (toxic comment), sentiment, topic, and various rules. [⚡ zap](lightning:rifat@getalby.com)
|
||||
- [nostr-filter-relay](https://github.com/atrifat/nostr-filter-relay) - A nostr relay docker image package which filter content based on content type (SFW/NSFW), user type, language, hate speech (toxic comment), sentiment, topic, and various rules. [⚡ zap](https://nostr.net/grant/?zap=rifat@getalby.com)
|
||||
- [nostr-relay-nestjs](https://github.com/CodyTseng/nostr-relay-nestjs) - A Nostr relay with a clear architecture and high test coverage (PostgreSQL, MeiliSearch, NestJS)
|
||||
- [nostr-relay](https://github.com/mattn/nostr-relay) - Nostr relay in Go based on relayer. Backend by sqlite3/PostgreSQL/mysql.
|
||||
- [nostr-rs-relay](https://sr.ht/~gheartsfield/nostr-rs-relay/) - a minimalistic relay written in Rust that saves data on SQLite
|
||||
@@ -158,7 +158,7 @@ Websites with lists of relays and their performance/health:
|
||||
- [Habla.news](https://github.com/verbiricha/habla.news) - Habla allows you to read, write, curate and monetize long-form content over Nostr, a censorship-resistant protocol for social media that uses long-form Nostr content.
|
||||
- [Highlighter](https://highlighter.com) - Discover and share curated insights by people you trust.
|
||||
- [Breefly](https://breefly.social) - A low-stimulus environment where you can read articles published on nostr.
|
||||
- [Decent Newsroom](https://decentnewsroom.com/) - Explore, publish and create long form articles and magazines on nostr. [⚡ zap](lightning:decentnewsroom@rizful.com)
|
||||
- [Decent Newsroom](https://decentnewsroom.com/) - Explore, publish and create long form articles and magazines on nostr. [⚡ zap](https://nostr.net/grant/?zap=decentnewsroom@rizful.com)
|
||||
- [readwithboris.com](https://www.readwithboris.com/) - Long form reading and highlighting app.
|
||||
- [blogo](https://github.com/pluja/blogo) - A simple, fast and clean blog platform powered by Nostr.
|
||||
- [blogstack.io](https://blogstack.io) - Long-form publishing platform on Nostr.
|
||||
@@ -278,7 +278,7 @@ Websites with lists of relays and their performance/health:
|
||||
- [Jester instance](https://jesterui.github.io/)
|
||||
- [JiYou](https://github.com/TimA314/JiYou) - A nostr PWA client with a highly customizable UI
|
||||
- [JiYou.social](https://JiYou.social) - live instance
|
||||
- [Jumble](https://github.com/CodyTseng/jumble) - A web client focused on browsing relay feeds [⚡ zap](lightning:codytseng@getalby.com)
|
||||
- [Jumble](https://github.com/CodyTseng/jumble) - A web client focused on browsing relay feeds [⚡ zap](https://nostr.net/grant/?zap=codytseng@getalby.com)
|
||||
- [jumble.social](https://jumble.social/) - live instance
|
||||
- [Lightning.Pub](https://github.com/shocknet/Lightning.Pub) - A nostr daemon for Lightning nodes
|
||||
- [Listr](https://listr.lol/) - Curate, organize and discover everything Nostr has to offer. Listr is the best way to create, manage, and browse Nostr lists.
|
||||
@@ -306,7 +306,7 @@ Websites with lists of relays and their performance/health:
|
||||
- [ni.py](https://github.com/0n4t3/nipy) - CLI post only client for Nostr, Activity Pub, and the AT Protocol written in Python.
|
||||
- [Noflux](https://github.com/fiatjaf/noflux) - minimalist and opinionated feed reader
|
||||
- [Nootti](https://nootti.com) - Cross-posting iOS & iPad client app for Bluesky, Mastodon and Nostr
|
||||
- [Nos](https://github.com/planetary-social/nos)  - A UX-focused iOS / MacOS native app focused on a polished new user experience. [planetary.social](https://planetary.social) [⚡ zap](lightning:strongsnail1@primal.net)
|
||||
- [Nos](https://github.com/planetary-social/nos)  - A UX-focused iOS / MacOS native app focused on a polished new user experience. [planetary.social](https://planetary.social) [⚡ zap](https://nostr.net/grant/?zap=strongsnail1@primal.net)
|
||||
- [nos.social](https://nos.social)
|
||||
- [nosbin](https://nosbin.com/) - pastebin over nostr
|
||||
- [noscl](https://github.com/fiatjaf/noscl) - a basic command-line client written in Go
|
||||
@@ -339,18 +339,18 @@ Websites with lists of relays and their performance/health:
|
||||
- [Nostrord](https://github.com/nostrord/nostrord) - A cross-platform NIP-29 group chat client built with Kotlin Multiplatform & Compose Multiplatform.
|
||||
- [Nostros](https://github.com/KoalaSat/nostros) - A nostr mobile client for Android
|
||||
- [Nostrtium](https://github.com/pjv/nostrtium) - Post to Nostr directly from within WordPress
|
||||
- [noStrudel](https://github.com/hzrd149/nostrudel) - hzrd149's personal nostr client. [⚡ zap](lightning:nostrudel@npub.cash)
|
||||
- [noStrudel](https://github.com/hzrd149/nostrudel) - hzrd149's personal nostr client. [⚡ zap](https://nostr.net/grant/?zap=nostrudel@npub.cash)
|
||||
- [nostrudel.ninja](https://nostrudel.ninja/) - live instance
|
||||
- [nostrweb](https://git.qcode.ch/nostr/nostrweb) - another Nostr web client in vanilla JS
|
||||
- [nostr.ch](https://nostr.ch/) - live instance
|
||||
- [nostter](https://github.com/SnowCait/nostter) - Twitter-like web client
|
||||
- [nostui](https://github.com/akiomik/nostui) - A TUI client for Nostr
|
||||
- [Nostur](https://nostur.com) - Nostr client app for iOS and MacOS. ([Apple Store link](https://apps.apple.com/us/app/nostur/id1672780508)) [⚡ zap](lightning:weathereddarkness25@getalby.com)
|
||||
- [Nostur](https://nostur.com) - Nostr client app for iOS and MacOS. ([Apple Store link](https://apps.apple.com/us/app/nostur/id1672780508)) [⚡ zap](https://nostr.net/grant/?zap=weathereddarkness25@getalby.com)
|
||||
- [Notedeck](https://github.com/damus-io/notedeck) - Rust based desktop nostr browser by Damus
|
||||
- [notestack.com](https://notestack.com) - Blogging site for nostr, supports markdown
|
||||
- [NOW - Nostr Outbox for Wordpress](https://github.com/Mnpezz/nostr-outbox-for-wordpress/tree/main) - Send WordPress and WooCommerce notifications via Nostr instead of email. Includes Lightning payments at checkout, Nostr login, NIP-05 verification, and encrypted direct messaging.
|
||||
- [npub.world](https://npub.world/) - A nostr profile search engine
|
||||
- [Nuxstr](https://github.com/sebastix/nuxstr) - Starter template for building a Nostr client with the Nuxt Vue framework and Nostr Dev Kit (NDK). [⚡ zap](lightning:sebastian@lnd.sebastix.com)
|
||||
- [Nuxstr](https://github.com/sebastix/nuxstr) - Starter template for building a Nostr client with the Nuxt Vue framework and Nostr Dev Kit (NDK). [⚡ zap](https://nostr.net/grant/?zap=sebastian@lnd.sebastix.com)
|
||||
- [nuxstr.nostrver.se](https://nuxstr.nostrver.se) - demo
|
||||
- [n_cord](https://github.com/0n4t3/n_cord) - A Discord inspired chat style client standard Nostr notes, built in static HTML & JavaScript.
|
||||
- [0n4t3.github.io/n_cord/](https://0n4t3.github.io/n_cord/) - live instance
|
||||
@@ -404,7 +404,7 @@ Websites with lists of relays and their performance/health:
|
||||
- [u-blog.vercel.app](https://u-blog.vercel.app)
|
||||
- [Vector](https://github.com/VectorPrivacy/Vector) - A privacy-focused encrypted messenger built on Nostr using NIP-17, with zero metadata leakage. Available for Windows, macOS, Linux, and Android.
|
||||
- [vectorapp.io](https://vectorapp.io)
|
||||
- [Vega](https://github.com/hoornet/vega) - A client for Linux, Windows and macOS (Tauri + React), with long-form writing and reading (NIP-23), V4V podcast streaming, WoT filtering and an optional built-in relay. [⚡ zap](lightning:jure@getalby.com)
|
||||
- [Vega](https://github.com/hoornet/vega) - A client for Linux, Windows and macOS (Tauri + React), with long-form writing and reading (NIP-23), V4V podcast streaming, WoT filtering and an optional built-in relay. [⚡ zap](https://nostr.net/grant/?zap=jure@getalby.com)
|
||||
- [veganostr.com](https://veganostr.com/)
|
||||
- [Votestr](https://votestr.com/) - Poll web app with nostr authentication and blind signature unlinkability
|
||||
- [Voyage](https://github.com/dluvian/voyage) - Lightweight Android client with a Reddit-like UI
|
||||
@@ -420,7 +420,7 @@ Websites with lists of relays and their performance/health:
|
||||
- [Yana](https://github.com/frnandu/yana) - Yana is a nostr client focused on performance in slower devices and modularity of features.
|
||||
- [yana.do](https://yana.do)
|
||||
- [ygege](https://github.com/UwUDev/ygege) - Support Tor High-performance torrents indexer for services using the U2P system written in Rust.
|
||||
- [Zap Cooking](https://zap.cooking/) - Nostr's only recipe-sharing client. A place where food culture can live openly and grow naturally. [⚡ zap](lightning:zapcooking@sats.zap.cooking)
|
||||
- [Zap Cooking](https://zap.cooking/) - Nostr's only recipe-sharing client. A place where food culture can live openly and grow naturally. [⚡ zap](https://nostr.net/grant/?zap=zapcooking@sats.zap.cooking)
|
||||
- [zapddit](https://zapddit.com)  - Reddit-style client for nostr where you can follow topics (similar to subreddits), mute certain topics (like #bitcoin), upzap and downzap notes using your hard-earned sats.
|
||||
- [Zaplytics](https://github.com/derekross/zaplytics) - Analytics for your Nostr Zaps, helping creators dive into their Zap earnings. [Zaplytics.app](https://zaplytics.app/)
|
||||
- [Zappix](https://github.com/derekross/zappix) - A nostr image sharing application for browsing, sharing, and zapping visual content. [Zappix.app](https://zappix.app/)
|
||||
@@ -467,7 +467,7 @@ Websites with lists of relays and their performance/health:
|
||||
- [Shopstr](https://github.com/shopstr-eng/shopstr) - The Lightning and Cashu-native self-sovereign marketplace built on top of NIP-99 includes fixed-price items
|
||||
- [Kartapio](https://github.com/vstabile/kartapio) - A Nostr-based marketplace.
|
||||
- [Milk Market](https://milk.market) - A Nostr-native marketplace.
|
||||
- [Mostro Mobile](https://github.com/MostroP2P/mobile) - Mobile client for the Mostro P2P exchange platform. [⚡ zap](lightning:mostro_p2p@sats.mobi)
|
||||
- [Mostro Mobile](https://github.com/MostroP2P/mobile) - Mobile client for the Mostro P2P exchange platform. [⚡ zap](https://nostr.net/grant/?zap=mostro_p2p@sats.mobi)
|
||||
|
||||
### Web Bookmarking ([NIP-B0](https://github.com/nostr-protocol/nips/blob/master/B0.md))
|
||||
- [Community Curated Nostr Stuff (CCNS)](https://github.com/Sebastix/CCNS)![stars] - CCNS is a Nostr-focused community platform centered around link aggregation and discussion topics.
|
||||
@@ -503,7 +503,7 @@ Websites with lists of relays and their performance/health:
|
||||
- [nip07-awaiter](https://github.com/penpenpng/nip07-awaiter) - Minimal utility to access NIP-07 interface safely.
|
||||
- [nmostr](https://github.com/Gruruya/nmostr) - a Nim library for Nostr
|
||||
- [NNostr.Client](https://github.com/Kukks/NNostr) - a C# Nostr library for use by clients
|
||||
- [noscrypt](https://github.com/vnuge/noscrypt) - A C89 library for nostr specific cryptography operations. [⚡ zap](lightning:chiptuner@coinos.io)
|
||||
- [noscrypt](https://github.com/vnuge/noscrypt) - A C89 library for nostr specific cryptography operations. [⚡ zap](https://nostr.net/grant/?zap=chiptuner@coinos.io)
|
||||
- [nostr (zig-nostr)](https://github.com/zig-nostr/nostr) - A fast Nostr protocol library for Zig. Native libsecp256k1 signing and a memory-mapped LMDB store give zero-copy, local-first reads with sub-millisecond feed queries. Covers keys and events, encrypted messaging and remote signing (NIP-44/46/49), and a relay transport.
|
||||
- [nostr_rust](https://github.com/0xtlt/nostr_rust) - Functional Rust implementation of the nostr protocol
|
||||
- [Nostrbook](https://nostrbook.dev/) - A Comprehensive Registry of Nostr Documentation. Structured, detailed knowledge about Nostr for both humans and AI.
|
||||
@@ -515,7 +515,7 @@ Websites with lists of relays and their performance/health:
|
||||
- [nostr-double-ratchet](https://github.com/mmalmi/nostr-double-ratchet) - Signal-style secure private messaging channels
|
||||
- [nostr-fetch](https://github.com/jiftechnify/nostr-fetch) - A utility library that allows JS/TS apps to effortlessly fetch past events from Nostr relays.
|
||||
- [nostr-geotags](https://github.com/sandwichfarm/nostr-geotags) - NPM module that generates geotags for nostr events given data points such as GPS/DD, an ISO-3166-1 countryCode and/or an ISO-3166-2 regionName, as well as many passthroughts. Supports ISO-3166-1/2/3
|
||||
- [nostr-hooks](https://github.com/ostyjs/nostr-hooks) - React hooks for developing Nostr clients. It's simple and intelligent. [⚡ zap](lightning:sepehr@getalby.com)
|
||||
- [nostr-hooks](https://github.com/ostyjs/nostr-hooks) - React hooks for developing Nostr clients. It's simple and intelligent. [⚡ zap](https://nostr.net/grant/?zap=sepehr@getalby.com)
|
||||
- [nostr-java](https://github.com/tcheeric/nostr-java) - A nostr client library, written in java, for generating, signing and publishing events.
|
||||
- [nostr-js](https://github.com/jb55/nostr-js) - a javascript implementation of the nostr protocol
|
||||
- [nostr_relay_management](https://github.com/anasfik/nostr_relay_management) - Dart/Flutter support for NIP-86 (Relay Management) with better developer experience.
|
||||
@@ -600,7 +600,7 @@ Websites with lists of relays and their performance/health:
|
||||
- [bray](https://github.com/forgesworn/bray) - Trust-aware Nostr MCP server for AI agents. 234 tools across identity, social, trust, dispatch, relay, marketplace, privacy, and encrypted access. Works with Claude, ChatGPT, Gemini, Cursor, or any MCP client.
|
||||
- [Bookmarkstr](https://bookmarkstr.store/) - A browser extension for reading and managing nostr bookmarks
|
||||
- [BlazeJump.NostrConnect](https://github.com/drmikesamy/BlazeJump.NostrConnect) - an Android based remote NostrConnect signer and web project using QR codes and Nip44 encryption by default
|
||||
- [cafe-society.news](https://github.com/colealbon/cafe-society) - Self-sovereign machine learning training tool for nostr global feed. Trained models can be monetized/distributed over nostr private messages. Your pre-paid model subscribers register via lightning payments. [⚡ zap](lightning:cafe@getalby.com)
|
||||
- [cafe-society.news](https://github.com/colealbon/cafe-society) - Self-sovereign machine learning training tool for nostr global feed. Trained models can be monetized/distributed over nostr private messages. Your pre-paid model subscribers register via lightning payments. [⚡ zap](https://nostr.net/grant/?zap=cafe@getalby.com)
|
||||
- [CSV Importer](https://csv-importer.coracle.social/) - Publish Nostr events in bulk from CSV files.
|
||||
- [Chief](https://github.com/0xtrr/chief) - A Strfry write policy plugin that provides blacklists for public keys, event kinds and words/sentences.
|
||||
- [Cloud Seeder](https://github.com/ipv6rslimited/cloudseeder) - A 1-click deployment and management tool for nostr-rs-relay and other appliances.
|
||||
@@ -663,7 +663,7 @@ Websites with lists of relays and their performance/health:
|
||||
- [nostr-cln-events](http://git.jb55.com/nostr-cln-events) - A CLN plugin to push clightning node events to nostr
|
||||
- [nostr-commander](https://github.com/8go/nostr-commander-rs) - simple but convenient CLI-based Nostr app for following users, sending DMs, etc.
|
||||
- [nostr-components](https://github.com/saiy2k/nostr-components) - Nostr Components makes it easy to embed Nostr profiles, posts, follow buttons, Live chat box, comment section, DM buttons in any website
|
||||
- [NostrComments](https://github.com/briskness-byte/NostrComments) - Browser extension adding a comment thread to any web page, stored on relays rather than on the site being discussed, so the page owner cannot remove it. Chrome, Firefox and userscript. [⚡ zap](lightning:slurpnc@coinos.io)
|
||||
- [NostrComments](https://github.com/briskness-byte/NostrComments) - Browser extension adding a comment thread to any web page, stored on relays rather than on the site being discussed, so the page owner cannot remove it. Chrome, Firefox and userscript. [⚡ zap](https://nostr.net/grant/?zap=slurpnc@coinos.io)
|
||||
- [nostr-crdt](https://github.com/YousefED/nostr-crdt)  - Use Nostr for collaborative, decentralized, local-first applications with nostr-CRDT Yjs provider.
|
||||
- [nostr-delete](https://github.com/blakejakopovic/nostr_delete) - generate delete events requesting relays drop and delete content you've published. Blasts out delete requests to many relays.
|
||||
- [nostr-delete web app](https://nostr-delete.vercel.app/)
|
||||
@@ -687,7 +687,7 @@ Websites with lists of relays and their performance/health:
|
||||
- [nostr.json generator](https://github.com/SnowCait/nostr-json-generator) - Generate NIP-05 nostr.json from NIP-65 or NIP-07
|
||||
- [NostrAirTracker](https://github.com/gourcetools/NostrAirTracker) - Elonjet on Nostr
|
||||
- [nostraap](https://github.com/ccs-mz/nostraap) - NostraApp is a decentralized messaging application inspired by WhatsApp, built on the Nostr protocol, with native support for end-to-end encryption, distributed relay networks, and Bitcoin Lightning payments (Zaps)
|
||||
- [nostress](https://github.com/4383/nostress) - ⚡ Modern Python CLI for Nostr protocol interactions - secure key management, event creation, and relay operations [⚡ zap](lightning:hberaud@nostrcheck.me)
|
||||
- [nostress](https://github.com/4383/nostress) - ⚡ Modern Python CLI for Nostr protocol interactions - secure key management, event creation, and relay operations [⚡ zap](https://nostr.net/grant/?zap=hberaud@nostrcheck.me)
|
||||
- [nostrame](https://github.com/Anderson-Juhasc/nostrame) - Nostr Signer and Account Management Extension
|
||||
- [nostrandom.netlify.app](https://nostrandom.netlify.app/) - generate publish-able Nostr event with random keys
|
||||
- [nostrefresh](https://github.com/melvincarvalho/nostrefresh) - simple refresh function for nostr web pages
|
||||
@@ -710,7 +710,7 @@ Websites with lists of relays and their performance/health:
|
||||
- [Note Nuke](https://www.mutable.top/note-nuke) - A standalone feature of Mutable that lets users delete an event with maximum relay coverage.
|
||||
- [novia](https://github.com/teamnovia/novia) - Nostr video archive
|
||||
- [nsecbunkerd](https://github.com/kind-0/nsecbunkerd) - Keep your nostr keys in a single place and provide fine-grained access to your team members.
|
||||
- [Obsidian Nostr Writer](https://github.com/jamesmagoo/nostr-writer#readme) - A free Obsidian plugin that allows writers to seamlessly publish to Nostr [⚡ zap](lightning:magoo@getalby.com)
|
||||
- [Obsidian Nostr Writer](https://github.com/jamesmagoo/nostr-writer#readme) - A free Obsidian plugin that allows writers to seamlessly publish to Nostr [⚡ zap](https://nostr.net/grant/?zap=magoo@getalby.com)
|
||||
- [osint-user-discovery](https://github.com/Inforensics/osint-user-discovery) - OSINT Discovery is a set of Python scripts designed to search for users or URLs across different social media platforms(nostr, mastodon) and caching services.
|
||||
- [Plebs vs. Zombies](https://www.plebsvszombies.cc) - A Nostr utility for managing dormant follows and cleaning up your follow list.
|
||||
- [powrelay.xyz](https://powrelay.xyz) - A proof of work-based nostr explorer.
|
||||
@@ -729,7 +729,7 @@ Websites with lists of relays and their performance/health:
|
||||
- [Spamster](https://github.com/gourcetools/spamster) - Spamster is for testing relays and spam filters.
|
||||
- [strfry policies](https://gitlab.com/soapbox-pub/strfry-policies) - A collection of moderation & antispam policies for the strfry relay developed in TypeScript/Deno.
|
||||
- [TaskQ5](https://github.com/duozhutuan/Taskq5) - TaskQ5 is a task distribution platform built on nostr where you can post tasks if you need help
|
||||
- [toll-booth](https://github.com/forgesworn/toll-booth) - HTTP 402 payment middleware with NWC backend and Cashu support. Companion tools: toll-booth-announce (kind 31402 service discovery), toll-booth-dvm (NIP-90 DVM bridge), 402-mcp (AI agent L402 client). [⚡ zap](lightning:profusemeat89@walletofsatoshi.com)
|
||||
- [toll-booth](https://github.com/forgesworn/toll-booth) - HTTP 402 payment middleware with NWC backend and Cashu support. Companion tools: toll-booth-announce (kind 31402 service discovery), toll-booth-dvm (NIP-90 DVM bridge), 402-mcp (AI agent L402 client). [⚡ zap](https://nostr.net/grant/?zap=profusemeat89@walletofsatoshi.com)
|
||||
- [tostr](https://github.com/slaninas/tostr) - a twitter to nostr bot
|
||||
- [Undelete my Nostr](https://yonle.github.io/undelete-my-nostr) - Simple tool for restoring deleted nostr account.
|
||||
- [y-ndk](https://github.com/colealbon/y-ndk) - yjs provider over nostr relays
|
||||
@@ -790,7 +790,7 @@ Websites with lists of relays and their performance/health:
|
||||
- [nanostr](https://github.com/xbol0/nanostr) - A NIP-05 name server written in Deno.
|
||||
- [Nostr-Check.com](https://nostr-check.com) - A free NIP-05 ID registration service.
|
||||
- [NostrAddress.com](https://nostraddress.com) - Free and Paid Nostr Address (NIP-05) identifier service with premium relay and vanity domains.
|
||||
- [nostrcheck.me](https://nostrcheck.me/) - A free NIP-05 ID (nostr address) registration service, lightning redirection and media uploads. [⚡ zap](lightning:public@nostrcheck.me)
|
||||
- [nostrcheck.me](https://nostrcheck.me/) - A free NIP-05 ID (nostr address) registration service, lightning redirection and media uploads. [⚡ zap](https://nostr.net/grant/?zap=public@nostrcheck.me)
|
||||
- [Nostrich House](https://nostrich.house) - Paid NIP-05 service with nostr bot interface. Buy your nostr address with DM to nostrich@nostrich.house for 1 sat/hour, anonymous, immediate.
|
||||
- [nostrich.love](https://uselessshit.co/nostr/nip-05/) - A Nostr Address registration service.
|
||||
- [nostrplebs](https://nostrplebs.com) - The oldest and original Nostr address registration and identity management service.
|
||||
@@ -798,7 +798,7 @@ Websites with lists of relays and their performance/health:
|
||||
- [pleroma2nip05](https://code.taurix.net/guy/pleroma2nip05) - A Python based service to link pleroma ID's to nostr keys.
|
||||
- [siamstr.com](https://siamstr.com) - A free NIP-05 ID registration service, lightning redirection.
|
||||
- [younostr.com](https://younostr.com) - A NIP-05 ID registration service (in portuguese).
|
||||
- [hunos.hu](https://hunos.hu) - Free NIP-05 identity for the Hungarian community. [⚡ zap](lightning:hunosrelay@minibits.cash)
|
||||
- [hunos.hu](https://hunos.hu) - Free NIP-05 identity for the Hungarian community. [⚡ zap](https://nostr.net/grant/?zap=hunosrelay@minibits.cash)
|
||||
- [zap.club](https://zap.club) - NIP-05 ID service for @zap.club handles.
|
||||
- [zaps.lol](https://zaps.lol)- A free and open source NIP-05 ID registration service. [Run your own](https://github.com/jigglycrumb/nostr-address-provider).
|
||||
|
||||
@@ -930,7 +930,7 @@ Endpoints (services or apps that expose a LN wallet via NWC)
|
||||
- [Wallet of Satoshi](https://www.walletofsatoshi.com/) - Custodial lightning wallet
|
||||
- [zap_server](https://github.com/UTXOnly/zap_server) - An LNURL server to recieve zaps to tor hosted node and generate kind 9735 zap receipt events
|
||||
- [Zebedee app](https://zebedee.io/app) - Zebedee's wallet/lightning app
|
||||
- [ZeusLN](https://github.com/ZeusLN/zeus) - A mobile Bitcoin/Lightning app for LND, Core Lightning, and Eclair node operators [⚡ zap](lightning:tips@pay.zeusln.app)
|
||||
- [ZeusLN](https://github.com/ZeusLN/zeus) - A mobile Bitcoin/Lightning app for LND, Core Lightning, and Eclair node operators [⚡ zap](https://nostr.net/grant/?zap=tips@pay.zeusln.app)
|
||||
- [CDK](https://cashudevkit.org) - Cashu Development Kit for building ecash wallets and mints.
|
||||
- [eNuts](https://enuts.cash) - Cross-platform Cashu ecash wallet with Nostr integration.
|
||||
- [Minibits](https://github.com/minibits-cash/minibits_wallet) - Mobile Cashu ecash wallet with Lightning and Nostr.
|
||||
@@ -963,10 +963,10 @@ Endpoints (services or apps that expose a LN wallet via NWC)
|
||||
## NIP-96 File Storage Servers
|
||||
- [mockingyou.com](https://mockingyou.com)
|
||||
- [nostpic](https://nostpic.com)
|
||||
- [nostr.build](https://nostr.build) [⚡ zap](lightning:nostrbob@primal.net)
|
||||
- [nostr.build](https://nostr.build) [⚡ zap](https://nostr.net/grant/?zap=nostrbob@primal.net)
|
||||
- [nostrcheck.me](https://nostrcheck.me)
|
||||
- [nostrage](https://nostrage.com)
|
||||
- [NostrMedia.com](https://nostrmedia.com) [⚡ zap](lightning:b0cc79@wallet.yakihonne.com)
|
||||
- [NostrMedia.com](https://nostrmedia.com) [⚡ zap](https://nostr.net/grant/?zap=b0cc79@wallet.yakihonne.com)
|
||||
- [sovbit](https://files.sovbit.host)
|
||||
- [sove](https://sove.rent)
|
||||
- [void.cat](https://void.cat)
|
||||
@@ -1087,7 +1087,7 @@ Outside of nostr itself, you find the community on:
|
||||
- [Tracker for Undocumented Nostr Event Kinds](https://undocumented.nostrkinds.info/) - monitors undocumented event kinds in the nostr network
|
||||
- [vanilla-js-nostr](https://github.com/supertestnet/vanilla-js-nostr) - a demo of posting and viewing a feed in nostr using vanilla javascript
|
||||
- [wellorder nostr datasets](https://wiki.wellorder.net/wiki/nostr-datasets/) - Public standardized nostr datasets for benchmarking, data science, or other analysis.
|
||||
- [Zaplife](https://zaplife.lol) - Real-time feed for nostr zaps. The best tool to shut up the "lightning doesn't work" people. [⚡ zap](lightning:pablof7z@primal.net)
|
||||
- [Zaplife](https://zaplife.lol) - Real-time feed for nostr zaps. The best tool to shut up the "lightning doesn't work" people. [⚡ zap](https://nostr.net/grant/?zap=pablof7z@primal.net)
|
||||
- [The Attention Protocol](https://joinnextblock.com/billboard/book) - a love story published on nostr
|
||||
- [AndOtherStuff](https://andotherstuff.org/) - a collective that creates and stewards freedom tech, open tools, protocols, and applications.
|
||||
|
||||
@@ -1111,7 +1111,7 @@ Outside of nostr itself, you find the community on:
|
||||
- [nostore](https://github.com/ursuscamp/nostore) - Nostr Signer Extension for iOS/macOS Safari
|
||||
- [nostrpy](https://github.com/monty888/nostrpy) - relay, client, and other tooling in python (No longer being developed.)
|
||||
- [Nozzle](https://github.com/dluvian/Nozzle) - A lightweight Android client
|
||||
- [Plebstr](https://plebstr.com) - Nostr client Reimagined, the most beautiful Twitter-like nostr client for iOS & Android. [⚡ zap](lightning:passivebit94@walletofsatoshi.com)
|
||||
- [Plebstr](https://plebstr.com) - Nostr client Reimagined, the most beautiful Twitter-like nostr client for iOS & Android. [⚡ zap](https://nostr.net/grant/?zap=passivebit94@walletofsatoshi.com)
|
||||
- [rsslay](https://github.com/piraces/rsslay) - fork of the rsslay by @fiatjaf. a bridge that puts RSS feeds into Nostr optimized, more funcionalities and UI improvements. Live at [rsslay.nostr.moe](https://rsslay.nostr.moe/)
|
||||
- [Nsec App](https://nsec.app) - Browser-based NIP-46 bunker that lets you sign events without exposing your nsec.
|
||||
- [nostrapp.link](https://nostrapp.link/) - Nostr App Manager
|
||||
@@ -1122,10 +1122,10 @@ Outside of nostr itself, you find the community on:
|
||||
|
||||
If you'd like to add something to this list, please submit a [Pull Request on GitHub](https://github.com/aljazceru/awesome-nostr/).
|
||||
|
||||
Project maintainers can make their entry zappable by appending a lightning chip (and optionally a donate link) to their entry — visitors can then zap it directly from [nostr.net/grant](https://nostr.net/grant/):
|
||||
Project maintainers can make their entry zappable by appending a zap chip (and optionally a donate link) to their entry — visitors can then zap it from GitHub, from [nostr.net/grant](https://nostr.net/grant/), and everywhere on the list. Just put your lightning address in the chip's query string:
|
||||
|
||||
```
|
||||
- [Your Project](https://example.com) - What it does [⚡ zap](lightning:you@wallet.com) [donate](https://geyser.fund/project/xyz)
|
||||
- [Your Project](https://example.com) - What it does [⚡ zap](https://nostr.net/grant/?zap=you@wallet.com) [donate](https://geyser.fund/project/xyz)
|
||||
```
|
||||
|
||||
Only submit an address you control or that is officially published by the project.
|
||||
|
||||
+4
-1
@@ -11,6 +11,7 @@ permalink: /grant/
|
||||
<link rel="icon" type="image/png" href="Logo.png">
|
||||
<link rel="apple-touch-icon" href="Logo.png">
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css">
|
||||
<link rel="stylesheet" href="styles.css">
|
||||
<style>
|
||||
@import url("https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap");
|
||||
|
||||
@@ -213,10 +214,12 @@ permalink: /grant/
|
||||
|
||||
<h2>Project maintainer?</h2>
|
||||
<p>Add a zap chip to your entry on the list via pull request:</p>
|
||||
<pre>- [Your Project](https://example.com) - What it does [⚡ zap](lightning:you@wallet.com)</pre>
|
||||
<pre>- [Your Project](https://example.com) - What it does [⚡ zap](https://nostr.net/grant/?zap=you@wallet.com)</pre>
|
||||
<p><a class="pr-link" href="https://github.com/aljazceru/awesome-nostr/">Submit a PR on GitHub →</a></p>
|
||||
</main>
|
||||
|
||||
<footer>© 2025 nostr.net</footer>
|
||||
<script src="zap-core.js"></script>
|
||||
<script src="zap.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -761,8 +761,26 @@ function parseResourceLine(line) {
|
||||
// ===== grantless: zap/donate chip support =====
|
||||
// Reads a rendered markdown <li> and extracts the resource link plus the
|
||||
// optional chips from the README convention:
|
||||
// - [Name](https://...) - description [⚡ zap](lightning:addr@host) [donate](https://...)
|
||||
// - [Name](https://...) - description [⚡ zap](https://nostr.net/grant/?zap=addr@host) [donate](https://...)
|
||||
// GitHub's sanitizer strips lightning: links entirely (verified via the
|
||||
// GitHub markdown API), so chips carry an https link to our own grant page,
|
||||
// which opens the zap dialog (QR / open-wallet / in-page zap). Plain
|
||||
// lightning: chips are still recognized for back-compat.
|
||||
const LIGHTNING_SCHEME_RE = /^lightning:/i;
|
||||
const ZAP_LABEL_RE = /^\s*⚡\s*zap\s*$/i;
|
||||
// chip host: our own grant page carries the address in the query string
|
||||
const GRANT_CHIP_RE = /^https:\/\/nostr\.net\/grant\/\?zap=([A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+)(&|$)/i;
|
||||
|
||||
// chip href + anchor label → lightning address, or null
|
||||
function lnAddressFromChip(href, label) {
|
||||
href = href || '';
|
||||
if (LIGHTNING_SCHEME_RE.test(href)) return href.replace(LIGHTNING_SCHEME_RE, '');
|
||||
if (ZAP_LABEL_RE.test(label || '')) {
|
||||
const m = href.match(GRANT_CHIP_RE);
|
||||
if (m) return decodeURIComponent(m[1]);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function parseListItem(li) {
|
||||
let name = '';
|
||||
@@ -772,13 +790,14 @@ function parseListItem(li) {
|
||||
|
||||
Array.from(li.querySelectorAll('a')).forEach(a => {
|
||||
const href = a.getAttribute('href') || '';
|
||||
const label = a.textContent.trim().toLowerCase();
|
||||
if (LIGHTNING_SCHEME_RE.test(href)) {
|
||||
if (lnAddress === null) lnAddress = href.replace(LIGHTNING_SCHEME_RE, '');
|
||||
} else if (label === 'donate' && /^https?:/i.test(href)) {
|
||||
const label = a.textContent.trim();
|
||||
const chipAddr = lnAddressFromChip(href, label);
|
||||
if (chipAddr) {
|
||||
if (lnAddress === null) lnAddress = chipAddr;
|
||||
} else if (label.toLowerCase() === 'donate' && /^https?:/i.test(href)) {
|
||||
if (donateUrl === null) donateUrl = href;
|
||||
} else if (!name) {
|
||||
name = a.textContent.trim();
|
||||
name = label;
|
||||
link = href;
|
||||
}
|
||||
});
|
||||
@@ -789,8 +808,8 @@ function parseListItem(li) {
|
||||
clone.querySelectorAll('img').forEach(i => i.remove());
|
||||
clone.querySelectorAll('a').forEach(a => {
|
||||
const href = a.getAttribute('href') || '';
|
||||
const label = a.textContent.trim().toLowerCase();
|
||||
if (LIGHTNING_SCHEME_RE.test(href) || label === 'donate') a.remove();
|
||||
const label = a.textContent.trim();
|
||||
if (lnAddressFromChip(href, label) || label.toLowerCase() === 'donate') a.remove();
|
||||
});
|
||||
let description = clone.textContent.replace(/\s+/g, ' ').trim();
|
||||
if (name && description.toLowerCase().startsWith(name.toLowerCase())) {
|
||||
|
||||
+18
-2
@@ -189,8 +189,10 @@ test('invoice missing the payment hash tag is rejected', async () => {
|
||||
|
||||
test('mixed-case invoice is rejected', async () => {
|
||||
const inv = craftInvoice({ amountHrp: '10u', hHex: sha256Hex('[]') });
|
||||
// flip one data character to upper — mixed case is invalid bech32
|
||||
const mixed = inv.slice(0, 12) + inv[12].toUpperCase() + inv.slice(13);
|
||||
// flip the first data character whose case actually changes
|
||||
const i = inv.slice(8).split('').findIndex(c => c !== c.toUpperCase() && /[a-z]/.test(c));
|
||||
const mixed = inv.slice(0, 8 + i) + inv[8 + i].toUpperCase() + inv.slice(8 + i + 1);
|
||||
assert.notStrictEqual(mixed, inv, 'fixture must actually change case');
|
||||
const r = await core.decodeBolt11(mixed);
|
||||
assert.strictEqual(r.ok, false);
|
||||
assert.match(r.error, /mixed case/);
|
||||
@@ -332,6 +334,20 @@ test('lnurlEncode round-trips to the lnurlp endpoint', () => {
|
||||
assert.ok(url.startsWith('https://sendsats.lol/.well-known/lnurlp/damus'));
|
||||
});
|
||||
|
||||
test('lnurlDecode round-trips encode and rejects tampering', () => {
|
||||
const url = 'https://primal.net/.well-known/lnurlp/bitkarrot';
|
||||
const ln = core.lnurlEncode(url).toUpperCase();
|
||||
assert.strictEqual(core.lnurlDecode(ln), url);
|
||||
assert.strictEqual(core.lnurlDecode(ln.toLowerCase()), url, 'lowercase form also valid');
|
||||
// swap two chars in the data part → checksum must fail
|
||||
const tampered = ln.slice(0, 20) + (ln[20] === 'Q' ? 'P' : 'Q') + ln.slice(21);
|
||||
assert.strictEqual(core.lnurlDecode(tampered), null);
|
||||
assert.strictEqual(core.lnurlDecode('lnurl1' + 'q'.repeat(40)), null, 'garbage data');
|
||||
assert.strictEqual(core.lnurlDecode('notlnurl1abcdef'), null, 'wrong hrp');
|
||||
assert.strictEqual(core.lnurlDecode(''), null);
|
||||
assert.strictEqual(core.lnurlDecode(null), null);
|
||||
});
|
||||
|
||||
test('escapeHtml neutralizes markup', () => {
|
||||
assert.ok(!/[<>"']/.test(core.escapeHtml('<img src=x onerror="alert(1)">')));
|
||||
});
|
||||
|
||||
+30
-1
@@ -49,6 +49,35 @@
|
||||
return 'lnurl' + '1' + [...data, ...cs].map(d => CHARSET[d]).join('');
|
||||
}
|
||||
|
||||
// decode a bech32 LNURL back to its URL (checksum-verified); null on any
|
||||
// malformation — used to turn GitHub-safe getalby chip links back into
|
||||
// lightning addresses without a third-party round trip
|
||||
function lnurlDecode(lnurl) {
|
||||
try {
|
||||
const s = String(lnurl).trim();
|
||||
const pos = s.lastIndexOf('1');
|
||||
if (pos < 1) return null;
|
||||
const hrp = s.slice(0, pos).toLowerCase();
|
||||
if (hrp !== 'lnurl') return null;
|
||||
const chars = s.slice(pos + 1);
|
||||
if (/[a-z]/.test(chars) && /[A-Z]/.test(chars)) return null; // mixed case invalid
|
||||
const words = [...chars.toLowerCase()].map(c => CHARSET.indexOf(c));
|
||||
if (words.length < 7 || words.some(w => w < 0)) return null;
|
||||
if (bech32Polymod(hrpExpand(hrp).concat(words)) !== 1) return null;
|
||||
const d5 = words.slice(0, -6);
|
||||
let acc = 0, bits = 0;
|
||||
const bytes = [];
|
||||
for (const w of d5) {
|
||||
acc = (acc << 5) | w; bits += 5;
|
||||
while (bits >= 8) { bits -= 8; bytes.push((acc >> bits) & 255); }
|
||||
}
|
||||
if (bits >= 5 || ((acc << (8 - bits)) & 255)) return null; // non-zero padding
|
||||
return new TextDecoder().decode(new Uint8Array(bytes));
|
||||
} catch (e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// ---------- misc ----------
|
||||
const escapeHtml = (s) => String(s).replace(/[&<>"']/g, c =>
|
||||
({ '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' }[c]));
|
||||
@@ -241,7 +270,7 @@
|
||||
}
|
||||
|
||||
return {
|
||||
lnurlpUrl, lnurlEncode, escapeHtml, sha256Hex, decodeBolt11, createProviderSelector,
|
||||
lnurlpUrl, lnurlEncode, lnurlDecode, escapeHtml, sha256Hex, decodeBolt11, createProviderSelector,
|
||||
isTransientPaymentError, createZapGuard, resolveZapAmount,
|
||||
__internals: { CHARSET, bech32Polymod, hrpExpand, convertBits, wordsToTrimmedHex }
|
||||
};
|
||||
|
||||
@@ -604,4 +604,19 @@
|
||||
const addr = chip.dataset.lnAddress || href.replace(/^lightning:/i, '');
|
||||
if (addr.includes('@')) fetchLnurlParamsCached(addr).catch(() => {});
|
||||
}, { passive: true });
|
||||
|
||||
// ---------- grant page: ?zap=addr@host → open the zap dialog ----------
|
||||
// GitHub-facing chips link to https://nostr.net/grant/?zap=… — on arrival,
|
||||
// show the full zap dialog (QR / open wallet / connect) immediately
|
||||
if (/\/grant\/?$|grant\.html$/.test(location.pathname)) {
|
||||
const m = location.href.match(/[?&]zap=([A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+)/);
|
||||
if (m) {
|
||||
const addr = decodeURIComponent(m[1]);
|
||||
const name = addr.split('@')[0];
|
||||
setTimeout(() => {
|
||||
if (weblnReady()) zap(addr, name, null);
|
||||
else showZapModal({ lnAddress: addr, name, chip: null });
|
||||
}, 700);
|
||||
}
|
||||
}
|
||||
})();
|
||||
|
||||
Reference in New Issue
Block a user