chore: remove dvm utils file and use useDvm hook instead
This commit is contained in:
parent
3615de70ad
commit
0ea6ba0033
@ -193,70 +193,6 @@ export class RelayController {
|
||||
return events[0] || null
|
||||
}
|
||||
|
||||
/**
|
||||
* Subscribes to events from multiple relays.
|
||||
*
|
||||
* This method connects to the specified relay URLs and subscribes to events
|
||||
* using the provided filter. It handles incoming events through the given
|
||||
* `eventHandler` callback and manages the subscription lifecycle.
|
||||
*
|
||||
* @param filter - The filter criteria to apply when subscribing to events.
|
||||
* @param relayUrls - An optional array of relay URLs to connect to. The default relay URL (`SIGIT_RELAY`) is added automatically.
|
||||
* @param eventHandler - A callback function to handle incoming events. It receives an `Event` object.
|
||||
*
|
||||
*/
|
||||
subscribeForEvents = async (
|
||||
filter: Filter,
|
||||
relayUrls: string[] = [],
|
||||
eventHandler: (event: Event) => void
|
||||
) => {
|
||||
if (!relayUrls.includes(SIGIT_RELAY)) {
|
||||
/**
|
||||
* NOTE: To avoid side-effects on external relayUrls array passed as argument
|
||||
* re-assigned relayUrls with added sigit relay instead of just appending to same array
|
||||
*/
|
||||
relayUrls = [...relayUrls, SIGIT_RELAY] // Add app relay to relays array if not exists already
|
||||
}
|
||||
|
||||
// connect to all specified relays
|
||||
const relays = await settleAllFullfilfedPromises(
|
||||
relayUrls,
|
||||
this.connectRelay
|
||||
)
|
||||
|
||||
// Check if any relays are connected
|
||||
if (relays.length === 0) {
|
||||
throw new Error('No relay is connected to fetch events!')
|
||||
}
|
||||
|
||||
const processedEvents: string[] = [] // To keep track of processed events
|
||||
|
||||
// Create a promise for each relay subscription
|
||||
const subPromises = relays.map((relay) => {
|
||||
return new Promise<void>((resolve) => {
|
||||
// Subscribe to the relay with the specified filter
|
||||
const sub = relay.subscribe([filter], {
|
||||
// Handle incoming events
|
||||
onevent: (e) => {
|
||||
// Process event only if it hasn't been processed before
|
||||
if (!processedEvents.includes(e.id)) {
|
||||
processedEvents.push(e.id)
|
||||
eventHandler(e) // Call the event handler with the event
|
||||
}
|
||||
},
|
||||
// Handle the End-Of-Stream (EOSE) message
|
||||
oneose: () => {
|
||||
sub.close() // Close the subscription
|
||||
resolve() // Resolve the promise when EOSE is received
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
// Wait for all subscriptions to complete
|
||||
await Promise.allSettled(subPromises)
|
||||
}
|
||||
|
||||
publish = async (
|
||||
event: Event,
|
||||
relayUrls: string[] = []
|
||||
|
@ -13,15 +13,17 @@ import {
|
||||
createAndSaveAuthToken,
|
||||
getAuthToken,
|
||||
getEmptyMetadataEvent,
|
||||
getRelayMap,
|
||||
getRelayMapFromNDKRelayList,
|
||||
unixNow
|
||||
} from '../utils'
|
||||
import { useAppDispatch, useAppSelector } from './store'
|
||||
import { useNDKContext } from './useNDKContext'
|
||||
import { useDvm } from './useDvm'
|
||||
|
||||
export const useAuth = () => {
|
||||
const dispatch = useAppDispatch()
|
||||
const { findMetadata } = useNDKContext()
|
||||
const { getRelayInfo } = useDvm()
|
||||
const { findMetadata, getNDKRelayList } = useNDKContext()
|
||||
|
||||
const { auth: authState, relays: relaysState } = useAppSelector(
|
||||
(state) => state
|
||||
@ -101,23 +103,32 @@ export const useAuth = () => {
|
||||
})
|
||||
)
|
||||
|
||||
const relayMap = await getRelayMap(pubkey)
|
||||
const ndkRelayList = await getNDKRelayList(pubkey)
|
||||
const relays = ndkRelayList.relays
|
||||
|
||||
if (Object.keys(relayMap).length < 1) {
|
||||
if (relays.length < 1) {
|
||||
// Navigate user to relays page if relay map is empty
|
||||
return appPrivateRoutes.relays
|
||||
}
|
||||
|
||||
if (
|
||||
authState.loggedIn &&
|
||||
!compareObjects(relaysState?.map, relayMap.map)
|
||||
) {
|
||||
dispatch(setRelayMapAction(relayMap.map))
|
||||
getRelayInfo(relays)
|
||||
|
||||
const relayMap = getRelayMapFromNDKRelayList(ndkRelayList)
|
||||
|
||||
if (authState.loggedIn && !compareObjects(relaysState?.map, relayMap)) {
|
||||
dispatch(setRelayMapAction(relayMap))
|
||||
}
|
||||
|
||||
return appPrivateRoutes.homePage
|
||||
},
|
||||
[dispatch, findMetadata, authState, relaysState]
|
||||
[
|
||||
dispatch,
|
||||
findMetadata,
|
||||
getNDKRelayList,
|
||||
getRelayInfo,
|
||||
authState,
|
||||
relaysState
|
||||
]
|
||||
)
|
||||
|
||||
return {
|
||||
|
@ -1,98 +0,0 @@
|
||||
import NDK, { NDKEvent, NDKSubscription } from '@nostr-dev-kit/ndk'
|
||||
import { EventTemplate } from 'nostr-tools'
|
||||
import { compareObjects, unixNow } from '.'
|
||||
import { NostrController, relayController } from '../controllers'
|
||||
import { setRelayInfoAction } from '../store/actions'
|
||||
import store from '../store/store'
|
||||
import { RelayInfoObject } from '../types'
|
||||
|
||||
/**
|
||||
* Sets information about relays into relays.info app state.
|
||||
* @param relayURIs - relay URIs to get information about
|
||||
*/
|
||||
export 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)
|
||||
|
||||
const relays = [
|
||||
'wss://relay.damus.io',
|
||||
'wss://relay.primal.net',
|
||||
'wss://relayable.org'
|
||||
]
|
||||
|
||||
// publish job request
|
||||
await relayController.publish(jobSignedEvent, relays)
|
||||
|
||||
console.log('jobSignedEvent :>> ', jobSignedEvent)
|
||||
|
||||
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))
|
||||
})
|
||||
}
|
||||
|
||||
const dvmNDK = new NDK({
|
||||
explicitRelayUrls: relays
|
||||
})
|
||||
|
||||
await dvmNDK.connect(2000)
|
||||
|
||||
// filter for getting DVM job's result
|
||||
const sub = dvmNDK.subscribe({
|
||||
kinds: [68002 as number],
|
||||
'#e': [jobSignedEvent.id],
|
||||
'#p': [jobSignedEvent.pubkey]
|
||||
})
|
||||
|
||||
// asynchronously get block number 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 relaysInfo: RelayInfoObject
|
||||
|
||||
try {
|
||||
relaysInfo = JSON.parse(dvmJobResult)
|
||||
} catch (error) {
|
||||
return Promise.reject(`Invalid relay(s) information.`)
|
||||
}
|
||||
|
||||
if (
|
||||
relaysInfo &&
|
||||
!compareObjects(store.getState().relays?.info, relaysInfo)
|
||||
) {
|
||||
store.dispatch(setRelayInfoAction(relaysInfo))
|
||||
}
|
||||
}
|
@ -1,172 +1,43 @@
|
||||
import { Event, Filter, kinds, UnsignedEvent } from 'nostr-tools'
|
||||
import { RelayList } from 'nostr-tools/kinds'
|
||||
import { getRelayInfo, unixNow } from '.'
|
||||
import { NostrController, relayController } from '../controllers'
|
||||
import { localCache } from '../services'
|
||||
import { RelayMap, RelaySet } from '../types'
|
||||
import {
|
||||
DEFAULT_LOOK_UP_RELAY_LIST,
|
||||
ONE_DAY_IN_MS,
|
||||
ONE_WEEK_IN_MS,
|
||||
SIGIT_RELAY
|
||||
} from './const'
|
||||
import NDK, { NDKEvent } from '@nostr-dev-kit/ndk'
|
||||
import NDK, { NDKEvent, NDKRelayList } from '@nostr-dev-kit/ndk'
|
||||
import { kinds, UnsignedEvent } from 'nostr-tools'
|
||||
import { normalizeWebSocketURL, unixNow } from '.'
|
||||
import { NostrController } from '../controllers'
|
||||
import { RelayMap } from '../types'
|
||||
import { SIGIT_RELAY } from './const'
|
||||
|
||||
const READ_MARKER = 'read'
|
||||
const WRITE_MARKER = 'write'
|
||||
export const getRelayMapFromNDKRelayList = (ndkRelayList: NDKRelayList) => {
|
||||
const relayMap: RelayMap = {}
|
||||
|
||||
/**
|
||||
* Attempts to find a relay list from the provided lookUpRelays.
|
||||
* If the relay list is found, it will be added to the user relay list metadata.
|
||||
* @param lookUpRelays
|
||||
* @param hexKey
|
||||
* @return found relay list or null
|
||||
*/
|
||||
const findRelayListAndUpdateCache = async (
|
||||
lookUpRelays: string[],
|
||||
hexKey: string
|
||||
): Promise<Event | null> => {
|
||||
try {
|
||||
const eventFilter: Filter = {
|
||||
kinds: [RelayList],
|
||||
authors: [hexKey]
|
||||
ndkRelayList.readRelayUrls.forEach((relayUrl) => {
|
||||
const normalizedUrl = normalizeWebSocketURL(relayUrl)
|
||||
|
||||
relayMap[normalizedUrl] = {
|
||||
read: true,
|
||||
write: false
|
||||
}
|
||||
})
|
||||
|
||||
const event = await relayController.fetchEvent(eventFilter, lookUpRelays)
|
||||
if (event) {
|
||||
await localCache.addUserRelayListMetadata(event)
|
||||
ndkRelayList.writeRelayUrls.forEach((relayUrl) => {
|
||||
const normalizedUrl = normalizeWebSocketURL(relayUrl)
|
||||
|
||||
const existing = relayMap[normalizedUrl]
|
||||
if (existing) {
|
||||
existing.write = true
|
||||
} else {
|
||||
relayMap[normalizedUrl] = {
|
||||
read: false,
|
||||
write: true
|
||||
}
|
||||
}
|
||||
return event
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
return null
|
||||
}
|
||||
})
|
||||
|
||||
return relayMap
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to find a relay list in cache. If it is present, it will check that the cached event is not
|
||||
* older than one week.
|
||||
* @param hexKey
|
||||
* @return RelayList event if it's not older than a week; otherwise null
|
||||
*/
|
||||
const findRelayListInCache = async (hexKey: string): Promise<Event | null> => {
|
||||
try {
|
||||
// Attempt to retrieve the metadata event from the local cache
|
||||
const cachedRelayListMetadataEvent =
|
||||
await localCache.getUserRelayListMetadata(hexKey)
|
||||
|
||||
// Check if the cached event is not older than one week
|
||||
if (
|
||||
cachedRelayListMetadataEvent &&
|
||||
!isOlderThanOneWeek(cachedRelayListMetadataEvent.cachedAt)
|
||||
) {
|
||||
return cachedRelayListMetadataEvent.event
|
||||
}
|
||||
|
||||
return null
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms a list of relay tags from a Nostr Event to a RelaySet.
|
||||
* @param tags
|
||||
*/
|
||||
const getUserRelaySet = (tags: string[][]): RelaySet => {
|
||||
return tags
|
||||
.filter(isRelayTag)
|
||||
.reduce<RelaySet>(toRelaySet, getDefaultRelaySet())
|
||||
}
|
||||
|
||||
const getDefaultRelaySet = (): RelaySet => ({
|
||||
read: [SIGIT_RELAY],
|
||||
write: [SIGIT_RELAY]
|
||||
})
|
||||
|
||||
const getDefaultRelayMap = (): RelayMap => ({
|
||||
export const getDefaultRelayMap = (): RelayMap => ({
|
||||
[SIGIT_RELAY]: { write: true, read: true }
|
||||
})
|
||||
|
||||
const isOlderThanOneWeek = (cachedAt: number) => {
|
||||
return Date.now() - cachedAt > ONE_WEEK_IN_MS
|
||||
}
|
||||
|
||||
const isOlderThanOneDay = (cachedAt: number) => {
|
||||
return Date.now() - cachedAt > ONE_DAY_IN_MS
|
||||
}
|
||||
|
||||
const isRelayTag = (tag: string[]): boolean => tag[0] === 'r'
|
||||
|
||||
const toRelaySet = (obj: RelaySet, tag: string[]): RelaySet => {
|
||||
if (tag.length >= 3) {
|
||||
const marker = tag[2]
|
||||
|
||||
if (marker === READ_MARKER) {
|
||||
obj.read.push(tag[1])
|
||||
} else if (marker === WRITE_MARKER) {
|
||||
obj.write.push(tag[1])
|
||||
}
|
||||
}
|
||||
if (tag.length === 2) {
|
||||
obj.read.push(tag[1])
|
||||
obj.write.push(tag[1])
|
||||
}
|
||||
|
||||
return obj
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides relay map.
|
||||
* @param npub - user's npub
|
||||
* @returns - promise that resolves into relay map and a timestamp when it has been updated.
|
||||
*/
|
||||
const getRelayMap = async (
|
||||
npub: string
|
||||
): Promise<{ map: RelayMap; mapUpdated?: number }> => {
|
||||
// More info about this kind of event available https://github.com/nostr-protocol/nips/blob/master/65.md
|
||||
const eventFilter: Filter = {
|
||||
kinds: [kinds.RelayList],
|
||||
authors: [npub]
|
||||
}
|
||||
|
||||
const event = await relayController
|
||||
.fetchEvent(eventFilter, DEFAULT_LOOK_UP_RELAY_LIST)
|
||||
.catch((err) => {
|
||||
return Promise.reject(err)
|
||||
})
|
||||
|
||||
if (event) {
|
||||
// Handle founded 10002 event
|
||||
const relaysMap: RelayMap = {}
|
||||
|
||||
// 'r' stands for 'relay'
|
||||
const relayTags = event.tags.filter((tag) => tag[0] === 'r')
|
||||
|
||||
relayTags.forEach((tag) => {
|
||||
const uri = tag[1]
|
||||
const relayType = tag[2]
|
||||
|
||||
// if 3rd element of relay tag is undefined, relay is WRITE and READ
|
||||
relaysMap[uri] = {
|
||||
write: relayType ? relayType === 'write' : true,
|
||||
read: relayType ? relayType === 'read' : true
|
||||
}
|
||||
})
|
||||
|
||||
Object.keys(relaysMap).forEach((relayUrl) =>
|
||||
relayController.connectRelay(relayUrl)
|
||||
)
|
||||
|
||||
getRelayInfo(Object.keys(relaysMap))
|
||||
|
||||
return Promise.resolve({ map: relaysMap, mapUpdated: event.created_at })
|
||||
} else {
|
||||
return Promise.resolve({ map: getDefaultRelayMap() })
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Publishes relay map.
|
||||
* @param relayMap - relay map.
|
||||
@ -174,7 +45,7 @@ const getRelayMap = async (
|
||||
* @param extraRelaysToPublish - optional relays to publish relay map.
|
||||
* @returns - promise that resolves into a string representing publishing result.
|
||||
*/
|
||||
const publishRelayMap = async (
|
||||
export const publishRelayMap = async (
|
||||
relayMap: RelayMap,
|
||||
npub: string,
|
||||
ndk: NDK,
|
||||
@ -218,15 +89,3 @@ const publishRelayMap = async (
|
||||
|
||||
return Promise.reject('Publishing updated relay map was unsuccessful.')
|
||||
}
|
||||
|
||||
export {
|
||||
findRelayListAndUpdateCache,
|
||||
findRelayListInCache,
|
||||
getDefaultRelayMap,
|
||||
getDefaultRelaySet,
|
||||
getRelayMap,
|
||||
getUserRelaySet,
|
||||
isOlderThanOneDay,
|
||||
isOlderThanOneWeek,
|
||||
publishRelayMap
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user