diff --git a/electrum/lnworker.py b/electrum/lnworker.py index 98da4fc91..4ce2c7999 100644 --- a/electrum/lnworker.py +++ b/electrum/lnworker.py @@ -912,6 +912,11 @@ class LNWallet(LNWorker): return (self.can_have_recoverable_channels() and self.config.LIGHTNING_USE_RECOVERABLE_CHANNELS) + def has_anchor_channels(self) -> bool: + """Returns True if any active channel is an anchor channel.""" + return any(chan.has_anchors() and not chan.is_redeemed() + for chan in self.channels.values()) + @property def channels(self) -> Mapping[bytes, Channel]: """Returns a read-only copy of channels.""" diff --git a/electrum/submarine_swaps.py b/electrum/submarine_swaps.py index c69e63283..00c5da81d 100644 --- a/electrum/submarine_swaps.py +++ b/electrum/submarine_swaps.py @@ -926,12 +926,8 @@ class SwapManager(Logger): """ for server """ self.percentage = float(self.config.SWAPSERVER_FEE_MILLIONTHS) / 10000 # type: ignore self._min_amount = 20000 - anchor_reserve = self.config.LN_UTXO_RESERVE \ - if (any(chan.has_anchors() and not chan.is_redeemed() - for chan in self.lnworker.channels.values())) else 0 - oc_balance = max(sum([coin.value_sats() for coin in self.wallet.get_spendable_coins()]) - - anchor_reserve, 0) - max_forward: int = min(int(self.lnworker.num_sats_can_receive()), oc_balance, 10000000) + oc_balance_sat: int = self.wallet.get_spendable_balance_sat() + max_forward: int = min(int(self.lnworker.num_sats_can_receive()), oc_balance_sat, 10000000) max_reverse: int = min(int(self.lnworker.num_sats_can_send()), 10000000) self._max_forward: int = self._keep_leading_digits(max_forward, 2) self._max_reverse: int = self._keep_leading_digits(max_reverse, 2) diff --git a/electrum/wallet.py b/electrum/wallet.py index 3475e6053..c81348598 100644 --- a/electrum/wallet.py +++ b/electrum/wallet.py @@ -1069,6 +1069,23 @@ class Abstract_Wallet(ABC, Logger, EventListener): domain = self.get_addresses() return self.adb.get_balance(domain, **kwargs) + def anchor_reserve(self) -> int: + if self.lnworker is None or not isinstance(self.lnworker, LNWallet): + return 0 + if not self.lnworker.has_anchor_channels(): + return 0 + return self.config.LN_UTXO_RESERVE + + def get_spendable_balance_sat( + self, + deduct_anchor_reserve: bool = True, + **kwargs + ) -> int: + anchor_reserve = self.anchor_reserve() if deduct_anchor_reserve else 0 + spendable_coins = self.get_spendable_coins(**kwargs) + oc_balance = sum([coin.value_sats() for coin in spendable_coins]) - anchor_reserve + return max(0, oc_balance) + def get_addr_balance(self, address): return self.adb.get_balance([address]) @@ -1843,7 +1860,7 @@ class Abstract_Wallet(ABC, Logger, EventListener): tx_outputs: List[PartialTxOutput], is_anchor_channel_opening: bool, ) -> bool: - channels_need_reserve = self.lnworker and any(chan.has_anchors() and not chan.is_redeemed() for chan in self.lnworker.channels.values()) + channels_need_reserve = self.lnworker and self.lnworker.has_anchor_channels() # note: is_anchor_channel_opening is used in unit tests, without lnworker is_reserve_needed = is_anchor_channel_opening or channels_need_reserve if not is_reserve_needed: