Skip to content

Conversation

abh3po
Copy link
Contributor

@abh3po abh3po commented Sep 23, 2025

  • Allows backends to work without cloud providers.
  • You wouldn't need a reverse tunnel to reach your backend.

Server Implementation: https://github.com/abh3po/nrpc_server
Client Implementation: abh3po/nostr-forms#383

cc: @fiatjaf @staab @vitorpamplona

@vitorpamplona
Copy link
Collaborator

I am not sure if it makes sense to make general kinds for all RPC calls. Usually, each RPC service has its own little tweaks in the payload structure that can be better handled by its own NIP with a specific event kind just for them, similar to how NIP-47 and NIP-46 do.

@abh3po
Copy link
Contributor Author

abh3po commented Sep 23, 2025

@vitorpamplona Each http api has its own structure and contract. But we still follow the same status codes and over all generic structure, following a generic protocol will help us reuse all the repeated code for request and response cycling since most people can reuse the same things.

We can always make specific stuff and specific nips for usecases where they are actually needed

@staab
Copy link
Member

staab commented Sep 23, 2025

How is this different from DVMs? I'm with @vitorpamplona, I don't think there's much benefit to defining a framework beyond nostr event kinds that have their own schema/flows. See #1942 for more discussion about this.

@pippellia-btc
Copy link

This is almost identical to what Vertex runs in production, which is inspired by NIP-90 aka DVMs (see this example).

  • Instead of the method tag, we use different kinds.

  • Instead of the result tag, we use the content field.

So yeah, I kind like the idea.

@vitorpamplona
Copy link
Collaborator

we still follow the same status codes and over all generic structure,

That's just a design pattern. Not really a NIP IMO.

following a generic protocol will help us reuse all the repeated code for request and response cycling since most people can reuse the same things.

I don't think that code reuse will EVER happen. Everyone tries to make general things in Nostr just to die off later when everyone just specializes in their own nips and event kinds, with so many tweaks that make general things too complex to manage all the differences. I just spent a huge amount of time de-generalizing Amethyst as a whole. The code gets much simpler, faster, and better when each implementation has the freedom it needs to do its own thing.

@abh3po
Copy link
Contributor Author

abh3po commented Sep 23, 2025

@staab DVMs serve a different purpose those are public advertisements of services for specific jobs, although your rewrite changes that a bit, it's still similar. NRPC calls could be for your own private home automation, a specific service that has nothing to do with the rest of the world, everybody could use it. It's meant as a replacement for HTTP. Both have different problems they are trying to solve, there maybe an overlap but the existence of one doesn't deny the existence of the other.

@abh3po
Copy link
Contributor Author

abh3po commented Sep 23, 2025

@vitorpamplona code reuse happens all the time with nostr-tools and other stuff.

If code reuse doesn't happen, it's alright, this is just a way to do procedure calls over nostr, I outlined it, formstr is going to use it, and if anyone else wants to do it similarly, the spec exists here, I will update it for private comms when i implement it.

I'm coolbeans with nostr repo masters not merging it because they have some high and powerful vision of exactly how things should be.

I'm okay with answering technicals and solving real problems with the spec if they exist.

I'm not going answer existential questions on why this spec shouldn't exist because it is in conflict with something.

@vitorpamplona
Copy link
Collaborator

code reuse happens all the time with nostr-tools and other stuff.

Lol, yeah, I have seen it and used it. It sucks. Anyway...

I outlined it, formstr is going to use it

That's great. Then do a NIP for the exact params, methods, and formats formstr will be using so that other clients can code it too and integrate with formstr specifically. Don't do a generic NIP that is intended to solve all RPC use cases. That's never going to solve everybody's needs at the same time and will just keep you frustrated that no one will ever merge because it doesn't please all use cases.

@abh3po
Copy link
Contributor Author

abh3po commented Sep 23, 2025

@vitorpamplona This is exactly what formstr uses, anyone can create any form and the values are passed as params which are different for each form. This is exactly the nip it needs and can be easily extended to anything else.

And I do want to re-iterate that I dont care if this gets merged. So if you don't want to do it, its on you for keeping something beneficial away from the readers of this repo.

@vitorpamplona
Copy link
Collaborator

Sure, but then this text is missing a TON of information. For starters, what are the method names for the form creation and which params do what?

@abh3po
Copy link
Contributor Author

abh3po commented Sep 23, 2025

Method names can be different for different people formstr just calls the webhook with whatever method names the user configures,.and params are the questions and values are the users response to it.

@abh3po
Copy link
Contributor Author

abh3po commented Sep 23, 2025

@vitorpamplona is this useful feature too generic for you, should formstr remove it too?

@vitorpamplona
Copy link
Collaborator

Method names can be different for different people formstr just calls the webhook with whatever method names the user configures,.and params are the questions and values are the users response to it.

Cool, write that "user configuration" in. Where do those method names come from? Otherwise, there is no point in standardizing anything. Other clients need to know where to get those names, params, and formats they take, and so on. If we don't have that, clients will just be sending random requests to servers that only process other random requests, and then nothing never comes back.

@abh3po
Copy link
Contributor Author

abh3po commented Sep 23, 2025

@vitorpamplona service providers have their own method names, exactly like how http backends have different routes yet http exists as a protocol. I don't know why you want to control it and I don't like where you want this to head, so I won't be continuing this discussion further.

You obviously have the option to not merge it.

As I said, I'm fine with discussing technicals with whomever wants to discuss it. I will not entertain existential questions on this nip.

@vitorpamplona
Copy link
Collaborator

vitorpamplona commented Sep 23, 2025

I don't want to control it. I just want to know what they are or where to get them so that I can code this. Right now, this NIP is completely unspecified. It's just a design pattern. There is no spec at all in this.

And again, I don 't care about any service provider. I care about what formstr is doing. I don't want to even see events with any other RPC call that is not from formstr because I am not going to support that anyway.

@abh3po
Copy link
Contributor Author

abh3po commented Sep 23, 2025

@vitorpamplona at Max I can add a "getMethods" recommendation for service providers so clients can see what methods are callable for each npub with what Params they expect, but surely you have to understand that they are dynamic, and cannot and should not be written down in this spec.

@vitorpamplona
Copy link
Collaborator

vitorpamplona commented Sep 23, 2025

Sure, whatever you need to do to tell people how to code this. I need the method names; params, types, encoding and defaults, for each method. And then for each method, the format of the reply, with the description of the encoding used, types, etc. If error messages that are custom to the problem, they MUST also be defined somewhere.

Otherwise, there is no interoperability. Just people coding their own methods. And for that, there is no need for any NIP.

@staab
Copy link
Member

staab commented Sep 23, 2025

@abh3po if there's nothing concrete in the spec, or the spec doesn't drastically reduce implementation complexity, there's no basis on which interoperability can happen, and therefore no justification for a spec.

There is a case to be made for abstractions; in fact, we need some: signatures, encryption, event serialization for example. But every abstraction comes with a few different costs. In particular the need to trace complex dependencies, making specs harder to understand, and harder to change or adapt to particular use cases. There are many cases in which nostr specs are already overly abstract, with little benefit and plenty of headache: "global" tags, DVMs, kind ranges, NIP 32 labels, etc.

One interesting exception to this is NIP 59, which is a NIP that does only contain an abstract pattern. The reason I think this was the correct call is that it's not only widely applicable (as this PR is), but also complex enough to warrant a generic, shared implementation. In most cases though, establishing conventions apart from concrete use case provides almost no benefits. Using a result tag instead of a content tag depending on use case is not difficult, and doesn't warrant an abstraction.

Also: PRs are not where you ask permission to do something on nostr, they're a place to ask for feedback from other nostr developers. IMO, this PR only establishes meaningless standardization, but that's just my opinion. If you want to evangelize for this pattern, go right ahead (although if you take my advice, it would be better to merge it not as an abstraction, but as a common pattern between NIPs).

@abh3po
Copy link
Contributor Author

abh3po commented Sep 23, 2025

Sure, whatever you need to do to tell people how to code this. I need the method names; params, types, encoding and defaults, for each method. And then for each method, the format of the reply, with the description of the encoding used, types, etc. If error messages that are custom to the problem, they MUST also be defined somewhere.

@vitorpamplona sure, but that cannot be a part of the nip, the nip can atmost outline how you can request something like that from a service provider.

I will add this.

@abh3po
Copy link
Contributor Author

abh3po commented Sep 23, 2025

@abh3po if there's nothing concrete in the spec, or the spec doesn't drastically reduce implementation complexity, there's no basis on which interoperability can happen, and therefore no justification for a spec.

There is a case to be made for abstractions; in fact, we need some: signatures, encryption, event serialization for example. But every abstraction comes with a few different costs. In particular the need to trace complex dependencies, making specs harder to understand, and harder to change or adapt to particular use cases. There are many cases in which nostr specs are already overly abstract, with little benefit and plenty of headache: "global" tags, DVMs, kind ranges, NIP 32 labels, etc.

One interesting exception to this is NIP 59, which is a NIP that does only contain an abstract pattern. The reason I think this was the correct call is that it's not only widely applicable (as this PR is), but also complex enough to warrant a generic, shared implementation. In most cases though, establishing conventions apart from concrete use case provides almost no benefits. Using a result tag instead of a content tag depending on use case is not difficult, and doesn't warrant an abstraction.

Also: PRs are not where you ask permission to do something on nostr, they're a place to ask for feedback from other nostr developers. IMO, this PR only establishes meaningless standardization, but that's just my opinion. If you want to evangelize for this pattern, go right ahead (although if you take my advice, it would be better to merge it not as an abstraction, but as a common pattern between NIPs).

@staab
I do not request permission.

I'm sharing this NIP for technical feedback, not a moral lecture.

I take @vitorpamplona 's recommendations for adding a way to integrate into clients, because it is good feedback and makes the NIP better.

I don't know what to do with any of your comments other than taking notes of what are the bureaucratic necessities for getting a NIP merged in this repository, but thats just my opinion.

@vitorpamplona
Copy link
Collaborator

I don't know what to do with any of your comments other than taking notes of what are the bureaucratic necessities for getting a NIP merged in this repository, but thats just my opinion.

I think you are missing the point of this repo and this process, @abh3po

NIPs either completely specify how things should be coded to drastically reduce implementation complexity in such a way that it allows devs to declare full compliance to EVERYTHING that can eventually happen there, or there is no need for the NIP.

There is no way to declare compliance with this NIP because I don't know what methods and answers are available so that I can code this in a way that Amethyst can interact with ANY provider without having to hardcode payloads that are specific to each of them. If I have to hard-code stuff for each provider, then the NIP is irrelevant.

@abh3po
Copy link
Contributor Author

abh3po commented Sep 23, 2025

@vitorpamplona @staab i think you guys are being too bureaucratic with what you think deserves to be a NIP. I don't even care about this one getting in. Just the idea that someone could come up with something brilliant and path breaking and yet their stuff would never see the light of day, because it doesn't meet your standards, which I dont think align with the ethos of the protocol. As for this NIP, I'm going to update it, with what's discussed and some more. But I do not agree with your ideas about NIPs being specific, I think you're just robbing yourselves of what's possible by sticking with this hardline rigidity.

@vitorpamplona
Copy link
Collaborator

vitorpamplona commented Sep 23, 2025

I think you guys are being too bureaucratic with what you think deserves to be a NIP

I don't know what you mean about bureocracy... All we are saying is that the NIP doesn't do anything... yet. As it stands, it's just an IDEA, not a spec in any way. The key work in this spec is to define how to get the methods so that multiple clients and service providers can actually code it without having to talk to one another to figure out what they need as payloads.

Also, using RPC in Nostr is nothing new. If we just want to define how to use RPC in Nostr, we can just use NIP-46, NIP-47 as an idea. This notion of "Sovereign Backends" already exist in different NIPs, including as DVMs.

So, again, the work is on defining how many methods are available, what do they do, how to get data back and what is the exact format of each method so that we don't need to hardcode each other's clients.

@abh3po
Copy link
Contributor Author

abh3po commented Sep 23, 2025

I think you guys are being too bureaucratic with what you think deserves to be a NIP

I don't know what you mean about bureocracy... All we are saying is that the NIP doesn't do anything... yet. As it stands, it's just an IDEA, not a spec in any way. The key work in this spec is to define how to get the methods so that multiple clients and service providers can actually code it without having to talk to one another to figure out what they need as payloads.

Also, using RPC in Nostr is nothing new. If we just want to define how to use RPC in Nostr, we can just use NIP-46, NIP-47 as an idea. This notion of "Sovereign Backends" already exist in different NIPs, including as DVMs.

So, again, the work is on defining how many methods are available, what do they do, how to get data back and what is the exact format of each method so that we don't need to hardcode each other's clients.

@vitorpamplona even without getMethods, this is how amethyst can use it:

Let users set up their own automations (amethyst doesnt have to know what they are, just when to trigger them, with what params)

And the users can supply their own params for their own webhooks.

As long as users are listening on these event kinds and for their own pubkeys, where amethyst is making a request, they will be able to use it.

Users can make their own webhooks for scheduling posts, out of town replies on messages and anything they want.

Amethyst doesnt have to know what its calling. Users can tell it.

And this is the part that is bothering me about this discourse, this can happen right now, with the current spec, interoperably, which you guys are insistent on calling useless.

This is a formstr form configured with a webhook on my laptop if you want to test it out

https://beta.formstr.app/f/naddr1qvzqqqr4mqpzqd7cqdp95resewu0yl83n3te6xk7pm8ax36v7dse6xup40tv2nejqy2hwumn8ghj7un9d3shjtnyv9kh2uewd9hj7qqydejhweghnf02m?viewKey=6313a8ae5d07a0580e1d8324e3a7cd4cf571a3b82c07975c49484aa4c4e1e789

If you use this spec people can reuse the same webhook for formstr and amethyst. Im not sure how that is not interoperability.

@vitorpamplona
Copy link
Collaborator

How would my user tell Amethyst what to do with the response from that call? Yes, users can fill in urls and parameters, but this NIP needs so much more. Let's say a provider is returning Stock prices via this NIP, and the user asks for Apple Stock, how does Amethyst know what to do with the response?

That "Service" should just be a click on the $APPL ticker in any post. But in this NIP, the user needs to find the URL of the provider, discover how to write the parameter, write a value "APPL" everytime they need an updated price and request. And even with all that, the app doesn't know what to do with the answer, so it just shows a bunch of text in a popup. It's terrible design for what could have been just an automated "Apple ($APPL +3%) launched the new iPhone".

This is assuming, of course, that people would do this without any help, like figuring out the exact spelling and encoding of each parameter to be sent and having to manually type both the parameter name and its value, since Amethyst cannot know where to get it from and how to help the user.

If this is for Automations, why don't you focus the NIP on Automations instead of this 100x broader any-RPC-call-goes type of NIP? You could set up lots of little automation stacks in the NIP that people can just implement. For instance, my user could add an automation to pay their relays every month. But that automation needs a UI for approval and to make the payment. It can only be done if Amethyst knows what the call is actually trying to do.

@abh3po
Copy link
Contributor Author

abh3po commented Sep 23, 2025

Agreed, will expand it, should be expanded, my issues are with calling it useless and not interoperable now, when I am clearly using it and it is super useful, and atleast the automations are interoperable even now.

@vitorpamplona
Copy link
Collaborator

my issues are with calling it useless and not interoperable now, when I am clearly using it and it is super useful, and atleast the automations are interoperable even now

It's great that you got something, but that doesn't mean it is interoperable. I, for once, have no idea what the service URL is, its parameters, or the result formats. It's useful for you, but not for anyone else at this point. That's not "interoperable" at all.

@abh3po
Copy link
Contributor Author

abh3po commented Sep 24, 2025

There is no service URL, there is a service npub.... that's kind of the whole point.

But its alright, I have a spec for introspection, I will test it and update this.

@abh3po
Copy link
Contributor Author

abh3po commented Sep 24, 2025

@vitorpamplona @staab updated the NIP with an introspection mechanism

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants