Avatar
Cesar Dias
c6603b0f1ccfec625d9c08b753e4f774eaf7d1cf2769223125b5fd4da728019e
Building https://dev.nosotros.app
Replying to Avatar fiatjaf

I've made this wss://inbox.relays.land/ relay that filters out hellthreads from your inbox as well as anyone that isn't in your "network". It's meant to be used as your only (well, ideally it would be combined with others of course, but if these others don't filter out the hellthread then you're in bad shape) "read" relay (see NIP-65).

The problem is that it doesn't work because clients are all trying to be smart and connecting to different relays in order to fetch more notifications. But those issues are being addressed, see below:

nostr:nevent1qvzqqqqqqypzqwlsccluhy6xxsr6l9a9uhhxf75g85g8a709tprjcn4e42h053vaqyd8wumn8ghj7mr0vd4kymmc9enxjct5dfskvtnrdakj7qg6waehxw309ac8junpd45kgtnxd9shg6npvchxxmmd9uq3kamnwvaz7tmjv4kxz7fwwajhxar9wfhxyarr9e3k7mf0qqsqqq828005nj9yz2u3e8q7e65hkm0plgruwmjshde4mf0qh6ua9ks9uwmg8

I can't test if it works on nostr:nprofile1qyv8wumn8ghj7un9d3shjtnsd3jkyum5wghxxmmd9uq36amnwvaz7tmwdaehgu3dxqezu7tpdd5ksmmwdejjucm0d5hszxnhwden5te0dehhxarj9eax2cn9v3jk2tnrd3hh2ep0qyfhwumn8ghj7mmxve3ksctfdch8qatz9uq32amnwvaz7tmjv4kxz7fwv3sk6atn9e5k7tcqyqsfsmac8em4m9k33r99e803pnndvylqadl9w69q7zcjkd7d4ssmxuy89lh, nostr:nprofile1qy88wumn8ghj7mn0wvhxcmmv9uq3samnwvaz7tmxv93xjctw9ehx7um5wgcjucm0d5hszythwden5te0dehhxarj9emkjmn99uqs6ctvvahjuat50phjummwv5q32amnwvaz7te3xgmjuvpwxqhrzw358qmrjtcqyzd7p0swvnfc52dfemy6tj80tkrnc2l62d32fd2cmf0ldx7rewupu92043l's Nostur, nostr:nprofile1qyt8wumn8ghj7etyv4hzumn0wd68ytnvv9hxgtcpz4mhxue69uhhyetvv9ujuerpd46hxtnfduhszrnhwden5te0dehhxtnvdakz7qgnwaehxw309ac82unsd3jhqct89ejhxtcpzamhxue69uhhyetvv9ujumn0wvh8xmmrd9skctcqyq8j9srw4sgqy6zwlnrg7459gr5rgtgkp82s30x5xykq8rnpjnutv7rcpf0, Yana, Nostrmo and others for now, but if you do please let me know.

Next version of nosotros will work, now I can't see your inbox events as read-only because your single inbox-relay is asking for auth

Boa tarde, remova algo.utxo.one da sua lista de relays, alguns clients não vão funcionar direito e não vão achar seus posts, e coloque wss://relay.damus.io, wss://nos.lol e wss://nostr.mom

Oh, I thought it was a fake Alex, i'm checking now, a fake Ross Ulbricht messaged me the other day you know 🤣

RxJs is a mental journey, so embrace it haha, I know you do a bunch of functional programming throughout all coracle code, rxjs will just fit if you embrace it's declarative approach, like your `await tryCatch` function is kinda rxjs `catchError`.

If you have any other question or want to schedule a call just let me know

Replying to Avatar hzrd149

nostr:npub1cesrkrcuelkxyhvupzm48e8hwn4005w0ya5jyvf9kh75mfegqx0q4kt37c a few weeks back I threw this together as a exercise, It has some bugs with reconnecting and DOS the relay but I liked how the NIP-42 auth turned out and that I was able to write it in <200 lines

https://github.com/hzrd149/applesauce/blob/master/packages/relay/src/relay.ts

I'm not really part of this conversation and I'm distracted by other projects but I still really want to help build a pure rxjs relay connection library 😁

wow, this is looking really good, just found weird req returns "EOSE" | NostrEvent, If I want to listen for "EOSE" I would listen on subscribe({complete: () => {}}) or `finalize` operator, but might going to steal you waitForAuth, I am think I am gonna need it 🤣

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

Replying to Avatar hodlbod

Thanks, that rfc looks really nice. I also looked through nosotros/core and the code is super clean and includes a number of patterns that took a while for me to identify (like the relayFilters stuff). Have you looked into https://github.com/penpenpng/rx-nostr at all? My impression was that everything was pretty tightly coupled, making it hard to implement custom policy. Speaking of which, how do you handle relay AUTH when using websocketSubject? I am using policy functions that patch my socket adapter: https://github.com/coracle-social/welshman/blob/net2-rxjs/packages/net2/src/policy.ts

Yes, relayFilters stream approach was something that I came up with the outbox in mind, it's been very useful and easy to split filters of a single subscription, I also designed in a way to work batching multiple unrelated subscriptions together, everything becomes a queue at the end consumed by the start() operators, this approach has been working really well for me and haven't touch much in a while.

rx-nostr is indeed too tightly coupled and when I started my mind was mainly focus on the batcher.

The way I been designing things is the core the be completely stateless and lazy, you can create a subscription and the core will never initiate any subscription for you, just like rxjs itself wouldn't, it just gives you the building blocks.

Working with websocketSubjects has been very easy and flexible, I can even push messages before the websocket was connected and the subject will buffer after connected.

webSocketSubjects just like the other subjects are multicasted.

this will only open 1 connection no matter how many subscriptions you have

```ts

const relay = webSocketSubject('wss://relay1.com')

relay.subscribe()

relay.subscribe()

```

now creating multiple webSocketSubjects it will open multiple connections.

webSocketSubjects multiplex will make a unicast subscription, this will make multiple nostr subscriptions in the same connection.

```ts

const relay = webSocketSubject('wss://relay1.com')

const sub = relay.multiplex(() => ["REQ", , ], () => ['CLOSE', ], (msg) => msg msg[1] === )

sub.subscribe()

sub.subscribe()

```

You can pass the webSocketSubject as you wish as it's also a observable, I store relays as webSocketSubjects in a Map in the Pool which doesn't do anything special, just blacklist relays with errors so it doesn't try to connect again.

Current my core/pool is doing the relay subscription which is incorrect, the consumer should be responsible to initiate the relay connection because he could put any policy mechanism for a particular relay, something like a rxjs retry to reconnect or some auth policy, currently my pool exposes a open callback and we could do something like this (pseudo code)

I am still working on auth and trying to think about some flexible way to do it, I'm a little bit hesitant to replay old messages after a a successful auth as I need to store these messages somewhere, but here's a small authenticator (which I think I should rename to createAuthPolicy or something) what takes a pool, a signer a options like whitelist which is an observable as the user can whitelist a observable after the auth was received.

Still half backed as I am still testing locally

Highly recommend rxjs, it's been an incredible journey for me and I had to learn some things the hard way.

After a heavy year on rxjs, I manage to build very complex pipelines with have very little state (variables) and close to no imperative code, I kinda got to a point of no way back.

Your approach of takeUntil is totally correct, which is the rxjs way of doing things, a powerful advice to rxjs is to avoid Subjects at all costs, they deviate the concepts of reactive programming and forces you in the imperative approach, people using rxjs with only Subjects aren't really using rxjs at all, just a fancy event emitter (the meme), there's a reason why xstream (a alternative library to rxjs) called their `next` function `shamefullySendNext` (yes, there's use cases for Subjects)

I have no issues with typescript in rxjs, it works pretty well and point-free operators would work just fine, I have issues naming things properly.

You have to be careful as well where you subscribe to the observables, it should be the final stage and usually close to the UI, and unsubscribe when the ui is "unmounted".

I was writing this document for nostr:nprofile1qydhwumn8ghj7umpw3jkcmrfw3jju6r6wfjrzdpe9e3k7mgpz9mhxue69uhkummnw3e82efwvdhk6qg5waehxw309aex2mrp0yhxgctdw4eju6t0qyxhwumn8ghj7mn0wvhxcmmvqyg8wumn8ghj7mn0wd68ytnhd9hx2qpqye5ptcxfyyxl5vjvdjar2ua3f0hynkjzpx552mu5snj3qmx5pzjs7haql4 the other day but never had a change to finish, which is my client approach for nostr subscription in rxjs https://github.com/cesardeazevedo/nostr-observable, the idea was to have a 100% stateless library for nostr.

This file is how I handle subscription and everything else is built on top of it https://github.com/cesardeazevedo/nosotros/blob/main/src/core/operators/subscribe.ts

If you have any questions don't hesitate to ask, I would love to help anything rxjs related.

I think I am getting owned by relays urls ending with a slash

Eu também uso vim a muito tempo, acabei largando por outras ides depois meu sistema de configuração simplesmente ficou impossível de configurar pra LSPs e outras coisas, eu não aguentava mais vimscript, voltei pro vim faz um ano (agora com neovim), e estou usando o LazyVim, sempre tem alguns probleminhas mas tem me atendido bem, a configuração do folke é um pouco chatinha.

Atualmente estou portando ao poucos as coisas que eu realmente uso pro kickstart.nvim, que é bem mais limpo e assim consigo ter controle 100% do código