2024-08-12 14:26:03 +02:00
|
|
|
import { CreateSignatureEventContent, Meta } from '../types'
|
2024-08-13 11:52:05 +02:00
|
|
|
import { fromUnixTimestamp, parseJson } from '.'
|
2024-08-15 17:48:05 +02:00
|
|
|
import { Event, verifyEvent } from 'nostr-tools'
|
2024-08-12 14:26:03 +02:00
|
|
|
import { toast } from 'react-toastify'
|
2024-08-22 18:20:54 +02:00
|
|
|
import { extractFileExtensions } from './file'
|
2024-08-28 09:29:05 +02:00
|
|
|
import { handleError } from '../types/errors'
|
|
|
|
import { MetaParseError } from '../types/errors/MetaParseError'
|
2024-08-12 14:26:03 +02:00
|
|
|
|
|
|
|
export enum SignStatus {
|
|
|
|
Signed = 'Signed',
|
2024-08-14 14:27:49 +02:00
|
|
|
Awaiting = 'Awaiting',
|
2024-08-12 14:26:03 +02:00
|
|
|
Pending = 'Pending',
|
2024-08-14 14:27:49 +02:00
|
|
|
Invalid = 'Invalid',
|
|
|
|
Viewer = 'Viewer'
|
2024-08-12 14:26:03 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
export enum SigitStatus {
|
|
|
|
Partial = 'In-Progress',
|
|
|
|
Complete = 'Completed'
|
|
|
|
}
|
|
|
|
|
|
|
|
// Reuse common error messages for meta parsing
|
|
|
|
export enum SigitMetaParseErrorType {
|
2024-08-13 17:28:14 +02:00
|
|
|
'PARSE_ERROR_EVENT' = 'error occurred in parsing the create signature event',
|
2024-08-12 14:26:03 +02:00
|
|
|
'PARSE_ERROR_SIGNATURE_EVENT_CONTENT' = "err in parsing the createSignature event's content"
|
|
|
|
}
|
|
|
|
|
|
|
|
export interface SigitCardDisplayInfo {
|
|
|
|
createdAt?: number
|
|
|
|
title?: string
|
2024-08-13 13:32:32 +02:00
|
|
|
submittedBy?: `npub1${string}`
|
2024-08-12 14:26:03 +02:00
|
|
|
signers: `npub1${string}`[]
|
|
|
|
fileExtensions: string[]
|
|
|
|
signedStatus: SigitStatus
|
2024-08-15 17:48:05 +02:00
|
|
|
isValid: boolean
|
2024-08-12 14:26:03 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2024-08-13 17:28:14 +02:00
|
|
|
* Wrapper for event parser that throws custom SigitMetaParseError with cause and context
|
2024-08-12 14:26:03 +02:00
|
|
|
* @param raw Raw string for parsing
|
|
|
|
* @returns parsed Event
|
|
|
|
*/
|
2024-08-13 17:28:14 +02:00
|
|
|
export const parseNostrEvent = async (raw: string): Promise<Event> => {
|
2024-08-12 14:26:03 +02:00
|
|
|
try {
|
2024-08-13 17:28:14 +02:00
|
|
|
const event = await parseJson<Event>(raw)
|
|
|
|
return event
|
2024-08-12 14:26:03 +02:00
|
|
|
} catch (error) {
|
2024-08-28 09:29:05 +02:00
|
|
|
throw new MetaParseError(SigitMetaParseErrorType.PARSE_ERROR_EVENT, {
|
2024-08-13 17:28:14 +02:00
|
|
|
cause: handleError(error),
|
|
|
|
context: raw
|
|
|
|
})
|
2024-08-12 14:26:03 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Wrapper for event content parser that throws custom SigitMetaParseError with cause and context
|
|
|
|
* @param raw Raw string for parsing
|
|
|
|
* @returns parsed CreateSignatureEventContent
|
|
|
|
*/
|
|
|
|
export const parseCreateSignatureEventContent = async (
|
|
|
|
raw: string
|
|
|
|
): Promise<CreateSignatureEventContent> => {
|
|
|
|
try {
|
|
|
|
const createSignatureEventContent =
|
|
|
|
await parseJson<CreateSignatureEventContent>(raw)
|
|
|
|
return createSignatureEventContent
|
|
|
|
} catch (error) {
|
2024-08-28 09:29:05 +02:00
|
|
|
throw new MetaParseError(
|
2024-08-12 14:26:03 +02:00
|
|
|
SigitMetaParseErrorType.PARSE_ERROR_SIGNATURE_EVENT_CONTENT,
|
|
|
|
{
|
|
|
|
cause: handleError(error),
|
|
|
|
context: raw
|
|
|
|
}
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Extracts only necessary metadata for the card display
|
|
|
|
* @param meta Sigit metadata
|
|
|
|
* @returns SigitCardDisplayInfo
|
|
|
|
*/
|
|
|
|
export const extractSigitCardDisplayInfo = async (meta: Meta) => {
|
|
|
|
if (!meta?.createSignature) return
|
|
|
|
|
|
|
|
const sigitInfo: SigitCardDisplayInfo = {
|
|
|
|
signers: [],
|
|
|
|
fileExtensions: [],
|
2024-08-15 17:48:05 +02:00
|
|
|
signedStatus: SigitStatus.Partial,
|
|
|
|
isValid: false
|
2024-08-12 14:26:03 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
try {
|
2024-08-13 17:28:14 +02:00
|
|
|
const createSignatureEvent = await parseNostrEvent(meta.createSignature)
|
2024-08-12 14:26:03 +02:00
|
|
|
|
2024-08-15 17:48:05 +02:00
|
|
|
sigitInfo.isValid = verifyEvent(createSignatureEvent)
|
|
|
|
|
2024-08-12 14:26:03 +02:00
|
|
|
// created_at in nostr events are stored in seconds
|
2024-08-13 11:52:05 +02:00
|
|
|
sigitInfo.createdAt = fromUnixTimestamp(createSignatureEvent.created_at)
|
2024-08-12 14:26:03 +02:00
|
|
|
|
|
|
|
const createSignatureContent = await parseCreateSignatureEventContent(
|
|
|
|
createSignatureEvent.content
|
|
|
|
)
|
|
|
|
|
|
|
|
const files = Object.keys(createSignatureContent.fileHashes)
|
2024-08-14 18:59:00 +02:00
|
|
|
const { extensions } = extractFileExtensions(files)
|
2024-08-12 14:26:03 +02:00
|
|
|
|
|
|
|
const signedBy = Object.keys(meta.docSignatures) as `npub1${string}`[]
|
|
|
|
const isCompletelySigned = createSignatureContent.signers.every((signer) =>
|
|
|
|
signedBy.includes(signer)
|
|
|
|
)
|
|
|
|
|
|
|
|
sigitInfo.title = createSignatureContent.title
|
2024-08-13 13:32:32 +02:00
|
|
|
sigitInfo.submittedBy = createSignatureEvent.pubkey as `npub1${string}`
|
2024-08-12 14:26:03 +02:00
|
|
|
sigitInfo.signers = createSignatureContent.signers
|
|
|
|
sigitInfo.fileExtensions = extensions
|
|
|
|
|
|
|
|
if (isCompletelySigned) {
|
|
|
|
sigitInfo.signedStatus = SigitStatus.Complete
|
|
|
|
}
|
|
|
|
|
|
|
|
return sigitInfo
|
|
|
|
} catch (error) {
|
2024-08-28 09:29:05 +02:00
|
|
|
if (error instanceof MetaParseError) {
|
2024-08-12 14:26:03 +02:00
|
|
|
toast.error(error.message)
|
|
|
|
console.error(error.name, error.message, error.cause, error.context)
|
|
|
|
} else {
|
|
|
|
console.error('Unexpected error', error)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|