diff --git a/src/pages/create/index.tsx b/src/pages/create/index.tsx index 0e9b1ec..7b04b01 100644 --- a/src/pages/create/index.tsx +++ b/src/pages/create/index.tsx @@ -20,7 +20,7 @@ import { CreateSignatureEventContent, Meta, ProfileMetadata, - Timestamp, + SignedEvent, User, UserRole } from '../../types' @@ -62,7 +62,7 @@ import { faUpload } from '@fortawesome/free-solid-svg-icons' import { SigitFile } from '../../utils/file.ts' -import { generateTimestamps } from '../../utils/opentimestamps.ts' +import { generateTimestamp } from '../../utils/opentimestamps.ts' export const CreatePage = () => { const navigate = useNavigate() @@ -560,8 +560,7 @@ export const CreatePage = () => { fileHashes: { [key: string]: string }, - zipUrl: string, - timestamps?: Timestamp[] + zipUrl: string ) => { const content: CreateSignatureEventContent = { signers: signers.map((signer) => hexToNpub(signer.pubkey)), @@ -569,8 +568,7 @@ export const CreatePage = () => { fileHashes, markConfig, zipUrl, - title, - ...(timestamps && { timestamps }) + title } setLoadingSpinnerDesc('Signing nostr event for create signature') @@ -602,6 +600,11 @@ export const CreatePage = () => { return receivers.map((receiver) => sendNotification(receiver, meta)) } + const extractNostrId = (stringifiedEvent: string): string => { + const e = JSON.parse(stringifiedEvent) as SignedEvent + return e.id + } + const handleCreate = async () => { try { if (!validateInputs()) return @@ -611,10 +614,6 @@ export const CreatePage = () => { const fileHashes = await generateFileHashes() if (!fileHashes) return - setLoadingSpinnerDesc('Timestamping your files') - const timestamps = await generateTimestamps(Object.values(fileHashes)) - if (!timestamps) return - setLoadingSpinnerDesc('Generating encryption key') const encryptionKey = await generateEncryptionKey() @@ -639,8 +638,7 @@ export const CreatePage = () => { const createSignature = await generateCreateSignature( markConfig, fileHashes, - fileUrl, - timestamps + fileUrl ) if (!createSignature) return @@ -656,6 +654,10 @@ export const CreatePage = () => { const keys = await generateKeys(pubkeys, encryptionKey) if (!keys) return + const timestamp = await generateTimestamp( + extractNostrId(createSignature) + ) + const meta: Meta = { createSignature, keys, @@ -663,6 +665,10 @@ export const CreatePage = () => { docSignatures: {} } + if (timestamp) { + meta.timestamps = [timestamp] + } + setLoadingSpinnerDesc('Updating user app data') const event = await updateUsersAppData(meta) if (!event) return diff --git a/src/types/core.ts b/src/types/core.ts index b4cd18c..5d4e4ac 100644 --- a/src/types/core.ts +++ b/src/types/core.ts @@ -18,6 +18,7 @@ export interface Meta { docSignatures: { [key: `npub1${string}`]: string } exportSignature?: string keys?: { sender: string; keys: { [user: `npub1${string}`]: string } } + timestamps?: Timestamp[] } export interface CreateSignatureEventContent { @@ -27,13 +28,11 @@ export interface CreateSignatureEventContent { markConfig: Mark[] title: string zipUrl: string - timestamps?: Timestamp[] } export interface SignedEventContent { prevSig: string marks: Mark[] - timestamps: Timestamp[] } export interface Sigit { @@ -42,7 +41,7 @@ export interface Sigit { } export interface Timestamp { - fileHash: string + nostrId: string timestamp: string } diff --git a/src/utils/opentimestamps.ts b/src/utils/opentimestamps.ts index 9a6a583..3d6bb78 100644 --- a/src/utils/opentimestamps.ts +++ b/src/utils/opentimestamps.ts @@ -1,28 +1,26 @@ import { Timestamp } from '../types' -import { isPromiseFulfilled } from './utils.ts' -import { retryAll } from './retry.ts' +import { retry } from './retry.ts' import { bytesToHex, hexToBytes } from '@noble/hashes/utils' /** - * Generates a timestamp for the provided document hashes. - * @returns Timestamp in a hex string format + * Generates a timestamp for the provided nostr event ID. + * @returns Timestamp with its value and the nostr event ID. */ -export const generateTimestamps = async ( - fileHashes: string[] -): Promise => { - const promises = fileHashes.map((fileHash) => () => timestamp(fileHash)) - const resolvedPromises = await retryAll(promises) - if (resolvedPromises.every(isPromiseFulfilled)) { - return resolvedPromises.map(({ value }, index) => { - return { - fileHash: fileHashes[index], - timestamp: value - } - }) +export const generateTimestamp = async ( + nostrId: string +): Promise => { + try { + return { + timestamp: await retry(() => timestamp(nostrId)), + nostrId: nostrId + } + } catch (error) { + console.error(error) + return } } -const timestamp = async (hash: string) => { +const timestamp = async (hash: string): Promise => { const detachedTimestamp = window.OpenTimestamps.DetachedTimestampFile.fromHash( new window.OpenTimestamps.Ops.OpSHA256(),