Thanks for the code, just doing some quick code review here.
I think the first issue I spotted is the assigning a stream send$ to itself `socket.send$ = send$.pipe` try to think some other way to do that, it's very easy to compose multiple observables that derives from the same source in a functional style.
I would do something like on socket.ts
```ts
this.socket = webSocketSubject('...')
this.events$ = socket.pipe(filter(msg => msg[0] === 'event'))
this.auths$ = socket.pipe(filter(msg => msg[0] === 'AUTH'))
this.authsJoin$ = auths$.pipe(filter(msg => msg[1].kind === 28934))
this.oks$ = socket.pipe(filter(msg => msg[0] === 'OK'))
```
I would also remove the `authState.subscribe` for something like `return authState.pipe(tap(() => {}))`, but AuthState is a subject with a bunch of subscriptions inside there... hmmm, that's a bit bad, by looking at the commit history you basically kinda ported a event emitter system to rxjs right? you gonna have to embrace some heavy changes to see the gains of rxjs.
Try to think this way, let's say you have a single nostr subscription to a single relay, this subscription has all sorts of complex policies attached to the main stream, the main stream is also connected with other subscription stream like getting each user for each note in the main stream with also their own set of policies, then you decided to call unsubscribe() from the main stream, then the entire pipeline is unsubscribed and garbage collected, nothing left, with your current approach I am not seeing this happening, you might ended up with some parts of stream still listening for changes, unless you complete/unsubscribe the streams manually in multiple places which is a lot of work, which is something you have to do with event emitters.
I also did these exact mistakes a year ago, so I really don't judge you 😅
this angular tutorial describes really well the issue.
https://www.youtube.com/watch?v=bxslNFZvOvQ