Skip to content

Commit 768371c

Browse files
committed
chore: add pubsub example
1 parent 711d44c commit 768371c

File tree

10 files changed

+595
-0
lines changed

10 files changed

+595
-0
lines changed

.github/workflows/ci.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ jobs:
2020
fail-fast: false
2121
matrix:
2222
project:
23+
- js-libp2p-example-browser-pubsub
2324
- js-libp2p-example-chat
2425
- js-libp2p-example-circuit-relay
2526
- js-libp2p-example-connection-encryption
@@ -70,6 +71,7 @@ jobs:
7071
fail-fast: true
7172
matrix:
7273
project:
74+
- js-libp2p-example-browser-pubsub
7375
- js-libp2p-example-chat
7476
- js-libp2p-example-circuit-relay
7577
- js-libp2p-example-connection-encryption
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# ⚠️ IMPORTANT ⚠️
2+
3+
# Please do not create a Pull Request for this repository
4+
5+
The contents of this repository are automatically synced from the parent [js-libp2p Examples Project](https://github.com/libp2p/js-libp2p-examples) so any changes made to the standalone repository will be lost after the next sync.
6+
7+
Please open a PR against [js-libp2p Examples](https://github.com/libp2p/js-libp2p-examples) instead.
8+
9+
## Contributing
10+
11+
Contributions are what make the open source community such an amazing place to be learn, inspire, and create. Any contributions you make are **greatly appreciated**.
12+
13+
1. Fork the [js-libp2p Examples Project](https://github.com/libp2p/js-libp2p-examples)
14+
2. Create your Feature Branch (`git checkout -b feature/amazing-example`)
15+
3. Commit your Changes (`git commit -a -m 'feat: add some amazing example'`)
16+
4. Push to the Branch (`git push origin feature/amazing-example`)
17+
5. Open a Pull Request
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
name: pull
2+
3+
on:
4+
workflow_dispatch
5+
6+
jobs:
7+
sync:
8+
runs-on: ubuntu-latest
9+
steps:
10+
- uses: actions/checkout@v2
11+
- name: Pull from another repository
12+
uses: ipfs-examples/actions-pull-directory-from-repo@main
13+
with:
14+
source-repo: libp2p/js-libp2p-examples
15+
source-folder-path: examples/${{ github.event.repository.name }}
16+
source-branch: main
17+
target-branch: main
18+
git-username: github-actions
19+
git-email: [email protected]
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
# @libp2p/example-browser-pubsub <!-- omit in toc -->
2+
3+
[![libp2p.io](https://img.shields.io/badge/project-libp2p-yellow.svg?style=flat-square)](http://libp2p.io/)
4+
[![Discuss](https://img.shields.io/discourse/https/discuss.libp2p.io/posts.svg?style=flat-square)](https://discuss.libp2p.io)
5+
[![codecov](https://img.shields.io/codecov/c/github/libp2p/js-libp2p-examples.svg?style=flat-square)](https://codecov.io/gh/libp2p/js-libp2p-examples)
6+
[![CI](https://img.shields.io/github/actions/workflow/status/libp2p/js-libp2p-examples/ci.yml?branch=main\&style=flat-square)](https://github.com/libp2p/js-libp2p-examples/actions/workflows/ci.yml?query=branch%3Amain)
7+
8+
> User libp2p pubsub in browsers
9+
10+
This example leverages the [vite bundler](https://vitejs.dev/) to compile and serve the libp2p code in the browser. You can use other bundlers such as Webpack, but we will not be covering them here.
11+
12+
## Table of contents <!-- omit in toc -->
13+
14+
- [Setup](#setup)
15+
- [Running](#running)
16+
- [Why do I need a Relay Server?](#why-do-i-need-a-relay-server)
17+
- [Start the Relay Server](#start-the-relay-server)
18+
- [Running the Example](#running-the-example)
19+
- [License](#license)
20+
- [Contribution](#contribution)
21+
22+
## Setup
23+
24+
1. Install example depenedencies and build the project
25+
```console
26+
$ npm install
27+
$ npm run build
28+
```
29+
2. Open 2 terminal windows in the `./src` directory.
30+
31+
## Running
32+
33+
This example has three components. Two browser windows which will send pubsub messages and a relay server that they will use to establish the initial connection.
34+
35+
### Why do I need a Relay Server?
36+
37+
The only transport available to browser nodes that lets them be dialed by remote peers is the [WebRTC](https://www.npmjs.com/package/@libp2p/webrtc) transport.
38+
39+
This transport requires an initial [handshake](https://en.wikipedia.org/wiki/Session_Description_Protocol) to be done out-of-band, during which the two peers exchange their capabilities, addresses and open ports.
40+
41+
We use a [Circuit Relay](https://docs.libp2p.io/concepts/nat/circuit-relay/) server to establish an initial communication channel between the two browsers for this process, after which they will have negotiated a peer-to-peer connection and the relay will no longer be used.
42+
43+
```mermaid
44+
sequenceDiagram
45+
Browser A->>Relay: Create reservation
46+
activate Relay
47+
Browser B->>Relay: Dial Browser A
48+
Relay->>Browser A: Relayed dial from Browser B
49+
Browser B->>Relay: WebRTC handshake request
50+
Relay->>Browser A: Relayed WebRTC handshake request
51+
Browser A->>Relay: WebRTC handshake response
52+
Relay->>Browser B: Relayed WebRTC handshake response
53+
deactivate Relay
54+
Browser B->>Browser A: WebRTC connection
55+
```
56+
57+
### Start the Relay Server
58+
59+
For browsers to communicate, we first need to run the libp2p relay server:
60+
61+
```console
62+
$ npm run relay
63+
```
64+
65+
Copy one of the multiaddresses in the output.
66+
67+
### Running the Example
68+
69+
Start the Vite server:
70+
71+
```console
72+
$ npm start
73+
```
74+
75+
A browser window will automatically open. Let's call this `Browser A`.
76+
77+
1. Paste the copied multiaddress from the relay server, paste it into the `Dial MultiAddr` input and click the `Connect` button
78+
2. `Browser A` is now connected to the relay server
79+
3. Copy the multiaddress located after the `Listening on` message
80+
81+
Now open a second browser with the url `http://localhost:5173/`. Let's call this `Browser B`.
82+
83+
1. Using the copied multiaddress from `Listening on` section in `Browser A`, paste it into the `Remote MultiAddress` input and click the `Connect` button
84+
2. `Browser B` is now connected to `Browser A`
85+
86+
You can now shut down the relay server if you wish.
87+
88+
1. In both `Browser A` and `Browser B`, enter the same topic name in the "Subscribe to topic" input and click the "Subscribe" button
89+
2. In either browser, enter a message in the `Send Message to Topic` field and click "Send"
90+
91+
You should see the message appear in the output section towards the bottom of the other browser window.
92+
93+
## License
94+
95+
Licensed under either of
96+
97+
- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / <http://www.apache.org/licenses/LICENSE-2.0>)
98+
- MIT ([LICENSE-MIT](LICENSE-MIT) / <http://opensource.org/licenses/MIT>)
99+
100+
## Contribution
101+
102+
Unless you explicitly state otherwise, any contribution intentionally submitted
103+
for inclusion in the work by you, as defined in the Apache-2.0 license, shall be
104+
dual licensed as above, without any additional terms or conditions.
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8" />
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
6+
<title>js-libp2p browser pubsub</title>
7+
<style>
8+
label,
9+
button {
10+
display: block;
11+
font-weight: bold;
12+
margin: 5px 0;
13+
}
14+
div {
15+
margin-bottom: 20px;
16+
}
17+
#send-section {
18+
display: none;
19+
}
20+
input[type="text"] {
21+
width: 800px;
22+
}
23+
</style>
24+
</head>
25+
<body>
26+
<h1>libp2p Browser PubSub example</h1>
27+
<p>This example demonstrates the pubsub API running in a browser</p>
28+
<ol>
29+
<li>Start a relay using the command line: <pre>$ node ./relay.js
30+
Relay listening on multiaddr(s): [
31+
'${multiaddr}'
32+
]
33+
</pre></li>
34+
<li>Copy the relay's multiaddr and use the "Dial Multaddr" section to dial the relay</li>
35+
<li>Wait for a WebRTC address to appear in the "Listening Addresses" area</li>
36+
<li>Open the same page in another browser window</li>
37+
<li>Use the "Dial Multiaddr" section in the second window to dial the WebRTC address from the first</li>
38+
<li>Subscribe both windows to the same topic using the "PubSub" section</li>
39+
<li>Send messages between the windows using the "PubSub" section</li>
40+
</ol>
41+
<hr />
42+
<div>
43+
<h2>Node</h2>
44+
<label for="relay">Dial MultiAddr</label>
45+
<input type="text" id="dial-multiaddr-input" placeholder="/ip4/127.0.0.1/tcp/1234/ws/p2p/123Foo" />
46+
<button id="dial-multiaddr-button">Connect</button>
47+
48+
<h4>PeerId</h4>
49+
<p id="peer-id"></p>
50+
51+
<h4>Listening Addresses</h4>
52+
<ul id="listening-addresses">
53+
<li>None</li>
54+
</ul>
55+
56+
<h4>Connected Peers</h4>
57+
<ul id="peer-connections">
58+
<li>None</li>
59+
</ul>
60+
</div>
61+
<hr />
62+
<div>
63+
<h2>PubSub</h2>
64+
<label for="topic">Subscribe to topic</label>
65+
<input type="text" id="subscribe-topic-input" placeholder="my-topic" />
66+
<button id="subscribe-topic-button">Subscribe</button>
67+
68+
<h4>Topic Peers</h4>
69+
<ul id="topic-peers">
70+
<li>None</li>
71+
</ul>
72+
73+
<label for="topic">Send Message to Topic</label>
74+
<input type="text" id="send-topic-message-input" placeholder="hello world" disabled="disabled" />
75+
<button id="send-topic-message-button" disabled="disabled">Send</button>
76+
</div>
77+
<hr />
78+
<div>
79+
<h2>Output</h2>
80+
<pre id="output"></pre>
81+
</div>
82+
<script type="module" src="./index.js"></script>
83+
</body>
84+
</html>

0 commit comments

Comments
 (0)