diff --git a/src/components/AppBar/AppBar.tsx b/src/components/AppBar/AppBar.tsx
index 56f5495..b712993 100644
--- a/src/components/AppBar/AppBar.tsx
+++ b/src/components/AppBar/AppBar.tsx
@@ -135,6 +135,12 @@ export const AppBar = () => {
to={appPrivateRoutes.decryptZip}
component={Link}
/>
+
)}
@@ -201,6 +207,18 @@ export const AppBar = () => {
Decrypt Zip
+
+
>
)}
diff --git a/src/pages/home/index.tsx b/src/pages/home/index.tsx
index 2381ec9..85586b5 100644
--- a/src/pages/home/index.tsx
+++ b/src/pages/home/index.tsx
@@ -13,10 +13,8 @@ import {
TextField,
Typography
} from '@mui/material'
-import axios from 'axios'
import JSZip from 'jszip'
import { MuiFileInput } from 'mui-file-input'
-import { EventTemplate } from 'nostr-tools'
import { useEffect, useState } from 'react'
import { useSelector } from 'react-redux'
import { Link } from 'react-router-dom'
@@ -30,10 +28,13 @@ import { ProfileMetadata } from '../../types'
import {
encryptArrayBuffer,
generateEncryptionKey,
- getFileHash,
+ getHash,
pubToHex,
queryNip05,
- shorten
+ sendDM,
+ shorten,
+ signEventForMetaFile,
+ uploadToFileStorage
} from '../../utils'
import styles from './style.module.scss'
@@ -162,7 +163,25 @@ export const HomePage = () => {
const fileHashes: { [key: string]: string } = {}
for (const file of selectedFiles) {
- const hash = await getFileHash(file)
+ const arraybuffer = await file.arrayBuffer().catch((err) => {
+ console.log(
+ `err while getting arrayBuffer of file ${file.name} :>> `,
+ err
+ )
+ toast.error(
+ err.message || `err while getting arrayBuffer of file ${file.name}`
+ )
+ return null
+ })
+
+ if (!arraybuffer) return
+
+ const hash = await getHash(arraybuffer)
+
+ if (!hash) {
+ setIsLoading(false)
+ return
+ }
fileHashes[file.name] = hash
}
@@ -173,20 +192,13 @@ export const HomePage = () => {
zip.file(`files/${file.name}`, file)
})
- const event: EventTemplate = {
- kind: 1,
- tags: [['r', signers[0]]],
- content: JSON.stringify(fileHashes),
- created_at: Math.floor(Date.now() / 1000)
- }
-
setLoadingSpinnerDesc('Signing nostr event')
- const signedEvent = await nostrController.signEvent(event).catch((err) => {
- console.error(err)
- toast.error(err.message || 'Error occurred in signing nostr event')
- setIsLoading(false)
- return null
- })
+ const signedEvent = await signEventForMetaFile(
+ signers[0],
+ fileHashes,
+ nostrController,
+ setIsLoading
+ )
if (!signedEvent) return
@@ -238,7 +250,7 @@ export const HomePage = () => {
const blob = new Blob([encryptedArrayBuffer])
setLoadingSpinnerDesc('Uploading zip file to file storage.')
- const fileUrl = await uploadToFileStorage(blob)
+ const fileUrl = await uploadToFileStorage(blob, nostrController)
.then((url) => {
toast.success('zip file uploaded to file storage')
return url
@@ -251,134 +263,19 @@ export const HomePage = () => {
if (!fileUrl) return
- await sendDMToFirstSigner(fileUrl, encryptionKey, signers[0])
+ setLoadingSpinnerDesc('Sending DM to first signer')
+ await sendDM(
+ fileUrl,
+ encryptionKey,
+ signers[0],
+ nostrController,
+ true,
+ setAuthUrl
+ )
setIsLoading(false)
}
- const uploadToFileStorage = async (blob: Blob) => {
- const unixNow = Math.floor(Date.now() / 1000)
-
- const file = new File([blob], `zipped-${unixNow}.zip`, {
- type: 'application/zip'
- })
-
- const event: EventTemplate = {
- kind: 24242,
- content: 'Authorize Upload',
- created_at: Math.floor(Date.now() / 1000),
- tags: [
- ['t', 'upload'],
- ['expiration', String(unixNow + 60 * 5)],
- ['name', file.name],
- ['size', String(file.size)]
- ]
- }
-
- setLoadingSpinnerDesc('Signing auth event for uploading zip')
- const authEvent = await nostrController.signEvent(event)
-
- // todo: use env variable
- const FILE_STORAGE_URL = 'https://blossom.sigit.io'
-
- const response = await axios.put(`${FILE_STORAGE_URL}/upload`, file, {
- headers: {
- Authorization: 'Nostr ' + btoa(JSON.stringify(authEvent)),
- 'Content-Type': 'application/zip'
- }
- })
-
- return response.data.url as string
- }
-
- const sendDMToFirstSigner = async (
- fileUrl: string,
- encryptionKey: string,
- pubkey: string
- ) => {
- const content = `You have been requested for a signature.\nHere is the url for zip file that you can download.\n
- ${fileUrl}\nHowever this zip file is encrypted and you need to decrypt it using https://app.sigit.io\n Encryption key: ${encryptionKey}`
-
- nostrController.on('nsecbunker-auth', (url) => {
- setAuthUrl(url)
- })
-
- setLoadingSpinnerDesc('encrypting content for DM')
-
- const timeoutPromise = new Promise((_, reject) => {
- setTimeout(() => {
- reject(new Error('Timeout occurred'))
- }, 15000) // timeout duration = 15 sec
- })
-
- const encrypted = await Promise.race([
- nostrController.nip04Encrypt(pubkey, content),
- timeoutPromise
- ])
- .then((res) => {
- return res
- })
- .catch((err) => {
- console.log('err :>> ', err)
- toast.error(
- err.message || 'An error occurred while encrypting DM content'
- )
- return null
- })
- .finally(() => {
- setAuthUrl(undefined)
- })
-
- if (!encrypted) return
-
- const event: EventTemplate = {
- kind: 4,
- content: encrypted,
- created_at: Math.floor(Date.now() / 1000),
- tags: [['p', signers[0]]]
- }
-
- setLoadingSpinnerDesc('signing event for DM')
- const signedEvent = await nostrController.signEvent(event).catch((err) => {
- console.log('err :>> ', err)
- toast.error(err.message || 'An error occurred while signing event for DM')
- return null
- })
-
- if (!signedEvent) return
-
- setLoadingSpinnerDesc('Publishing encrypted DM')
-
- const metadataController = new MetadataController()
- const relaySet = await metadataController
- .findRelayListMetadata(pubkey)
- .catch((err) => {
- toast.error(
- err.message || 'An error occurred while finding relay list metadata'
- )
- return null
- })
-
- if (!relaySet) return
-
- // NOTE: according to Nip65
- // DMs SHOULD only be broadcasted to the author's WRITE relays and to the receiver's READ relays to keep maximum privacy.
- if (relaySet.read.length === 0) {
- toast.error('No relay found for publishing encrypted DM')
- }
-
- await nostrController
- .publishEvent(signedEvent, relaySet.read)
- .then((relays) => {
- toast.success(`Encrypted DM sent on: ${relays.join('\n')}`)
- })
- .catch((err) => {
- console.log('err :>> ', err)
- toast.error(err.message || 'An error occurred while publishing DM')
- return null
- })
- }
-
if (authUrl) {
return (