Skip to content

Commit a3b95bb

Browse files
committed
demo+connect: add pages to connect to a node
1 parent dd8d24b commit a3b95bb

File tree

9 files changed

+365
-27
lines changed

9 files changed

+365
-27
lines changed
47.5 MB
Binary file not shown.

demos/connect-demo/src/App.tsx

Lines changed: 4 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,17 @@
11
import React from 'react';
2-
import { Container, Navbar } from 'react-bootstrap';
32
import { BrowserRouter, Route, Routes } from 'react-router-dom';
4-
import logo from './logo.svg';
3+
import Connect from './pages/Connect';
54
import Home from './pages/Home';
5+
import Login from './pages/Login';
66

77
function App() {
88
return (
99
<>
10-
<Navbar bg="dark" variant="dark" className="mb-3">
11-
<Container>
12-
<Navbar.Brand href="#home">
13-
<img
14-
alt="logo"
15-
src={logo}
16-
width="30"
17-
height="30"
18-
className="d-inline-block align-top"
19-
/>{' '}
20-
lnc-web demo
21-
</Navbar.Brand>
22-
</Container>
23-
</Navbar>
2410
<BrowserRouter>
2511
<Routes>
2612
<Route index element={<Home />} />
13+
<Route path="connect" element={<Connect />} />
14+
<Route path="login" element={<Login />} />
2715
</Routes>
2816
</BrowserRouter>
2917
</>
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
import React, { useEffect, useState } from 'react';
2+
import { Table } from 'react-bootstrap';
3+
import useLNC from '../hooks/useLNC';
4+
5+
const GetInfo: React.FC = () => {
6+
const { lnc } = useLNC();
7+
const [info, setInfo] = useState<any>();
8+
9+
useEffect(() => {
10+
if (lnc.isConnected) {
11+
const sendRequest = async () => {
12+
const res = await lnc.lnd.lightning.getInfo();
13+
setInfo(res);
14+
};
15+
sendRequest();
16+
}
17+
}, [lnc.isConnected, lnc.lnd.lightning]);
18+
19+
if (!lnc.isConnected || !info) return null;
20+
21+
return (
22+
<>
23+
<h4 className="mt-5">GetInfo Response</h4>
24+
<Table bordered hover responsive>
25+
<thead>
26+
<tr>
27+
<th>Info</th>
28+
<th>Value</th>
29+
</tr>
30+
</thead>
31+
<tbody>
32+
<tr>
33+
<td>Alias</td>
34+
<td>{info.alias}</td>
35+
</tr>
36+
<tr>
37+
<td>Pubkey</td>
38+
<td>{info.identityPubkey}</td>
39+
</tr>
40+
<tr>
41+
<td>Version</td>
42+
<td>{info.version}</td>
43+
</tr>
44+
<tr>
45+
<td>Pending Channels</td>
46+
<td>{info.numPendingChannels}</td>
47+
</tr>
48+
<tr>
49+
<td>Active Channels</td>
50+
<td>{info.numActiveChannels}</td>
51+
</tr>
52+
<tr>
53+
<td>Inactive Channels</td>
54+
<td>{info.numInactiveChannels}</td>
55+
</tr>
56+
<tr>
57+
<td>Peers</td>
58+
<td>{info.numPeers}</td>
59+
</tr>
60+
<tr>
61+
<td>Block Height</td>
62+
<td>{info.blockHeight}</td>
63+
</tr>
64+
<tr>
65+
<td>Synced to Chain</td>
66+
<td>{info.syncedToChain.toString()}</td>
67+
</tr>
68+
<tr>
69+
<td>Synced to Graph</td>
70+
<td>{info.syncedToGraph.toString()}</td>
71+
</tr>
72+
</tbody>
73+
</Table>
74+
</>
75+
);
76+
};
77+
78+
export default GetInfo;
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
import React from 'react';
2+
import { Button, Col, Container, Nav, Navbar, Row } from 'react-bootstrap';
3+
import { Link } from 'react-router-dom';
4+
import useLNC from '../hooks/useLNC';
5+
import logo from '../logo.svg';
6+
7+
interface Props {
8+
children?: React.ReactNode;
9+
}
10+
11+
const Page: React.FC<Props> = ({ children }) => {
12+
const { lnc } = useLNC();
13+
14+
return (
15+
<>
16+
<Navbar bg="dark" variant="dark" expand="lg" className="mb-3">
17+
<Container>
18+
<Link to="/" className="navbar-brand">
19+
<img
20+
alt="logo"
21+
src={logo}
22+
width="30"
23+
height="30"
24+
className="d-inline-block align-top"
25+
/>{' '}
26+
LNC Demo
27+
</Link>
28+
<Navbar.Toggle aria-controls="basic-navbar-nav" />
29+
<Navbar.Collapse id="basic-navbar-nav">
30+
<Nav className="ml-auto">
31+
{lnc.isConnected ? (
32+
<>
33+
<Navbar.Text>Connected</Navbar.Text>
34+
<a href="/">
35+
<Button variant="link">Logout</Button>
36+
</a>
37+
</>
38+
) : lnc.isPaired ? (
39+
<Link to="/login">
40+
<Button>Login</Button>
41+
</Link>
42+
) : (
43+
<Link to="/connect">
44+
<Button>Connect</Button>
45+
</Link>
46+
)}
47+
</Nav>
48+
</Navbar.Collapse>
49+
</Container>
50+
</Navbar>
51+
<Container>
52+
<Row>
53+
<Col>{children}</Col>
54+
</Row>
55+
</Container>
56+
</>
57+
);
58+
};
59+
60+
export default Page;
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import { useCallback } from 'react';
2+
import LNC from '@lightninglabs/lnc-web';
3+
4+
// create a singleton instance of LNC that will live for the lifetime of the app
5+
const lnc = new LNC({
6+
// use the LNC wasm file stored in the public dir
7+
wasmClientCode: '/lnc-v0.1.10-alpha.wasm',
8+
});
9+
10+
/**
11+
* A hook that exposes a single LNC instance of LNC to all component that need it.
12+
* It also returns a couple helper functions to simplify the usage of LNC
13+
*/
14+
const useLNC = () => {
15+
/** Connects to LNC using the provided pairing phrase and password */
16+
const connect = useCallback(async (pairingPhrase: string, password: string) => {
17+
lnc.setPassword(password);
18+
lnc.setPairingPhrase(pairingPhrase);
19+
await lnc.connect();
20+
}, []);
21+
22+
/** Connects to LNC using the password to decrypt the stored keys */
23+
const login = useCallback(async (password: string) => {
24+
lnc.setPassword(password);
25+
await lnc.connect();
26+
}, []);
27+
28+
return { lnc, connect, login };
29+
};
30+
31+
export default useLNC;

demos/connect-demo/src/index.tsx

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,7 @@ import App from './App';
55
import reportWebVitals from './reportWebVitals';
66

77
const root = ReactDOM.createRoot(document.getElementById('root') as HTMLElement);
8-
root.render(
9-
<React.StrictMode>
10-
<App />
11-
</React.StrictMode>,
12-
);
8+
root.render(<App />);
139

1410
// If you want to start measuring performance in your app, pass a function
1511
// to log results (for example: reportWebVitals(console.log))
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
import React, { useCallback, useEffect, useState } from 'react';
2+
import { Alert, Button, Form } from 'react-bootstrap';
3+
import { useNavigate } from 'react-router-dom';
4+
import Page from '../components/Page';
5+
import useLNC from '../hooks/useLNC';
6+
7+
const Connect: React.FC = () => {
8+
const { lnc, connect } = useLNC();
9+
const navigate = useNavigate();
10+
const [phrase, setPhrase] = useState('');
11+
const [password, setPassword] = useState('');
12+
const [loading, setLoading] = useState(false);
13+
const [error, setError] = useState('');
14+
15+
useEffect(() => {
16+
// preload the WASM file when this component is mounted
17+
lnc.preload();
18+
}, [lnc]);
19+
20+
const handleSubmit = useCallback(
21+
(e: React.FormEvent<HTMLFormElement>) => {
22+
// wrap LNC calls into an async function
23+
const connectAsync = async () => {
24+
e.preventDefault();
25+
try {
26+
setLoading(true);
27+
setError('');
28+
if (!phrase || !password) throw new Error('Enter a phrase and password');
29+
30+
// connect to the litd node via LNC
31+
await connect(phrase, password);
32+
33+
navigate('/');
34+
} catch (err) {
35+
setError((err as Error).message);
36+
// tslint:disable-next-line: no-console
37+
console.error(err);
38+
} finally {
39+
setLoading(false);
40+
}
41+
};
42+
connectAsync();
43+
},
44+
[phrase, password, navigate, connect],
45+
);
46+
47+
return (
48+
<Page>
49+
<h2>Connect to Lightning Terminal</h2>
50+
51+
{error && <Alert variant="danger">{error}</Alert>}
52+
53+
<Form onSubmit={handleSubmit}>
54+
<Form.Group className="mb-3" controlId="formBasicEmail">
55+
<Form.Label>Pairing Phrase</Form.Label>
56+
<Form.Control
57+
autoComplete="off"
58+
value={phrase}
59+
onChange={e => setPhrase(e.target.value)}
60+
disabled={loading}
61+
/>
62+
<Form.Text className="text-muted">
63+
Obtain a new pairing phrase from <code>litd</code> and enter it here
64+
</Form.Text>
65+
</Form.Group>
66+
<Form.Group className="mb-3" controlId="formBasicPassword">
67+
<Form.Label>Create Password</Form.Label>
68+
<Form.Control
69+
type="password"
70+
autoComplete="new-password"
71+
value={password}
72+
onChange={e => setPassword(e.target.value)}
73+
disabled={loading}
74+
/>
75+
<Form.Text className="text-muted">
76+
lnc-web stores connection data in localStorage. This password will be used to
77+
encrypt the data at rest.
78+
</Form.Text>
79+
</Form.Group>
80+
<Button variant="primary" type="submit" disabled={loading}>
81+
Submit
82+
</Button>
83+
</Form>
84+
</Page>
85+
);
86+
};
87+
88+
export default Connect;

demos/connect-demo/src/pages/Home.tsx

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,21 @@
11
import React from 'react';
2-
import { Col, Container, Row } from 'react-bootstrap';
2+
import GetInfo from '../components/GetInfo';
3+
import Page from '../components/Page';
4+
import useLNC from '../hooks/useLNC';
35

46
const Home: React.FC = () => {
7+
const { lnc } = useLNC();
8+
59
return (
6-
<Container>
7-
<Row>
8-
<Col>Welcome to lnc-web</Col>
9-
</Row>
10-
</Container>
10+
<Page>
11+
<h2 className="text-center">Welcome to lnc-web</h2>
12+
<p className="text-center">
13+
{lnc.isConnected
14+
? 'You are now connected to your Lightning node.'
15+
: 'Connect or Login to view your Lightning node info.'}
16+
</p>
17+
<GetInfo />
18+
</Page>
1119
);
1220
};
1321

0 commit comments

Comments
 (0)