diff --git a/frontend/squeak-node-frontend/src/pages/wallet/Wallet.js b/frontend/squeak-node-frontend/src/pages/wallet/Wallet.js index ca7d5489..11659657 100644 --- a/frontend/squeak-node-frontend/src/pages/wallet/Wallet.js +++ b/frontend/squeak-node-frontend/src/pages/wallet/Wallet.js @@ -335,6 +335,7 @@ export default function WalletPage() { + @@ -349,6 +350,12 @@ export default function WalletPage() { : NoBalanceContent() } + + {(lndInfo && walletBalance) + ? NodeInfoContent() + : NoBalanceContent() + } + ) } diff --git a/itests/tests/test_squeak_node.py b/itests/tests/test_squeak_node.py index b231a454..66fb934a 100644 --- a/itests/tests/test_squeak_node.py +++ b/itests/tests/test_squeak_node.py @@ -631,3 +631,67 @@ def test_new_address(server_stub, admin_stub, lightning_client): print(new_address_response.address) assert len(new_address_response.address) > 0 + + +def test_list_channels(server_stub, admin_stub, lightning_client, saved_squeak_hash): + # Get the squeak from the server + get_response = server_stub.GetSqueak( + squeak_server_pb2.GetSqueakRequest(hash=saved_squeak_hash) + ) + get_response_squeak = squeak_from_msg(get_response.squeak) + CheckSqueak(get_response_squeak, skipDecryptionCheck=True) + + # Generate a challenge to verify the offer + expected_proof = generate_challenge_proof() + encryption_key = get_response_squeak.GetEncryptionKey() + challenge = get_challenge(encryption_key, expected_proof) + + # Buy the squeak data key + buy_response = server_stub.BuySqueak( + squeak_server_pb2.BuySqueakRequest( + hash=saved_squeak_hash, + challenge=challenge, + ) + ) + assert buy_response.offer.payment_request.startswith("ln") + + # Decode the payment request string + decode_pay_req_response = lightning_client.decode_pay_req( + buy_response.offer.payment_request + ) + destination = decode_pay_req_response.destination + + # Connect to the server lightning node + try: + connect_peer_response = lightning_client.connect_peer( + destination, buy_response.offer.host + ) + except: + pass + + # Open channel to the server lightning node + pubkey_bytes = string_to_hex(destination) + open_channel_response = lightning_client.open_channel(pubkey_bytes, 1000000) + print("Opening channel...") + for update in open_channel_response: + if update.HasField("chan_open"): + channel_point = update.chan_open.channel_point + print("Channel now open: " + str(channel_point)) + break + + # List channels + get_info_response = lightning_client.get_info() + list_channels_response = admin_stub.LndListChannels(ln.ListChannelsRequest()) + + assert len(list_channels_response.channels) > 0 + assert any([ + channel.remote_pubkey == get_info_response.identity_pubkey + for channel in list_channels_response.channels + ]) + + # Close the channel + time.sleep(2) + for update in lightning_client.close_channel(channel_point): + if update.HasField("chan_close"): + print("Channel closed.") + break diff --git a/proto/squeak_admin.proto b/proto/squeak_admin.proto index 005189c0..1e84e142 100644 --- a/proto/squeak_admin.proto +++ b/proto/squeak_admin.proto @@ -24,6 +24,10 @@ service SqueakAdmin { */ rpc LndNewAddress (lnrpc.NewAddressRequest) returns (lnrpc.NewAddressResponse) {} + /** sqkadmin: `lndlistchannels` + */ + rpc LndListChannels (lnrpc.ListChannelsRequest) returns (lnrpc.ListChannelsResponse) {} + /** sqkadmin: `createsigningprofile` */ rpc CreateSigningProfile (CreateSigningProfileRequest) returns (CreateSigningProfileReply) {} diff --git a/squeakserver/admin/squeak_admin_server_handler.py b/squeakserver/admin/squeak_admin_server_handler.py index 469b3dac..b358e0cb 100644 --- a/squeakserver/admin/squeak_admin_server_handler.py +++ b/squeakserver/admin/squeak_admin_server_handler.py @@ -29,6 +29,10 @@ class SqueakAdminServerHandler(object): logger.info("Handle lnd new address with type: {}".format(address_type)) return self.lightning_client.new_address(address_type) + def handle_lnd_list_channels(self): + logger.info("Handle lnd list channels: {}") + return self.lightning_client.list_channels() + def handle_create_signing_profile(self, profile_name): logger.info("Handle create signing profile with name: {}".format(profile_name)) profile_id = self.squeak_node.create_signing_profile(profile_name) diff --git a/squeakserver/admin/squeak_admin_server_servicer.py b/squeakserver/admin/squeak_admin_server_servicer.py index 095f5f7c..0d490b49 100644 --- a/squeakserver/admin/squeak_admin_server_servicer.py +++ b/squeakserver/admin/squeak_admin_server_servicer.py @@ -28,6 +28,9 @@ class SqueakAdminServerServicer(squeak_admin_pb2_grpc.SqueakAdminServicer): address_type = request.type return self.handler.handle_lnd_new_address(address_type) + def LndListChannels(self, request, context): + return self.handler.handle_lnd_list_channels() + def CreateSigningProfile(self, request, context): profile_name = request.profile_name profile_id = self.handler.handle_create_signing_profile(profile_name) diff --git a/squeakserver/common/lnd_lightning_client.py b/squeakserver/common/lnd_lightning_client.py index 5e0baf8f..f48a1c19 100644 --- a/squeakserver/common/lnd_lightning_client.py +++ b/squeakserver/common/lnd_lightning_client.py @@ -178,3 +178,11 @@ class LNDLightningClient: new_address_request, metadata=[("macaroon", self.macaroon)], ) + + def list_channels(self): + # NewAddress creates a new address under control of the local wallet. + list_channels_request = lnd_pb2.ListChannelsRequest() + return self.stub.ListChannels( + list_channels_request, + metadata=[("macaroon", self.macaroon)], + )