@@ -24,5 +24,36 @@ fun LnurlPayData.commentAllowed(): Boolean = commentAllowed?.let { it > 0u } ==
2424fun LnurlPayData.maxSendableSat (): ULong = maxSendable / MSATS_PER_SAT
2525fun LnurlPayData.minSendableSat (): ULong = msatsToSatsCeil(minSendable)
2626
27+ /* *
28+ * True when the LNURL-pay endpoint specifies a single exact amount.
29+ *
30+ * This also covers the sub-sat edge case where `minSendable` and `maxSendable` differ
31+ * in their sub-sat fraction but map to the same (or inverted) sat range after rounding,
32+ * e.g. `minSendable = 500500, maxSendable = 500500` → `minSendableSat() = 501, maxSendableSat() = 500`.
33+ */
34+ fun LnurlPayData.isFixedAmount (): Boolean =
35+ minSendable == maxSendable || (minSendable > 0u && minSendableSat() > maxSendableSat())
36+
37+ /* *
38+ * Returns the amount in millisatoshis to send in the LNURL-pay callback.
39+ *
40+ * For fixed-amount requests (including sub-sat ranges) the original msat value
41+ * from the server is returned verbatim, avoiding precision loss from the
42+ * msat→sat→msat round-trip.
43+ *
44+ * For variable-amount requests the user-selected sat amount is converted to msats.
45+ */
46+ fun LnurlPayData.callbackAmountMsats (userSats : ULong? = null): ULong =
47+ if (isFixedAmount()) minSendable else (userSats ? : minSendableSat()) * MSATS_PER_SAT
48+
2749fun LnurlWithdrawData.minWithdrawableSat (): ULong = msatsToSatsCeil(minWithdrawable ? : 0u )
2850fun LnurlWithdrawData.maxWithdrawableSat (): ULong = maxWithdrawable / MSATS_PER_SAT
51+
52+ /* *
53+ * True when the LNURL-withdraw endpoint specifies a single exact amount,
54+ * including the sub-sat edge case where rounding causes `min > max` in whole sats.
55+ */
56+ fun LnurlWithdrawData.isFixedAmount (): Boolean {
57+ val min = minWithdrawable ? : 0u
58+ return min == maxWithdrawable || (min > 0u && minWithdrawableSat() > maxWithdrawableSat())
59+ }
0 commit comments