Conversation
NDK 3 changes two defaults that between them break Cashu mint discovery. NDKPool.connect() now resolves only once every relay reports CONNECTED, racing that against a timeout promise that is never created when no timeout argument is passed. DEFAULT_NOSTR_RELAYS is never fully reachable in practice (nostr.land sits in AUTH_REQUIRED, others are often down), so `await ndk.connect()` never returns and Discover Mints spins forever with no error surfaced. Pass an explicit connect timeout. The outbox model also flipped from opt-in to on by default. Mint discovery subscribes with hundreds of authors, and outbox tracking resolves each author's relay list and reconnects the subscription as those lists arrive, growing the pool past 40 relays and starving the JS thread: a 10 second collection timer fired after 94 seconds. Opt out to keep the 2.x behavior. Verified on device against live relays that mint discovery, trusted mints from both the ZEUS npub and a custom npub, and reviewer profile lookups all return the same results in the same time as 2.13.0-rc2.
kaloudis
force-pushed
the
fix/ndk-3-mint-discovery
branch
from
September 22, 2026 14:34
4b5ae85 to
5fc09b6
Compare
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Relates to issue: ZEUS-0000
Supersedes #4605. Dependabot's bump of
@nostr-dev-kit/ndkto 3.0.3 cannot merge on its own: NDK 3 changes two defaults that between them break Cashu mint discovery entirely. This PR carries the same bump plus the two-line behavioral opt-outs needed to keep the old behavior, with before/after measurements on device.Full analysis is in #4605 (comment). Summary:
1.
NDKPool.connect()never resolves without a timeout argument. 3.x races "every relay reported CONNECTED" against a timeout promise that isnew Promise(() => {})when no timeout is passed:2.13.0-rc2 instead awaited the per-relay connect promises, each of which resolves as soon as the socket is created.
DEFAULT_NOSTR_RELAYSis never fully connected in practice (only 4 to 5 of 8 reach CONNECTED,wss://nostr.landsits in AUTH_REQUIRED,wss://nostr.wineandwss://relay.8333.spaceare usually down), soawait this.ndk.connect()never returns. Discover Mints and the trusted-mints list spin forever with no error, because the 10s safety timeout insubscribeAndCollectEventsis never even reached.2. The outbox model flipped from opt-in to on by default. 2.13 had
if (opts.enableOutboxModel); 3.0.3 hasif (!(opts.enableOutboxModel === false)). Mint discovery from follows subscribes with the followed author set (613 pubkeys for the ZEUS npub), and outbox tracking resolves each author's relay list and reconnects the subscription as those lists arrive. Measured effect: the relay pool grew from 8 to 43 relays and the JS thread was starved badly enough that asetTimeout(resolve, 10000)fired after 94 seconds. Even with fix 1 alone, trusted mints took ~122s instead of ~10s.Both opt-outs are scoped to the three
new NDK(...)sites instores/CashuStore.ts, which are the only NDK usage in the app.Measurements
Same device, same checkout, live relays, calling the real store methods:
fetchMints()(Discover Mints)fetchMintsFromFollows()(ZEUS npub)fetchMintsFromFollows(custom npub)fetchReviewerProfiles()[]+ "Invalid npub format"[]+ "Invalid npub format"Top recommended mints come back identical and in the same order before and after (
mint.cashu.chat(7),mint.minibits.cash/Bitcoin(5),mint.coinos.io(3)for Discover Mints).Note that CI is blind to all of this:
tscpasses against 3.0.3, andstores/CashuStore.test.tsdoesjest.mock('@nostr-dev-kit/ndk', () => ({})).This pull request is categorized as a:
Checklist
yarn run tscand made sure my code compiles correctlyyarn run lintand made sure my code didn’t contain any problematic patternsyarn run prettierand made sure my code is formatted correctlyyarn run testand made sure all of the tests passTesting
If you modified or added a utility file, did you add new unit tests?
No utility file was modified.
stores/CashuStore.test.tsmocks NDK out entirely, so a unit test cannot cover this; verification was done against live relays on device, as tabulated above.I have tested this PR on the following platforms (please specify OS version and phone model/VM):
Android run still owed.
I have tested this PR with the following types of nodes (please specify node version and API version where appropriate):
On-device
Remote
The affected code path is Cashu mint discovery over nostr relays, which does not talk to the Lightning backend, so no backend-specific behavior is exercised here.
Locales
Third Party Dependencies and Packages
yarnafter this PR is merged inpackage.jsonandyarn.lockhave been properly updatedyarn.lockalso picks up shiki and sandpack, which NDK 3 declares as runtime dependencies (a docs-tooling leak upstream). Itsdistnever imports them, so this is node_modules bloat only and they stay out of the bundle; confirmed by bundling for iOS.Other: