@@ -83,6 +83,7 @@ import to.bitkit.models.NewTransactionSheetType
8383import to.bitkit.models.Suggestion
8484import to.bitkit.models.Toast
8585import to.bitkit.models.TransactionSpeed
86+ import to.bitkit.models.safe
8687import to.bitkit.models.toActivityFilter
8788import to.bitkit.models.toTxType
8889import to.bitkit.repositories.ActivityRepo
@@ -472,6 +473,10 @@ class AppViewModel @Inject constructor(
472473 SendEvent .SwipeToPay -> onSwipeToPay()
473474 is SendEvent .ConfirmAmountWarning -> onConfirmAmountWarning(it.warning)
474475 SendEvent .DismissAmountWarning -> onDismissAmountWarning()
476+ SendEvent .EstimateMaxRoutingFee -> viewModelScope.launch {
477+ estimateMaxAmountRoutingFee()
478+ }
479+
475480 SendEvent .PayConfirmed -> onConfirmPay()
476481 SendEvent .ClearPayConfirmation -> _sendUiState .update { s -> s.copy(shouldConfirmPay = false ) }
477482 SendEvent .BackToAmount -> setSendEffect(SendEffect .PopBack (SendRoute .Amount ))
@@ -1042,9 +1047,12 @@ class AppViewModel @Inject constructor(
10421047 if (_sendUiState .value.showSanityWarningDialog != null ) return
10431048
10441049 val settings = settingsStore.data.first()
1045-
1050+ val balanceToCheck = when (_sendUiState .value.payMethod) {
1051+ SendMethod .ONCHAIN -> walletRepo.balanceState.value.maxSendOnchainSats
1052+ SendMethod .LIGHTNING -> walletRepo.balanceState.value.maxSendLightningSats
1053+ }
10461054 if (
1047- amountSats > BigDecimal .valueOf(walletRepo.balanceState.value.totalSats .toLong())
1055+ amountSats > BigDecimal .valueOf(balanceToCheck .toLong())
10481056 .times(BigDecimal (MAX_BALANCE_FRACTION )).toLong().toUInt() &&
10491057 SanityWarning .OVER_HALF_BALANCE !in _sendUiState .value.confirmedWarnings
10501058 ) {
@@ -1458,6 +1466,37 @@ class AppViewModel @Inject constructor(
14581466 }
14591467 }
14601468
1469+ private suspend fun estimateMaxAmountRoutingFee () {
1470+ val currentState = _sendUiState .value
1471+ if (currentState.payMethod != SendMethod .LIGHTNING ) return
1472+
1473+ val decodedInvoice = currentState.decodedInvoice ? : return
1474+ val bolt11 = decodedInvoice.bolt11
1475+
1476+ val maxSendLightning = walletRepo.balanceState.value.maxSendLightningSats
1477+ if (maxSendLightning == 0uL ) {
1478+ _sendUiState .update { it.copy(estimatedRoutingFee = 0uL ) }
1479+ return
1480+ }
1481+
1482+ val buffer = 2uL
1483+ val amountToEstimate = maxSendLightning.safe() - buffer.safe()
1484+
1485+ val feeResult = lightningRepo.estimateRoutingFeesForAmount(
1486+ bolt11 = bolt11,
1487+ amountSats = amountToEstimate
1488+ )
1489+
1490+ feeResult.onSuccess { fee ->
1491+ _sendUiState .update {
1492+ it.copy(estimatedRoutingFee = fee + buffer)
1493+ }
1494+ }.onFailure { e ->
1495+ Logger .error(" Failed to estimate routing fee for max amount" , e, context = TAG )
1496+ _sendUiState .update { it.copy(estimatedRoutingFee = 0uL ) }
1497+ }
1498+ }
1499+
14611500 private suspend fun getFeeEstimate (speed : TransactionSpeed ? = null): Long {
14621501 val currentState = _sendUiState .value
14631502 return lightningRepo.calculateTotalFee(
@@ -2001,6 +2040,7 @@ data class SendUiState(
20012040 val feeRates : FeeRates ? = null ,
20022041 val fee : SendFee ? = null ,
20032042 val fees : Map <FeeRate , Long > = emptyMap(),
2043+ val estimatedRoutingFee : ULong = 0uL ,
20042044)
20052045
20062046enum class SanityWarning (@StringRes val message : Int , val testTag : String ) {
@@ -2064,6 +2104,7 @@ sealed interface SendEvent {
20642104 data object SpeedAndFee : SendEvent
20652105 data object PaymentMethodSwitch : SendEvent
20662106 data class ConfirmAmountWarning (val warning : SanityWarning ) : SendEvent
2107+ data object EstimateMaxRoutingFee : SendEvent
20672108 data object DismissAmountWarning : SendEvent
20682109 data object PayConfirmed : SendEvent
20692110 data object ClearPayConfirmation : SendEvent
0 commit comments