-
Notifications
You must be signed in to change notification settings - Fork 47
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
NUT-XX and NUT-XX+1: Mint / Melt Bitcoin On-Chain #107
base: main
Are you sure you want to change the base?
Conversation
looks great so far, nice work! question about the minting How do we know when the payment is complete? Do we just try to proceed with mint, and see if it works? Or is there a way to look up the Also, is there a way to let the client know, how many more confs are required, before the mint can take place? Last question, what happens if the tx confirmation time exceeds the expiry? |
18.md
Outdated
The mint can return multiple `PostMeltQuoteBtcOnchainResponse` with different `fees` and `expiry` dates. The wallet can choose which one to pay and the other ones will expire. Where `quote` is the quote ID, `amount` the amount that needs to be provided, and `fee` the additional fee that is required. The mint expects `Alice` to include `Proofs` of *at least* `total_amount = amount + fee`. `paid` indicates whether the request as been paid and `expiry` is the Unix timestamp until which the melt quote is valid. | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it's worth mentioning that there are (at least) two ways of handing the variable fee rate problem here.
One option could be that the wallet chooses a fee in PostMeltQuoteBtcOnchainRequest
this would be a bit like a Lightning node choosing the max_fee
for a payment. The mint could then respond with a response or an error depending on whether it agrees. I think this would have to accompanied with some info setting where the mint announces it's accepted fee range.
The other option, as you've proposed, would be for the mint to limit the users's choices by returning multiple melt quotes.
Did you consider the first option as well? I wonder if it has any benefits. Happy to hear thoughts from others on this as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Interesting idea. No haven't thought about it yet.
You can use the following endpoint as per
This would be cool but I suspect it won't be generally possible to determine this number with every on-chain backend. Take for example a service like Strike or Blink. Obviously, this would be possible with a bitcoin core, lnd, cln, ... on-chain wallet.
That's a very good question. While LN invoices can have a clear expiry, on-chain is a bit more tricky. It might be worth to consider removing this from onchain mints. I think melt expiry doesn't have this problem. |
17.md
Outdated
"quote": <str>, | ||
"address": <str>, | ||
"paid": <bool>, | ||
"expiry": <int> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This expiry field might be problematic (cf @gandlafbtc's comment).
Awesome NUT, feels complete! Looking forward to implementing it. Left a few comments, I don't see any issues other than the |
Co-authored-by: callebtc <[email protected]>
Co-authored-by: callebtc <[email protected]>
Co-authored-by: thesimplekid <[email protected]>
Good point. I think it's problematic in both way: A wallet could choose a fee that is to low to get in the next block before the quote expires. |
Worth noting that for sat denominated quotes a long expiry is fine, but for units with an exchange rate (ie sat/usd) it introduces some risk to the mint where wallets could attempt to arbitrage the exchange rate since its up to them to execute the quote or not so i don't think long expiry times should be recommended for non sat units. EDIT: Is this NUT limited to only the sat unit like NUT04? if so the above can be ignored. |
This comment was marked as resolved.
This comment was marked as resolved.
18.md
Outdated
GET https://mint.host:3338/v1/melt/btconchain/{tx_id} | ||
``` | ||
|
||
The mint `Bob` responds with a `GetMeltBtcOnchainResponse`. | ||
|
||
```json | ||
{ | ||
"paid": false | ||
} | ||
``` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is this paid
field different than calling GET /v1/melt/quote/btconchain/{quote_id}
and getting that paid
status there?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this should be removed. I don't see any benefit over just using GET /v1/melt/quote/btconchain/{quote_id}
.
A related open question I have is should the mint broadcast the transaction as soon as it receives valid proofs for the melt, or can the mint decide to wait and include it in a batch of multiple melts?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this should be removed. I don't see any benefit over just using
GET /v1/melt/quote/btconchain/{quote_id}
.
yeah
A related open question I have is should the mint broadcast the transaction as soon as it receives valid proofs for the melt, or can the mint decide to wait and include it in a batch of multiple melts?
interesting. That will require some changes to the response of the quote state call
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I removed the redundant GET https://mint.host:3338/v1/melt/btconchain/{tx_id} endpoint
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this should be removed. I don't see any benefit over just using
GET /v1/melt/quote/btconchain/{quote_id}
.A related open question I have is should the mint broadcast the transaction as soon as it receives valid proofs for the melt, or can the mint decide to wait and include it in a batch of multiple melts?
IMO the mint can decide if it wants to batch transaction or not. This is same as centralized btc exchanges handle this. We could add a property to the info-endpoint to signal that a mint might delay the melt for batching, but I don't think this is necessary
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IMO the mint can decide if it wants to batch transaction or not. This is same as centralized btc exchanges handle this. We could add a property to the info-endpoint to signal that a mint might delay the melt for batching, but I don't think this is necessary
I think we do need to signal this and it needs to be more concrete then the mint may delay. I would suggest we add a time component to the MeltQuoteResponse
this way if the user wants the withdrawal more quickly they will need to pay a higher fee if they are willing to wait and allow the mint to batch they can select a Quote
with a lower fee and wait longer.
Allowing the mint to delay for batching but not defining what a delay means will lead to a bad user experience where they don't know when their transaction will be process and they may need it immediately and be willing to pay for that.
This comment was marked as resolved.
This comment was marked as resolved.
Co-authored-by: thesimplekid <[email protected]>
Co-authored-by: thesimplekid <[email protected]>
No idea if this is relevant but was reviewing it and thought of this thread/PR/NUT.
|
17.md
Outdated
```json | ||
{ | ||
"amount": <int>, | ||
"unit": <str_enum["sat"]> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"unit": <str_enum["sat"]> |
Note: All PostMintQuoteBtcOnchainRequest
's are denominated in sat.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why should we remove the unit-field from the PostMintQuoteOnchainRequest? If the mint uses blink as a backend for handling the onchain transactions it can support onchain snd/receive with usd as a currency. Hopefully in the future there will be similar services. https://dev.blink.sv/api/usd-onchain-send
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a question of scoping this NUT. To support other units where a conversion rate is involved how expiration is handled as well as how confirmation time is defined is much more important as the conversion rate could change outside an acceptable slippage. So in order to support other units how confirmation and expiration is defined needs to be included as well.
So what should we do? I think it would be best to change the expiry for mint-requests to optional so a mint can use a expiry for usd based mints and no expiry for sat based mint requests? Any other suggestions @gandlafbtc @callebtc @thesimplekid |
Co-authored-by: thesimplekid <[email protected]>
Co-authored-by: thesimplekid <[email protected]>
The issue with on chain is there is no way to expire an address unlike ln, so how is a deposit after an expiration handled is it considered a donation to the mint? If that is that case I think that needs to be made explicit. I think this maybe okay since even in the case of removing expiration that is effectively the case if a deposit is made to a mint that is no longer in operation (if the mint operator still has the keys), so having the explicit handling of expiration might be an improvement. Of course there is the opportunity for a benevolent mint operator to settle a quote paid after out of band if they are known or have contact info set in the NUT-06. I noticed this is how the strike api handles it, though that has its own trade offs. As i mentioned above definition of confirmation needs to be included as well with the expiration to signal what needs to happen before the expiration in order for the quote to be settled, num blocks conf, transaction broadcast. This could even be split for example transaction needs to be broadcast before x time to get the exchange rate, but ecash wont be issued until x confirmations. |
Yes, good point. I have added min_confirmations to the info-endpoint |
"address": "bc1qkyfgd7mus7ykfd7qkwakq75qsf7rtm...", | ||
"state": "UNPAID", | ||
"expiry": 1701704757 | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it worth adding the txid here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It might though this question made me think what if a a quote is payed with multiple transaction, I think that should still be valid? So to cover that it would need to be a list of txid? Unless we explicitly say it MUST be paid in one tx.
``` | ||
|
||
The wallet **MUST** store the `amount` in the request and the `quote` id in the response in its database so it can later request the tokens after paying the request. After payment, the wallet continues with the next section. | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it would be worth adding a note here that wallets SHOULD display the quote as a BIP21 URI or BIP21 URI encoded as a QR code to the user. This would help reduce errors of underpaying or overpaying accidentally.
NOTE: There is a draft to replace BIP21 bitcoin/bips#1555 but as its backwards compatible i suggest we say bip21 for now and can update later.
I wonder if we want to allow minting/melting on Liquid chain and if yes, then whether it should be part of these two nuts or a new pair of nuts. |
I think it makes more sense to keep separate NUTS, especially since its support should be signaled differently by NUT-06. |
Ah yes, that is indeed a good reason. |
It does not necessarily impact the spec, but something like this should be the recommended way to handle address generation: https://blog.zaprite.com/optimizing-address-usage-for-the-gap-limit/ |
```json | ||
[ | ||
{ | ||
"quote": <str>, | ||
"description": <str|null>, | ||
"amount": <int>, | ||
"fee": <int>, | ||
"state": <str_enum[STATE]>, | ||
"expiry": <int> | ||
} | ||
] | ||
``` | ||
The mint can return multiple `PostMeltQuoteBtcOnchainResponse` with different `fees` and `expiry` dates. The wallet can choose which one to pay and the other ones will expire. Where `quote` is the quote ID, `amount` the amount that needs to be provided, and `fee` the additional fee that is required. The mint expects `Alice` to include `Proofs` of *at least* `total_amount = amount + fee`. `paid` indicates whether the request as been paid and `expiry` is the Unix timestamp until which the melt quote is valid. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It maybe better if we express fee in sats but also with a time component. This would allow the mint to batch transactions. For example fee of x sats will be paid within the hour, fee of y sats within the day etc. This leaves it up to the mint to actually set the final sats per vbyte to meet whatever time period they agreed to in the quote.
```json | ||
{ | ||
"amount": <int>, | ||
"unit": <str_enum["sat"]> | ||
} | ||
``` | ||
with the requested `amount` and the `unit`. | ||
|
||
The mint `Bob` then responds with a `PostMintQuoteBtcOnchainResponse`: | ||
|
||
```json | ||
{ | ||
"quote": <str>, | ||
"address": <str>, | ||
"state": <str_enum[STATE]>, | ||
"expiry": <int> | ||
} | ||
``` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If unit is included here don't we need to add an amount in sats to the quote response so the mint can signal the exchange rate. Otherwise if it is non bitcoin unit the wallet will not know how much bitcoin to send to the address to fill the quote.
That being said because of the imprecise nature of sending a bitcoin onchain transaction I would be for removing the unit and limiting it to sat denominated quotes.
First draft for minting and melting tokens On-Chain.