URI: 
       t(fix) allow opening LN wallet with --offline - electrum - Electrum Bitcoin wallet
  HTML git clone https://git.parazyd.org/electrum
   DIR Log
   DIR Files
   DIR Refs
   DIR Submodules
       ---
   DIR commit 1d187d36f0a90b13a88c8bd2f8e4f89f518b451d
   DIR parent 97c79d52f96cfcb191b75439185e068d37ca9f90
  HTML Author: SomberNight <somber.night@protonmail.com>
       Date:   Thu, 15 Oct 2020 14:20:51 +0200
       
       (fix) allow opening LN wallet with --offline
       
       Diffstat:
         M electrum/gui/qt/channels_list.py    |       2 +-
         M electrum/gui/qt/swap_dialog.py      |       3 +++
         M electrum/lnworker.py                |       6 ++++--
         M electrum/submarine_swaps.py         |      33 +++++++++++++++++++++++--------
       
       4 files changed, 33 insertions(+), 11 deletions(-)
       ---
   DIR diff --git a/electrum/gui/qt/channels_list.py b/electrum/gui/qt/channels_list.py
       t@@ -79,7 +79,7 @@ class ChannelsList(MyTreeView):
                    labels[subject] = label
                status = chan.get_state_for_GUI()
                closed = chan.is_closed()
       -        if self.parent.network.is_lightning_running():
       +        if self.network and self.network.is_lightning_running():
                    node_info = self.parent.network.channel_db.get_node_info_for_node_id(chan.node_id)
                    node_alias = (node_info.alias if node_info else '') or ''
                else:
   DIR diff --git a/electrum/gui/qt/swap_dialog.py b/electrum/gui/qt/swap_dialog.py
       t@@ -194,6 +194,9 @@ class SwapDialog(WindowModalDialog):
                self.fee_label.repaint()  # macOS hack for #6269
        
            def run(self):
       +        if not self.network:
       +            self.window.show_error(_("You are offline."))
       +            return
                self.window.run_coroutine_from_thread(self.swap_manager.get_pairs(), lambda x: self.update())
                if not self.exec_():
                    return
   DIR diff --git a/electrum/lnworker.py b/electrum/lnworker.py
       t@@ -522,6 +522,8 @@ class LNWallet(LNWorker):
        
                self.pending_payments = defaultdict(asyncio.Future)  # type: Dict[bytes, asyncio.Future[BarePaymentAttemptLog]]
        
       +        self.swap_manager = SwapManager(wallet=self.wallet, lnworker=self)
       +
            @property
            def channels(self) -> Mapping[bytes, Channel]:
                """Returns a read-only copy of channels."""
       t@@ -581,7 +583,7 @@ class LNWallet(LNWorker):
                self.lnwatcher = LNWalletWatcher(self, network)
                self.lnwatcher.start_network(network)
                self.network = network
       -        self.swap_manager = SwapManager(self.wallet, network)
       +        self.swap_manager.start_network(network=network, lnwatcher=self.lnwatcher)
        
                for chan in self.channels.values():
                    self.lnwatcher.add_channel(chan.funding_outpoint.to_str(), chan.get_funding_address())
       t@@ -703,7 +705,7 @@ class LNWallet(LNWorker):
                    out[closing_txid] = item
                # add info about submarine swaps
                settled_payments = self.get_settled_payments()
       -        current_height = self.network.get_local_height()
       +        current_height = self.wallet.get_local_height()
                for payment_hash_hex, swap in self.swap_manager.swaps.items():
                    txid = swap.spending_txid if swap.is_reverse else swap.funding_txid
                    if txid is None:
   DIR diff --git a/electrum/submarine_swaps.py b/electrum/submarine_swaps.py
       t@@ -21,6 +21,8 @@ from . import constants
        if TYPE_CHECKING:
            from .network import Network
            from .wallet import Abstract_Wallet
       +    from .lnwatcher import LNWalletWatcher
       +    from .lnworker import LNWallet
        
        
        API_URL_MAINNET = 'https://swaps.electrum.org/api'
       t@@ -113,25 +115,23 @@ def create_claim_tx(
        
        class SwapManager(Logger):
        
       -    def __init__(self, wallet: 'Abstract_Wallet', network: 'Network'):
       +    network: Optional['Network'] = None
       +    lnwatcher: Optional['LNWalletWatcher'] = None
       +
       +    def __init__(self, *, wallet: 'Abstract_Wallet', lnworker: 'LNWallet'):
                Logger.__init__(self)
                self.normal_fee = 0
                self.lockup_fee = 0
                self.percentage = 0
                self.min_amount = 0
                self._max_amount = 0
       -        self.network = network
                self.wallet = wallet
       -        self.lnworker = wallet.lnworker
       -        self.lnwatcher = self.wallet.lnworker.lnwatcher
       +        self.lnworker = lnworker
                self.swaps = self.wallet.db.get_dict('submarine_swaps')  # type: Dict[str, SwapData]
                self.prepayments = {}  # type: Dict[bytes, bytes] # fee_preimage -> preimage
                for k, swap in self.swaps.items():
                    if swap.is_reverse and swap.prepay_hash is not None:
                        self.prepayments[swap.prepay_hash] = bytes.fromhex(k)
       -            if swap.is_redeemed:
       -                continue
       -            self.add_lnwatcher_callback(swap)
                # api url
                if constants.net == constants.BitcoinMainnet:
                    self.api_url = API_URL_MAINNET
       t@@ -140,8 +140,20 @@ class SwapManager(Logger):
                else:
                    self.api_url = API_URL_REGTEST
        
       +    def start_network(self, *, network: 'Network', lnwatcher: 'LNWalletWatcher'):
       +        assert network
       +        assert lnwatcher
       +        self.network = network
       +        self.lnwatcher = lnwatcher
       +        for k, swap in self.swaps.items():
       +            if swap.is_redeemed:
       +                continue
       +            self.add_lnwatcher_callback(swap)
       +
            @log_exceptions
            async def _claim_swap(self, swap: SwapData) -> None:
       +        assert self.network
       +        assert self.lnwatcher
                if not self.lnwatcher.is_up_to_date():
                    return
                current_height = self.network.get_local_height()
       t@@ -189,7 +201,7 @@ class SwapManager(Logger):
                        self.wallet.set_label(tx.txid(), 'Swap refund')
        
            def get_claim_fee(self):
       -        return self.lnwatcher.config.estimate_fee(136, allow_fallback_to_static_rates=True)
       +        return self.wallet.config.estimate_fee(136, allow_fallback_to_static_rates=True)
        
            def get_swap(self, payment_hash: bytes) -> Optional[SwapData]:
                # for history
       t@@ -207,6 +219,8 @@ class SwapManager(Logger):
            async def normal_swap(self, lightning_amount: int, expected_onchain_amount: int,
                                  password, *, tx: PartialTransaction = None) -> str:
                """send on-chain BTC, receive on Lightning"""
       +        assert self.network
       +        assert self.lnwatcher
                privkey = os.urandom(32)
                pubkey = ECPrivkey(privkey).get_public_key_bytes(compressed=True)
                lnaddr, invoice = await self.lnworker.create_invoice(lightning_amount, 'swap', expiry=3600*24)
       t@@ -283,6 +297,8 @@ class SwapManager(Logger):
        
            async def reverse_swap(self, amount_sat: int, expected_amount: int) -> bool:
                """send on Lightning, receive on-chain"""
       +        assert self.network
       +        assert self.lnwatcher
                privkey = os.urandom(32)
                pubkey = ECPrivkey(privkey).get_public_key_bytes(compressed=True)
                preimage = os.urandom(32)
       t@@ -370,6 +386,7 @@ class SwapManager(Logger):
                return success
        
            async def get_pairs(self) -> None:
       +        assert self.network
                response = await self.network._send_http_on_proxy(
                    'get',
                    self.api_url + '/getpairs',