fix(pairing): default relay to the transport's nostrrelay, not nostrclient proxy
Some checks failed
ci.yml / fix(pairing): default relay to the transport's nostrrelay, not nostrclient proxy (pull_request) Failing after 0s

The nostrclient endpoint is a subscription MULTIPLEXER, not a full relay: its
router forwards a client's EVENT upstream but never returns an OK ack (see
nostrclient/router.py). A transport client that awaits OK on publish therefore
times out ("publish timed out"), so kind-21000 RPCs never complete — verified
on the Sintra: connect succeeded but list_wallets hung, and switching to the
nostrrelay endpoint made the whole flow work (wallet, balance, availability).

default_relay_endpoint now derives from settings.nostr_transport_relays — the
relay the transport actually listens on: use it as-is when already
machine-reachable, or re-home its path on lnbits_baseurl when it's a co-located
loopback relay (the bundled nostrrelay). Validation/localhost-reject and the
pair-dialog pre-fill/hint carry over; wording updated to "transport relay".

227 tests pass.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Padreug 2026-07-02 00:43:54 +02:00
commit 0bb9939822
6 changed files with 89 additions and 49 deletions

View file

@ -301,9 +301,8 @@ async def api_create_machine(
@spirekeeper_api_router.get("/api/v1/dca/default-relay")
async def api_default_relay(user: User = Depends(check_user_exists)) -> dict:
"""The relay a pairing seed defaults to when the operator leaves it blank —
this lnbits' nostrclient proxy endpoint, derived from lnbits_baseurl
(bitspire#70). The pair dialog pre-fills it. `None` if lnbits_baseurl is
unset."""
the relay the transport listens on, derived from the transport config
(bitspire#70). The pair dialog pre-fills it. `None` if it can't be derived."""
_ = user
return {"relay": default_relay_endpoint()}
@ -326,8 +325,8 @@ async def api_pair_machine(
`duration_hours` (optional) time-bounds the token; revoke via the
sibling `POST .../revoke` endpoint."""
machine = await _machine_owned_by(machine_id, user.id)
# relays may be omitted — pair_spire defaults to this lnbits' nostrclient
# proxy endpoint and validates reachability (raises PairingError → 502).
# relays may be omitted — pair_spire defaults to the transport relay and
# validates reachability (raises PairingError → 502).
try:
async with NsecBunkerAdminClient.from_settings() as client: