feat(renotifications): can re-notify users on the signing page

This commit is contained in:
eugene 2024-09-02 15:41:09 +03:00
parent 9cefdad3fc
commit 89f6cd1dbe
3 changed files with 108 additions and 71 deletions

View File

@ -46,9 +46,7 @@ import {
shorten, shorten,
signEventForMetaFile, signEventForMetaFile,
updateUsersAppData, updateUsersAppData,
uploadToFileStorage, uploadToFileStorage
isPromiseFulfilled,
isPromiseRejected
} from '../../utils' } from '../../utils'
import { Container } from '../../components/Container' import { Container } from '../../components/Container'
import styles from './style.module.scss' import styles from './style.module.scss'
@ -86,6 +84,7 @@ import {
faUpload faUpload
} from '@fortawesome/free-solid-svg-icons' } from '@fortawesome/free-solid-svg-icons'
import { SigitFile } from '../../utils/file.ts' import { SigitFile } from '../../utils/file.ts'
import { checkNotifications } from '../../utils/notifications.ts'
export const CreatePage = () => { export const CreatePage = () => {
const navigate = useNavigate() const navigate = useNavigate()
@ -787,14 +786,7 @@ export const CreatePage = () => {
setLoadingSpinnerDesc('Sending notifications to counterparties') setLoadingSpinnerDesc('Sending notifications to counterparties')
const notifications = await Promise.allSettled(sendNotifications(meta)) const notifications = await Promise.allSettled(sendNotifications(meta))
if (notifications.every(isPromiseFulfilled)) { checkNotifications(notifications)
toast.success('Notifications sent successfully')
} else {
logRejectedNotifications(notifications)
toast.error(
'Some notifications failed to publish. Please rebroadcast them again.'
)
}
navigate(appPrivateRoutes.sign, { state: { meta: meta } }) navigate(appPrivateRoutes.sign, { state: { meta: meta } })
} else { } else {
const zip = new JSZip() const zip = new JSZip()
@ -850,15 +842,6 @@ export const CreatePage = () => {
} }
} }
const logRejectedNotifications = (
notifications: PromiseSettledResult<string[]>[]
) => {
notifications
.filter(isPromiseRejected)
.map((res: PromiseRejectedResult) => (res.reason as Error).message)
.forEach((message: string) => console.log(message))
}
const onDrawFieldsChange = (sigitFiles: SigitFile[]) => { const onDrawFieldsChange = (sigitFiles: SigitFile[]) => {
setDrawnFiles(sigitFiles) setDrawnFiles(sigitFiles)
} }

View File

@ -53,6 +53,7 @@ import {
SigitFile SigitFile
} from '../../utils/file.ts' } from '../../utils/file.ts'
import { ARRAY_BUFFER, DEFLATE } from '../../utils/const.ts' import { ARRAY_BUFFER, DEFLATE } from '../../utils/const.ts'
import { checkNotifications } from '../../utils/notifications.ts'
enum SignedStatus { enum SignedStatus {
Fully_Signed, Fully_Signed,
User_Is_Next_Signer, User_Is_Next_Signer,
@ -663,59 +664,22 @@ export const SignPage = () => {
// Handle the online flow: update users app data and send notifications // Handle the online flow: update users app data and send notifications
const handleOnlineFlow = async (meta: Meta) => { const handleOnlineFlow = async (meta: Meta) => {
setLoadingSpinnerDesc('Updating users app data') try {
const updatedEvent = await updateUsersAppData(meta) setLoadingSpinnerDesc('Updating users app data')
if (!updatedEvent) { const updatedEvent = await updateUsersAppData(meta)
if (!updatedEvent) {
throw new Error('There was an error updating user app data.')
}
setLoadingSpinnerDesc('Sending notifications')
const notifications = await notifyUsers(meta)
checkNotifications(notifications)
} catch (error) {
console.error(error)
toast.error('There was an error finalising signatures.')
} finally {
setIsLoading(false) setIsLoading(false)
return
} }
const userSet = new Set<`npub1${string}`>()
if (submittedBy && submittedBy !== usersPubkey) {
userSet.add(hexToNpub(submittedBy))
}
const usersNpub = hexToNpub(usersPubkey!)
const isLastSigner = checkIsLastSigner(signers)
if (isLastSigner) {
signers.forEach((signer) => {
if (signer !== usersNpub) {
userSet.add(signer)
}
})
viewers.forEach((viewer) => {
userSet.add(viewer)
})
} else {
const currentSignerIndex = signers.indexOf(usersNpub)
const prevSigners = signers.slice(0, currentSignerIndex)
prevSigners.forEach((signer) => {
userSet.add(signer)
})
const nextSigner = signers[currentSignerIndex + 1]
userSet.add(nextSigner)
}
setLoadingSpinnerDesc('Sending notifications')
const users = Array.from(userSet)
console.log('users: ', users)
const publishedRelays = await Promise.all(
users.map(async (user) => sendNotification(npubToHex(user)!, meta))
)
console.log('published relays: ', publishedRelays)
// await Promise.all(promises)
// .then(() => {
// toast.success('Notifications sent successfully')
// setMeta(meta)
// })
// .catch(() => {
// toast.error('Failed to publish notifications')
// })
setIsLoading(false)
} }
// Check if the current user is the last signer // Check if the current user is the last signer
@ -873,6 +837,64 @@ export const SignPage = () => {
} }
} }
const getUsersToNotify = (): `npub1${string}`[] => {
const userSet = new Set<`npub1${string}`>()
if (submittedBy && submittedBy !== usersPubkey) {
userSet.add(hexToNpub(submittedBy))
}
const usersNpub = hexToNpub(usersPubkey!)
const isLastSigner = checkIsLastSigner(signers)
if (isLastSigner) {
signers.forEach((signer) => {
if (signer !== usersNpub) {
userSet.add(signer)
}
})
viewers.forEach((viewer) => userSet.add(viewer))
} else {
const currentSignerIndex = signers.indexOf(usersNpub)
const prevSigners = signers.slice(0, currentSignerIndex)
prevSigners.forEach((signer) => {
userSet.add(signer)
})
const nextSigner = signers[currentSignerIndex + 1]
userSet.add(nextSigner)
}
return Array.from(userSet)
}
const notifyUsers = async (meta: Meta) => {
try {
const usersToNotify = getUsersToNotify()
return await Promise.allSettled(
usersToNotify.map(async (user) =>
sendNotification(npubToHex(user)!, meta)
)
)
} catch (error) {
throw new Error('There was a problem sending notifications to users', {
cause: error
})
}
}
const handleRenotifyUsers = async () => {
try {
setIsLoading(true)
const notifications = await notifyUsers(meta!)
checkNotifications(notifications)
} catch (error) {
console.error(error)
toast.error('There was an error re-notifying users')
} finally {
setIsLoading(false)
}
}
if (authUrl) { if (authUrl) {
return ( return (
<iframe <iframe
@ -969,6 +991,12 @@ export const SignPage = () => {
</Button> </Button>
</Box> </Box>
)} )}
<Box sx={{ mt: 1, display: 'flex', justifyContent: 'center' }}>
<Button onClick={handleRenotifyUsers} variant="contained">
Re-notify Next Signer
</Button>
</Box>
</> </>
)} )}
</Container> </Container>

View File

@ -0,0 +1,26 @@
import { isPromiseFulfilled, isPromiseRejected } from './utils.ts'
import { toast } from 'react-toastify'
const checkNotifications = (
notifications: PromiseSettledResult<string[]>[]
) => {
if (notifications.every(isPromiseFulfilled)) {
toast.success('Notifications sent successfully')
} else {
logRejectedNotifications(notifications)
toast.error(
'Some notifications failed to publish. Please rebroadcast them again.'
)
}
}
const logRejectedNotifications = (
notifications: PromiseSettledResult<string[]>[]
) => {
notifications
.filter(isPromiseRejected)
.map((res: PromiseRejectedResult) => (res.reason as Error).message)
.forEach((message: string) => console.log(message))
}
export { checkNotifications }