'use client'; import { AlertCircle, CheckCircle, ChevronDown, ChevronRight, Clock, Copy, ExternalLink, Key, Shield, } from 'lucide-react'; import { useState } from 'react'; import { cn } from '../../../lib/utils'; import { Badge } from '../../ui/badge'; import { Button } from '../../ui/button'; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '../../ui/card'; import { Tabs, TabsContent, TabsList, TabsTrigger } from '../../ui/tabs'; /** * UCAN capability structure */ export interface UCANCapability { with: string; // Resource identifier can: string; // Action/permission nb?: Record; // Additional constraints } /** * UCAN token structure */ export interface UCANToken { iss: string; // Issuer DID aud: string; // Audience DID exp?: number; // Expiration timestamp nbf?: number; // Not before timestamp att: UCANCapability[]; // Attenuations/capabilities prf?: string[]; // Proof chain fct?: Record; // Facts } /** * Props for UCANViewer component */ export interface UCANViewerProps { token: UCANToken; showRaw?: boolean; showProofChain?: boolean; onCopyToken?: () => void; onVerify?: () => Promise; className?: string; } /** * Viewer for UCAN token visualization and capability display */ export function UCANViewer({ token, showRaw = true, showProofChain = true, onCopyToken, onVerify, className, }: UCANViewerProps) { const [expandedCapabilities, setExpandedCapabilities] = useState>(new Set()); const [verificationStatus, setVerificationStatus] = useState< 'idle' | 'verifying' | 'valid' | 'invalid' >('idle'); const toggleCapability = (index: number) => { const newExpanded = new Set(expandedCapabilities); if (newExpanded.has(index)) { newExpanded.delete(index); } else { newExpanded.add(index); } setExpandedCapabilities(newExpanded); }; const handleVerify = async () => { if (!onVerify) return; setVerificationStatus('verifying'); try { const isValid = await onVerify(); setVerificationStatus(isValid ? 'valid' : 'invalid'); } catch { setVerificationStatus('invalid'); } }; const formatDate = (timestamp?: number) => { if (!timestamp) return 'Never'; return new Date(timestamp * 1000).toLocaleString(); }; const isExpired = token.exp && token.exp * 1000 < Date.now(); const isNotYetValid = token.nbf && token.nbf * 1000 > Date.now(); return (
UCAN Token
{isExpired && ( Expired )} {isNotYetValid && ( Not Yet Valid )} {verificationStatus === 'valid' && ( Verified )} {verificationStatus === 'invalid' && ( Invalid )}
User-Controlled Authorization Network token with delegated capabilities
Details Capabilities ({token.att.length}) {showRaw && Raw Token}

Issuer

{token.iss}

Audience

{token.aud}
{token.exp && (

Expires

{formatDate(token.exp)}

)} {token.nbf && (

Not Before

{formatDate(token.nbf)}

)} {showProofChain && token.prf && token.prf.length > 0 && (

Proof Chain

{token.prf.map((proof, index) => ( {proof} ))}
)}
{onVerify && ( )} {onCopyToken && ( )}
{token.att.map((capability, index) => ( toggleCapability(index)} >
{expandedCapabilities.has(index) ? ( ) : ( )} {capability.can} {capability.with}
{expandedCapabilities.has(index) && capability.nb && (

Constraints:

                          {JSON.stringify(capability.nb, null, 2)}
                        
)}
))} {token.att.length === 0 && (
No capabilities defined
)}
{showRaw && (
                  {JSON.stringify(token, null, 2)}
                
)}
); }