import { useState } from "react"; import { useLightningStore } from "../../stores/lightning"; import { useUserStore } from "../../stores/user"; import { isValidNwcUri, parseNwcUri } from "../../lib/lightning/nwc"; // ── Wallet catalogue ───────────────────────────────────────────────────────── interface WalletDef { id: string; name: string; tagline: string; setupUrl: string; steps: string[]; detect: (relay: string) => boolean; } const WALLETS: WalletDef[] = [ { id: "alby-hub", name: "Alby Hub", tagline: "Self-hosted · full control", setupUrl: "https://albyhub.com", steps: [ "Open your Alby Hub dashboard", 'Go to Connections → "Add connection"', "Copy the Nostr Wallet Connect URI", "Paste it below", ], detect: (r) => r.includes("albyhub") || (r.includes("getalby") && r.includes("hub")), }, { id: "alby", name: "Alby Extension", tagline: "Browser extension", setupUrl: "https://getalby.com/apps/new", steps: [ "Go to getalby.com/apps/new", "Create a new app connection", "Copy the Nostr Wallet Connect URI", "Paste it below", ], detect: (r) => r.includes("getalby") && !r.includes("albyhub"), }, { id: "mutiny", name: "Mutiny", tagline: "Web-based wallet", setupUrl: "https://app.mutinywallet.com/#/settings/connections", steps: [ "Open Mutiny Wallet", "Go to Settings → Nostr Wallet Connect", "Create a new connection", "Copy the URI and paste it below", ], detect: (r) => r.includes("mutiny"), }, { id: "phoenix", name: "Phoenix", tagline: "Mobile · self-custodial", setupUrl: "https://phoenix.acinq.co", steps: [ "Open Phoenix on your phone", "Go to Settings → Nostr Wallet Connect", "Tap 'Link a new wallet'", "Copy the URI and paste it below", ], detect: (r) => r.includes("phoenix") || r.includes("acinq"), }, ]; const GENERIC: WalletDef = { id: "generic", name: "Other wallet", tagline: "", setupUrl: "", steps: [ "Open your Lightning wallet", "Find the Nostr Wallet Connect section", "Generate a new NWC connection URI", "Paste it below", ], detect: () => true, }; function detectWallet(nwcUri: string): WalletDef { try { const { relayUrl } = parseNwcUri(nwcUri); return WALLETS.find((w) => w.detect(relayUrl)) ?? GENERIC; } catch { return GENERIC; } } // ── Connected state ─────────────────────────────────────────────────────────── function ConnectedState({ nwcUri, onDisconnect }: { nwcUri: string; onDisconnect: () => void }) { const wallet = detectWallet(nwcUri); let relay = ""; try { relay = parseNwcUri(nwcUri).relayUrl; const u = new URL(relay); relay = u.hostname; } catch { /* keep raw */ } return (
{wallet.name} connected {relay && via {relay}}

Your NWC connection is active. You can zap notes and profiles.

); } // ── Wallet card ─────────────────────────────────────────────────────────────── function WalletCard({ wallet, onSelect }: { wallet: WalletDef; onSelect: () => void }) { return (
{wallet.name}
{wallet.tagline}
{wallet.setupUrl && ( e.stopPropagation()} > open ↗ )}
); } // ── Paste step ──────────────────────────────────────────────────────────────── function PasteStep({ wallet, onBack, onConnected, }: { wallet: WalletDef; onBack: () => void; onConnected: () => void; }) { const { setNwcUri } = useLightningStore(); const { pubkey } = useUserStore(); const [input, setInput] = useState(""); const [error, setError] = useState(null); const valid = isValidNwcUri(input.trim()); let parsedRelay = ""; if (valid) { try { parsedRelay = new URL(parseNwcUri(input.trim()).relayUrl).hostname; } catch { /* keep raw */ } } const formatError = input.trim() && !valid ? input.trim().startsWith("nostr+walletconnect://") ? "URI is incomplete — missing relay or secret parameter" : "Should start with nostr+walletconnect://" : null; const handleConnect = () => { const uri = input.trim(); if (!isValidNwcUri(uri)) { setError("Invalid NWC URI — check and try again"); return; } try { setNwcUri(uri, pubkey ?? undefined); onConnected(); } catch (err) { setError(String(err)); } }; return (
{/* Step-by-step instructions */}
    {wallet.steps.map((step, i) => (
  1. {i + 1}. {step}
  2. ))}
{/* URI input */}