Avatar
Marius Kjeldahl
2e1b0646bb603b8c4febc648a2801d7134d18b5a766ad2bb87bf53db3eca0c6f
Software developer. Currently building on Bitcoin Cash (BCH) & Nostr.

What are the odds? I was just debugging some poor state management leading to pumps being accumulated wrongly. And simulatenously users start pumping the very post I used for a small test pump. Debugging a live service can be challenging. Still appreciated though. nostr:npub1s024kwkjt9ymyg66la2n9l6d0vc0suuwxkr782gxzg6cwvpxs0vs9ts66n

https://cdn.nostrcheck.me/2e1b0646bb603b8c4febc648a2801d7134d18b5a766ad2bb87bf53db3eca0c6f/7cf029abc36cfae8ef7d5c80f9e0f232746e4be095968f6368f9704e703dd722.webp

From "Flowee" / Tom on X:

Today we talked about what our metrics of success are for Bitcoin Cash.

The first observation is that most websites graph the price. This, to most is the beginning and end of it. But that is largely irrelevant for a peer to peer cash.

Lets look with transaction volume. Can't claim to have a lot of usage if you have no transactions.

Using the excellent 3xpl we can see that:

Bitcoin Cash has about 2½ times the volume of Monero.

Bitcoin Cash has about half the volume of Litecoin.

Bitcoin Cash has about a quarter of the volume of BTC.

Mind you, we don't really know how much of that BTC volume is Ordinals.

And to complete the payment coins comparison: we have about 10x the volume of Dash.

Bitcoin Cash does roughly every day 100.000 transactions. With every other day peaking at half a million transactions. With 2 million tx/day peaks too.

For a world wide peer to peer cash, I would argue this is pretty good. Frankly, the volumes are amazingly stable year over year.

Growth would be nice, but the most important part is that 100k tx/day is clearly showing a lot of interest. People are using this.

It has been hard to find graphs on actual transaction volume, everyone is focusing on price. Historical price charts are everywhere. We are really in the time of traders and betting. And that distorts the entire industry.

Focusing on our strengths may be something we need to repeat more often.

Replying to Avatar Marius Kjeldahl

When writing Nostr clients, working with relays are \"challenging\" to say the least. There is little information stating exactly how it \"should\" be done. A lot of relays are misbehaving, or at least are punishing people messing up their own clients. Relays might accept connections, but not react to anything. Or they might react but with usage limits (connections and/or a limit on the number of simultaneous pending requests).

When a traditional (\"X style\") Nostr client starts up, there is a lot of things to be done. You need to fetch user metadata on the currently logged in user, including some profile data, followers list, relay list and similar.

Then you need to connect to the relays and ask for historical posts (nobody wants a blank feed). So you connect to each relay in the user relay list and they will throw events at your like there is no tomorrow. At least the ones that bother to reply.

So now you have lots of events. Guess what you now need to do? For each one of these, you need to get the user metadata for the poster (people want to see who is posting). If it's a repost, you might want to fetch the original post as well (there's a couple of different ways Nostr handles this). And if it's a reply, you might want to show that it is a reply (and to which user and which post). Yeah, more requests to relays.

So with your recently populated list of historical posts, you know have lots of queries to the relays to fill in the missing pieces for each post (at least for reposts and replies). So you start hitting the relays again.

So this is where you need a relay connection pool manager. You want to avoid reconnecting to all the relays for each query/subscription, because this takes time, and relays do not appreciate you eating all their sockets. Fine, just send them over the same connection then. Well, the relays don't like too many pending requests/subscriptions either. So if you hit some magical number - typically 10 - the relays will start rate limiting you, and not accepting new queries. And keep in mind relays might have different \"politics\" on how to handle this.

For my own client - Pumpstr - I initially tried to use the pool manager that comes with nostr-utils. It's a great resource, but the pool manager does not really work for clients. It works great as a starting point to learn about Nostr, but you can not rely on this when writing a \"full\" Nostr client. It's just too primitive. It really does not have the concept of \"subscriptions\" versus \"relay connections\", and when closing a subscription it will typically also kill your relay connections. Good like trying to writing a well behaved Nostr client with that.

So I rabbit holed this deeply (as usual), and rewrote my own Nostr connection pool manager. It now tracks the number of pending queries/subscriptions on a per relay basis, and connections are independent from subscriptions. When a relay disconnects you - they will periodically - it also automatically resubscribes to existing subscriptions.

It might not be perfect just yet, but it is getting pretty damned close!

Posting and "quotes" works fine. The misquoted quotes is because I had to rescue the original post from a browser log after it failed the first time. And that quoted them which I forgot to clean up before trying to post again.

When writing Nostr clients, working with relays are \"challenging\" to say the least. There is little information stating exactly how it \"should\" be done. A lot of relays are misbehaving, or at least are punishing people messing up their own clients. Relays might accept connections, but not react to anything. Or they might react but with usage limits (connections and/or a limit on the number of simultaneous pending requests).

When a traditional (\"X style\") Nostr client starts up, there is a lot of things to be done. You need to fetch user metadata on the currently logged in user, including some profile data, followers list, relay list and similar.

Then you need to connect to the relays and ask for historical posts (nobody wants a blank feed). So you connect to each relay in the user relay list and they will throw events at your like there is no tomorrow. At least the ones that bother to reply.

So now you have lots of events. Guess what you now need to do? For each one of these, you need to get the user metadata for the poster (people want to see who is posting). If it's a repost, you might want to fetch the original post as well (there's a couple of different ways Nostr handles this). And if it's a reply, you might want to show that it is a reply (and to which user and which post). Yeah, more requests to relays.

So with your recently populated list of historical posts, you know have lots of queries to the relays to fill in the missing pieces for each post (at least for reposts and replies). So you start hitting the relays again.

So this is where you need a relay connection pool manager. You want to avoid reconnecting to all the relays for each query/subscription, because this takes time, and relays do not appreciate you eating all their sockets. Fine, just send them over the same connection then. Well, the relays don't like too many pending requests/subscriptions either. So if you hit some magical number - typically 10 - the relays will start rate limiting you, and not accepting new queries. And keep in mind relays might have different \"politics\" on how to handle this.

For my own client - Pumpstr - I initially tried to use the pool manager that comes with nostr-utils. It's a great resource, but the pool manager does not really work for clients. It works great as a starting point to learn about Nostr, but you can not rely on this when writing a \"full\" Nostr client. It's just too primitive. It really does not have the concept of \"subscriptions\" versus \"relay connections\", and when closing a subscription it will typically also kill your relay connections. Good like trying to writing a well behaved Nostr client with that.

So I rabbit holed this deeply (as usual), and rewrote my own Nostr connection pool manager. It now tracks the number of pending queries/subscriptions on a per relay basis, and connections are independent from subscriptions. When a relay disconnects you - they will periodically - it also automatically resubscribes to existing subscriptions.

It might not be perfect just yet, but it is getting pretty damned close!

Test posting from my own Nostr connection pool library.

Hey thanks a bunch for giving it a spin again. I'm currently rewriting the relay connection manager to make everything even more solid before making another push for more usage. While there are a few open source tools for handling relays and connection pools (nostr-tools...), most of them behave poorly under pressure, and end the client end up fighting with the relays for stable connections. Stay tuned.

Not sure if I'm doing anything wrong or not when talking to Nostr relays. But when I try to look up "replies" (kind 1&6, combined with an "e tag" search), it consistently takes around 4 seconds or longer. Sure, I can "cache" anything, but hammering relays for caching a "start view" of some 50 Nostr posts and all their replies also doesn't seem very nice.

I now have a Nostr client running, Pumpstr, that supports reading, replying and reposting. Let's see if pumps are still working (I will try to pump this post). If so, another nice set of features would be to display aggregated likes and reposts, in addition to pumps. Looks like many clients do not do this until a post is selected, so it may be a bit heavy on the relays for the "all posts" view. Time will show.

First reply from the very same!

First post from my very own Pumpstr, a Nostr client with integrated BCH pumps!

Use Javascript, and React (or even Vue, seems popular as well). Code everything server and client side in the same language, and you can even re-use code client- and server side (the infamous "common" folder). Then WHEN or IF you have enough success that scalability or a huge userbase makes it practical, then you can become a language snob and reimplement everything natively on whatever computer you are running on. javascript+node.js is good enough to move really fast and you can focus on building a userbase before becoming bogged down in learning a bunch of "not needed yet" stuff. You'll do better with flexible technology you know really well and can use everywhere rather than having to learn the "optimal choice" for every little sub-decision you need to make on your journey.

Anybody knows why picture in picture mode on Chrome on Mac does NOT display in ALL desktop/workspaces? On Safari it does.

Chrome on Android doesn't like websockets without a full URL (Chrome on desktops, Safari and Mobile Safari accepts it). Fixed now. Thanks again.

Thanks, will look into it asap. I've tested desktop and iOS/iPhone only lately (should have mentioned that). Sorry for the inconvenience.