mirror of
https://github.com/StijnBTC/Ringtools.git
synced 2024-11-19 00:50:03 +01:00
Implemented c-lightning support with short channel IDs
This commit is contained in:
parent
66fd5da20d
commit
93af2a2731
15
checkring.py
15
checkring.py
@ -7,8 +7,8 @@ from yachalk import chalk
|
||||
|
||||
|
||||
class CheckRing:
|
||||
def __init__(self, lnd, output, pubkeys_file, write_channels, show_fees, channels_file):
|
||||
self.lnd = lnd
|
||||
def __init__(self, client, output, pubkeys_file, write_channels, show_fees, channels_file):
|
||||
self.client = client
|
||||
self.output = output
|
||||
self.pubkeys_file = pubkeys_file
|
||||
self.show_fees = show_fees
|
||||
@ -34,10 +34,11 @@ class CheckRing:
|
||||
# pubkeys format is <pubkey>,<telegram username> to be able to mimic the manual pubkey overview with usernames
|
||||
pubkey = pubkeyInfo.split(',')
|
||||
try:
|
||||
response = self.lnd.get_node_channels(pubkey[0])
|
||||
alias = self.client.get_node_alias(pubkey[0])
|
||||
response = self.client.get_node_channels(pubkey[0])
|
||||
|
||||
print("%s" %
|
||||
(chalk.yellow(response.node.alias)))
|
||||
(chalk.yellow(alias)))
|
||||
|
||||
channelTo = pubkeys[(idx+1) % (len(pubkeys))].split(',')[0]
|
||||
hasChannel = False
|
||||
@ -62,9 +63,9 @@ class CheckRing:
|
||||
print(chalk.green("Channel is open with ID: %s") % channelId)
|
||||
|
||||
if self.show_fees:
|
||||
response = self.lnd.get_edge(int(channelId))
|
||||
node1 = self.lnd.get_node(response.node1_pub)
|
||||
node2 = self.lnd.get_node(response.node2_pub)
|
||||
response = self.client.get_edge(int(channelId))
|
||||
node1 = self.client.get_node(response.node1_pub)
|
||||
node2 = self.client.get_node(response.node2_pub)
|
||||
disabled = response.node1_policy.disabled or response.node2_policy.disabled
|
||||
self.print_channel(
|
||||
channelInfo, node1.alias, node2.alias, disabled)
|
||||
|
52
clightning.py
Normal file
52
clightning.py
Normal file
@ -0,0 +1,52 @@
|
||||
from os.path import expanduser
|
||||
|
||||
from pyln.client import LightningRpc
|
||||
import argparse
|
||||
from lnclient import LNClient
|
||||
|
||||
class CLightning(LNClient):
|
||||
def __init__(self, clrpc):
|
||||
self.rpc = LightningRpc(clrpc)
|
||||
|
||||
# TODO: handle invalid channel ids
|
||||
def get_edge(self, channel_id):
|
||||
response = self.rpc.listchannels(short_channel_id=channel_id)['channels']
|
||||
return self.convert_cl_to_lnd(response)
|
||||
|
||||
def get_node_channels(self, pub_key):
|
||||
response =self.rpc.listchannels(source=pub_key)['channels']
|
||||
|
||||
output = argparse.Namespace()
|
||||
output.channels = []
|
||||
for r in response:
|
||||
output.channels.append(self.get_edge(r['short_channel_id']))
|
||||
return output
|
||||
|
||||
def get_node_alias(self, pub_key):
|
||||
return self.get_node(pub_key).alias
|
||||
|
||||
def get_node(self, pub_key):
|
||||
return argparse.Namespace(**self.rpc.listnodes(pub_key)['nodes'][0])
|
||||
|
||||
def convert_cl_to_lnd(self, d):
|
||||
output = argparse.Namespace()
|
||||
output.channel_id = d[0]['short_channel_id']
|
||||
output.node1_pub = d[0]['source']
|
||||
output.node2_pub = d[0]['destination']
|
||||
|
||||
output.node1_policy = argparse.Namespace()
|
||||
output.node2_policy = argparse.Namespace()
|
||||
|
||||
output.node1_policy.disabled = not d[0]['active']
|
||||
|
||||
if (len(d) > 1):
|
||||
output.node2_policy.disabled = not d[1]['active']
|
||||
|
||||
output.node1_policy.fee_base_msat = d[0]['base_fee_millisatoshi']
|
||||
output.node1_policy.fee_rate_milli_msat = d[0]['fee_per_millionth']
|
||||
|
||||
if (len(d) > 1):
|
||||
output.node2_policy.fee_base_msat = d[1]['base_fee_millisatoshi']
|
||||
output.node2_policy.fee_rate_milli_msat = d[1]['fee_per_millionth']
|
||||
|
||||
return output
|
18
lnclient.py
Normal file
18
lnclient.py
Normal file
@ -0,0 +1,18 @@
|
||||
from abc import ABC, abstractmethod
|
||||
class LNClient(ABC):
|
||||
|
||||
@abstractmethod
|
||||
def get_edge(self, channel_id):
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def get_node_channels(self, pub_key):
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def get_node_alias(self, pub_key):
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def get_node(self, pub_key):
|
||||
pass
|
3
lnd.py
3
lnd.py
@ -8,11 +8,12 @@ from grpc_gen import router_pb2 as lnrouter
|
||||
from grpc_gen import router_pb2_grpc as lnrouterrpc
|
||||
from grpc_gen import lightning_pb2 as ln
|
||||
from grpc_gen import lightning_bp2_grpc as lnrpc
|
||||
from lnclient import LNClient
|
||||
|
||||
MESSAGE_SIZE_MB = 50 * 1024 * 1024
|
||||
|
||||
|
||||
class Lnd:
|
||||
class Lnd(LNClient):
|
||||
def __init__(self, lnd_dir, server):
|
||||
os.environ["GRPC_SSL_CIPHER_SUITES"] = "HIGH+ECDSA"
|
||||
lnd_dir = expanduser(lnd_dir)
|
||||
|
@ -2,3 +2,4 @@ googleapis-common-protos==1.53.0
|
||||
grpcio==1.39.0
|
||||
protobuf==3.17.3
|
||||
yachalk==0.1.4
|
||||
pyln-client==0.10.2.post0
|
28
ringtools.py
28
ringtools.py
@ -1,5 +1,6 @@
|
||||
import argparse
|
||||
import sys
|
||||
from clightning import CLightning
|
||||
|
||||
from lnd import Lnd
|
||||
from output import Output
|
||||
@ -9,19 +10,22 @@ from checkring import CheckRing
|
||||
|
||||
class RingTools:
|
||||
def __init__(self, arguments):
|
||||
self.lnd = Lnd(arguments.lnddir, arguments.grpc)
|
||||
self.output = Output(self.lnd)
|
||||
if (arguments.client == 'cl'):
|
||||
self.client = CLightning(arguments.clrpc)
|
||||
else:
|
||||
self.client = Lnd(arguments.lnddir, arguments.grpc)
|
||||
self.output = Output(self.client)
|
||||
self.arguments = arguments
|
||||
|
||||
def start(self):
|
||||
if self.arguments.function == "status":
|
||||
Status(self.lnd,
|
||||
Status(self.client,
|
||||
self.output,
|
||||
self.arguments.channels_file,
|
||||
self.arguments.loop,
|
||||
self.arguments.show_fees).run()
|
||||
elif self.arguments.function == "check":
|
||||
CheckRing(self.lnd,
|
||||
CheckRing(self.client,
|
||||
self.output,
|
||||
self.arguments.pubkeys_file,
|
||||
self.arguments.write_channels,
|
||||
@ -47,6 +51,15 @@ def get_argument_parser():
|
||||
"like to use",
|
||||
default="help",
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
"--client",
|
||||
choices=['lnd', 'cl'],
|
||||
default="lnd",
|
||||
dest="client",
|
||||
help="(default: lnd) Which client to use",
|
||||
)
|
||||
|
||||
#If nodeos is Umbrel use the default umbrel lnd location
|
||||
lnd_dir = "~/.lnd"
|
||||
if is_umbrel():
|
||||
@ -65,6 +78,13 @@ def get_argument_parser():
|
||||
help="(default localhost:10009) lnd gRPC endpoint",
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
"--clrpc",
|
||||
default="~/.lightning/bitcoin/lightning-rpc",
|
||||
dest="clrpc",
|
||||
help="(default ~/.lightning/bitcoin/lightning-rpc) C-Lightning unix-socket",
|
||||
)
|
||||
|
||||
status_group = parser.add_argument_group(
|
||||
"status",
|
||||
"Get the current status of all channels",
|
||||
|
20
status.py
20
status.py
@ -8,8 +8,8 @@ LOOP_SLEEP_TIME = 10
|
||||
|
||||
|
||||
class Status:
|
||||
def __init__(self, lnd, output, channels_file, keep_loop, show_fees):
|
||||
self.lnd = lnd
|
||||
def __init__(self, client, output, channels_file, keep_loop, show_fees):
|
||||
self.client = client
|
||||
self.output = output
|
||||
self.channels_file = channels_file
|
||||
self.keep_loop = keep_loop
|
||||
@ -37,15 +37,17 @@ class Status:
|
||||
def once(self):
|
||||
channels = self.read_file(self.channels_file)
|
||||
for channelID in channels:
|
||||
if len(channelID) != 18:
|
||||
continue
|
||||
if not channelID.isnumeric():
|
||||
continue
|
||||
# TODO: Fix this with short channel ids or convert between formats
|
||||
# if len(channelID) != 18:
|
||||
# continue
|
||||
# if not channelID.isnumeric():
|
||||
# continue
|
||||
|
||||
try:
|
||||
response = self.lnd.get_edge(int(channelID))
|
||||
node1 = self.lnd.get_node(response.node1_pub)
|
||||
node2 = self.lnd.get_node(response.node2_pub)
|
||||
response = self.client.get_edge(channelID)
|
||||
node1 = self.client.get_node(response.node1_pub)
|
||||
node2 = self.client.get_node(response.node2_pub)
|
||||
|
||||
disabled = response.node1_policy.disabled or response.node2_policy.disabled
|
||||
self.print_channel(response, node1.alias, node2.alias, disabled)
|
||||
except grpc.RpcError as e:
|
||||
|
Loading…
Reference in New Issue
Block a user