Compare commits
No commits in common. "35f6a639e6aebbcf897b050e1f55b01d98aa9cd6" and "7bb83695c9e41627df1aab665abcf6b6cdbd4078" have entirely different histories.
35f6a639e6
...
7bb83695c9
@ -420,10 +420,12 @@ export const DrawPDFFields = (props: Props) => {
|
|||||||
{users
|
{users
|
||||||
.filter((u) => u.role === UserRole.signer)
|
.filter((u) => u.role === UserRole.signer)
|
||||||
.map((user, index) => {
|
.map((user, index) => {
|
||||||
const npub = hexToNpub(user.pubkey)
|
let displayValue = truncate(
|
||||||
let displayValue = truncate(npub, {
|
hexToNpub(user.pubkey),
|
||||||
|
{
|
||||||
length: 16
|
length: 16
|
||||||
})
|
}
|
||||||
|
)
|
||||||
|
|
||||||
const metadata = props.metadata[user.pubkey]
|
const metadata = props.metadata[user.pubkey]
|
||||||
|
|
||||||
@ -431,8 +433,7 @@ export const DrawPDFFields = (props: Props) => {
|
|||||||
displayValue = truncate(
|
displayValue = truncate(
|
||||||
metadata.name ||
|
metadata.name ||
|
||||||
metadata.display_name ||
|
metadata.display_name ||
|
||||||
metadata.username ||
|
metadata.username,
|
||||||
npub,
|
|
||||||
{
|
{
|
||||||
length: 16
|
length: 16
|
||||||
}
|
}
|
||||||
|
@ -15,16 +15,15 @@ import {
|
|||||||
findRelayListAndUpdateCache,
|
findRelayListAndUpdateCache,
|
||||||
findRelayListInCache,
|
findRelayListInCache,
|
||||||
getDefaultRelaySet,
|
getDefaultRelaySet,
|
||||||
|
getMostPopularRelays,
|
||||||
getUserRelaySet,
|
getUserRelaySet,
|
||||||
isOlderThanOneDay,
|
isOlderThanOneWeek,
|
||||||
unixNow
|
unixNow
|
||||||
} from '../utils'
|
} from '../utils'
|
||||||
import { DEFAULT_LOOK_UP_RELAY_LIST } from '../utils/const'
|
|
||||||
|
|
||||||
export class MetadataController extends EventEmitter {
|
export class MetadataController extends EventEmitter {
|
||||||
private nostrController: NostrController
|
private nostrController: NostrController
|
||||||
private specialMetadataRelay = 'wss://purplepag.es'
|
private specialMetadataRelay = 'wss://purplepag.es'
|
||||||
private pendingFetches = new Map<string, Promise<Event | null>>() // Track pending fetches
|
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super()
|
super()
|
||||||
@ -43,55 +42,70 @@ export class MetadataController extends EventEmitter {
|
|||||||
hexKey: string,
|
hexKey: string,
|
||||||
currentEvent: Event | null
|
currentEvent: Event | null
|
||||||
): Promise<Event | null> {
|
): Promise<Event | null> {
|
||||||
// Return the ongoing fetch promise if one exists for the same hexKey
|
|
||||||
if (this.pendingFetches.has(hexKey)) {
|
|
||||||
return this.pendingFetches.get(hexKey)!
|
|
||||||
}
|
|
||||||
|
|
||||||
// Define the event filter to only include metadata events authored by the given key
|
// Define the event filter to only include metadata events authored by the given key
|
||||||
const eventFilter: Filter = {
|
const eventFilter: Filter = {
|
||||||
kinds: [kinds.Metadata],
|
kinds: [kinds.Metadata], // Only metadata events
|
||||||
authors: [hexKey]
|
authors: [hexKey] // Authored by the specified key
|
||||||
}
|
}
|
||||||
|
|
||||||
const fetchPromise = relayController
|
// Try to get the metadata event from a special relay (wss://purplepag.es)
|
||||||
.fetchEvent(eventFilter, DEFAULT_LOOK_UP_RELAY_LIST)
|
const metadataEvent = await relayController
|
||||||
|
.fetchEvent(eventFilter, [this.specialMetadataRelay])
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
console.error(err)
|
console.error(err) // Log any errors
|
||||||
return null
|
return null // Return null if an error occurs
|
||||||
})
|
|
||||||
.finally(() => {
|
|
||||||
this.pendingFetches.delete(hexKey)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
this.pendingFetches.set(hexKey, fetchPromise)
|
// If a valid metadata event is found from the special relay
|
||||||
|
|
||||||
const metadataEvent = await fetchPromise
|
|
||||||
|
|
||||||
if (
|
if (
|
||||||
metadataEvent &&
|
metadataEvent &&
|
||||||
validateEvent(metadataEvent) &&
|
validateEvent(metadataEvent) && // Validate the event
|
||||||
verifyEvent(metadataEvent)
|
verifyEvent(metadataEvent) // Verify the event's authenticity
|
||||||
) {
|
) {
|
||||||
|
// If there's no current event or the new metadata event is more recent
|
||||||
if (
|
if (
|
||||||
!currentEvent ||
|
!currentEvent ||
|
||||||
metadataEvent.created_at >= currentEvent.created_at
|
metadataEvent.created_at >= currentEvent.created_at
|
||||||
) {
|
) {
|
||||||
|
// Handle the new metadata event
|
||||||
this.handleNewMetadataEvent(metadataEvent)
|
this.handleNewMetadataEvent(metadataEvent)
|
||||||
}
|
}
|
||||||
|
|
||||||
return metadataEvent
|
return metadataEvent
|
||||||
}
|
}
|
||||||
|
|
||||||
// todo/implement: if no valid metadata event is found in DEFAULT_LOOK_UP_RELAY_LIST
|
// If no valid metadata event is found from the special relay, get the most popular relays
|
||||||
// try to query user relay list
|
const mostPopularRelays = await getMostPopularRelays()
|
||||||
|
|
||||||
// if current event is null we should cache empty metadata event for provided hexKey
|
// Query the most popular relays for metadata events
|
||||||
if (!currentEvent) {
|
|
||||||
const emptyMetadata = this.getEmptyMetadataEvent(hexKey)
|
const events = await relayController
|
||||||
this.handleNewMetadataEvent(emptyMetadata as VerifiedEvent)
|
.fetchEvents(eventFilter, mostPopularRelays)
|
||||||
|
.catch((err) => {
|
||||||
|
console.error(err) // Log any errors
|
||||||
|
return null // Return null if an error occurs
|
||||||
|
})
|
||||||
|
|
||||||
|
// If events are found from the popular relays
|
||||||
|
if (events && events.length) {
|
||||||
|
events.sort((a, b) => b.created_at - a.created_at) // Sort events by creation date (descending)
|
||||||
|
|
||||||
|
// Iterate through the events
|
||||||
|
for (const event of events) {
|
||||||
|
// If the event is valid, authentic, and more recent than the current event
|
||||||
|
if (
|
||||||
|
validateEvent(event) &&
|
||||||
|
verifyEvent(event) &&
|
||||||
|
(!currentEvent || event.created_at > currentEvent.created_at)
|
||||||
|
) {
|
||||||
|
// Handle the new metadata event
|
||||||
|
this.handleNewMetadataEvent(event)
|
||||||
|
return event
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return currentEvent
|
return currentEvent // Return the current event if no newer event is found
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -116,8 +130,8 @@ export class MetadataController extends EventEmitter {
|
|||||||
|
|
||||||
// If cached metadata is found, check its validity
|
// If cached metadata is found, check its validity
|
||||||
if (cachedMetadataEvent) {
|
if (cachedMetadataEvent) {
|
||||||
// Check if the cached metadata is older than one day
|
// Check if the cached metadata is older than one week
|
||||||
if (isOlderThanOneDay(cachedMetadataEvent.cachedAt)) {
|
if (isOlderThanOneWeek(cachedMetadataEvent.cachedAt)) {
|
||||||
// If older than one week, find the metadata from relays in background
|
// If older than one week, find the metadata from relays in background
|
||||||
|
|
||||||
this.checkForMoreRecentMetadata(hexKey, cachedMetadataEvent.event)
|
this.checkForMoreRecentMetadata(hexKey, cachedMetadataEvent.event)
|
||||||
@ -147,7 +161,11 @@ export class MetadataController extends EventEmitter {
|
|||||||
public findRelayListMetadata = async (hexKey: string): Promise<RelaySet> => {
|
public findRelayListMetadata = async (hexKey: string): Promise<RelaySet> => {
|
||||||
const relayEvent =
|
const relayEvent =
|
||||||
(await findRelayListInCache(hexKey)) ||
|
(await findRelayListInCache(hexKey)) ||
|
||||||
(await findRelayListAndUpdateCache(DEFAULT_LOOK_UP_RELAY_LIST, hexKey))
|
(await findRelayListAndUpdateCache(
|
||||||
|
[this.specialMetadataRelay],
|
||||||
|
hexKey
|
||||||
|
)) ||
|
||||||
|
(await findRelayListAndUpdateCache(await getMostPopularRelays(), hexKey))
|
||||||
|
|
||||||
return relayEvent ? getUserRelaySet(relayEvent.tags) : getDefaultRelaySet()
|
return relayEvent ? getUserRelaySet(relayEvent.tags) : getDefaultRelaySet()
|
||||||
}
|
}
|
||||||
@ -198,13 +216,13 @@ export class MetadataController extends EventEmitter {
|
|||||||
|
|
||||||
public validate = (event: Event) => validateEvent(event) && verifyEvent(event)
|
public validate = (event: Event) => validateEvent(event) && verifyEvent(event)
|
||||||
|
|
||||||
public getEmptyMetadataEvent = (pubkey?: string): Event => {
|
public getEmptyMetadataEvent = (): Event => {
|
||||||
return {
|
return {
|
||||||
content: '',
|
content: '',
|
||||||
created_at: new Date().valueOf(),
|
created_at: new Date().valueOf(),
|
||||||
id: '',
|
id: '',
|
||||||
kind: 0,
|
kind: 0,
|
||||||
pubkey: pubkey || '',
|
pubkey: '',
|
||||||
sig: '',
|
sig: '',
|
||||||
tags: []
|
tags: []
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,6 @@ import { SIGIT_RELAY } from '../utils/const'
|
|||||||
*/
|
*/
|
||||||
export class RelayController {
|
export class RelayController {
|
||||||
private static instance: RelayController
|
private static instance: RelayController
|
||||||
private pendingConnections = new Map<string, Promise<Relay | null>>() // Track pending connections
|
|
||||||
public connectedRelays = new Map<string, Relay>()
|
public connectedRelays = new Map<string, Relay>()
|
||||||
|
|
||||||
private constructor() {}
|
private constructor() {}
|
||||||
@ -36,26 +35,23 @@ export class RelayController {
|
|||||||
* @returns A promise that resolves to the connected relay object if successful, or `null` if the connection fails.
|
* @returns A promise that resolves to the connected relay object if successful, or `null` if the connection fails.
|
||||||
*/
|
*/
|
||||||
public connectRelay = async (relayUrl: string): Promise<Relay | null> => {
|
public connectRelay = async (relayUrl: string): Promise<Relay | null> => {
|
||||||
|
// Check if a relay with the same URL is already connected
|
||||||
const normalizedWebSocketURL = normalizeWebSocketURL(relayUrl)
|
const normalizedWebSocketURL = normalizeWebSocketURL(relayUrl)
|
||||||
const relay = this.connectedRelays.get(normalizedWebSocketURL)
|
const relay = this.connectedRelays.get(normalizedWebSocketURL)
|
||||||
|
|
||||||
if (relay) {
|
if (relay) {
|
||||||
|
// If a relay is found in connectedRelay map and is connected, just return it
|
||||||
if (relay.connected) return relay
|
if (relay.connected) return relay
|
||||||
|
|
||||||
// If relay is found in connectedRelay map but not connected,
|
// If relay is found in connectedRelay map but not connected,
|
||||||
// remove it from map and call connectRelay method again
|
// remove it from map and call connectRelay method again
|
||||||
this.connectedRelays.delete(relayUrl)
|
this.connectedRelays.delete(relayUrl)
|
||||||
|
|
||||||
return this.connectRelay(relayUrl)
|
return this.connectRelay(relayUrl)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if there's already a pending connection for this relay URL
|
// Attempt to connect to the relay using the provided URL
|
||||||
if (this.pendingConnections.has(relayUrl)) {
|
const newRelay = await Relay.connect(relayUrl)
|
||||||
// Return the existing promise to avoid making another connection
|
|
||||||
return this.pendingConnections.get(relayUrl)!
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create a new connection promise and store it in pendingConnections
|
|
||||||
const connectionPromise = Relay.connect(relayUrl)
|
|
||||||
.then((relay) => {
|
.then((relay) => {
|
||||||
if (relay.connected) {
|
if (relay.connected) {
|
||||||
// Add the newly connected relay to the connected relays map
|
// Add the newly connected relay to the connected relays map
|
||||||
@ -74,13 +70,8 @@ export class RelayController {
|
|||||||
// Return null to indicate connection failure
|
// Return null to indicate connection failure
|
||||||
return null
|
return null
|
||||||
})
|
})
|
||||||
.finally(() => {
|
|
||||||
// Remove the connection from pendingConnections once it settles
|
|
||||||
this.pendingConnections.delete(relayUrl)
|
|
||||||
})
|
|
||||||
|
|
||||||
this.pendingConnections.set(relayUrl, connectionPromise)
|
return newRelay
|
||||||
return connectionPromise
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -95,17 +86,8 @@ export class RelayController {
|
|||||||
filter: Filter,
|
filter: Filter,
|
||||||
relayUrls: string[] = []
|
relayUrls: string[] = []
|
||||||
): Promise<Event[]> => {
|
): Promise<Event[]> => {
|
||||||
if (!relayUrls.includes(SIGIT_RELAY)) {
|
// Add app relay to relays array and connect to all specified relays
|
||||||
/**
|
const relayPromises = [...relayUrls, SIGIT_RELAY].map((relayUrl) =>
|
||||||
* 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 relayPromises = relayUrls.map((relayUrl) =>
|
|
||||||
this.connectRelay(relayUrl)
|
this.connectRelay(relayUrl)
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -219,18 +201,11 @@ export class RelayController {
|
|||||||
relayUrls: string[] = [],
|
relayUrls: string[] = [],
|
||||||
eventHandler: (event: Event) => void
|
eventHandler: (event: Event) => void
|
||||||
) => {
|
) => {
|
||||||
if (!relayUrls.includes(SIGIT_RELAY)) {
|
// Add app relay to relays array and connect to all specified relays
|
||||||
/**
|
|
||||||
* 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 relayPromises = [...relayUrls, SIGIT_RELAY].map((relayUrl) =>
|
||||||
const relayPromises = relayUrls.map((relayUrl) => {
|
this.connectRelay(relayUrl)
|
||||||
return this.connectRelay(relayUrl)
|
)
|
||||||
})
|
|
||||||
|
|
||||||
// Use Promise.allSettled to wait for all promises to settle
|
// Use Promise.allSettled to wait for all promises to settle
|
||||||
const results = await Promise.allSettled(relayPromises)
|
const results = await Promise.allSettled(relayPromises)
|
||||||
@ -283,16 +258,9 @@ export class RelayController {
|
|||||||
event: Event,
|
event: Event,
|
||||||
relayUrls: string[] = []
|
relayUrls: string[] = []
|
||||||
): Promise<string[]> => {
|
): Promise<string[]> => {
|
||||||
if (!relayUrls.includes(SIGIT_RELAY)) {
|
// Add app relay to relays array and connect to all specified relays
|
||||||
/**
|
|
||||||
* 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 relayPromises = [...relayUrls, SIGIT_RELAY].map((relayUrl) =>
|
||||||
const relayPromises = relayUrls.map((relayUrl) =>
|
|
||||||
this.connectRelay(relayUrl)
|
this.connectRelay(relayUrl)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -15,6 +15,7 @@ export const SET_USER_ROBOT_IMAGE = 'SET_USER_ROBOT_IMAGE'
|
|||||||
export const SET_RELAY_MAP = 'SET_RELAY_MAP'
|
export const SET_RELAY_MAP = 'SET_RELAY_MAP'
|
||||||
export const SET_RELAY_INFO = 'SET_RELAY_INFO'
|
export const SET_RELAY_INFO = 'SET_RELAY_INFO'
|
||||||
export const SET_RELAY_MAP_UPDATED = 'SET_RELAY_MAP_UPDATED'
|
export const SET_RELAY_MAP_UPDATED = 'SET_RELAY_MAP_UPDATED'
|
||||||
|
export const SET_MOST_POPULAR_RELAYS = 'SET_MOST_POPULAR_RELAYS'
|
||||||
|
|
||||||
export const UPDATE_USER_APP_DATA = 'UPDATE_USER_APP_DATA'
|
export const UPDATE_USER_APP_DATA = 'UPDATE_USER_APP_DATA'
|
||||||
export const UPDATE_PROCESSED_GIFT_WRAPS = 'UPDATE_PROCESSED_GIFT_WRAPS'
|
export const UPDATE_PROCESSED_GIFT_WRAPS = 'UPDATE_PROCESSED_GIFT_WRAPS'
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import * as ActionTypes from '../actionTypes'
|
import * as ActionTypes from '../actionTypes'
|
||||||
import {
|
import {
|
||||||
SetRelayMapAction,
|
SetRelayMapAction,
|
||||||
|
SetMostPopularRelaysAction,
|
||||||
SetRelayInfoAction,
|
SetRelayInfoAction,
|
||||||
SetRelayMapUpdatedAction
|
SetRelayMapUpdatedAction
|
||||||
} from './types'
|
} from './types'
|
||||||
@ -18,6 +19,13 @@ export const setRelayInfoAction = (
|
|||||||
payload
|
payload
|
||||||
})
|
})
|
||||||
|
|
||||||
|
export const setMostPopularRelaysAction = (
|
||||||
|
payload: string[]
|
||||||
|
): SetMostPopularRelaysAction => ({
|
||||||
|
type: ActionTypes.SET_MOST_POPULAR_RELAYS,
|
||||||
|
payload
|
||||||
|
})
|
||||||
|
|
||||||
export const setRelayMapUpdatedAction = (): SetRelayMapUpdatedAction => ({
|
export const setRelayMapUpdatedAction = (): SetRelayMapUpdatedAction => ({
|
||||||
type: ActionTypes.SET_RELAY_MAP_UPDATED
|
type: ActionTypes.SET_RELAY_MAP_UPDATED
|
||||||
})
|
})
|
||||||
|
@ -4,6 +4,7 @@ import { RelaysDispatchTypes, RelaysState } from './types'
|
|||||||
const initialState: RelaysState = {
|
const initialState: RelaysState = {
|
||||||
map: undefined,
|
map: undefined,
|
||||||
mapUpdated: undefined,
|
mapUpdated: undefined,
|
||||||
|
mostPopular: undefined,
|
||||||
info: undefined
|
info: undefined
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -24,6 +25,9 @@ const reducer = (
|
|||||||
info: { ...state.info, ...action.payload }
|
info: { ...state.info, ...action.payload }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case ActionTypes.SET_MOST_POPULAR_RELAYS:
|
||||||
|
return { ...state, mostPopular: [...action.payload] }
|
||||||
|
|
||||||
case ActionTypes.RESTORE_STATE:
|
case ActionTypes.RESTORE_STATE:
|
||||||
return action.payload.relays
|
return action.payload.relays
|
||||||
|
|
||||||
|
@ -5,6 +5,7 @@ import { RelayMap, RelayInfoObject } from '../../types'
|
|||||||
export type RelaysState = {
|
export type RelaysState = {
|
||||||
map?: RelayMap
|
map?: RelayMap
|
||||||
mapUpdated?: number
|
mapUpdated?: number
|
||||||
|
mostPopular?: string[]
|
||||||
info?: RelayInfoObject
|
info?: RelayInfoObject
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -13,6 +14,11 @@ export interface SetRelayMapAction {
|
|||||||
payload: RelayMap
|
payload: RelayMap
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface SetMostPopularRelaysAction {
|
||||||
|
type: typeof ActionTypes.SET_MOST_POPULAR_RELAYS
|
||||||
|
payload: string[]
|
||||||
|
}
|
||||||
|
|
||||||
export interface SetRelayInfoAction {
|
export interface SetRelayInfoAction {
|
||||||
type: typeof ActionTypes.SET_RELAY_INFO
|
type: typeof ActionTypes.SET_RELAY_INFO
|
||||||
payload: RelayInfoObject
|
payload: RelayInfoObject
|
||||||
@ -26,4 +32,5 @@ export type RelaysDispatchTypes =
|
|||||||
| SetRelayMapAction
|
| SetRelayMapAction
|
||||||
| SetRelayInfoAction
|
| SetRelayInfoAction
|
||||||
| SetRelayMapUpdatedAction
|
| SetRelayMapUpdatedAction
|
||||||
|
| SetMostPopularRelaysAction
|
||||||
| RestoreState
|
| RestoreState
|
||||||
|
@ -11,18 +11,7 @@ export const DEFLATE = 'DEFLATE'
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Number of milliseconds in one week.
|
* Number of milliseconds in one week.
|
||||||
|
* Calc based on: 7 * 24 * 60 * 60 * 1000
|
||||||
*/
|
*/
|
||||||
export const ONE_WEEK_IN_MS = 7 * 24 * 60 * 60 * 1000
|
export const ONE_WEEK_IN_MS: number = 604800000
|
||||||
|
export const SIGIT_RELAY: string = 'wss://relay.sigit.io'
|
||||||
/**
|
|
||||||
* Number of milliseconds in one day.
|
|
||||||
*/
|
|
||||||
export const ONE_DAY_IN_MS = 24 * 60 * 60 * 1000
|
|
||||||
|
|
||||||
export const SIGIT_RELAY = 'wss://relay.sigit.io'
|
|
||||||
|
|
||||||
export const DEFAULT_LOOK_UP_RELAY_LIST = [
|
|
||||||
SIGIT_RELAY,
|
|
||||||
'wss://user.kindpag.es',
|
|
||||||
'wss://purplepag.es'
|
|
||||||
]
|
|
||||||
|
@ -33,7 +33,6 @@ import { Meta, SignedEvent, UserAppData } from '../types'
|
|||||||
import { getHash } from './hash'
|
import { getHash } from './hash'
|
||||||
import { parseJson, removeLeadingSlash } from './string'
|
import { parseJson, removeLeadingSlash } from './string'
|
||||||
import { timeout } from './utils'
|
import { timeout } from './utils'
|
||||||
import { getDefaultRelayMap } from './relays'
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param hexKey hex private or public key
|
* @param hexKey hex private or public key
|
||||||
@ -599,8 +598,7 @@ export const updateUsersAppData = async (meta: Meta) => {
|
|||||||
|
|
||||||
if (!signedEvent) return null
|
if (!signedEvent) return null
|
||||||
|
|
||||||
const relayMap =
|
const relayMap = (store.getState().relays as RelaysState).map!
|
||||||
(store.getState().relays as RelaysState).map || getDefaultRelayMap()
|
|
||||||
const writeRelays = Object.keys(relayMap).filter((key) => relayMap[key].write)
|
const writeRelays = Object.keys(relayMap).filter((key) => relayMap[key].write)
|
||||||
|
|
||||||
const publishResult = await Promise.race([
|
const publishResult = await Promise.race([
|
||||||
|
@ -1,14 +1,13 @@
|
|||||||
|
import axios from 'axios'
|
||||||
import { Event, Filter, kinds, UnsignedEvent } from 'nostr-tools'
|
import { Event, Filter, kinds, UnsignedEvent } from 'nostr-tools'
|
||||||
import { RelayList } from 'nostr-tools/kinds'
|
import { RelayList } from 'nostr-tools/kinds'
|
||||||
import { getRelayInfo, unixNow } from '.'
|
import { getRelayInfo, unixNow } from '.'
|
||||||
import { NostrController, relayController } from '../controllers'
|
import { NostrController, relayController } from '../controllers'
|
||||||
import { localCache } from '../services'
|
import { localCache } from '../services'
|
||||||
import { RelayMap, RelaySet } from '../types'
|
import { setMostPopularRelaysAction } from '../store/actions'
|
||||||
import {
|
import store from '../store/store'
|
||||||
DEFAULT_LOOK_UP_RELAY_LIST,
|
import { RelayMap, RelayReadStats, RelaySet, RelayStats } from '../types'
|
||||||
ONE_WEEK_IN_MS,
|
import { ONE_WEEK_IN_MS, SIGIT_RELAY } from './const'
|
||||||
SIGIT_RELAY
|
|
||||||
} from './const'
|
|
||||||
|
|
||||||
const READ_MARKER = 'read'
|
const READ_MARKER = 'read'
|
||||||
const WRITE_MARKER = 'write'
|
const WRITE_MARKER = 'write'
|
||||||
@ -30,7 +29,6 @@ const findRelayListAndUpdateCache = async (
|
|||||||
authors: [hexKey]
|
authors: [hexKey]
|
||||||
}
|
}
|
||||||
|
|
||||||
console.count('findRelayListAndUpdateCache')
|
|
||||||
const event = await relayController.fetchEvent(eventFilter, lookUpRelays)
|
const event = await relayController.fetchEvent(eventFilter, lookUpRelays)
|
||||||
if (event) {
|
if (event) {
|
||||||
await localCache.addUserRelayListMetadata(event)
|
await localCache.addUserRelayListMetadata(event)
|
||||||
@ -92,10 +90,6 @@ const isOlderThanOneWeek = (cachedAt: number) => {
|
|||||||
return Date.now() - cachedAt < ONE_WEEK_IN_MS
|
return Date.now() - cachedAt < ONE_WEEK_IN_MS
|
||||||
}
|
}
|
||||||
|
|
||||||
const isOlderThanOneDay = (cachedAt: number) => {
|
|
||||||
return Date.now() - cachedAt < ONE_WEEK_IN_MS
|
|
||||||
}
|
|
||||||
|
|
||||||
const isRelayTag = (tag: string[]): boolean => tag[0] === 'r'
|
const isRelayTag = (tag: string[]): boolean => tag[0] === 'r'
|
||||||
|
|
||||||
const toRelaySet = (obj: RelaySet, tag: string[]): RelaySet => {
|
const toRelaySet = (obj: RelaySet, tag: string[]): RelaySet => {
|
||||||
@ -116,6 +110,51 @@ const toRelaySet = (obj: RelaySet, tag: string[]): RelaySet => {
|
|||||||
return obj
|
return obj
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides most popular relays.
|
||||||
|
* @param numberOfTopRelays - number representing how many most popular relays to provide
|
||||||
|
* @returns - promise that resolves into an array of most popular relays
|
||||||
|
*/
|
||||||
|
const getMostPopularRelays = async (
|
||||||
|
numberOfTopRelays: number = 30
|
||||||
|
): Promise<string[]> => {
|
||||||
|
const mostPopularRelaysState = store.getState().relays?.mostPopular
|
||||||
|
|
||||||
|
// return most popular relays from app state if present
|
||||||
|
if (mostPopularRelaysState) return mostPopularRelaysState
|
||||||
|
|
||||||
|
// relays in env
|
||||||
|
const { VITE_MOST_POPULAR_RELAYS } = import.meta.env
|
||||||
|
const hardcodedPopularRelays = (VITE_MOST_POPULAR_RELAYS || '').split(' ')
|
||||||
|
const url = `https://stats.nostr.band/stats_api?method=stats`
|
||||||
|
|
||||||
|
const response = await axios.get<RelayStats>(url).catch(() => undefined)
|
||||||
|
|
||||||
|
if (!response) {
|
||||||
|
return hardcodedPopularRelays //return hardcoded relay list
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = response.data
|
||||||
|
|
||||||
|
if (!data) {
|
||||||
|
return hardcodedPopularRelays //return hardcoded relay list
|
||||||
|
}
|
||||||
|
|
||||||
|
const apiTopRelays = data.relay_stats.user_picks.read_relays
|
||||||
|
.slice(0, numberOfTopRelays)
|
||||||
|
.map((relay: RelayReadStats) => relay.d)
|
||||||
|
|
||||||
|
if (!apiTopRelays.length) {
|
||||||
|
return Promise.reject(`Couldn't fetch popular relays.`)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (store.getState().auth?.loggedIn) {
|
||||||
|
store.dispatch(setMostPopularRelaysAction(apiTopRelays))
|
||||||
|
}
|
||||||
|
|
||||||
|
return apiTopRelays
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides relay map.
|
* Provides relay map.
|
||||||
* @param npub - user's npub
|
* @param npub - user's npub
|
||||||
@ -124,6 +163,8 @@ const toRelaySet = (obj: RelaySet, tag: string[]): RelaySet => {
|
|||||||
const getRelayMap = async (
|
const getRelayMap = async (
|
||||||
npub: string
|
npub: string
|
||||||
): Promise<{ map: RelayMap; mapUpdated?: number }> => {
|
): Promise<{ map: RelayMap; mapUpdated?: number }> => {
|
||||||
|
const mostPopularRelays = await getMostPopularRelays()
|
||||||
|
|
||||||
// More info about this kind of event available https://github.com/nostr-protocol/nips/blob/master/65.md
|
// More info about this kind of event available https://github.com/nostr-protocol/nips/blob/master/65.md
|
||||||
const eventFilter: Filter = {
|
const eventFilter: Filter = {
|
||||||
kinds: [kinds.RelayList],
|
kinds: [kinds.RelayList],
|
||||||
@ -131,7 +172,7 @@ const getRelayMap = async (
|
|||||||
}
|
}
|
||||||
|
|
||||||
const event = await relayController
|
const event = await relayController
|
||||||
.fetchEvent(eventFilter, DEFAULT_LOOK_UP_RELAY_LIST)
|
.fetchEvent(eventFilter, mostPopularRelays)
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
return Promise.reject(err)
|
return Promise.reject(err)
|
||||||
})
|
})
|
||||||
@ -154,9 +195,9 @@ const getRelayMap = async (
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
Object.keys(relaysMap).forEach((relayUrl) =>
|
Object.keys(relaysMap).forEach((relayUrl) => {
|
||||||
relayController.connectRelay(relayUrl)
|
relayController.connectRelay(relayUrl)
|
||||||
)
|
})
|
||||||
|
|
||||||
getRelayInfo(Object.keys(relaysMap))
|
getRelayInfo(Object.keys(relaysMap))
|
||||||
|
|
||||||
@ -214,8 +255,9 @@ const publishRelayMap = async (
|
|||||||
|
|
||||||
// If relay map is empty, use most popular relay URIs
|
// If relay map is empty, use most popular relay URIs
|
||||||
if (!relaysToPublish.length) {
|
if (!relaysToPublish.length) {
|
||||||
relaysToPublish = DEFAULT_LOOK_UP_RELAY_LIST
|
relaysToPublish = await getMostPopularRelays()
|
||||||
}
|
}
|
||||||
|
|
||||||
const publishResult = await relayController.publish(
|
const publishResult = await relayController.publish(
|
||||||
signedEvent,
|
signedEvent,
|
||||||
relaysToPublish
|
relaysToPublish
|
||||||
@ -235,9 +277,9 @@ export {
|
|||||||
findRelayListInCache,
|
findRelayListInCache,
|
||||||
getDefaultRelayMap,
|
getDefaultRelayMap,
|
||||||
getDefaultRelaySet,
|
getDefaultRelaySet,
|
||||||
|
getMostPopularRelays,
|
||||||
getRelayMap,
|
getRelayMap,
|
||||||
|
publishRelayMap,
|
||||||
getUserRelaySet,
|
getUserRelaySet,
|
||||||
isOlderThanOneDay,
|
isOlderThanOneWeek
|
||||||
isOlderThanOneWeek,
|
|
||||||
publishRelayMap
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user