Add peer address page (#927)

* Go to peer address page on connected peer item click

* Added disconnect button to peer address page

* Add get connected peer rpc method

* Add disconnect button to peer address page

* Add both connect and disconnect button to peer address page

* Update frontend build
This commit is contained in:
Jonathan Zernik 2021-08-12 21:59:26 -07:00 committed by GitHub
parent e64289be7d
commit aab50fa287
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
26 changed files with 333 additions and 28 deletions

View file

@ -34,6 +34,7 @@ import Icons from "../../pages/icons";
import Charts from "../../pages/charts";
import Peers from "../../pages/peers";
import Peer from "../../pages/peer";
import PeerAddress from "../../pages/peeraddress";
// context
import { useLayoutState } from "../../context/LayoutContext";
@ -73,6 +74,7 @@ function Layout(props) {
<Route path="/app/channel/:txId/:outputIndex" component={Channel} />
<Route path="/app/peers" component={Peers} />
<Route path="/app/peer/:id" component={Peer} />
<Route path="/app/peeraddress/:host/:port" component={PeerAddress} />
<Route path="/app/notifications" component={Notifications} />
<Route
exact

View file

@ -11,7 +11,7 @@ import ComputerIcon from '@material-ui/icons/Computer';
import useStyles from "../../pages/wallet/styles";
import {
goToPeerPage,
goToPeerAddressPage,
} from "../../navigation/navigation"
@ -27,11 +27,12 @@ export default function PeerListItem({
const onPeerClick = (event) => {
event.preventDefault();
console.log("Handling peer click...");
const peerId = peer.getPeerId();
console.log("Handling peer address click...");
const host = peer.getHost();
const port = peer.getPort();
//const host = getPeerHost();
//const port = getPeerPort();
goToPeerPage(history, peerId);
goToPeerAddressPage(history, host, port);
}
// const getPeerHost = () => {

View file

@ -6,6 +6,10 @@ export const goToPeerPage = (history, peerId) => {
history.push("/app/peer/" + peerId);
};
export const goToPeerAddressPage = (history, host, port) => {
history.push("/app/peeraddress/" + host + "/" + port);
};
export const goToLightningNodePage = (history, pubkey, host, port) => {
console.log("Go to lightning node for pubkey: " + pubkey);
if (pubkey && host && port) {

View file

@ -0,0 +1,189 @@
import React, { useState, useEffect } from 'react';
import { useParams } from 'react-router-dom';
import {useHistory} from "react-router-dom";
import {
Grid,
Button,
Box,
} from "@material-ui/core";
// styles
import useStyles from "./styles";
// components
import PageTitle from "../../components/PageTitle";
import Widget from "../../components/Widget";
import SqueakThreadItem from "../../components/SqueakThreadItem";
import CreateContactProfileDialog from "../../components/CreateContactProfileDialog";
import SqueakUserAvatar from "../../components/SqueakUserAvatar";
import Timeline from '@material-ui/lab/Timeline';
import TimelineItem from '@material-ui/lab/TimelineItem';
import TimelineSeparator from '@material-ui/lab/TimelineSeparator';
import TimelineConnector from '@material-ui/lab/TimelineConnector';
import TimelineContent from '@material-ui/lab/TimelineContent';
import TimelineOppositeContent from '@material-ui/lab/TimelineOppositeContent';
import FaceIcon from '@material-ui/icons/Face';
import {
getSqueakProfileByAddressRequest,
getAddressSqueakDisplaysRequest,
connectSqueakPeerRequest,
disconnectSqueakPeerRequest,
getConnectedPeerRequest,
} from "../../squeakclient/requests"
import {
goToSqueakAddressPage,
goToProfilePage,
} from "../../navigation/navigation"
export default function PeerAddressPage() {
var classes = useStyles();
const history = useHistory();
const { host, port } = useParams();
const [connectedPeer, setConnectedPeer] = useState([]);
// const [squeakProfile, setSqueakProfile] = useState(null);
// const [createContactProfileDialogOpen, setCreateContactProfileDialogOpen] = useState(false);
// const [disconnectPeerDialogOpen, setDisconnectPeerDialogOpen] = useState(false);
// const getSqueakProfile = (address) => {
// getSqueakProfileByAddressRequest(address, setSqueakProfile);
// };
// const handleClickOpenCreateContactProfileDialog = () => {
// setCreateContactProfileDialogOpen(true);
// };
//
// const handleCloseCreateContactProfileDialog = () => {
// setCreateContactProfileDialogOpen(false);
// };
const getConnectedPeer = () => {
getConnectedPeerRequest(host, port, setConnectedPeer);
};
// const handleClickOpenDisconnectPeerDialog = () => {
// setDisconnectPeerDialogOpen(true);
// };
//
// const handleCloseDisconnectPeerDialog = () => {
// setDisconnectPeerDialogOpen(false);
// };
// useEffect(()=>{
// getSqueakProfile(address)
// },[address]);
// function NoProfileContent() {
// return (
// <div>
// No profile for address.
// <Button variant="contained" onClick={() => {
// handleClickOpenCreateContactProfileDialog();
// }}>Create Profile</Button>
// </div>
// )
// }
//
// function ProfileContent() {
// return (
// <div className={classes.root}>
// Profile:
// <Button variant="contained" onClick={() => {
// goToProfilePage(history, squeakProfile.getProfileId());
// }}>{squeakProfile.getProfileName()}</Button>
// </div>
// )
// }
// function DisconnectPeerDialogContent() {
// return (
// <>
// <ConnectPeerDialog
// open={connectPeerDialogOpen}
// handleClose={handleCloseConnectPeerDialog}
// ></ConnectPeerDialog>
// </>
// )
// }
useEffect(() => {
getConnectedPeer()
}, []);
function DisconnectPeerButton() {
return (
<>
<Grid item xs={12}>
<div className={classes.root}>
<Button
variant="contained"
onClick={() => {
disconnectSqueakPeerRequest(host, port, () => {
// TODO: nothing maybe
});
}}>Disconnect Peer
</Button>
</div>
</Grid>
</>
)
}
function ConnectPeerButton() {
return (
<>
<Grid item xs={12}>
<div className={classes.root}>
<Button
variant="contained"
onClick={() => {
connectSqueakPeerRequest(host, port, () => {
// TODO: nothing maybe
});
}}>Connect Peer
</Button>
</div>
</Grid>
</>
)
}
function ConnectionStatusContent() {
console.log(connectedPeer);
return (
<>
<Grid item xs={12}>
Status: {(connectedPeer)
? "Connected"
: "Disconnected"
}
</Grid>
</>
)
}
function ConnectionActionContent() {
console.log(connectedPeer);
return (
<>
<Grid item xs={12}>
{(connectedPeer)
? DisconnectPeerButton()
: ConnectPeerButton()
}
</Grid>
</>
)
}
return (
<>
<PageTitle title={'Peer Address: ' + host + ":" + port} />
{ConnectionStatusContent()}
{ConnectionActionContent()}
</>
);
}

View file

@ -0,0 +1,6 @@
{
"name": "PeerAddress",
"version": "0.0.0",
"main": "PeerAddress.js",
"private": true
}

View file

@ -0,0 +1,20 @@
import { makeStyles } from "@material-ui/styles";
export default makeStyles(theme => ({
dashedBorder: {
border: "1px dashed",
borderColor: theme.palette.primary.main,
padding: theme.spacing(2),
paddingTop: theme.spacing(4),
paddingBottom: theme.spacing(4),
marginTop: theme.spacing(1),
},
text: {
marginBottom: theme.spacing(2),
},
oppositeContent: {
// TODO: adjust this value accordingly
flex: 0.0,
padding: 0,
}
}));

View file

@ -35,6 +35,7 @@ import {
} from "../../squeakclient/requests"
import {
goToPeerPage,
goToPeerAddressPage,
} from "../../navigation/navigation"

View file

@ -110,6 +110,8 @@ import {
GetLikedSqueakDisplaysReply,
GetConnectedPeersRequest,
GetConnectedPeersReply,
GetConnectedPeerRequest,
GetConnectedPeerReply,
ConnectPeerRequest as ConnectSqueakPeerRequest,
ConnectPeerReply as ConnectSqueakPeerReply,
DisconnectPeerRequest as DisconnectSqueakPeerRequest,
@ -823,6 +825,20 @@ export function getConnectedPeersRequest(handleResponse) {
);
}
export function getConnectedPeerRequest(host, port, handleResponse) {
var request = new GetConnectedPeerRequest();
request.setHost(host);
request.setPort(port);
makeRequest(
'getconnectedpeer',
request,
GetConnectedPeerReply.deserializeBinary,
(response) => {
handleResponse(response.getConnectedPeer());
}
);
}
export function connectSqueakPeerRequest(host, port, handleResponse) {
var request = new ConnectSqueakPeerRequest();
request.setHost(host);

View file

@ -12,6 +12,7 @@ from proto import squeak_admin_pb2
from tests.util import connect_peer
from tests.util import generate_signing_key
from tests.util import get_address
from tests.util import get_connected_peer
from tests.util import get_connected_peers
from tests.util import get_hash
from tests.util import open_channel
@ -1010,6 +1011,7 @@ def test_connect_peer(admin_stub, other_admin_stub):
):
time.sleep(2)
connected_peers = get_connected_peers(admin_stub)
print(connected_peers)
assert len(connected_peers) == 1
# print("Admin node connected to peers: ")
# print(connected_peers)
@ -1017,6 +1019,9 @@ def test_connect_peer(admin_stub, other_admin_stub):
assert len(other_connected_peers) == 1
# print("Other Admin node connected to peers: ")
# print(other_connected_peers)
connected_peer = get_connected_peer(
other_admin_stub, "squeaknode", 18777)
assert connected_peer is not None
time.sleep(2)
connected_peers = get_connected_peers(admin_stub)

View file

@ -157,6 +157,7 @@ def open_peer_connection(node_stub, peer_name, peer_host, peer_port):
except Exception as e:
print("Failed to connect to peer: {}:{}.".format(peer_host, peer_port))
print(e)
raise
finally:
# Disconnect the peer
node_stub.DisconnectPeer(
@ -178,3 +179,13 @@ def get_connected_peers(node_stub):
squeak_admin_pb2.GetConnectedPeersRequest()
)
return get_connected_peers_response.connected_peers
def get_connected_peer(node_stub, host, port):
get_connected_peer_response = node_stub.GetConnectedPeer(
squeak_admin_pb2.GetConnectedPeerRequest(
host=host,
port=port,
)
)
return get_connected_peer_response.connected_peer

View file

@ -256,6 +256,10 @@ service SqueakAdmin {
*/
rpc GetConnectedPeers (GetConnectedPeersRequest) returns (GetConnectedPeersReply) {}
/** sqkadmin: `getconnectedpeer`
*/
rpc GetConnectedPeer (GetConnectedPeerRequest) returns (GetConnectedPeerReply) {}
/** sqkadmin: `disconnectpeer`
*/
rpc DisconnectPeer (DisconnectPeerRequest) returns (DisconnectPeerReply) {}
@ -944,6 +948,18 @@ message GetConnectedPeersReply {
repeated ConnectedPeer connected_peers = 1;
}
message GetConnectedPeerRequest {
/// Host
string host = 1;
/// Port
int32 port = 2;
}
message GetConnectedPeerReply {
ConnectedPeer connected_peer = 1;
}
message DisconnectPeerRequest {
/// Host
string host = 1;

View file

@ -663,6 +663,25 @@ class SqueakAdminServerHandler(object):
connected_peers=connected_peers_display_msgs
)
def handle_get_connected_peer(self, request):
host = request.host
port = request.port
logger.info("Handle get connected peer host: {}, port: {}".format(
host, port
))
connected_peer = self.squeak_controller.get_connected_peer(host, port)
logger.info("Connected peer: {}".format(
connected_peer,
))
if connected_peer is None:
return squeak_admin_pb2.GetConnectedPeerReply(
connected_peer=None
)
connected_peers_display_msg = connected_peer_to_message(connected_peer)
return squeak_admin_pb2.GetConnectedPeerReply(
connected_peer=connected_peers_display_msg
)
def handle_disconnect_peer(self, request):
host = request.host
port = request.port

View file

@ -232,5 +232,8 @@ class SqueakAdminServerServicer(squeak_admin_pb2_grpc.SqueakAdminServicer):
def GetConnectedPeers(self, request, context):
return self.handler.handle_get_connected_peers(request)
def GetConnectedPeer(self, request, context):
return self.handler.handle_get_connected_peer(request)
def DisconnectPeer(self, request, context):
return self.handler.handle_disconnect_peer(request)

View file

@ -539,6 +539,14 @@ def create_app(handler, username, password):
handler.handle_get_connected_peers,
)
@app.route("/getconnectedpeer", methods=["POST"])
@login_required
def getconnectedpeer():
return handle_request(
squeak_admin_pb2.GetConnectedPeerRequest(),
handler.handle_get_connected_peer,
)
@app.route("/connectpeer", methods=["POST"])
@login_required
def connectpeer():

View file

@ -1,17 +1,17 @@
{
"files": {
"main.js": "/static/js/main.6f283238.chunk.js",
"main.js.map": "/static/js/main.6f283238.chunk.js.map",
"main.js": "/static/js/main.731801c8.chunk.js",
"main.js.map": "/static/js/main.731801c8.chunk.js.map",
"runtime-main.js": "/static/js/runtime-main.9f0ba400.js",
"runtime-main.js.map": "/static/js/runtime-main.9f0ba400.js.map",
"static/css/2.ea4ba2f0.chunk.css": "/static/css/2.ea4ba2f0.chunk.css",
"static/js/2.3924cad9.chunk.js": "/static/js/2.3924cad9.chunk.js",
"static/js/2.3924cad9.chunk.js.map": "/static/js/2.3924cad9.chunk.js.map",
"static/js/2.5f141017.chunk.js": "/static/js/2.5f141017.chunk.js",
"static/js/2.5f141017.chunk.js.map": "/static/js/2.5f141017.chunk.js.map",
"index.html": "/index.html",
"precache-manifest.1994efa5cef897126cd62847bae4b52e.js": "/precache-manifest.1994efa5cef897126cd62847bae4b52e.js",
"precache-manifest.7b90a7f7b67b51dc1116265964aa70e8.js": "/precache-manifest.7b90a7f7b67b51dc1116265964aa70e8.js",
"service-worker.js": "/service-worker.js",
"static/css/2.ea4ba2f0.chunk.css.map": "/static/css/2.ea4ba2f0.chunk.css.map",
"static/js/2.3924cad9.chunk.js.LICENSE.txt": "/static/js/2.3924cad9.chunk.js.LICENSE.txt",
"static/js/2.5f141017.chunk.js.LICENSE.txt": "/static/js/2.5f141017.chunk.js.LICENSE.txt",
"static/media/font-awesome.min.css": "/static/media/fontawesome-webfont.fee66e71.woff",
"static/media/google.svg": "/static/media/google.695a3160.svg",
"static/media/logo.svg": "/static/media/logo.a0185b04.svg"
@ -19,7 +19,7 @@
"entrypoints": [
"static/js/runtime-main.9f0ba400.js",
"static/css/2.ea4ba2f0.chunk.css",
"static/js/2.3924cad9.chunk.js",
"static/js/main.6f283238.chunk.js"
"static/js/2.5f141017.chunk.js",
"static/js/main.731801c8.chunk.js"
]
}

View file

@ -1 +1 @@
<!doctype html><html lang="en"><head><meta charset="utf-8"/><link rel="shortcut icon" href="/favicon.ico"/><meta name="viewport" content="width=device-width,initial-scale=1,shrink-to-fit=no"/><meta name="theme-color" content="#000000"/><link rel="manifest" href="/manifest.json"/><title>Squeak Node</title><meta name="description" content="Squeak Node is a frontend for accessing a squeak node"><meta name="keywords" content="squeak, bitcoin, lightning"><meta name="author" content="Flatlogic LLC."><link href="/static/css/2.ea4ba2f0.chunk.css" rel="stylesheet"></head><body style="font-family:Roboto,sans-serif"><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div><script>!function(e){function r(r){for(var n,f,l=r[0],a=r[1],i=r[2],c=0,s=[];c<l.length;c++)f=l[c],Object.prototype.hasOwnProperty.call(o,f)&&o[f]&&s.push(o[f][0]),o[f]=0;for(n in a)Object.prototype.hasOwnProperty.call(a,n)&&(e[n]=a[n]);for(p&&p(r);s.length;)s.shift()();return u.push.apply(u,i||[]),t()}function t(){for(var e,r=0;r<u.length;r++){for(var t=u[r],n=!0,l=1;l<t.length;l++){var a=t[l];0!==o[a]&&(n=!1)}n&&(u.splice(r--,1),e=f(f.s=t[0]))}return e}var n={},o={1:0},u=[];function f(r){if(n[r])return n[r].exports;var t=n[r]={i:r,l:!1,exports:{}};return e[r].call(t.exports,t,t.exports,f),t.l=!0,t.exports}f.m=e,f.c=n,f.d=function(e,r,t){f.o(e,r)||Object.defineProperty(e,r,{enumerable:!0,get:t})},f.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},f.t=function(e,r){if(1&r&&(e=f(e)),8&r)return e;if(4&r&&"object"==typeof e&&e&&e.__esModule)return e;var t=Object.create(null);if(f.r(t),Object.defineProperty(t,"default",{enumerable:!0,value:e}),2&r&&"string"!=typeof e)for(var n in e)f.d(t,n,function(r){return e[r]}.bind(null,n));return t},f.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return f.d(r,"a",r),r},f.o=function(e,r){return Object.prototype.hasOwnProperty.call(e,r)},f.p="/";var l=this["webpackJsonpsqueak-node-frontend"]=this["webpackJsonpsqueak-node-frontend"]||[],a=l.push.bind(l);l.push=r,l=l.slice();for(var i=0;i<l.length;i++)r(l[i]);var p=a;t()}([])</script><script src="/static/js/2.3924cad9.chunk.js"></script><script src="/static/js/main.6f283238.chunk.js"></script></body></html>
<!doctype html><html lang="en"><head><meta charset="utf-8"/><link rel="shortcut icon" href="/favicon.ico"/><meta name="viewport" content="width=device-width,initial-scale=1,shrink-to-fit=no"/><meta name="theme-color" content="#000000"/><link rel="manifest" href="/manifest.json"/><title>Squeak Node</title><meta name="description" content="Squeak Node is a frontend for accessing a squeak node"><meta name="keywords" content="squeak, bitcoin, lightning"><meta name="author" content="Flatlogic LLC."><link href="/static/css/2.ea4ba2f0.chunk.css" rel="stylesheet"></head><body style="font-family:Roboto,sans-serif"><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div><script>!function(e){function r(r){for(var n,f,l=r[0],a=r[1],i=r[2],c=0,s=[];c<l.length;c++)f=l[c],Object.prototype.hasOwnProperty.call(o,f)&&o[f]&&s.push(o[f][0]),o[f]=0;for(n in a)Object.prototype.hasOwnProperty.call(a,n)&&(e[n]=a[n]);for(p&&p(r);s.length;)s.shift()();return u.push.apply(u,i||[]),t()}function t(){for(var e,r=0;r<u.length;r++){for(var t=u[r],n=!0,l=1;l<t.length;l++){var a=t[l];0!==o[a]&&(n=!1)}n&&(u.splice(r--,1),e=f(f.s=t[0]))}return e}var n={},o={1:0},u=[];function f(r){if(n[r])return n[r].exports;var t=n[r]={i:r,l:!1,exports:{}};return e[r].call(t.exports,t,t.exports,f),t.l=!0,t.exports}f.m=e,f.c=n,f.d=function(e,r,t){f.o(e,r)||Object.defineProperty(e,r,{enumerable:!0,get:t})},f.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},f.t=function(e,r){if(1&r&&(e=f(e)),8&r)return e;if(4&r&&"object"==typeof e&&e&&e.__esModule)return e;var t=Object.create(null);if(f.r(t),Object.defineProperty(t,"default",{enumerable:!0,value:e}),2&r&&"string"!=typeof e)for(var n in e)f.d(t,n,function(r){return e[r]}.bind(null,n));return t},f.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return f.d(r,"a",r),r},f.o=function(e,r){return Object.prototype.hasOwnProperty.call(e,r)},f.p="/";var l=this["webpackJsonpsqueak-node-frontend"]=this["webpackJsonpsqueak-node-frontend"]||[],a=l.push.bind(l);l.push=r,l=l.slice();for(var i=0;i<l.length;i++)r(l[i]);var p=a;t()}([])</script><script src="/static/js/2.5f141017.chunk.js"></script><script src="/static/js/main.731801c8.chunk.js"></script></body></html>

View file

@ -1,23 +1,23 @@
self.__precacheManifest = (self.__precacheManifest || []).concat([
{
"revision": "ec852a5bde17bd51d175360be0971f1a",
"revision": "40f4ec895353f04ee91dc90b7ec05668",
"url": "/index.html"
},
{
"revision": "578c0b336411b6c545b7",
"revision": "82816855ef13d12de539",
"url": "/static/css/2.ea4ba2f0.chunk.css"
},
{
"revision": "578c0b336411b6c545b7",
"url": "/static/js/2.3924cad9.chunk.js"
"revision": "82816855ef13d12de539",
"url": "/static/js/2.5f141017.chunk.js"
},
{
"revision": "7156b2c9571000777b9be03b3c6006ee",
"url": "/static/js/2.3924cad9.chunk.js.LICENSE.txt"
"url": "/static/js/2.5f141017.chunk.js.LICENSE.txt"
},
{
"revision": "83ed3dc95fac43113db1",
"url": "/static/js/main.6f283238.chunk.js"
"revision": "52137e175ebaf8cc7cd5",
"url": "/static/js/main.731801c8.chunk.js"
},
{
"revision": "cc9816de5a8639d377ea",

View file

@ -14,7 +14,7 @@
importScripts("https://storage.googleapis.com/workbox-cdn/releases/4.3.1/workbox-sw.js");
importScripts(
"/precache-manifest.1994efa5cef897126cd62847bae4b52e.js"
"/precache-manifest.7b90a7f7b67b51dc1116265964aa70e8.js"
);
self.addEventListener('message', (event) => {

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -596,6 +596,10 @@ class SqueakController:
def get_connected_peers(self):
return self.connection_manager.peers
def get_connected_peer(self, host, port):
address = (host, port)
return self.connection_manager.get_peer(address)
def lookup_squeaks_for_interest(
self,
address: str,