Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions apps/frontend/src/components/connect/GossipPill/GossipPill.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,28 @@ import { useSelector } from 'react-redux';
import { HttpService } from '../../../services/http.service';
import { selectActiveProfileId } from '../../../store/nodesSelectors';

/**
* Gossip Pill — live status pill on /connect.
*
* What it renders
* A small pill that tells the user how big their gossip view is:
* N nodes / M channels. Formatted as compact "1.2k" / "1M" using
* the local formatCount helper.
*
* Why it's there: when discovery seems "thin" (few LSPs in the
* discovered list), the user wants to know whether the wallet's
* own node sees enough of the network to find them. A pill saying
* "12k nodes / 50k channels" reassures them the discovery is
* real; "5 nodes / 0 channels" tells them their CLN is still
* syncing.
*
* Side effects
* - HttpService.fetchGossipCounts() every 30s (GOSSIP_REFRESH_MS)
*
* Props contract
* None — reads activeProfileId from Redux and the gossip counts
* from the backend on a poll.
*/
const GOSSIP_REFRESH_MS = 30_000;

const formatCount = (n: number): string => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,30 @@
import { useState } from 'react';
import { Modal, Button, Form, Alert } from 'react-bootstrap';

/* Task #119: manual-connect modal.
/**
* Manual Connect Modal — pubkey@host:port direct-target form (Task #119).
*
* The "Open Factories" Card on the Connect page only lists LSPs that a
* rendezvous coordinator has advertised. "Join via invite link" requires
* a full superscalar:// URL with iid baked in. This modal fills the
* remaining gap: someone DMs you "my LSP is <pubkey>@<host:port>, come
* browse my factories" and you want to talk to that LSP directly.
* What it renders
* The form that fills the gap between rendezvous-discovered LSPs
* (in ConnectList's discovered tab) and full invite URLs (which
* bake in a specific iid). The user pastes a "pubkey@host:port"
* string and the parent pops JoinFactoryModal pointed at that LSP.
*
* On submit we validate format and pass the entered pubkey + address back
* to the parent, which pops the existing JoinFactoryModal with those
* values. The plugin's auto-connect helper (#118) handles the BOLT-8 hop.
* Trigger scenario: someone DMs you "my LSP is X, browse my
* factories" without sending a full invite link.
*
* Validation
* - Pubkey must be 66 hex chars
* - Host:port required and parses successfully
*
* Side effects
* None — the parent owns the BOLT-8 connect via the plugin's
* auto-connect helper (#118).
*
* Props contract
* - `show: boolean`
* - `onHide: () => void`
* - `onSubmit: (pubkey, address) => void` — fires on valid submit
*
* No plugin RPC of our own: factory-browse-host (called by
* JoinFactoryModal) takes a peer + optional address hint, and the plugin
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,29 @@ import { FactoriesService } from '../../../services/http.service';
import logger from '../../../services/logger.service';

/**
* Task #152: surface the client's outgoing factory-join-request attempts
* + current status. Powered by the plugin's client-list-outgoing-joins RPC
* (added in PR #77). Renders on the Connect page so users can see what
* happened to invites they sent without having to grep CLN logs.
* My Join Attempts Card — outgoing factory-join-request audit (Task #152).
*
* What it renders
* A Card on /connect listing every factory-join-request this client
* has sent, with the LSP target + factory iid + status (queued /
* approved / refused / expired). Powered by the plugin's
* client-list-outgoing-joins RPC.
*
* Closes the "did my join go through?" question without making
* users grep CLN logs — important for first-time SuperScalar users
* whose first attempt may fail for any number of reasons (LSP
* offline, request rejected by auto-accept-threshold, expired).
*
* Key state
* - `attempts`: the list from client-list-outgoing-joins
* - `loading` / `error` per fetch
* - 10s refresh interval while modal open
*
* Side effects
* - Plugin RPC: client-list-outgoing-joins (poll every 10s)
*
* Props contract
* None — fully self-contained card on /connect.
*/

type OutgoingJoin = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,35 @@ import './RendezvousSettings.scss';
import { useEffect, useState } from 'react';
import { Accordion, Card, Form, Button, Row, Col, Spinner, Badge } from 'react-bootstrap';
import { useDispatch, useSelector } from 'react-redux';

/**
* Rendezvous Settings — Nostr relay + coordinator config.
*
* What it renders
* The /connect page's RendezvousSettings accordion. Lets the
* operator edit:
* - Relay list (which Nostr relays to query for vouches)
* - Coordinator npubs (which voucher identities to trust, per
* network: mainnet / signet / testnet4 / regtest)
* - Per-tier caps (channel / utxo / peer max vouches kept)
* - includePeer toggle (peer-tier is weaker; off by default)
*
* These settings flow through to the nostr.service.fetchVouches
* call inside ConnectList for discovery.
*
* Key state
* - `draft`: in-progress edits (separate from Redux until Save)
* - `saving` / `error` for the persist round-trip
*
* Side effects
* - On mount: RendezvousService.fetchSettings → dispatch into
* rendezvousSlice (lazy-injected here)
* - On Save: RendezvousService.saveSettings → re-dispatch
*
* Props contract
* None — fully self-contained accordion on /connect.
*/

import {
CoordinatorEntry,
CoordinatorNetwork,
Expand Down
Loading