From d2755d7232a0967463b8e997f1d5af4a09dd7d0a Mon Sep 17 00:00:00 2001 From: Ben Weeks Date: Mon, 22 Dec 2025 12:49:33 +0000 Subject: [PATCH] fix: improve nostrclient status detection and display MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Call nostrclient /relays API directly from frontend for accurate status - Show correct error messages from API response (body.detail) - Add orange warning state for no relays configured - Show relay count when connected (X of Y connected) - Simplify status logic: 200 = green, no relays = orange, error = red 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- static/js/index.js | 92 +++++++++++++++++++--------- templates/nostrmarket/_api_docs.html | 2 +- templates/nostrmarket/index.html | 32 +++++----- views_api.py | 52 +++++++++++----- 4 files changed, 118 insertions(+), 60 deletions(-) diff --git a/static/js/index.js b/static/js/index.js index 21f67f6..6cd50ad 100644 --- a/static/js/index.js +++ b/static/js/index.js @@ -18,21 +18,18 @@ window.app = Vue.createApp({ }, wsConnection: null, nostrStatus: { - nostrclient_available: false, - nostrclient_relays: [], - nostrclient_error: null, - nostrmarket_running: false, - websocket_connected: false + connected: false, + error: null, + relays_connected: 0, + relays_total: 0 } } }, computed: { nostrStatusColor: function () { - if (!this.nostrStatus.nostrclient_available) { - return 'red' - } else if (this.nostrStatus.websocket_connected) { + if (this.nostrStatus.connected) { return 'green' - } else if (this.nostrStatus.nostrmarket_running) { + } else if (this.nostrStatus.warning) { return 'orange' } return 'red' @@ -218,31 +215,61 @@ window.app = Vue.createApp({ }) } }, - checkNostrStatus: async function () { + checkNostrStatus: async function (showNotification = false) { try { - const {data} = await LNbits.api.request( - 'GET', - '/nostrmarket/api/v1/status', - this.g.user.wallets[0].inkey - ) - this.nostrStatus = data - if (!data.nostrclient_available) { + const response = await fetch('/nostrclient/api/v1/relays') + const body = await response.json() + console.log('Nostrclient /relays:', response.status, body) + + if (response.status === 200) { + const relaysConnected = body.filter(r => r.connected).length + if (body.length === 0) { + this.nostrStatus = { + connected: false, + error: 'No relays configured in Nostr Client', + relays_connected: 0, + relays_total: 0, + warning: true + } + } else { + this.nostrStatus = { + connected: true, + error: null, + relays_connected: relaysConnected, + relays_total: body.length + } + } + } else { + this.nostrStatus = { + connected: false, + error: body.detail, + relays_connected: 0, + relays_total: 0 + } + } + + if (showNotification) { this.$q.notify({ - timeout: 5000, - type: 'warning', - message: 'Nostrclient extension not available', - caption: - data.nostrclient_error || - 'Please install and configure the nostrclient extension' + timeout: 3000, + type: this.nostrStatus.connected ? 'positive' : 'warning', + message: this.nostrStatus.connected ? 'Connected' : 'Disconnected', + caption: this.nostrStatus.error || undefined }) } } catch (error) { + console.error('Failed to check nostr status:', error) this.nostrStatus = { - nostrclient_available: false, - nostrclient_relays: [], - nostrclient_error: 'Failed to check status', - nostrmarket_running: false, - websocket_connected: false + connected: false, + error: error.message, + relays_connected: 0, + relays_total: 0 + } + if (showNotification) { + this.$q.notify({ + timeout: 5000, + type: 'negative', + message: this.nostrStatus.error + }) } } }, @@ -253,13 +280,18 @@ window.app = Vue.createApp({ ) .onOk(async () => { try { + this.$q.notify({ + timeout: 2000, + type: 'info', + message: 'Reconnecting...' + }) await LNbits.api.request( 'PUT', '/nostrmarket/api/v1/restart', this.g.user.wallets[0].adminkey ) - // Check status after restart - setTimeout(() => this.checkNostrStatus(), 2000) + // Check status after restart (give time for websocket to reconnect) + setTimeout(() => this.checkNostrStatus(true), 3000) } catch (error) { LNbits.utils.notifyApiError(error) } diff --git a/templates/nostrmarket/_api_docs.html b/templates/nostrmarket/_api_docs.html index f4f7cab..d801649 100644 --- a/templates/nostrmarket/_api_docs.html +++ b/templates/nostrmarket/_api_docs.html @@ -1,6 +1,6 @@ -

+

Create, edit and publish products to your Nostr relays. Customers can browse your stalls and pay with Lightning.

diff --git a/templates/nostrmarket/index.html b/templates/nostrmarket/index.html index 319fbdb..0036428 100644 --- a/templates/nostrmarket/index.html +++ b/templates/nostrmarket/index.html @@ -170,7 +170,7 @@ - + @@ -185,27 +185,29 @@ - Nostrclient: + Status: -
- Relays: - configured
- WebSocket: -
+ Relays:  + + of + + connected + +
diff --git a/views_api.py b/views_api.py index ba10674..9dd8730 100644 --- a/views_api.py +++ b/views_api.py @@ -1113,31 +1113,55 @@ async def api_get_nostr_status( ) -> dict: """Get the status of the nostrclient extension.""" nostrclient_available = False - nostrclient_relays = [] - nostrclient_error = None + relays = [] + error = None try: async with httpx.AsyncClient() as client: - response = await client.get( - f"http://localhost:{settings.port}/nostrclient/api/v1/relays", - timeout=5.0, + url = f"http://127.0.0.1:{settings.port}/nostrclient/api/v1/relays" + logger.info(f"Calling nostrclient API: {url}") + response = await client.get(url, timeout=5.0) + logger.info( + f"Nostrclient response: status={response.status_code}, " + f"body={response.text[:500]}" ) + if response.status_code == 200: nostrclient_available = True - nostrclient_relays = response.json() + relays = response.json() + else: + # Any non-200 response means we can't verify nostrclient is working + try: + error = response.json().get("detail", f"HTTP {response.status_code}") + except Exception: + error = f"HTTP {response.status_code}" except httpx.ConnectError: - nostrclient_error = "Cannot connect to nostrclient extension" + error = "Cannot connect to nostrclient extension" except httpx.TimeoutException: - nostrclient_error = "Timeout connecting to nostrclient" + error = "Timeout connecting to nostrclient" except Exception as ex: - nostrclient_error = str(ex) + error = str(ex) + + # Only show connected if no errors and websocket is connected + connected = ( + nostrclient_available + and nostr_client.is_websocket_connected + and error is None + ) + + # If nostrclient exists but websocket not connected, explain why + if nostrclient_available and not nostr_client.is_websocket_connected and not error: + error = "Websocket not connected" + + # Count connected relays + relays_connected = sum(1 for r in relays if r.get("connected", False)) + relays_total = len(relays) return { - "nostrclient_available": nostrclient_available, - "nostrclient_relays": nostrclient_relays, - "nostrclient_error": nostrclient_error, - "nostrmarket_running": nostr_client.running, - "websocket_connected": nostr_client.is_websocket_connected, + "connected": connected, + "error": error, + "relays_connected": relays_connected, + "relays_total": relays_total, }