Skip to content

Commit d558dd2

Browse files
committed
fix: max sendable calc
1 parent 37e2b75 commit d558dd2

File tree

2 files changed

+52
-1
lines changed

2 files changed

+52
-1
lines changed

app/src/main/java/to/bitkit/ui/screens/wallets/send/SendAmountScreen.kt

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ import to.bitkit.models.BalanceState
3333
import to.bitkit.models.BitcoinDisplayUnit
3434
import to.bitkit.models.NodeLifecycleState
3535
import to.bitkit.models.Toast
36+
import to.bitkit.models.safe
3637
import to.bitkit.repositories.CurrencyState
3738
import to.bitkit.ui.LocalBalances
3839
import to.bitkit.ui.LocalCurrencies
@@ -91,6 +92,12 @@ fun SendAmountScreen(
9192
currentOnEvent(SendEvent.AmountChange(amountInputUiState.sats.toULong()))
9293
}
9394

95+
LaunchedEffect(uiState.decodedInvoice, uiState.payMethod) {
96+
if (uiState.payMethod == SendMethod.LIGHTNING && uiState.decodedInvoice != null) {
97+
currentOnEvent(SendEvent.EstimateMaxRoutingFee)
98+
}
99+
}
100+
94101
SendAmountContent(
95102
walletUiState = walletUiState,
96103
uiState = uiState,
@@ -190,7 +197,11 @@ private fun SendAmountNodeRunning(
190197
val availableAmount = when {
191198
isLnurlWithdraw -> uiState.lnurl.data.maxWithdrawableSat().toLong()
192199
uiState.payMethod == SendMethod.ONCHAIN -> balances.maxSendOnchainSats.toLong()
193-
else -> balances.maxSendLightningSats.toLong()
200+
else -> {
201+
val maxLightning = balances.maxSendLightningSats
202+
val routingFee = uiState.estimatedRoutingFee
203+
(maxLightning.safe() - routingFee.safe()).toLong()
204+
}
194205
}
195206

196207
Column(

app/src/main/java/to/bitkit/viewmodels/AppViewModel.kt

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -472,6 +472,9 @@ class AppViewModel @Inject constructor(
472472
SendEvent.SwipeToPay -> onSwipeToPay()
473473
is SendEvent.ConfirmAmountWarning -> onConfirmAmountWarning(it.warning)
474474
SendEvent.DismissAmountWarning -> onDismissAmountWarning()
475+
SendEvent.EstimateMaxRoutingFee -> viewModelScope.launch {
476+
estimateMaxAmountRoutingFee()
477+
}
475478
SendEvent.PayConfirmed -> onConfirmPay()
476479
SendEvent.ClearPayConfirmation -> _sendUiState.update { s -> s.copy(shouldConfirmPay = false) }
477480
SendEvent.BackToAmount -> setSendEffect(SendEffect.PopBack(SendRoute.Amount))
@@ -1458,6 +1461,41 @@ class AppViewModel @Inject constructor(
14581461
}
14591462
}
14601463

1464+
private suspend fun estimateMaxAmountRoutingFee() {
1465+
val currentState = _sendUiState.value
1466+
if (currentState.payMethod != SendMethod.LIGHTNING) return
1467+
1468+
val decodedInvoice = currentState.decodedInvoice ?: return
1469+
val bolt11 = decodedInvoice.bolt11
1470+
1471+
val maxSendLightning = walletRepo.balanceState.value.maxSendLightningSats
1472+
if (maxSendLightning == 0uL) {
1473+
_sendUiState.update { it.copy(estimatedRoutingFee = 0uL) }
1474+
return
1475+
}
1476+
1477+
val buffer = 2uL
1478+
val amountToEstimate = if (maxSendLightning > buffer) {
1479+
maxSendLightning - buffer
1480+
} else {
1481+
maxSendLightning
1482+
}
1483+
1484+
val feeResult = lightningRepo.estimateRoutingFeesForAmount(
1485+
bolt11 = bolt11,
1486+
amountSats = amountToEstimate
1487+
)
1488+
1489+
feeResult.onSuccess { fee ->
1490+
_sendUiState.update {
1491+
it.copy(estimatedRoutingFee = fee + buffer)
1492+
}
1493+
}.onFailure { e ->
1494+
Logger.error("Failed to estimate routing fee for max amount", e, context = TAG)
1495+
_sendUiState.update { it.copy(estimatedRoutingFee = 0uL) }
1496+
}
1497+
}
1498+
14611499
private suspend fun getFeeEstimate(speed: TransactionSpeed? = null): Long {
14621500
val currentState = _sendUiState.value
14631501
return lightningRepo.calculateTotalFee(
@@ -2001,6 +2039,7 @@ data class SendUiState(
20012039
val feeRates: FeeRates? = null,
20022040
val fee: SendFee? = null,
20032041
val fees: Map<FeeRate, Long> = emptyMap(),
2042+
val estimatedRoutingFee: ULong = 0uL,
20042043
)
20052044

20062045
enum class SanityWarning(@StringRes val message: Int, val testTag: String) {
@@ -2064,6 +2103,7 @@ sealed interface SendEvent {
20642103
data object SpeedAndFee : SendEvent
20652104
data object PaymentMethodSwitch : SendEvent
20662105
data class ConfirmAmountWarning(val warning: SanityWarning) : SendEvent
2106+
data object EstimateMaxRoutingFee : SendEvent
20672107
data object DismissAmountWarning : SendEvent
20682108
data object PayConfirmed : SendEvent
20692109
data object ClearPayConfirmation : SendEvent

0 commit comments

Comments
 (0)