Skip to content

BUD-07 Paid storage #29

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 30 commits into
base: master
Choose a base branch
from

Conversation

quentintaranpino
Copy link
Contributor

@quentintaranpino quentintaranpino commented Sep 10, 2024

BUD-07 Paid upload and download

This pull request introduces BUD-07, a new specification outlining how servers can require and handle payments for blob storage. It defines the use of 402 Payment Required responses, with payment details provided via X-{payment_method} headers adhering to method-specific standards like Cashu (NIP-18) and Lightning (BOLT-11).

The specification is designed to be extensible for future payment methods and includes guidance on client-server interactions.

Readable version here

@quentintaranpino quentintaranpino changed the title BUD07 Paid storage BUD-07 Paid storage Sep 10, 2024
Copy link
Owner

@hzrd149 hzrd149 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great, a few formatting fixes and one comment. but I really like how simple this is

@quentintaranpino
Copy link
Contributor Author

L402 has been discarded in favor of a simpler approach that maintains the overall intent while adding compatibility with any L2, and potentially even other payment methods.

@hzrd149 hzrd149 mentioned this pull request Nov 11, 2024
@quentintaranpino
Copy link
Contributor Author

New version for the PR. This new version replaces the generic X-Payment header with dedicated headers for each supported payment method (e.g., X-Cashu, X-Lightning). This change improves clarity, scalability, and compatibility with future payment systems.

@quentintaranpino
Copy link
Contributor Author

  • Clarified the usage of X-{payment_method} headers to include payment details per specification of each method.
  • Adjusted schema to indicate encoding aligns with the corresponding method's spec (e.g., NUT-18 for Cashu, BOLT-11 for Lightning).
  • Improved examples for both X-Cashu and X-Lightning headers with real-world use cases.
  • Enhanced client implementation details, specifying that payment proof aligns with the selected method's spec.
  • Added extensibility guidelines for future payment methods, emphasizing publicly available specifications.
  • Updated error handling to include refreshed payment details on failure.

@quentintaranpino
Copy link
Contributor Author

Added recurring payments section with support for Cashu (NIP-61) and Lightning (NIP-57), requiring an 'x' tag for blob hash reference.

Co-authored-by: hzrd149 <[email protected]>
@hzrd149 hzrd149 mentioned this pull request Jan 2, 2025
@v0l
Copy link
Contributor

v0l commented Feb 2, 2025

Would it not be better to have a simple POST /payment and a way to check quota like GET /account?

Returning 402 status on upload makes sense when quota is exceeded but automatically returning an invoice seems wrong.

@v0l
Copy link
Contributor

v0l commented Feb 2, 2025

Im looking to implement payments in route96 and i think a "standard" approach would be better, should i make a PR for my idea of payments?

@quentintaranpino
Copy link
Contributor Author

quentintaranpino commented Feb 2, 2025

Would it not be better to have a simple POST /payment and a way to check quota like GET /account?

Returning 402 status on upload makes sense when quota is exceeded but automatically returning an invoice seems wrong.

I see what you mean, but I don’t think it’s incompatible. This BUD is just about what happens when you try to access a paid resource, it lays out the expected behavior when payment is required.

In my server (which this BUD is up and running 🤓), the client does a HEAD /upload, gets the cost of the upload (which could be 0 if they have balance), and then decides whether to pay or not. These kinds of decisions are up to the server admin, so I wouldn’t go into that in this BUD. Keeping it simple is best! 😊

But if you’re thinking of submitting another BUD for managing user accounts, I’ve got some ideas for GET /account, it could return more useful data beyond just the pubkey balance.

As for the POST you mentioned, maybe it could be a more general PUT/account endpoint, where users could manage their account settings on the server, create accounts?, and why not, also add funds. What do you think?

@quentintaranpino
Copy link
Contributor Author

@v0l you can try it here:

https://playground.nostrcheck.me/

@hzrd149
Copy link
Owner

hzrd149 commented Feb 8, 2025

Im looking to implement payments in route96 and i think a "standard" approach would be better, should i make a PR for my idea of payments?

I would encourage you to use this BUD for payments, it only covers 402 payment requests per API call and not an account based system but as @quentintaranpino mentioned its implemented in nostrcheck and a new server by Leito
https://njump.me/nevent1qvzqqqqqqypzqmajvcqjcvqgxql9ftj4zs95d9t7n9uqnpqpmk357nvjrgn4h79mqyghwumn8ghj7mn0wd68ytnhd9hx2tcpz4mhxue69uhhyetvv9ujuerpd46hxtnfduhsqgqqqxj9uk777zexucqg003wrr6cdhsukjc94hdhkhukdhmsrg6wqvpslfw0

The only reason I have not merged this BUD yet is because I've been lazy and have neglected to make one last change for the X-Cashu header


### `X-Cashu` Header

When using the X-Cashu header, the server MUST adhere to the [NUT-18](https://github.com/cashubtc/nuts/blob/main/18.md) standard.
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
When using the X-Cashu header, the server MUST adhere to the [NUT-18](https://github.com/cashubtc/nuts/blob/main/18.md) standard.
When using cache for requesting payment for an endpoint, the server MUST respond with a `X-Cashu` header containing a base64 encoded JSON object (payment request)
The payment request should contain an `amount`, `mints`, `unit`, and `pubkey` fields
- `amount` The amount of ecash being requested
- `mints` An array of mints that this server uses
- `unit` The cashu `unit` from the `mints`
- `pubkey` (optional) a 33 byte pubkey to lock the tokens too. see [NUT-11](https://github.com/cashubtc/nuts/blob/main/11.md)
For example:
\`\`\`json
{
"amount": 21,
"unit": "sats",
"mints": ["https://mint.minibits.cash/Bitcoin"],
"pubkey": "02a82ec539a2bbd51039c480e8836316036ccb461b9a2e62b49b418c2897851b98"
}
\`\`\`
Would be encoded into
\`\`\`http
HTTP/1.1 402 Payment Required
X-Cashu: eyJhbW91bnQiOiAyMSwidW5pdCI6ICJzYXRzIiwibWludHMiOiBbImh0dHBzOi8vbWludC5taW5pYml0cy5jYXNoL0JpdGNvaW4iXSwicHVia2V5IjogIjAyYTgyZWM1MzlhMmJiZDUxMDM5YzQ4MGU4ODM2MzE2MDM2Y2NiNDYxYjlhMmU2MmI0OWI0MThjMjg5Nzg1MWI5OCJ9
\`\`\`

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Finally starting this discussion, I think the X-Cashu header from the server should be a base64 encoded JSON object instead of a NIP-18 payment request

The reason is because NIP-18 requires a transport method (http post, or nostr) and has no concept of paying the request using the same method that the request was delivered in

Also the format and encoding benefits of NIP-18 are geared towards showing the payment request to the user as a QRCode, but the primary use case of the X-Cashu header is clients and machines automatically responding with a payment in-band

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