fix: use relays from nip65 for broadcasting DMs
All checks were successful
Release / build_and_release (push) Successful in 57s
All checks were successful
Release / build_and_release (push) Successful in 57s
This commit is contained in:
parent
f4c26945c1
commit
349e26b628
@ -7,7 +7,7 @@ import {
|
||||
verifyEvent,
|
||||
Event
|
||||
} from 'nostr-tools'
|
||||
import { ProfileMetadata } from '../types'
|
||||
import { ProfileMetadata, RelaySet } from '../types'
|
||||
import { NostrController } from '.'
|
||||
import { toast } from 'react-toastify'
|
||||
|
||||
@ -64,6 +64,66 @@ export class MetadataController {
|
||||
throw new Error('Mo metadata found.')
|
||||
}
|
||||
|
||||
public findRelayListMetadata = async (hexKey: string) => {
|
||||
const eventFilter: Filter = {
|
||||
kinds: [kinds.RelayList],
|
||||
authors: [hexKey]
|
||||
}
|
||||
|
||||
const pool = new SimplePool()
|
||||
|
||||
let relayEvent = await pool
|
||||
.get([this.specialMetadataRelay], eventFilter)
|
||||
.catch((err) => {
|
||||
console.error(err)
|
||||
return null
|
||||
})
|
||||
|
||||
if (!relayEvent) {
|
||||
const mostPopularRelays = import.meta.env.VITE_MOST_POPULAR_RELAYS
|
||||
const hardcodedPopularRelays = (mostPopularRelays || '').split(' ')
|
||||
const relays = [...hardcodedPopularRelays]
|
||||
|
||||
relayEvent = await pool.get(relays, eventFilter).catch((err) => {
|
||||
console.error(err)
|
||||
return null
|
||||
})
|
||||
}
|
||||
|
||||
if (relayEvent) {
|
||||
const relaySet: RelaySet = {
|
||||
read: [],
|
||||
write: []
|
||||
}
|
||||
|
||||
// a list of r tags with relay URIs and a read or write marker.
|
||||
const relayTags = relayEvent.tags.filter((tag) => tag[0] === 'r')
|
||||
|
||||
// Relays marked as read / write are called READ / WRITE relays, respectively
|
||||
relayTags.forEach((tag) => {
|
||||
if (tag.length >= 3) {
|
||||
const marker = tag[2]
|
||||
|
||||
if (marker === 'read') {
|
||||
relaySet.read.push(tag[1])
|
||||
} else if (marker === 'write') {
|
||||
relaySet.write.push(tag[1])
|
||||
}
|
||||
}
|
||||
|
||||
// If the marker is omitted, the relay is used for both purposes
|
||||
if (tag.length === 2) {
|
||||
relaySet.read.push(tag[1])
|
||||
relaySet.write.push(tag[1])
|
||||
}
|
||||
})
|
||||
|
||||
return relaySet
|
||||
}
|
||||
|
||||
throw new Error('No relay list metadata found.')
|
||||
}
|
||||
|
||||
public extractProfileMetadataContent = (event: VerifiedEvent) => {
|
||||
try {
|
||||
return JSON.parse(event.content) as ProfileMetadata
|
||||
@ -94,9 +154,9 @@ export class MetadataController {
|
||||
}
|
||||
|
||||
await this.nostrController
|
||||
.publishEvent(signedMetadataEvent, this.specialMetadataRelay)
|
||||
.then((res) => {
|
||||
toast.success(`Metadata: ${res}`)
|
||||
.publishEvent(signedMetadataEvent, [this.specialMetadataRelay])
|
||||
.then((relays) => {
|
||||
toast.success(`Metadata event published on: ${relays.join('\n')}`)
|
||||
})
|
||||
.catch((err) => {
|
||||
toast.error(err.message)
|
||||
|
@ -1,4 +1,3 @@
|
||||
import { EventEmitter } from 'tseep'
|
||||
import NDK, {
|
||||
NDKEvent,
|
||||
NDKNip46Signer,
|
||||
@ -9,12 +8,13 @@ import NDK, {
|
||||
import {
|
||||
Event,
|
||||
EventTemplate,
|
||||
Relay,
|
||||
SimplePool,
|
||||
UnsignedEvent,
|
||||
finalizeEvent,
|
||||
nip04,
|
||||
nip19
|
||||
} from 'nostr-tools'
|
||||
import { EventEmitter } from 'tseep'
|
||||
import { updateNsecbunkerPubkey } from '../store/actions'
|
||||
import { AuthState, LoginMethods } from '../store/auth/types'
|
||||
import store from '../store/store'
|
||||
@ -195,14 +195,29 @@ export class NostrController extends EventEmitter {
|
||||
}
|
||||
|
||||
/**
|
||||
* Function will publish provided event to the provided relay
|
||||
* Function will publish provided event to the provided relays
|
||||
*/
|
||||
publishEvent = async (event: Event, relayUrl: string) => {
|
||||
const relay = await Relay.connect(relayUrl)
|
||||
await relay.publish(event)
|
||||
relay.close()
|
||||
publishEvent = async (event: Event, relays: string[]) => {
|
||||
const simplePool = new SimplePool()
|
||||
|
||||
return `event published to relay: ${relayUrl}`
|
||||
const promises = simplePool.publish(relays, event)
|
||||
|
||||
const results = await Promise.allSettled(promises)
|
||||
|
||||
const publishedRelays: string[] = []
|
||||
|
||||
console.log('results of publish event :>> ', results)
|
||||
|
||||
results.forEach((result, index) => {
|
||||
if (result.status === 'fulfilled') {
|
||||
publishedRelays.push(relays[index])
|
||||
}
|
||||
})
|
||||
|
||||
if (publishedRelays.length === 0)
|
||||
throw new Error(`Couldn't publish to any relay`)
|
||||
|
||||
return publishedRelays
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -278,6 +278,7 @@ export const HomePage = () => {
|
||||
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, {
|
||||
@ -304,9 +305,16 @@ export const HomePage = () => {
|
||||
|
||||
setLoadingSpinnerDesc('encrypting content for DM')
|
||||
|
||||
// todo: add timeout
|
||||
const encrypted = await nostrController
|
||||
.nip04Encrypt(pubkey, content)
|
||||
const timeoutPromise = new Promise<never>((_, 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
|
||||
})
|
||||
@ -339,15 +347,30 @@ export const HomePage = () => {
|
||||
|
||||
if (!signedEvent) return
|
||||
|
||||
// const metadata = metadataMap[pubkey]
|
||||
|
||||
setLoadingSpinnerDesc('Publishing encrypted DM')
|
||||
|
||||
// todo: do not use hardcoded relay
|
||||
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, 'wss://relay.damus.io')
|
||||
.then(() => {
|
||||
toast.success('DM sent to first signer')
|
||||
.publishEvent(signedEvent, relaySet.read)
|
||||
.then((relays) => {
|
||||
toast.success(`Encrypted DM sent on: ${relays.join('\n')}`)
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log('err :>> ', err)
|
||||
|
@ -7,3 +7,8 @@ export interface SignedEvent {
|
||||
id: string
|
||||
sig: string
|
||||
}
|
||||
|
||||
export interface RelaySet {
|
||||
read: string[]
|
||||
write: string[]
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user