99 lines
2.9 KiB
TypeScript
99 lines
2.9 KiB
TypeScript
import { NDKEvent, NDKSubscription } from '@nostr-dev-kit/ndk'
|
|
import { EventTemplate } from 'nostr-tools'
|
|
import { NostrController } from '../controllers'
|
|
import { setRelayInfoAction } from '../store/actions'
|
|
import { RelayInfoObject } from '../types'
|
|
import { compareObjects, unixNow } from '../utils'
|
|
import { useAppDispatch, useAppSelector } from './store'
|
|
import { useNDKContext } from './useNDKContext'
|
|
|
|
export const useDvm = () => {
|
|
const dvmRelays = [
|
|
'wss://relay.damus.io',
|
|
'wss://relay.primal.net',
|
|
'wss://relayable.org'
|
|
]
|
|
|
|
const relayInfo = useAppSelector((state) => state.relays.info)
|
|
|
|
const { ndk, publish } = useNDKContext()
|
|
const dispatch = useAppDispatch()
|
|
|
|
/**
|
|
* Sets information about relays into relays.info app state.
|
|
* @param relayURIs - relay URIs to get information about
|
|
*/
|
|
const getRelayInfo = async (relayURIs: string[]) => {
|
|
// initialize job request
|
|
const jobEventTemplate: EventTemplate = {
|
|
content: '',
|
|
created_at: unixNow(),
|
|
kind: 68001,
|
|
tags: [
|
|
['i', `${JSON.stringify(relayURIs)}`],
|
|
['j', 'relay-info']
|
|
]
|
|
}
|
|
|
|
const nostrController = NostrController.getInstance()
|
|
|
|
// sign job request event
|
|
const jobSignedEvent = await nostrController.signEvent(jobEventTemplate)
|
|
|
|
// publish job request
|
|
const ndkEvent = new NDKEvent(ndk, jobSignedEvent)
|
|
await publish(ndkEvent, dvmRelays)
|
|
|
|
const subscribeWithTimeout = (
|
|
subscription: NDKSubscription,
|
|
timeoutMs: number
|
|
): Promise<string> => {
|
|
return new Promise((resolve, reject) => {
|
|
const eventHandler = (event: NDKEvent) => {
|
|
subscription.stop()
|
|
resolve(event.content)
|
|
}
|
|
|
|
subscription.on('event', eventHandler)
|
|
|
|
// Set up a timeout to stop the subscription after a specified time
|
|
const timeout = setTimeout(() => {
|
|
subscription.stop() // Stop the subscription
|
|
reject(new Error('Subscription timed out')) // Reject the promise with a timeout error
|
|
}, timeoutMs)
|
|
|
|
// Handle subscription close event
|
|
subscription.on('close', () => clearTimeout(timeout))
|
|
})
|
|
}
|
|
|
|
// filter for getting DVM job's result
|
|
const sub = ndk.subscribe({
|
|
kinds: [68002 as number],
|
|
'#e': [jobSignedEvent.id],
|
|
'#p': [jobSignedEvent.pubkey]
|
|
})
|
|
|
|
// asynchronously get relay info from dvm job with 20 seconds timeout
|
|
const dvmJobResult = await subscribeWithTimeout(sub, 20000)
|
|
|
|
if (!dvmJobResult) {
|
|
return Promise.reject(`Relay(s) information wasn't received`)
|
|
}
|
|
|
|
let newRelaysInfo: RelayInfoObject
|
|
|
|
try {
|
|
newRelaysInfo = JSON.parse(dvmJobResult)
|
|
} catch (error) {
|
|
return Promise.reject(`Invalid relay(s) information.`)
|
|
}
|
|
|
|
if (newRelaysInfo && !compareObjects(relayInfo, newRelaysInfo)) {
|
|
dispatch(setRelayInfoAction(newRelaysInfo))
|
|
}
|
|
}
|
|
|
|
return { getRelayInfo }
|
|
}
|