@@ -11,6 +11,7 @@ import { normalizeURL } from './utils.ts'
1111import type { Event , EventTemplate , Nostr , VerifiedEvent } from './core.ts'
1212import { type Filter } from './filter.ts'
1313import { alwaysTrue } from './helpers.ts'
14+ import { Relay } from './relay.ts'
1415
1516export type SubCloser = { close : ( reason ?: string ) => void }
1617
@@ -19,6 +20,11 @@ export type AbstractPoolConstructorOptions = AbstractRelayConstructorOptions & {
1920 // in case that relay shouldn't be authenticated against
2021 // or a function to sign the AUTH event template otherwise (that function may still throw in case of failure)
2122 automaticallyAuth ?: ( relayURL : string ) => null | ( ( event : EventTemplate ) => Promise < VerifiedEvent > )
23+ // onRelayConnectionFailure is called with the URL of a relay that failed the initial connection
24+ onRelayConnectionFailure ?: ( url : string ) => void
25+ // allowConnectingToRelay takes a relay URL and the operation being performed
26+ // return false to skip connecting to that relay
27+ allowConnectingToRelay ?: ( url : string , operation : [ 'read' , Filter [ ] ] | [ 'write' , Event ] ) => boolean
2228}
2329
2430export type SubscribeManyParams = Omit < SubscriptionParams , 'onclose' > & {
@@ -40,6 +46,8 @@ export class AbstractSimplePool {
4046 public enableReconnect : boolean
4147 public automaticallyAuth ?: ( relayURL : string ) => null | ( ( event : EventTemplate ) => Promise < VerifiedEvent > )
4248 public trustedRelayURLs : Set < string > = new Set ( )
49+ public onRelayConnectionFailure ?: ( url : string ) => void
50+ public allowConnectingToRelay ?: ( url : string , operation : [ 'read' , Filter [ ] ] | [ 'write' , Event ] ) => boolean
4351
4452 private _WebSocket ?: typeof WebSocket
4553
@@ -49,6 +57,8 @@ export class AbstractSimplePool {
4957 this . enablePing = opts . enablePing
5058 this . enableReconnect = opts . enableReconnect || false
5159 this . automaticallyAuth = opts . automaticallyAuth
60+ this . onRelayConnectionFailure = opts . onRelayConnectionFailure
61+ this . allowConnectingToRelay = opts . allowConnectingToRelay
5262 }
5363
5464 async ensureRelay (
@@ -181,13 +191,19 @@ export class AbstractSimplePool {
181191 // open a subscription in all given relays
182192 const allOpened = Promise . all (
183193 groupedRequests . map ( async ( { url, filters } , i ) => {
194+ if ( this . allowConnectingToRelay ?.( url , [ 'read' , filters ] ) === false ) {
195+ handleClose ( i , 'connection skipped by allowConnectingToRelay' )
196+ return
197+ }
198+
184199 let relay : AbstractRelay
185200 try {
186201 relay = await this . ensureRelay ( url , {
187202 connectionTimeout : params . maxWait ? Math . max ( params . maxWait * 0.8 , params . maxWait - 1000 ) : undefined ,
188203 abort : params . abort ,
189204 } )
190205 } catch ( err ) {
206+ this . onRelayConnectionFailure ?.( url )
191207 handleClose ( i , ( err as any ) ?. message || String ( err ) )
192208 return
193209 }
@@ -306,7 +322,18 @@ export class AbstractSimplePool {
306322 return Promise . reject ( 'duplicate url' )
307323 }
308324
309- let r = await this . ensureRelay ( url )
325+ if ( this . allowConnectingToRelay ?.( url , [ 'write' , event ] ) === false ) {
326+ return Promise . reject ( 'connection skipped by allowConnectingToRelay' )
327+ }
328+
329+ let r : Relay
330+ try {
331+ r = await this . ensureRelay ( url )
332+ } catch ( err ) {
333+ this . onRelayConnectionFailure ?.( url )
334+ return String ( 'connection failure: ' + String ( err ) )
335+ }
336+
310337 return r
311338 . publish ( event )
312339 . catch ( async err => {
0 commit comments