-
Notifications
You must be signed in to change notification settings - Fork 8
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
Add "receive payment" snippets for channel opening fees #122
Add "receive payment" snippets for channel opening fees #122
Conversation
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.
Looks good
@ok300 Let's try to communicate to the developers exactly how they should show the fees involved to the user. Maybe even in a separate section called 'Communicating fees'? What about something like this? ## Communicating fees
In the LSP model, fees are involved when the user wants to receive a payment, but doesn't have sufficient receivable amount. This section provides recommendations on how to communicate these fees to a user.
### Before receiving a payment
When the user wants to receive a payment, a setup fee is paid when the resulting invoice would exceed the receivable amount.
The setup fee is made up of two parts:
- A minimum fee
- A proportional fee based on the amount
Before creating an invoice, the amount the user will want to receive is yet unknown. It is recommended to show the user a message consisting of the following information:
`A setup fee of x% with a minimum of y sats will be applied for receiving more than z sats.`
Below code sample constructs this message.
(TODO: code sample)
### When an invoice is created
After calling receive_payment, you would typically show the recipient a screen containing a QR code with the invoice that the sender can scan.
This is another point to show the user the opening fees applied to the invoice. At this point the amount the user wants to receive is known, so the message can be more concise:
`A setup fee of x sats is applied to this invoice.`
The fiat amount can be included. In case of a mobile app it is recommended to communicate to the user that the app has to be run in the foreground in order to be able to receive the payment.
Below code sample constructs this message.
(TODO: code sample)
### Receive onchain
For receiving onchain, there is a minimum and a maximum amount the user can receive. The fees are made up of the same components as receiving a lightning payment.
The user gets a onchain address from receive_onchain. There is no way to know ahead of time exactly the amount that will be received on this address, so it is recommended to show the user the receivable boundaries and the fees involved:
`Send more than v sats and up to w sats to this address. A setup fee of x% with a minimum of y sats will be applied for sending more than z sats. This address can only be used once.`
Below code sample constructs this message.
(TODO: code sample) |
I think you can simplify the example and text using the |
Thanks @dangeross , that's exactly what I was looking for! |
Looking closer, Setting it to 0 will return no fees and no fee param. Setting it to a small amount like 1, could return no fee param if the user already has a channel. Maybe we need a similar SDK method to prepare all fee thresholds for the pre-invoice phase? pub async fn receive_payment_fee_info(&self) -> SdkResult<ReceivePaymentFeeInfo> {
let lsp_info = self.lsp_info().await?;
let opening_fees = lsp_info.opening_fee_params_list.get_cheapest_opening_fee_params()?;
Ok(ReceivePaymentFeeInfo {
fee_percentage: opening_fees.proportional * 100_f64 / 1_000_000_f64,
min_fee_sat: opening_fees.min_msat / 1_000,
inbound_liquidity_sat: self.node_info()?.inbound_liquidity_msats / 1000,
})
}
/// The values needed for the app developer to show a message like
/// "A setup fee of X% with a minimum of Y sats will be applied for receiving more than Z sats."
pub struct ReceivePaymentFeeInfo {
pub fee_percentage: f32, // X
pub min_fee_sat: u64, // Y
pub inbound_liquidity_sat: u64 // Z
} |
I made the snippet more compact in 0ab6370 . I'm in favor of an SDK method, what do you think? Alternatively, we could use this (compacted) snippet, although unless people copy-paste it, those multiplications and divisions are pretty error-prone. |
The docs snippet is good, but only works in rust as |
That's true, that's simpler. I took a look at c-breez. There we do what @ok300 wrote in the example. But open_channel_fee is simpler, because then we don't have to explain the opening_fee_params exactly. |
I think I found a way to avoid relying on Alternatively, I tweaked the SDK method to pre-calculate these fields: breez/breez-sdk-greenlight#737 . With this change, the snippet would make only 1 SDK call: The 2nd way is better IMO, what do you think? |
eb9a0b0
to
afdea04
Compare
829c6fe
to
c7f078c
Compare
Snippet for fee info before receiving a LN payment: breez-sdk-docs/snippets/rust/src/communicating_fees.rs Lines 9 to 28 in 7dec9ba
Snippet for fee info before swaps: breez-sdk-docs/snippets/rust/src/communicating_fees.rs Lines 50 to 65 in 7dec9ba
@JssDWt @dangeross is there a simpler way I'm missing? Or would you say this is good enough? |
I think it looks pretty good. Didn't you update |
Good point, yes that's true, thanks. I'll have to wait until 0.2.16 though, as that change is not yet part of a release. The docs are now referencing 0.2.15, which is why I was coding against the older version. |
7deb280
to
e3f7eee
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.
Looking good, just a couple of comments
snippets/go/communicating_fees.go
Outdated
|
||
func getFeeInfoBeforeInvoiceCreated() { | ||
// ANCHOR: get-fee-info-before-receiving-payment | ||
if nodeInfo, err := sdk.NodeInfo(); err != nil { |
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 nodeInfo, err := sdk.NodeInfo(); err != nil { | |
if nodeInfo, err := sdk.NodeInfo(); err == nil { |
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.
Maybe coding pattern-wise its better to do
if nodeInfo, err := sdk.NodeInfo(); err != nil {
return err
}
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.
@JssDWt indeed looks better IMO, snippets will be more readable. How about I do that in a separate PR?
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.
Sure
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.
Perfect.
Then @dangeross this is addressed for now in e084005
...ts/kotlin_mpp_lib/shared/src/commonMain/kotlin/com/example/kotlinmpplib/CommunicatingFees.kt
Outdated
Show resolved
Hide resolved
...ts/kotlin_mpp_lib/shared/src/commonMain/kotlin/com/example/kotlinmpplib/CommunicatingFees.kt
Outdated
Show resolved
Hide resolved
...ts/kotlin_mpp_lib/shared/src/commonMain/kotlin/com/example/kotlinmpplib/CommunicatingFees.kt
Outdated
Show resolved
Hide resolved
Co-authored-by: Ross Savage <551697+dangeross@users.noreply.github.com>
Co-authored-by: Ross Savage <551697+dangeross@users.noreply.github.com>
Co-authored-by: Ross Savage <551697+dangeross@users.noreply.github.com>
Co-authored-by: Ross Savage <551697+dangeross@users.noreply.github.com>
Co-authored-by: Ross Savage <551697+dangeross@users.noreply.github.com>
Co-authored-by: Ross Savage <551697+dangeross@users.noreply.github.com>
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!
This PR documents the channel opening fee and provides sample code snippets to show how to retrieve it after
receive_payment
.Fixes #109