kivy: restore channel list to working state, add [force-]closing functionality
This commit is contained in:
@@ -1,9 +1,12 @@
|
||||
import asyncio
|
||||
import binascii
|
||||
from kivy.lang import Builder
|
||||
from kivy.factory import Factory
|
||||
from kivy.uix.popup import Popup
|
||||
from kivy.clock import Clock
|
||||
from electrum.gui.kivy.uix.context_menu import ContextMenu
|
||||
from electrum.util import bh2u
|
||||
from electrum.lnutil import LOCAL, REMOTE
|
||||
|
||||
Builder.load_string('''
|
||||
<LightningChannelItem@CardItem>
|
||||
@@ -15,6 +18,7 @@ Builder.load_string('''
|
||||
|
||||
<LightningChannelsDialog@Popup>:
|
||||
name: 'lightning_channels'
|
||||
title: 'Lightning channels. Tap to select.'
|
||||
BoxLayout:
|
||||
id: box
|
||||
orientation: 'vertical'
|
||||
@@ -86,19 +90,38 @@ class LightningChannelsDialog(Factory.Popup):
|
||||
self.clocks = []
|
||||
self.app = app
|
||||
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):
|
||||
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.open()
|
||||
|
||||
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):
|
||||
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)])
|
||||
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.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.clear_widgets()
|
||||
if "channels" in res:
|
||||
for i in res["channels"]:
|
||||
lnworker = self.app.wallet.lnworker
|
||||
for i in lnworker.channels.values():
|
||||
item = Factory.LightningChannelItem()
|
||||
item.screen = self
|
||||
print(i)
|
||||
item.channelId = i["chan_id"]
|
||||
item.active = i["active"]
|
||||
item.details = i
|
||||
item.channelId = self.presentable_chan_id(i)
|
||||
item.active = i.node_id in lnworker.peers
|
||||
item.details = self.channel_details(i)
|
||||
item._chan = i
|
||||
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()}
|
||||
|
||||
Reference in New Issue
Block a user