@@ -31,6 +31,7 @@ import to.bitkit.ext.totalNextOutboundHtlcLimitSats
3131import to.bitkit.models.AddressModel
3232import to.bitkit.models.BalanceState
3333import to.bitkit.models.NodeLifecycleState
34+ import to.bitkit.models.TransactionSpeed
3435import to.bitkit.models.toDerivationPath
3536import to.bitkit.services.CoreService
3637import to.bitkit.utils.AddressChecker
@@ -160,18 +161,22 @@ class WalletRepo @Inject constructor(
160161 }
161162
162163 suspend fun syncBalances () {
163- lightningRepo.getBalances()?.let { balance ->
164+ lightningRepo.getBalancesAsync().onSuccess { balance ->
165+ _walletState .update { it.copy(balanceDetails = balance) }
166+
164167 val totalSats = balance.totalLightningBalanceSats + balance.totalOnchainBalanceSats
165168
166169 val newBalance = BalanceState (
167170 totalOnchainSats = balance.totalOnchainBalanceSats,
168171 totalLightningSats = balance.totalLightningBalanceSats,
169172 maxSendLightningSats = lightningRepo.getChannels()?.totalNextOutboundHtlcLimitSats() ? : 0u ,
173+ maxSendOnchainSats = getMaxSendAmount(),
170174 totalSats = totalSats,
171175 )
172176 _balanceState .update { newBalance }
173- _walletState .update { it.copy(balanceDetails = lightningRepo.getBalances()) }
174177 saveBalanceState(newBalance)
178+ }.onFailure {
179+ Logger .warn(" Could not sync balances" , context = TAG )
175180 }
176181 }
177182
@@ -318,24 +323,6 @@ class WalletRepo @Inject constructor(
318323 _balanceState .update { balanceState }
319324 }
320325
321- suspend fun getMaxSendAmount (): ULong = withContext(bgDispatcher) {
322- val totalOnchainSats = balanceState.value.totalOnchainSats
323- if (totalOnchainSats == 0uL ) {
324- return @withContext 0uL
325- }
326-
327- try {
328- val fee = lightningRepo.calculateTotalFee(totalOnchainSats).getOrThrow()
329- val maxSendable = (totalOnchainSats - fee).coerceAtLeast(0u )
330-
331- return @withContext maxSendable
332- } catch (_: Throwable ) {
333- Logger .debug(" Could not calculate max send amount, using as fallback 90% of total" , context = TAG )
334- val fallbackMax = (totalOnchainSats.toDouble() * 0.9 ).toULong()
335- return @withContext fallbackMax
336- }
337- }
338-
339326 // BIP21 state management
340327 fun updateBip21AmountSats (amount : ULong? ) {
341328 _walletState .update { it.copy(bip21AmountSats = amount) }
@@ -478,6 +465,25 @@ class WalletRepo @Inject constructor(
478465 }
479466 }
480467
468+ private suspend fun getMaxSendAmount (): ULong = withContext(bgDispatcher) {
469+ val spendableOnchainSats = walletState.value.balanceDetails?.spendableOnchainBalanceSats ? : 0uL
470+ if (spendableOnchainSats == 0uL ) {
471+ return @withContext 0uL
472+ }
473+ val fallbackMaxFee = (spendableOnchainSats.toDouble() * FALLBACK_FEE_PERCENT ).toULong()
474+
475+ val fee = lightningRepo.calculateTotalFee(
476+ amountSats = spendableOnchainSats,
477+ speed = TransactionSpeed .default(),
478+ utxosToSpend = lightningRepo.listSpendableOutputs().getOrNull()
479+ ).onFailure {
480+ Logger .debug(" Could not calculate max send fee, using as fallback 10% of total" , context = TAG )
481+ }.getOrDefault(fallbackMaxFee)
482+
483+ val maxSendable = (spendableOnchainSats - fee).coerceAtLeast(0u )
484+ maxSendable
485+ }
486+
481487 private suspend fun Scanner.OnChain.extractLightningHash (): String? {
482488 val lightningInvoice: String = this .invoice.params?.get(" lightning" ) ? : return null
483489 val decoded = decode(lightningInvoice)
@@ -494,6 +500,7 @@ class WalletRepo @Inject constructor(
494500
495501 private companion object {
496502 const val TAG = " WalletRepo"
503+ const val FALLBACK_FEE_PERCENT = 0.1
497504 }
498505}
499506
0 commit comments