-
Notifications
You must be signed in to change notification settings - Fork 23
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
feat: Onboarding through a hodl invoice #2560
Conversation
Simulator.Screen.Recording.-.iPhone.15.-.2024-05-23.at.15.14.45.mp4🚀 |
d8e5b52
to
0bdeea6
Compare
31b2351
to
e113a8b
Compare
@bonomat I continued working on this and mainly tested the feature.
However, we need to introduce a minimum trader reserve for that as otherwise price movements could also result into a rejected order. (we need margin orders). I tried to add this to the ui, but failed, would be great if you could take over. |
@luckysori probably best to review the changed files. |
coordinator/migrations/2024-05-23-000406_hodl_invoice_table/up.sql
Outdated
Show resolved
Hide resolved
coordinator/migrations/2024-05-23-000406_hodl_invoice_table/up.sql
Outdated
Show resolved
Hide resolved
use sha2::Sha256; | ||
|
||
pub struct PreImage { | ||
// TODO(bonomat): instead of implementing `PreImage` we should create our |
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.
Note, only the hash needs to be url safe.
} | ||
|
||
pub async fn get_hodl_invoice_from_coordinator(amount: Amount) -> Result<HodlInvoice> { | ||
// TODO(bonomat): we might want to store this in the db so. |
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 don't think it's necessary..
a026c96
to
81d6e17
Compare
67a2bb4
to
4824f28
Compare
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 reviewed d81a770 and the logic seems sound.
If the external funding is insufficient, I think we should fail the whole thing earlier though. It seems to me like we have all the information available as soon as we get the match from the orderbook in process_new_market_order
, so we don't have to wait until we call open_dlc_channel
.
This will allow us to generically wrap a api model into a signed value model which covers the signature creation and verification.
4824f28
to
19a23f6
Compare
Thanks for you feedback, I've adapted the code, moved the check early and also now subtract the funding tx reserve and the channel fee reserve from the trader reserve. I think this is now ready to go, but I will wait for your final review and approval. |
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.
LGTM, I think this should work!
pub struct ChannelOpeningParams { | ||
pub trader_reserve: Amount, | ||
pub coordinator_reserve: Amount, | ||
pub external_funding: Option<Amount>, |
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 be simpler to just use Amount
, becase a zero amount and a None
are the same.
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.
hmm.. I kind of like the option better because it is a bit more expressive than automatically implying that a zero amount is a OpenSingleFundedChannel
match params.external_funding {
Some(external_funding) => {
TradeAction::OpenSingleFundedChannel { external_funding }
}
None => TradeAction::OpenDlcChannel,
}
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.
But what does it mean to have a 0-valued external_funding
then?
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.
Probably a bug. Any value below 250k is probably a bug.
EventType::PaymentClaimed, | ||
EventType::PaymentSent, | ||
EventType::PaymentFailed, |
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.
👀
mod position; | ||
mod unfunded_channel_opening_order; |
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.
🙃 Hmmm, we should align the terminology between coordinator and app.
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.
what do you mean? the coordinator doesn't know of an unfunded channel opening order.
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.
Yeah, I think you are right. I was confused at first because this is implicitly about a single-funded channel, which is a different name.
Maybe it would be clearer with unfunded_wallet_channel_opening_order
? The name would be annoyingly long though.
Creates a hodl invoices, subscribes to updates to it and returns the invoice to the app.
Co-authored-by: Richard Holzeis <richard@holzeis.me>
Before the button was jumping depending on whether the slider or the button was shown. I also changed the button text from "Confirm" to "Next" since there wouldn't be any semantical difference between funding with internal wallet or external.
The asterix was just not clear enough. I also did some minor styling improvements and removed the unused label argument from the fee expansion widget.
This will submit the order once a hodl invoice is paid. In the next step we have to extend the post order api to revail the pre image so that the coordinator can claim the payment and open a single sided channel.
api.rs should remain as a thin proxy to the flutter frontend.
we need to store the pre image to be able to refer to it later again. Also, it will help us get a good overview of who asked for what.
if the trader receives the note that the ln invoice has been funded, he shares the preimage with him when creating a new order. Upon receiving said preimage, the coordinator checks if the preimage fits to a known hash in the db. Next: redeem payment before matching the order
this is needed because we send a url_safe base64 version over the via.
If we received the lightning payment from the user we open the channel to the user with only the coordinator's funds. Co-authored-by: Richard Holzeis <richard@holzeis.me>
Otherwise, we might end up with "/" in the hash what will result in an endpoint not found error as the "/" is interpreted as path.
That should be enough to pay the lightning invoice and reduces the risk of price movements.
19a23f6
to
06909be
Compare
TraderRequiredLiquidity::None => ( | ||
margin_coordinator | ||
+ collateral_reserve_coordinator.to_sat() | ||
+ margin_trader | ||
+ collateral_reserve_trader | ||
// If the trader doesn't bring their own UTXOs, including the order matching fee | ||
// is not strictly necessary, but it's simpler to do so. | ||
+ order_matching_fee, | ||
0, | ||
dlc::FeeConfig::AllOffer, | ||
), | ||
TraderRequiredLiquidity::None => { | ||
( | ||
margin_coordinator | ||
+ collateral_reserve_coordinator.to_sat() | ||
+ margin_trader | ||
+ collateral_reserve_trader | ||
// If the trader doesn't bring their own UTXOs, including the order matching fee | ||
// is not strictly necessary, but it's simpler to do so. | ||
+ order_matching_fee, | ||
0, | ||
dlc::FeeConfig::AllOffer, | ||
) | ||
} |
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 nothing actually changed 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.
jap only the brakets have been added 🙈
let collateral_reserve_trader = params | ||
.trader_reserve | ||
.context("Missing trader collateral reserve")?; |
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 guess it's debatable, so none of this is a deal breaker at all.
What I dislike is leaking the knowledge of the external funding any further than necessary, and the fact that the trader_reserve
field is ignored, when it could be used to carry this information from the outside.
And I think we could avoid code duplication by reusing a helper function.
Introduces a lightning onboarding by leveraging an external lnd instance to manage a hodl invoice flow.
TODO:
In the next step we should look into the following issues.
Additionally we should look into adding an HTLC to our buffer transaction to make this swap trust less.