Browse Source

kivy: restore channel list to working state, add [force-]closing functionality

dependabot/pip/contrib/deterministic-build/ecdsa-0.13.3
Janus 6 years ago
committed by ThomasV
parent
commit
f803bb571d
  1. 57
      electrum/gui/kivy/uix/dialogs/lightning_channels.py

57
electrum/gui/kivy/uix/dialogs/lightning_channels.py

@ -1,9 +1,12 @@
import asyncio
import binascii import binascii
from kivy.lang import Builder from kivy.lang import Builder
from kivy.factory import Factory from kivy.factory import Factory
from kivy.uix.popup import Popup from kivy.uix.popup import Popup
from kivy.clock import Clock from kivy.clock import Clock
from electrum.gui.kivy.uix.context_menu import ContextMenu from electrum.gui.kivy.uix.context_menu import ContextMenu
from electrum.util import bh2u
from electrum.lnutil import LOCAL, REMOTE
Builder.load_string(''' Builder.load_string('''
<LightningChannelItem@CardItem> <LightningChannelItem@CardItem>
@ -15,6 +18,7 @@ Builder.load_string('''
<LightningChannelsDialog@Popup>: <LightningChannelsDialog@Popup>:
name: 'lightning_channels' name: 'lightning_channels'
title: 'Lightning channels. Tap to select.'
BoxLayout: BoxLayout:
id: box id: box
orientation: 'vertical' orientation: 'vertical'
@ -86,19 +90,38 @@ class LightningChannelsDialog(Factory.Popup):
self.clocks = [] self.clocks = []
self.app = app self.app = app
self.context_menu = None self.context_menu = None
self.app.wallet.lnworker.subscribe_channel_list_updates_from_other_thread(self.rpc_result_handler) self.app.wallet.network.register_callback(self.channels_update, ['channels'])
self.channels_update('bogus evt')
def show_channel_details(self, obj): def show_channel_details(self, obj):
p = Factory.ChannelDetailsPopup() p = Factory.ChannelDetailsPopup()
p.title = 'Lightning channels details for ' + self.presentable_chan_id(obj._chan)
p.data = [{'keyName': key, 'value': str(obj.details[key])} for key in obj.details.keys()] p.data = [{'keyName': key, 'value': str(obj.details[key])} for key in obj.details.keys()]
p.open() p.open()
def close_channel(self, obj): def close_channel(self, obj):
print("UNIMPLEMENTED asked to close channel", obj.channelId) # TODO loop = self.app.wallet.network.asyncio_loop
coro = asyncio.run_coroutine_threadsafe(self.app.wallet.lnworker.close_channel(obj._chan.channel_id), loop)
try:
coro.result(5)
self.app.show_info('Channel closed')
except Exception as e:
self.app.show_info('Could not close channel: ' + repr(e)) # repr because str(Exception()) == ''
def force_close_channel(self, obj):
loop = self.app.wallet.network.asyncio_loop
coro = asyncio.run_coroutine_threadsafe(self.app.wallet.lnworker.force_close_channel(obj._chan.channel_id), loop)
try:
coro.result(1)
self.app.show_info('Channel closed, you may need to wait at least ' + str(obj._chan.config[REMOTE].to_self_delay) + ' blocks, because of CSV delays')
except Exception as e:
self.app.show_info('Could not force close channel: ' + repr(e)) # repr because str(Exception()) == ''
def show_menu(self, obj): def show_menu(self, obj):
self.hide_menu() self.hide_menu()
self.context_menu = ContextMenu(obj, [("Close", self.close_channel), self.context_menu = ContextMenu(obj, [
("Force close", self.force_close_channel),
("Co-op close", self.close_channel),
("Details", self.show_channel_details)]) ("Details", self.show_channel_details)])
self.ids.box.add_widget(self.context_menu) self.ids.box.add_widget(self.context_menu)
@ -107,17 +130,27 @@ class LightningChannelsDialog(Factory.Popup):
self.ids.box.remove_widget(self.context_menu) self.ids.box.remove_widget(self.context_menu)
self.context_menu = None self.context_menu = None
def rpc_result_handler(self, res): def presentable_chan_id(self, i):
return bh2u(i.short_channel_id) if i.short_channel_id else bh2u(i.channel_id)[:16]
def channels_update(self, evt):
channel_cards = self.ids.lightning_channels_container channel_cards = self.ids.lightning_channels_container
channel_cards.clear_widgets() channel_cards.clear_widgets()
if "channels" in res: lnworker = self.app.wallet.lnworker
for i in res["channels"]: for i in lnworker.channels.values():
item = Factory.LightningChannelItem() item = Factory.LightningChannelItem()
item.screen = self item.screen = self
print(i) item.channelId = self.presentable_chan_id(i)
item.channelId = i["chan_id"] item.active = i.node_id in lnworker.peers
item.active = i["active"] item.details = self.channel_details(i)
item.details = i item._chan = i
channel_cards.add_widget(item) channel_cards.add_widget(item)
else:
self.app.show_info(res) def channel_details(self, chan):
return {'Node ID': bh2u(chan.node_id),
'Channel ID': bh2u(chan.channel_id),
'Capacity': self.app.format_amount_and_units(chan.constraints.capacity),
'Funding TXID': chan.funding_outpoint.txid,
'Short Chan ID': bh2u(chan.short_channel_id) if chan.short_channel_id else 'Not available',
'Available to spend': self.app.format_amount_and_units(chan.available_to_spend(LOCAL) // 1000),
'State': chan.get_state()}

Loading…
Cancel
Save