@@ -78,6 +78,7 @@ import to.bitkit.models.NewTransactionSheetType
7878import to.bitkit.models.Suggestion
7979import to.bitkit.models.Toast
8080import to.bitkit.models.TransactionSpeed
81+ import to.bitkit.models.safe
8182import to.bitkit.models.toActivityFilter
8283import to.bitkit.models.toTxType
8384import to.bitkit.repositories.ActivityRepo
@@ -484,6 +485,10 @@ class AppViewModel @Inject constructor(
484485 SendEvent .SwipeToPay -> onSwipeToPay()
485486 is SendEvent .ConfirmAmountWarning -> onConfirmAmountWarning(it.warning)
486487 SendEvent .DismissAmountWarning -> onDismissAmountWarning()
488+ SendEvent .EstimateMaxRoutingFee -> viewModelScope.launch {
489+ estimateMaxAmountRoutingFee()
490+ }
491+
487492 SendEvent .PayConfirmed -> onConfirmPay()
488493 SendEvent .ClearPayConfirmation -> _sendUiState .update { s -> s.copy(shouldConfirmPay = false ) }
489494 SendEvent .BackToAmount -> setSendEffect(SendEffect .PopBack (Routes .Send .Amount ()))
@@ -1018,9 +1023,12 @@ class AppViewModel @Inject constructor(
10181023 if (_sendUiState .value.showSanityWarningDialog != null ) return
10191024
10201025 val settings = settingsStore.data.first()
1021-
1026+ val balanceToCheck = when (_sendUiState .value.payMethod) {
1027+ SendMethod .ONCHAIN -> walletRepo.balanceState.value.maxSendOnchainSats
1028+ SendMethod .LIGHTNING -> walletRepo.balanceState.value.maxSendLightningSats
1029+ }
10221030 if (
1023- amountSats > BigDecimal .valueOf(walletRepo.balanceState.value.totalSats .toLong())
1031+ amountSats > BigDecimal .valueOf(balanceToCheck .toLong())
10241032 .times(BigDecimal (MAX_BALANCE_FRACTION )).toLong().toUInt() &&
10251033 SanityWarning .OVER_HALF_BALANCE !in _sendUiState .value.confirmedWarnings
10261034 ) {
@@ -1432,6 +1440,37 @@ class AppViewModel @Inject constructor(
14321440 }
14331441 }
14341442
1443+ private suspend fun estimateMaxAmountRoutingFee () {
1444+ val currentState = _sendUiState .value
1445+ if (currentState.payMethod != SendMethod .LIGHTNING ) return
1446+
1447+ val decodedInvoice = currentState.decodedInvoice ? : return
1448+ val bolt11 = decodedInvoice.bolt11
1449+
1450+ val maxSendLightning = walletRepo.balanceState.value.maxSendLightningSats
1451+ if (maxSendLightning == 0uL ) {
1452+ _sendUiState .update { it.copy(estimatedRoutingFee = 0uL ) }
1453+ return
1454+ }
1455+
1456+ val buffer = 2uL
1457+ val amountToEstimate = maxSendLightning.safe() - buffer.safe()
1458+
1459+ val feeResult = lightningRepo.estimateRoutingFeesForAmount(
1460+ bolt11 = bolt11,
1461+ amountSats = amountToEstimate
1462+ )
1463+
1464+ feeResult.onSuccess { fee ->
1465+ _sendUiState .update {
1466+ it.copy(estimatedRoutingFee = fee + buffer)
1467+ }
1468+ }.onFailure { e ->
1469+ Logger .error(" Failed to estimate routing fee for max amount" , e, context = TAG )
1470+ _sendUiState .update { it.copy(estimatedRoutingFee = 0uL ) }
1471+ }
1472+ }
1473+
14351474 private suspend fun getFeeEstimate (speed : TransactionSpeed ? = null): Long {
14361475 val currentState = _sendUiState .value
14371476 return lightningRepo.calculateTotalFee(
@@ -1750,6 +1789,7 @@ data class SendUiState(
17501789 val feeRates : FeeRates ? = null ,
17511790 val fee : SendFee ? = null ,
17521791 val fees : Map <FeeRate , Long > = emptyMap(),
1792+ val estimatedRoutingFee : ULong = 0uL ,
17531793)
17541794
17551795enum class SanityWarning (@StringRes val message : Int , val testTag : String ) {
@@ -1810,6 +1850,7 @@ sealed interface SendEvent {
18101850 data object SpeedAndFee : SendEvent
18111851 data object PaymentMethodSwitch : SendEvent
18121852 data class ConfirmAmountWarning (val warning : SanityWarning ) : SendEvent
1853+ data object EstimateMaxRoutingFee : SendEvent
18131854 data object DismissAmountWarning : SendEvent
18141855 data object PayConfirmed : SendEvent
18151856 data object ClearPayConfirmation : SendEvent
0 commit comments