import { useState } from 'react'; import { Card, CardContent, CardHeader, CardTitle, CardDescription } from '@/components/ui/card'; import { Button } from '@/components/ui/button'; import { Input } from '@/components/ui/input'; import { Label } from '@/components/ui/label'; import { Badge } from '@/components/ui/badge'; import { Alert, AlertDescription } from '@/components/ui/alert'; import { useToast } from '@/hooks/useToast'; import { enableRelatr, getRelatrConfig, disableRelatr } from '@/hooks/useRelatrScore'; import { useNostr } from '@nostrify/react'; import { Shield, ExternalLink, Search, CheckCircle2, ChevronDown, ChevronUp } from 'lucide-react'; import { Collapsible, CollapsibleContent, CollapsibleTrigger } from '@/components/ui/collapsible'; /** * RelatrSettings component for configuring Relatr global trust score integration * * Relatr publishes trust scores as NIP-85 Trusted Assertion events (kind 30382). * Auto-enabled by default for all users with ContextVM's official service. */ export function RelatrSettings() { const { toast } = useToast(); const { nostr } = useNostr(); const config = getRelatrConfig(); const [pubkey, setPubkey] = useState(config.servicePubkey); const [relay, setRelay] = useState(config.relay); const [isSearching, setIsSearching] = useState(false); const [isAdvancedOpen, setIsAdvancedOpen] = useState(false); const handleAutoDiscover = async () => { setIsSearching(true); toast({ title: 'Searching for Relatr service...', description: 'Querying Nostr for Relatr profiles', }); try { // Search for profiles mentioning "relatr" or "contextvm" const profiles = await nostr.query( [{ kinds: [0], search: 'relatr', limit: 10 }], { signal: AbortSignal.timeout(10000) } ); console.log('[RelatrSettings] Found profiles:', profiles); // Look for official Relatr service for (const profile of profiles) { try { const metadata = JSON.parse(profile.content); const name = metadata.name?.toLowerCase() || ''; const about = metadata.about?.toLowerCase() || ''; const website = metadata.website?.toLowerCase() || ''; if ( name.includes('relatr') || about.includes('trust score') || website.includes('relatr.xyz') ) { setPubkey(profile.pubkey); toast({ title: 'Found Relatr service!', description: `Service: ${metadata.name || 'Unknown'}`, }); return; } } catch { // Skip invalid JSON } } toast({ title: 'No Relatr service found', description: 'Try entering the pubkey manually or check https://www.relatr.xyz/', variant: 'destructive', }); } catch (error) { console.error('[RelatrSettings] Auto-discovery failed:', error); toast({ title: 'Search failed', description: 'Could not query Nostr for Relatr profiles', variant: 'destructive', }); } finally { setIsSearching(false); } }; const handleEnable = () => { if (!pubkey || pubkey.length !== 64) { toast({ title: 'Invalid pubkey', description: 'Please enter a valid 64-character hex pubkey', variant: 'destructive', }); return; } enableRelatr(pubkey, relay); toast({ title: 'Relatr enabled!', description: 'Global trust scores are now active.', }); }; const handleDisable = () => { disableRelatr(); toast({ title: 'Relatr disabled', description: 'Trust scores are no longer being fetched.', }); }; return ( Relatr Trust Scores Global trust scores help identify reliable users and reduce spam {/* Status - Always visible */}
{config.enabled ? ( <> Active ) : ( 'Disabled' )}
{/* Info Alert */} {config.enabled ? ( <> Relatr is active. Trust scores from ContextVM's global network analysis help identify reliable skaters and reduce spam. ) : ( <> Relatr is disabled. Enable it to get trust scores from the global Nostr network. )} {/* Quick Actions */} {config.enabled ? ( ) : ( )}
{/* Advanced Settings - Collapsible */} {/* Service Pubkey Input */}
setPubkey(e.target.value)} className="font-mono text-xs" maxLength={64} />

Default: ContextVM's official Relatr service (npub1dvmc...)

{/* Relay Input */}
setRelay(e.target.value)} className="font-mono text-xs" />

Default: wss://relay.contextvm.org (ContextVM's official relay)

{/* Apply Changes Button */} {/* Documentation Links */}

Learn More:

); }