Nostr Compass #27
- Top stories
- Amethyst v1.12.0 ships Cashu wallets, nutzaps, a CLINK driver, and Tor self-heal
- Mostro Core v0.13.0 cuts the relay middleman with Protocol v2
- Signet v1.11.0 patches a NIP-17 admin-command signature bypass
- Chama v3.2.0 through v3.5.0 redraw the trade room and harden the money path
- Clave 1.0 ships to the App Store with push-woken background signing
- Releases
- Amber v6.2.1 adds NIP-46 logout and trims signer battery drain
- Nostur 1.29.0 ships anonymous replies and remote-signer logout
- Citrine v3.0.0 ships Negentropy, NIP-42 AUTH, and onion-relay filtering
- FIPS v0.4.0-rc1 adds a Nym mixnet transport and mDNS LAN discovery
- Calendar by Formstr v1.6.1 and v1.6.2 add per-event notifications
- Bitchat v1.5.2 and v1.5.3 harden the Nostr-and-BLE transport
- Keep v1.0.5 moves the signer policy surface into the audited Rust core
- ants v0.4.5 adds article portal links and restores Habla in the portal set
- Morganite v0.0.3 ships a local Blossom cache for Android with Tor on demand
- Coracle 0.6.34 and 0.6.35 fix NIP-46 login, stale feeds, and reply toggling
- Zeus v13.1.0-rc1 ships CLINK noffers and queue-less NWC
- Alby Extension v3.14.3 migrates the noble/scure crypto stacks used by the NIP-07 signer
- Mostro Mobile v1.2.8 and v1.2.9 support Protocol v2 and surface the bond policy
- ZapBook builds 4 through 27 ship multi-account, Marmot key publication, and circle re-invitations
- Alby Hub v1.23.0 fixes NIP-47 publish for deleted apps and switches Bitrefill to NWC
- Also shipped
- Unreleased changes
- NIP updates and protocol spec work
- NIP deep dive: NIP-77 (Negentropy)
- NIP deep dive: NIP-61 (Nutzaps)
This week ran heavy on signer work, P2P trade protocols, and flagship client releases. Amethyst v1.12.0 @amethyst ships 170+ PRs adding NIP-60 Cashu wallets, NIP-61 nutzaps, NIP-82 software-app feeds, NIP-F4 podcast support, CLINK on-chain zap verification, KMP phase-1/2 iOS migration, and a Tor self-heal driver. Clave v1.0.0 (build 102) (@clave) was submitted to the App Store, bringing push-woken background signing and incoming-signature verification to iOS. Mostro Core v0.13.0 @Mostro ships Protocol v2, replacing relay-based order communication with NIP-44 gift-wrapped direct messages, and Mostro v0.17.5 made the operator-side anti-abuse bond optional and configurable. Signet v1.11.0 patches a NIP-17 (gift-wrapped private DMs) admin-command signature bypass that let anyone with public information forge kill-switch commands. Chama shipped seven escrow releases in six days, taking the trade room from a wall of controls to a per-seat conversation. On the signer side, Amber v6.2.1 (@greenart7c3), Clave (builds 100, 101, and 102), and Nostur 1.29.0 @Nostur all implement the new NIP-46 logout method that merged this week (PR #2373). Zeus v13.1.0-rc1 @ZEUS and Amethyst both ship CLINK noffer support, the proposed common Lightning interface for Nostr keys. NIP-29 relay groups picked up five open proposals covering banner tags, invite codes, message pinning, group reporting via NIP-17 DMs, and role-based access control.
Top stories
Amethyst v1.12.0 ships Cashu wallets, nutzaps, a CLINK driver, and Tor self-heal
Amethyst is the dominant Android Nostr client by Vitor Pamplona. v1.12.0 bundles the 93 PRs covered as unreleased work in Newsletter #25 (NIP-32 hashtag labeling, NIP-F4 podcast screen, music tracks, ephemeral signers, onchain zaps with NIP-05 filter) and Newsletter #26 (continued NIP-F4, Tor watchdog groundwork), plus a substantial new tranche this week. The new work centers on a Cashu/nutzap surface, a CLINK on-chain zap driver, a Tor self-heal cluster, and the KMP iOS migration.
NIP-60 Cashu wallet support and NIP-61 nutzap rendering land in PR #3075, with a per-mint balance view (PR #3115) and a unified payment card UI (PR #3191) that consolidates Lightning addresses, on-chain zaps, Cashu mints, and NWC on a single profile-payment screen (PR #3185). A CLINK driver for on-chain zap verification ships in PR #3039, PR #3177, and PR #3182. CLINK is the Common Lightning Interface for Nostr Keys, the same noffer interface Zeus v13.1.0-rc1 ships this week, and Amethyst adds a verification state machine, a reverify driver, and a minimum on-chain zap amount (PR #3030). PR #3201 introduces private notes by gift-wrapping kind-1 replies to p-tagged users per NIP-17, so the composer produces a public note or a sealed group reply depending on the targeting.
A Tor reliability cluster lands as a complete self-heal stack: PR #3053 bumps Arti to v2.3.0 with a watchdog and integration tests, PR #3223 gates Tor-routed relay dials until Tor is ready, PR #3224 bounds the Arti bootstrap with a 60-second timeout so a hostile network cannot wedge the loop, and PR #3231 self-heals when Tor is Active but every circuit is dead. The result is a Tor stack that recovers from network changes and sleep-resume cycles without manual intervention. Phase 1 and Phase 2 of the KMP iOS migration ship in PR #3047 and PR #3050, unblocking iOS CI for the quartz and commons modules and laying the foundation for an iOS Amethyst build.
Mostro Core v0.13.0 cuts the relay middleman with Protocol v2
Mostro is a Lightning-settled P2P Bitcoin exchange that uses Nostr as its order book and trade communication layer. v0.13.0 of mostro-core, the Rust library that defines the wire protocol, replaces the relay-routed messaging model with what the changelog describes as Protocol v2, an NIP-44 direct transport that rides on kind 14 events. Trade-specific actions now travel as kind 14 messages wrapped per NIP-44 and bound to the per-trade key the participant generated at order creation, without round-tripping the trade conversation through public addressable events.
Under the previous model, the entire trade conversation surface leaked to every relay carrying the events. Direct kind 14 transport keeps order setup, dispute flow, and settlement metadata between the two parties and the Mostro daemon, with the relays seeing only encrypted envelopes. Alongside the transport change, v0.13.0 also binds the v2 identity proof to the trade key (commit log), closing a class of replay risks against the new protocol. On the daemon side, Mostro v0.17.5 made the anti-abuse bond optional and operator-configurable: before starting certain trades, each side may need to lock a small bond returned on normal completion and forfeited on stalling, no-show, or grief. The bond is enabled at the node-operator level, not imposed network-wide, so Mostro stays non-custodial and each operator chooses the tradeoff between marketplace friction and abuse-resistance. On the client side, Mostro Mobile v1.2.8 shipped 17 features supporting the new path, including bootstrap relay discovery in place of pinned default relays (PR #610), maker anti-abuse bond on order creation as Phase 5 of the bond rollout (PR #608), and order cancellation persisted in notification history with context (PR #602). v1.2.9 followed two days later, surfacing the anti-abuse bond policy from the node info event so a user can see the bond rules of the Mostro instance before opening an order (PR #617).
Signet v1.11.0 patches a NIP-17 admin-command signature bypass
Signet is a remote bunker signer with a kill-switch surface that lets an administrator panic, revive, or check the signer over Nostr without touching the host machine. v1.11.0 fixes a security bug in that surface where the NIP-17 gift-wrap admin-command path checked only the unsigned inner rumor’s claimed author, never verifying the signed seal. Because NIP-44 conversation keys are symmetric, an attacker holding only public information (the signer pubkey, the admin npub, an admin relay) could forge a gift wrap from outside and execute any kill-switch command, including panic, resumeall, or alive. The fix calls verifyEvent on the seal and binds the rumor author to the seal signature, so unsigned forgeries are now rejected at the gate. Signet operators should upgrade promptly; the spec and the patched code path together give an attacker a clear repro recipe.
Chama v3.2.0 through v3.5.0 redraw the trade room and harden the money path
Chama is a Nostr-native P2P escrow client that pairs Fedimint ecash with 2-of-3 Shamir secret sharing for serverless trade settlement. Newsletter #26 covered the v2.0.0 through v3.1.0 run that crossed the standalone-app line and added per-seller storefronts. This week’s six follow-on releases pick up at v3.2.0 and end at v3.5.0 on June 15, redrawing the trade-room UI around a single per-seat question (what do I do right now) and hardening the money path against partial failures. v3.2.0 gave buyer, seller, and arbiter their own color-coded action prompts so every seat sees its own next move in every trade state. v3.3.0 tightened two consensus rules in the trade engine and required coordinated client adoption to take effect. v3.3.1 localized prices and payment methods to the trader’s community currency. v3.4.0 added five hardening fixes to the money path so a hiccup, a race, or a closed tab cannot quietly cost the user sats. v3.5.0 added two client-side guardrails around the arbiter role, the one seat that could otherwise quietly tilt a trade.
Clave 1.0 ships to the App Store with push-woken background signing
Clave is an iOS NIP-46 remote signer that keeps the user’s Nostr private key in the iPhone Keychain. Apps request signatures over an end-to-end encrypted channel and never receive the key itself. v1.0.0 build 102 was submitted to the App Store this week, marking the 1.0 milestone after eight months of TestFlight betas. The release ships push-woken background signing: Clave can decrypt a request, check permissions, sign, and respond with the app closed, so the iOS foreground requirement that previously gated signer responsiveness is gone. Incoming-signature verification is enforced with BIP-340 Schnorr over the canonical NIP-01 event-serialization format (the base spec defining how every signed Nostr event is hashed) plus a replay-freshness guard, so a malicious app cannot smuggle a re-signed event through the response channel.
The release also lands the updated NIP-44 encryption layer with a kind-scoped permission model and three sensitivity tiers, fixes the low-trust signing edge case where an “ask every time” request returned an error before the user could approve, and adds multi-account pairing so one app pairing can flow through several identities. Bunker pairings now surface real app identity through the NIP-46 connect-metadata extension Clave proposed in PR #2381. The clean disconnect flow uses the new NIP-46 logout method that merged in PR #2373, so a paired app can end its session cleanly without a manual unpair. Per-app trust levels (Full, Medium, Low) with per-event-kind overrides, an activity log for every signature, and bring-your-own push proxy round out the surface; the proxy stack is MIT-licensed and the per-client interop matrix is tracked in docs/nip46-compatibility.md.
Releases
Amber v6.2.1 adds NIP-46 logout and trims signer battery drain
Amber is the dominant Android Nostr signer. v6.2.1 reduces battery drain from relay reconnects and websocket pings, drops dead relays from the subscription pool, and stops waking the device when updating the relay notification. The release also adds NIP-46 logout method support so clients can end remote signer sessions cleanly (the same method merged into the spec this week as PR #2373) and adds parsing for event kind 39701 (public web bookmark) so users can sign bookmark events directly from Amber. Settings was rebuilt with grouped Material 3 cards and distinct icons, a navigation crash on the application permissions screen was fixed, and a per-account database connection leak was closed by building databases atomically.
Nostur 1.29.0 ships anonymous replies and remote-signer logout
Nostur is an iOS Nostr client by Fabian. 1.29.0-desktop adds support for replying to zap receipts and sending anonymous replies. On the signer side, the release improves the remote bunker connection flow, sends a NIP-46 logout to the remote signer when the user logs out of an account, and fixes a stuck spinner when a remote signer connection fails. The release also fixes DM loading issues caused by DM relays conflicting with app relays, fixes duplicate posts when navigating to a reply and back, and shows a media thumbnail in notification rows.
Citrine v3.0.0 ships Negentropy, NIP-42 AUTH, and onion-relay filtering
Citrine is an Android local relay aggregator. v3.0.0 is a major version bump that adds NIP-77 Negentropy support for set-reconciliation syncs, external signer and NIP-42 AUTH support in the relay aggregator, and NIP-51 mute-list honoring in aggregator fetches. The aggregator caps fetch at three relays per author with configurable source and indexer relays, reuses cached follow, mute, and metadata across restart and network change, pauses on limited or restricted networks, and filters onion relay URLs when the outbound proxy is disabled. Reposts that embed protected events are rejected, and mute lists are preserved from age-based deletion by default.
FIPS v0.4.0-rc1 adds a Nym mixnet transport and mDNS LAN discovery
FIPS (@jcorgan) is the FIPS mesh sync protocol implementation. v0.4.0-rc1 is wire-compatible with v0.3.0, so mixed meshes interoperate and there is no flag-day upgrade. The release adds two new ways for nodes to find and reach each other: a Nym mixnet outbound transport with a single-container demo and a mixnet-relay example, and opt-in mDNS / DNS-SD discovery on the local link. A new counter-only show_metrics query enables a Prometheus scraper at no hot-path cost, and FMP and FSP rekey were hardened to be hitless under packet loss in both directions.
Calendar by Formstr v1.6.1 and v1.6.2 add per-event notifications
Calendar by Formstr @Form* is a NIP-52 calendar client. v1.6.1 adds per-event notification preferences (PR #109) so a user can opt into or out of reminders for each individual calendar event. v1.6.2 fixes login with Amber (PR #185) so the new NIP-46 handshake from Amber 6.2.x works end to end.
Bitchat v1.5.2 and v1.5.3 harden the Nostr-and-BLE transport
Bitchat @bitchat is a Bluetooth-and-Nostr mesh chat client. v1.5.2 rate-limits iOS peer notifications to prevent flood (PR #972) and hardens Nostr validation and BLE announce checks (PR #1012) so the relay-side Nostr ingest path now rejects malformed messages before they reach the local mesh handler. v1.5.3 is a hotfix for a launch crash from a recursive dispatch_once between NostrRelayManager and NetworkActivationService (PR #1343).
Keep v1.0.5 moves the signer policy surface into the audited Rust core
Keep (@williamk⚡santiago🔑☢️) is an Android signer that wraps the keep Rust core. v1.0.5 pins to keep v0.4.8 and ships a bunker init race fix (PR #296) so the handshake no longer drops the first event under load, populates the Authorized Clients screen from the bunker onConnect callback (PR #291), and consolidates the kill switch on a single source of truth in keep-mobile (PR #284). The upstream Rust core landed v0.4.9 on June 13, which moves the NIP-55 and NIP-46 signer policy surface (permission decision, sensitive-kind duration clamp, expiry, keyed-HMAC tamper-evident audit chain, caller trust-on-first-use, persistent signing rate limiter) into the audited Rust core that previously duplicated logic in Kotlin, plus a NIP-44 v3 cipher implementation; that core will ship in the next keep-mobile bump.
ants v0.4.5 adds article portal links and restores Habla in the portal set
ants is dergigi’s Nostr search and reader tool. v0.4.5 adds article card actions for long-form posts, including article portal links, article-specific naddr sharing, nevent copy, and raw JSON access. The article portal set was refreshed by restoring Habla, replacing defunct destinations, and removing the imwald portal. The release also restores article footnote rendering with preserved in-article anchor navigation and waits for a relay connection before fetching the profile during login restore so the header avatar resolves correctly.
Morganite v0.0.3 ships a local Blossom cache for Android with Tor on demand
Morganite is a new local Blossom cache for Android by greenart7c3 (the author of Amber and Citrine). The cache acts as a BUD-08 local mirror that prunes least-used blobs once it exceeds 1GB. v0.0.3 starts Tor on demand and stops it when idle to save battery, disconnects the Nostr relay after author lookup to stop background drain, fixes battery drain from an unfiltered logcat stream and leaked HTTP clients, and releases replaced OkHttp clients off the main thread. The release also fetches the user’s inbox relays before querying the Blossom server list (so blob discovery follows the outbox model) and downloads the blob on HEAD requests when it is not cached locally, which keeps cache warmup tied to actual client demand.
Coracle 0.6.34 and 0.6.35 fix NIP-46 login, stale feeds, and reply toggling
Coracle (@hodlbod) is a Nostr web client by hodlbod. 0.6.34 fixes NIP-46 login, a stale feed state where the home timeline would not refresh after switching views, and a reply toggle that filtered everything out when toggled on. The release also rebuilds feed and list views, fixes a toast safe-area inset issue, and improves image loading. 0.6.35 is a small follow-up that fixes reposts being hidden when replies are disabled, so the repost filter no longer over-applies the reply filter.
Zeus v13.1.0-rc1 ships CLINK noffers and queue-less NWC
Zeus is a self-custody Bitcoin and Lightning wallet with a Nostr surface for wallet-connect and noffer payments. v13.1.0-rc1 adds queue-less NIP-47 Nostr Wallet Connect payments on iOS (in collaboration with Primal) so a paid NWC invoice no longer waits in a background queue, ships CLINK noffer payment support with Zeus Pay generating a CLINK noffer for every account so a sender can pay any Zeus user by Nostr key alone, and adds an opt-out for Nostr Zaps on Zeus Pay so a receiver can disable the kind 9735 receipt path without disabling NWC.
Alby Extension v3.14.3 migrates the noble/scure crypto stacks used by the NIP-07 signer
Alby Extension is the browser extension that provides NIP-07 signing and Nostr Wallet Connect alongside its Lightning surface. v3.14.3 migrates the @noble/curves, @noble/hashes, @noble/ciphers, @noble/secp256k1, @scure/bip32, and @scure/base stacks to v2 and v3 majors. Those are the cryptographic libraries the NIP-07 signer path relies on for event signing and NIP-44 encryption, so a major version bump touches the wire format the extension produces for every signed event request from a Nostr web client.
Mostro Mobile v1.2.8 and v1.2.9 support Protocol v2 and surface the bond policy
Mostro Mobile is the mobile client for Mostro. v1.2.8 lands the client-side support for mostro-core v0.13.0 Protocol v2 (covered in the top story above) and adds 17 features total, including the maker anti-abuse bond from PR #608, bootstrap relay discovery from PR #610, order cancellation persisted in notification history from PR #602, and fiat amount limits in the create-order screen from PR #605. v1.2.9 surfaces the anti-abuse bond policy from the node info event (PR #617) so a user can see the Mostro instance’s bond rules before opening an order.
ZapBook builds 4 through 27 ship multi-account, Marmot key publication, and circle re-invitations
ZapBook is a Nostr-native social reading app by codeswot for iOS and Android, organized around reading circles of 1 to 100 people who share milestones and zap each other sats as encouragement. Between build 4 on June 11 and build 27 on June 15, the project shipped 17 tagged builds and 7 merged PRs. Multi-account support with fluid account switching landed in PR #25, so a user can hold several Nostr identities in the app and migrate sessions between them. Initial Marmot key-package publication (kind 443) is now triggered automatically on onboarding completion (PR #20), which is the precondition for invite-only group messaging in the reading circles. Removed-circle-member handling now processes fresh re-invitations cleanly (PR #24), closing a class of bugs where re-added members did not receive new invites after being removed. The release line also offloads ONNX embedding inference to a background isolate (PR #19) for in-reader semantic search, and integrates the NWC service with an APP_ID_SUFFIX for environment-specific configurations so a single hub can serve multiple ZapBook builds.
Alby Hub v1.23.0 fixes NIP-47 publish for deleted apps and switches Bitrefill to NWC
Alby Hub @Alby is a self-hosted Lightning-and-Nostr hub. The non-Nostr surface of v1.23.0 is large (Just-in-Time channels, a Cards page for debit-card top-ups, an experimental Ark payment backend, and a stories home page) and falls outside Compass scope. On the NIP-47 side, the release stops retrying NIP-47 info publish for deleted apps so a removed connection no longer keeps republishing its kind 13194 info event (PR #2391), and removes the Bitrefill custom app entry in favor of a standard NWC connection (PR #2420). The readonly option for app-store apps (PR #2415) tightens permission scopes for NWC apps published through the in-hub store.
Also shipped
Smaller releases this week with Nostr-relevant content but limited per-release substance: Nostria v3.1.48 through v3.1.50 continuing the Web Bookmarks rollout with notification reliability and event-thread database optimization in v3.1.50; Deepmarks v0.7.0 through v0.7.5 iterating on the NIP-B0 social-bookmark client (the project also landed its website link this week in PR #96); Keep v1.1.1 through v1.1.4 shipping four F-Droid reproducible-build fixes on top of the v1.0.5 signer release covered above; NoorNote v0.11.1, v0.12.0, v0.13.0, and v0.13.1 on the desktop note client; Boris v0.12.2 on the Boris reader; Nostr Mail Client v0.13.0; Feeder 2.21.1; nak v0.19.13 as an empty maintenance bump on the Nostr CLI; Hashtree v0.2.68 through v0.2.71 refreshing gateway mutable-root caches for the hash-tree-addressed release publisher; NYM v3.72.501 and v3.72.502 bumping the Nostrify-based relay implementation; swift-nostr-client 0.3.0, 0.4.0, and 0.5.0 cutting three minor releases backed by 85 merged PRs on the iOS Nostr client; lawallet-nwc v0.11.0 with 18 merged PRs on the LaWallet Nostr Wallet Connect bridge; and Astraea v5.35.59 through v5.35.62 iterating on the Astraea Nostr client; and the BTC Recharge and giftcardshop NIP-05-verified Nostr DM bots added to the project directory under a new Shops category.
Unreleased changes
diVine merges 119 PRs toward the next short-form video drop
diVine (@rabble) is a Nostr-native short-form looping video client that restores the Vine archive on a Nostr backbone. The project merged 119 PRs this week without cutting a tagged release. The substantive Nostr-surface work covers a REST-first video publish path so a missing relay OK no longer surfaces as a failure (PR #5221 and PR #5220), blocklist refilter on curated and liked grids when the broad blocklist changes (PR #5208), DM conversation list recovery after a reinstall regression (PR #5202), restoration of the Nostr badge display on profiles (PR #5218), and linkified nostr: references in comment quotes (PR #5225). The video-editor stack added multi-select clip merge or delete, pinch-to-zoom canvas with a zoom-tracking letterbox scrim, and clip crop, rotate, flip transforms.
Pollerama merges 15 PRs in window with a signer rework and a feature wave
Pollerama (@ABH3PO) (repo formstr-hq/nostr-polls) is the Form*-family Nostr-native polls and feeds client, sibling to Calendar by Form* which shipped v1.6.2 this week. The latest tagged release on nostr-polls is v1.6.4 from March, so the in-window work is queued for the next tag and has not yet shipped, but the merge stream is heavy: fifteen pull requests landed between June 9 and June 16, with contributions from abh3po, geralt-debugs, and SIDDHANTCOOKIE. On the signer side, the project replaced the existing signing surface in PR #198 and upgraded the replacement in PR #201, and PR #200 stops kind-0 metadata updates from firing on login so a fresh sign-in no longer publishes a profile event the user did not request. The feature wave covers a profile editor with posting from the profile view (PR #205), an improved repost flow (PR #209), and an easier topic discovery path (PR #202). The next tagged release will pick all of this up.
Library and tooling work
NDK PR #375 and the merged work on the rust-nostr and nostr-tools repos were quiet this week, with one or two merged PRs each and no tagged releases. Activity on ContextVM SDK (1 merged PR), mesh-llm (37 merged PRs, 8 open PRs), Zap Cooking @ZapCooking (26 merged PRs), and Routstrd @routstr (2 merged PRs) continued without a release tag in the window.
NIP updates and protocol spec work
This week’s protocol work clusters in two places: signer hardening and NIP-29 group governance.
Merged this week:
- NIP-46 (Nostr Connect). PR #2373 adds a
logoutmethod that lets a client end a remote-signer session cleanly. Amber, Clave, and Nostur all shipped support in the same week. - NIP-CC (Community Chat). PR #2365 updates NIP-CC to reference the modern NIP-GC (Group Chat) specification for the client-side machinery, aligning the community-room spec with the canonical group-chat primitive.
Open NIP-29 cluster (relay-based group governance):
- Banner tags. PR #2383 adds a
bannertag to the group metadata kind 39000 event. - Invite code suffix. PR #2380 introduces an invite-code suffix on the group identifier so a one-shot invite can be encoded in the group ID itself.
- Message pinning. PR #2379 adds an update-pin-list moderation action and a kind 39005 event to broadcast the pinned set.
- Group reporting via NIP-17 DMs. PR #2377 defines a reporting flow where members report group abuse to the relay’s administrative contact over NIP-17 gift-wrapped DMs, keeping moderation traffic off the public group event stream.
- Role-based access control. PR #2376 adds an RBAC role surface on top of the existing admin/member split.
Open NIP-46 follow-ups:
- Client metadata in connect request. PR #2381 lets the connecting client send optional
name,url, andiconfields in its connect request so the signer can display the application’s identity on the pairing screen. Clave build 101 implements the proposal. - Avoid silent timeouts. PR #2375 tightens the spec so a signer that needs user input holds the request open until the user decides, fixing the failure mode Clave build 100 patched on the implementation side.
Other open work:
- NIP-100 Sovereign Agent Identity Network (SNIN). PR #2378 proposes an agent-to-agent protocol for autonomous-agent identity and capability discovery. The proposal is broad and is likely to get split into smaller pieces in review.
Blossom spec. BUD-00 PR #108 merged on June 15, broadening the BUD definition to cover client-side conventions and data formats built on Blossom blobs that servers do not implement. The change pulls BUDs like BUD-10 (the blossom: URI scheme) and BUD-08 (local-cache conventions Morganite implements this week) inside the canonical numbering surface, where they were previously treated as out-of-band extensions.
NIP deep dive: NIP-77 (Negentropy)
NIP-77 defines a set-reconciliation protocol for Nostr relays. Two parties (a client and a relay, or two relays in a bridge) each hold a set of events matching a filter, and they want to converge to the union without re-sending everything. The naive approach is to dump all event IDs over the wire and diff; for a busy filter that cost scales with the size of the larger set, regardless of how much of the set differs. NIP-77 reduces that cost to proportional to the symmetric difference.
The spec sits on top of two relay messages, NEG-OPEN and NEG-MSG. A client opens a reconciliation session with ["NEG-OPEN", <subscription_id>, <filter>, <initial_message>], where <initial_message> is a hex-encoded Negentropy payload describing the client’s view of the set. Replies arrive as NEG-MSG frames, and both sides exchange messages until they reach a fixed point. Each NEG-MSG either narrows the disagreement (by splitting a range into sub-ranges with their own fingerprints) or terminates a leaf (by listing the IDs in a small range, so the receiver can compute the diff directly). When a side decides the other has events it lacks, it sends a normal REQ for those IDs; when it has events the other lacks, the spec leaves the upload path to a normal EVENT publish on the other end.
The data structure underneath is a sequenced Merkle-tree variant. Each event in the local set is keyed by (created_at, id) and bucketed into ranges; each range carries a small fingerprint computed from the IDs it contains. When a fingerprint matches between client and relay, that range is converged and gets skipped. When it differs, the side replying splits the range into halves (or sub-ranges) and sends fingerprints for each, recursing into the disagreement. Leaf ranges (under a small threshold of events) get sent verbatim. The key property is that converged ranges cost almost nothing to confirm, regardless of how many events sit inside them.
The framing in created_at order matters for two reasons. First, Nostr’s existing pagination uses until and since against the same timestamp, so a reconciler can resume across sessions without re-syncing the whole archive: it caches the upper bound and starts the next sync from there. Second, range splits are deterministic given a sorted key, so client and relay always agree on which boundary to use next, with no need for a separate negotiation message. The cost of a sync is approximately O(d log n) where d is the size of the symmetric difference and n is the larger set, far below the O(n) cost of a naive ID-dump and far below the O(n) round trips of issuing N REQs.
Three implementation tradeoffs are worth flagging. The fingerprint size (the spec uses 32 bytes per range) is a tradeoff between collision probability and bandwidth: smaller fingerprints save bytes but raise the chance of a spurious match that drops events on the floor. The leaf threshold (when to stop splitting and dump IDs verbatim) is a tradeoff between round trips and per-message bandwidth: smaller thresholds mean more rounds, larger thresholds mean larger leaf messages. And the protocol assumes both parties can compute the same fingerprint over the same range; this requires a stable serialization of (created_at, id) pairs that both implementations agree on, which is why the spec is pedantic about the byte order in the fingerprint construction.
A relay that advertises NIP-77 in its NIP-11 supported_nips lets clients reconcile in place of (or alongside) a regular REQ-based sync. The client picks the protocol based on what it needs: a fresh subscription that wants tail traffic uses REQ because there is no prior state to reconcile; a long-running mirror that wants to catch up after downtime uses NEG-OPEN because the symmetric difference is small relative to the archive. The two paths complement each other in different deployment contexts.
Example NEG-OPEN exchange:
→ ["NEG-OPEN", "sync-1", {"kinds":[1],"authors":["abc..."]}, "<hex initial Negentropy message>"]
← ["NEG-MSG", "sync-1", "<hex relay response>"]
→ ["NEG-MSG", "sync-1", "<hex client refinement>"]
← ["NEG-MSG", "sync-1", "<hex leaf with IDs the relay has and client lacks>"]
→ ["REQ", "fetch-1", {"ids":[...]}]
← [...EVENT messages...]
← ["EOSE", "fetch-1"]
→ ["CLOSE", "sync-1"]
Citrine v3.0.0 ships NIP-77 support in the relay aggregator this week, the first time the Android local-relay surface can reconcile against external relays in place of bulk REQ pulls.
NIP deep dive: NIP-61 (Nutzaps)
NIP-61 defines peer-to-peer Cashu ecash payments delivered as Nostr events. A sender publishes a Cashu token locked to the recipient’s Nostr-derived public key, and the recipient redeems it from the mint when convenient. Unlike NIP-57 zaps, which require the receiver to be reachable over Lightning at the moment of payment, a nutzap is a self-contained ecash token that the recipient can redeem on their own schedule.
The spec composes three event kinds with Cashu’s P2PK lock primitive. Kind 10019 is the recipient’s mint recommendation: a replaceable event listing one or more mints the recipient accepts nutzaps from, plus the Cashu public key used to lock proofs to them. This key is distinct from the recipient’s Nostr identity key; it is a wallet-scoped key derived for nutzap receipt so the identity key never has to touch ecash secrets. Senders read kind 10019 before sending so the token they construct is one the recipient can redeem at a mint they already trust.
Kind 9321 is the payment event. It carries one or more Cashu proof tags (each holding a P2PK-locked proof bound to the recipient’s nutzap pubkey from kind 10019), a u tag with the mint URL, optional e and a tags identifying a zapped note, and a p tag for the recipient. The recipient receives the kind 9321 through their normal Nostr subscription, validates that the proofs are locked to their nutzap pubkey at a mint listed in their own kind 10019, unlocks the proofs with the corresponding private key, and either holds them in their NIP-60 wallet or melts them to Lightning. Kind 7375 records the redeemed proofs in the recipient’s wallet event chain so a wallet that re-syncs from relays does not double-count nutzap proofs against the same source.
The trust model is the explicit price of the design. Cashu mints hold the underlying value; a malicious or seized mint can refuse to redeem. NIP-61 inherits that custody risk from NIP-60 and does not try to remove it. What the design buys is offline-capable, instant-finality micropayments: the token is the payment, the recipient does not need to run a Lightning node or accept incoming HTLCs in real time, and a sender holding proofs at the same mint can pay without a single network hop to a custodian. The kind 10019 advertisement is the social-layer gate: senders that pick a mint outside the recipient’s trusted set risk an unredeemable token, which keeps the recipient’s redemption surface predictable.
Compared to NIP-57, the verification path is also simpler. A NIP-57 zap receipt is a kind 9735 published by the recipient’s LNURL service, requiring the verifier to fetch the LNURL endpoint and confirm the receipt’s signing key matches what the endpoint declared. A nutzap carries the cryptographic proof of payment inline (the P2PK-locked proofs themselves), so any verifier with the mint’s public keys can confirm the proofs are valid without round-tripping to a third party. The tradeoff is that nutzap verification requires understanding the mint’s keysets, while NIP-57 verification only requires standard LNURL infrastructure.
The two zap formats coexist as complements. NIP-57 zaps stay the right choice for receivers with Lightning routing in place and senders who want denominate-in-sats with Lightning settlement semantics. NIP-61 zaps become the right choice for offline receivers, micropayment-heavy flows where Lightning fees swamp the value transferred, and clients targeting users without Lightning infrastructure.
Example nutzap event:
{
"id": "a5f87fe2d4c8b9a0e3f1c4d5e6a7b8c9d0e1f2a3b4c5d6e7f8091a2b3c4d5e6f",
"pubkey": "79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798",
"created_at": 1750162800,
"kind": 9321,
"tags": [
["proof", "{\"amount\":21,\"secret\":\"...\",\"C\":\"...\",\"id\":\"...\"}"],
["u", "https://mint.example.com"],
["e", "8b39f4e5d6c7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2b3"],
["p", "c5d8a4e3b2a1f0e9d8c7b6a5949382716050403020100ffeeddccbbaa99887766"]
],
"content": "Great post!",
"sig": "f1e2d3c4b5a6978869504132c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f80192a3b4c5d6e7f80192a3b4c5d6e7f80192a3b4c5d6e7f80192a3b4c5d6e7f80192a3b4c5"
}
Amethyst v1.12.0 ships first-class NIP-61 nutzap rendering this week alongside its NIP-60 wallet surface (PR #3075), making Amethyst the first dominant Android client to render received nutzaps in the timeline and surface per-mint balance views in the wallet.
Write a comment