import { Box, Button, List, ListItem, ListSubheader, Typography, useTheme } from '@mui/material' import JSZip from 'jszip' import { MuiFileInput } from 'mui-file-input' import { useEffect, useState } from 'react' import { Link } from 'react-router-dom' import { toast } from 'react-toastify' import placeholderAvatar from '../../assets/images/nostr-logo.jpg' import { LoadingSpinner } from '../../components/LoadingSpinner' import { MetadataController } from '../../controllers' import { getProfileRoute } from '../../routes' import { Meta, ProfileMetadata } from '../../types' import { hexToNpub, parseJson, readContentOfZipEntry, shorten } from '../../utils' import styles from './style.module.scss' import { Event, verifyEvent } from 'nostr-tools' export const VerifyPage = () => { const theme = useTheme() const textColor = theme.palette.getContrastText( theme.palette.background.paper ) const [isLoading, setIsLoading] = useState(false) const [loadingSpinnerDesc, setLoadingSpinnerDesc] = useState('') const [selectedFile, setSelectedFile] = useState(null) const [meta, setMeta] = useState(null) const [metadata, setMetadata] = useState<{ [key: string]: ProfileMetadata }>( {} ) useEffect(() => { if (meta) { const metadataController = new MetadataController() const users = [meta.submittedBy, ...meta.signers, ...meta.viewers] users.forEach((user) => { if (!(user in metadata)) { metadataController .findMetadata(user) .then((metadataEvent) => { const metadataContent = metadataController.extractProfileMetadataContent(metadataEvent) if (metadataContent) setMetadata((prev) => ({ ...prev, [user]: metadataContent })) }) .catch((err) => { console.error( `error occurred in finding metadata for: ${user}`, err ) }) } }) } }, [meta]) const handleVerify = async () => { if (!selectedFile) return setIsLoading(true) const zip = await JSZip.loadAsync(selectedFile).catch((err) => { console.log('err in loading zip file :>> ', err) toast.error(err.message || 'An error occurred in loading zip file.') return null }) if (!zip) return setLoadingSpinnerDesc('Parsing meta.json') const metaFileContent = await readContentOfZipEntry( zip, 'meta.json', 'string' ) if (!metaFileContent) { setIsLoading(false) return } const parsedMetaJson = await parseJson(metaFileContent).catch( (err) => { console.log('err in parsing the content of meta.json :>> ', err) toast.error( err.message || 'error occurred in parsing the content of meta.json' ) setIsLoading(false) return null } ) setMeta(parsedMetaJson) setIsLoading(false) } const imageLoadError = (event: any) => { event.target.src = placeholderAvatar } const getRoboImageUrl = (pubkey: string) => { const npub = hexToNpub(pubkey) return `https://robohash.org/${npub}.png?set=set3` } const displayUser = (pubkey: string, verifySignature = false) => { const profile = metadata[pubkey] let isValidSignature = false if (verifySignature) { const signedEventString = meta ? meta.signedEvents[pubkey] : null if (signedEventString) { try { const signedEvent = JSON.parse(signedEventString) isValidSignature = verifyEvent(signedEvent) } catch (error) { console.error( `An error occurred in parsing and verifying the signature event for ${pubkey}`, error ) } } } return ( Profile Image {profile?.display_name || profile?.name || shorten(hexToNpub(pubkey))} {verifySignature && ( ({isValidSignature ? 'Valid' : 'Not Valid'} Signature) )} ) } const displayExportedBy = () => { if (!meta || !meta.exportSignature) return null const exportSignatureString = meta.exportSignature try { const exportSignatureEvent = JSON.parse(exportSignatureString) as Event if (verifyEvent(exportSignatureEvent)) { return displayUser(exportSignatureEvent.pubkey) } else { toast.error(`Invalid export signature!`) return ( Invalid export signature ) } } catch (error) { console.error(`An error occurred wile parsing exportSignature`, error) return null } } return ( <> {isLoading && } {!meta && ( <> Select exported zip file setSelectedFile(value)} InputProps={{ inputProps: { accept: '.zip' } }} /> {selectedFile && ( )} )} {meta && ( <> Meta Info } > Submitted By {displayUser(meta.submittedBy)} Exported By {displayExportedBy()} {meta.signers.length > 0 && ( Signers
    {meta.signers.map((signer) => (
  • {displayUser(signer, true)}
  • ))}
)} {meta.viewers.length > 0 && ( Viewers
    {meta.viewers.map((viewer) => (
  • {displayUser(viewer)}
  • ))}
)} Files
    {Object.keys(meta.fileHashes).map((file, index) => (
  • {file}
  • ))}
)}
) }