Skip to content

Commit 0ea38dc

Browse files
authored
Merge pull request libp2p#60 from little-bear-labs/feature/refactor-and-add-tests-and-coverage
Feature/refactor and add tests and coverage
2 parents b2e4f60 + f254822 commit 0ea38dc

27 files changed

+1717
-426
lines changed

.github/workflows/js-test-and-release.yml

Lines changed: 3 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,11 @@
1-
# File managed by web3-bot. DO NOT EDIT.
2-
# See https://github.com/protocol/.github/ for details.
3-
41
name: test & maybe release
52
on:
63
push:
74
branches:
8-
- master # with #262 - ${{{ github.default_branch }}}
5+
- main # with #262 - ${{{ github.default_branch }}}
96
pull_request:
107
branches:
11-
- master # with #262 - ${{{ github.default_branch }}}
8+
- main # with #262 - ${{{ github.default_branch }}}
129
- develop
1310

1411
jobs:
@@ -38,20 +35,6 @@ jobs:
3835
with:
3936
flags: chrome
4037

41-
test-chrome-webworker:
42-
needs: check
43-
runs-on: ubuntu-latest
44-
steps:
45-
- uses: actions/checkout@v3
46-
- uses: actions/setup-node@v2
47-
with:
48-
node-version: lts/*
49-
- uses: ipfs/aegir/actions/cache-node-modules@master
50-
- run: npm run --if-present test:chrome-webworker
51-
- uses: codecov/codecov-action@81cd2dc8148241f03f5839d295e000b8f761e378 # v3.1.0
52-
with:
53-
flags: chrome-webworker
54-
5538
test-firefox:
5639
needs: check
5740
runs-on: ubuntu-latest
@@ -66,36 +49,8 @@ jobs:
6649
with:
6750
flags: firefox
6851

69-
test-firefox-webworker:
70-
needs: check
71-
runs-on: ubuntu-latest
72-
steps:
73-
- uses: actions/checkout@v3
74-
- uses: actions/setup-node@v2
75-
with:
76-
node-version: lts/*
77-
- uses: ipfs/aegir/actions/cache-node-modules@master
78-
- run: npm run --if-present test:firefox-webworker
79-
- uses: codecov/codecov-action@81cd2dc8148241f03f5839d295e000b8f761e378 # v3.1.0
80-
with:
81-
flags: firefox-webworker
82-
83-
test-electron-main:
84-
needs: check
85-
runs-on: ubuntu-latest
86-
steps:
87-
- uses: actions/checkout@v3
88-
- uses: actions/setup-node@v2
89-
with:
90-
node-version: lts/*
91-
- uses: ipfs/aegir/actions/cache-node-modules@master
92-
- run: npx xvfb-maybe npm run --if-present test:electron-main
93-
- uses: codecov/codecov-action@81cd2dc8148241f03f5839d295e000b8f761e378 # v3.1.0
94-
with:
95-
flags: electron-main
96-
9752
release:
98-
needs: [test-chrome, test-chrome-webworker, test-firefox, test-firefox-webworker, test-electron-main]
53+
needs: [test-chrome, test-firefox]
9954
runs-on: ubuntu-latest
10055
if: github.event_name == 'push' && github.ref == 'refs/heads/master' # with #262 - 'refs/heads/${{{ github.default_branch }}}'
10156
steps:

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ public/css/main.css
1818

1919
# Coverage reports
2020
coverage
21+
.coverage
22+
.nyc_output
2123

2224
# API keys and secrets
2325
.env

README.md

Lines changed: 89 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -3,22 +3,23 @@
33
[![libp2p.io](https://img.shields.io/badge/project-libp2p-yellow.svg?style=flat-square)](http://libp2p.io/)
44
[![IRC](https://img.shields.io/badge/freenode-%23libp2p-yellow.svg?style=flat-square)](http://webchat.freenode.net/?channels=%23libp2p)
55
[![Discuss](https://img.shields.io/discourse/https/discuss.libp2p.io/posts.svg?style=flat-square)](https://discuss.libp2p.io)
6-
[![codecov](https://img.shields.io/codecov/c/github/little-bear-labs//js-libp2p-webrtc.svg?style=flat-square)](https://codecov.io/gh/little-bear-labs//js-libp2p-webrtc)
7-
[![CI](https://img.shields.io/github/workflow/status/libp2p/js-libp2p-interfaces/test%20&%20maybe%20release/master?style=flat-square)](https://github.com/little-bear-labs//js-libp2p-webrtc/actions/workflows/js-test-and-release.yml)
6+
[![codecov](https://img.shields.io/codecov/c/github/little-bear-labs/js-libp2p-webrtc.svg?style=flat-square)](https://codecov.io/gh/little-bear-labs/js-libp2p-webrtc)
7+
[![CI](https://img.shields.io/github/workflow/status/libp2p/js-libp2p-interfaces/test%20&%20maybe%20release/master?style=flat-square)](https://github.com/little-bear-labs/js-libp2p-webrtc/actions/workflows/js-test-and-release.yml)
88

99
> The browser implementation of the WebRTC module for libp2p.
1010
1111
## Table of contents <!-- omit in toc -->
1212

1313
- [Install](#install)
1414
- [Usage](#usage)
15-
- [API](#api)
15+
- [Examples](#examples)
16+
- [Interfaces](#interfaces)
1617
- [Transport](#transport)
1718
- [Connection](#connection)
18-
- [Hacking](#hacking)
1919
- [Contribute](#contribute)
20-
- [Development](#development)
2120
- [Build](#build)
21+
- [Protocol Buffers](#protocol-buffers)
22+
- [Test](#test)
2223
- [Lint](#lint)
2324
- [Clean](#clean)
2425
- [Check Dependencies](#check-dependencies)
@@ -35,49 +36,81 @@ npm i @libp2p/webrtc
3536
## Usage
3637

3738
```js
38-
import { createLibp2pNode } from 'libp2p'
39-
import { webRTC } from '@libp2p/webrtc'
40-
import { noise } from '@chainsafe/libp2p-noise'
39+
import { createLibp2p } from 'libp2p'
40+
import { Noise } from '@chainsafe/libp2p-noise'
4141
import { multiaddr } from '@multiformats/multiaddr'
42-
import { pipe } from 'it-pipe'
43-
import all from 'it-all'
44-
45-
const node = await createLibp2pNode({
46-
transports: [
47-
webRTC()
48-
],
49-
connectionEncryption: [
50-
noise()
51-
]
52-
})
53-
54-
const addr = multiaddr('/ip4/0.0.0.0/udp/56093/webrtc/certhash/uEiByaEfNSLBexWBNFZy_QB1vAKEj7JAXDizRs4_SnTflsQ')
55-
const { stream } = await node.dialProtocol(addr, '/my-protocol/1.0.0')
56-
const values = await pipe(stream, all)
42+
import first from "it-first";
43+
import { pipe } from "it-pipe";
44+
import { fromString, toString } from "uint8arrays";
45+
import { webRTC } from 'js-libp2p-webrtc'
46+
47+
const node = await createLibp2p({
48+
transports: [webRTC()],
49+
connectionEncryption: [() => new Noise()],
50+
});
51+
52+
await node.start()
53+
54+
const ma = multiaddr('/ip4/0.0.0.0/udp/56093/webrtc/certhash/uEiByaEfNSLBexWBNFZy_QB1vAKEj7JAXDizRs4_SnTflsQ')
55+
const stream = await node.dialProtocol(ma, ['/my-protocol/1.0.0'])
56+
const message = `Hello js-libp2p-webrtc\n`
57+
const response = await pipe([fromString(message)], stream, async (source) => await first(source))
58+
const responseDecoded = toString(response.slice(0, response.length))
5759
```
58-
## API
60+
61+
## Examples
62+
Examples can be found in the [examples folder](examples/README.md).
63+
64+
## Interfaces
5965

6066
### Transport
6167

62-
[![](https://raw.githubusercontent.com/libp2p/js-libp2p-interfaces/master/packages/libp2p-interfaces/src/transport/img/badge.png)](https://github.com/libp2p/js-libp2p-interfaces/tree/master/packages/libp2p-interfaces/src/transport)
68+
![https://github.com/libp2p/js-libp2p-interfaces/tree/master/packages/interface-transport](https://raw.githubusercontent.com/libp2p/js-libp2p-interfaces/master/packages/interface-transport/img/badge.png)
6369

64-
`libp2p-webrtc` accepts WebRTC encapsulated addresses: `/ip4/0.0.0.0/udp/56093/webrtc/certhash/uEiByaEfNSLBexWBNFZy_QB1vAKEj7JAXDizRs4_SnTflsQ`
70+
Browsers can only `dial`, so `listen` is not supported.
6571

66-
### Connection
72+
```js
73+
interface Transport {
74+
[Symbol.toStringTag]: string
75+
[symbol]: true
76+
dial: (ma: Multiaddr, options: DialOptions) => Promise<Connection>
77+
createListener: (options: CreateListenerOptions) => Listener
78+
filter: MultiaddrFilter
79+
}
80+
81+
class WebRTCTransport implements Transport {
82+
83+
async dial (ma: Multiaddr, options: WebRTCDialOptions): Promise<Connection> {
84+
const rawConn = await this._connect(ma, options)
85+
log(`dialing address - ${ma.toString()}`)
86+
return rawConn
87+
}
88+
89+
createListener (options: CreateListenerOptions): Listener {
90+
throw unimplemented('WebRTCTransport.createListener')
91+
}
92+
}
93+
```
6794

68-
[![](https://raw.githubusercontent.com/libp2p/js-libp2p-interfaces/master/packages/libp2p-interfaces/src/connection/img/badge.png)](https://github.com/libp2p/js-libp2p-interfaces/tree/master/packages/libp2p-interfaces/src/connection)
95+
### Connection
6996

70-
## Hacking
97+
![https://github.com/libp2p/js-libp2p-interfaces/tree/master/packages/interface-connection](https://raw.githubusercontent.com/libp2p/js-libp2p-interfaces/master/packages/interface-connection/img/badge.png)
7198

72-
Besides the usual `npm install` to get dependencies, `npm run build` to invoke tsc, and `npm run test` to execute unit tests...
99+
```js
100+
interface MultiaddrConnection extends Duplex<Uint8Array> {
101+
close: (err?: Error) => Promise<void>
102+
remoteAddr: Multiaddr
103+
timeline: MultiaddrConnectionTimeline
104+
}
73105

74-
There is also `npm run autogen` which uses ProtoBuf's protoc to populate the generated code directory `proto_ts` based on `*.proto` files in src. Don't forget to run this step before `build` any time you make a change to any of the `*.proto` files.
106+
class WebRTCMultiaddrConnection implements MultiaddrConnection { }
107+
```
75108

76109
## Contribute
77110

78111
Contributions are welcome! The libp2p implementation in JavaScript is a work in progress. As such, there's a few things you can do right now to help out:
79112

80-
- [Check out the existing issues](//github.com/little-bear-labs//js-libp2p-webrtc/issues).
113+
- [Check out the existing issues](//github.com/little-bear-labs/js-libp2p-webrtc/issues).
81114
- **Perform code reviews**.
82115
- **Add tests**. There can never be enough tests.
83116
- Go through the modules and **check out existing issues**. This is especially useful for modules in active development. Some knowledge of IPFS/libp2p may be required, as well as the infrastructure behind it - for instance, you may need to read up on p2p and more complex operations like muxing to be able to help technically.
@@ -86,8 +119,6 @@ Please be aware that all interactions related to libp2p are subject to the IPFS
86119

87120
Small note: If editing the README, please conform to the [standard-readme](https://github.com/RichardLitt/standard-readme) specification.
88121

89-
## Development
90-
91122
This module leans heavily on (Aegir)[https://github.com/ipfs/aegir] for most of the `package.json` scripts.
92123

93124
### Build
@@ -99,6 +130,30 @@ npm run build
99130

100131
The build will be located in the `/dist` folder.
101132

133+
### Protocol Buffers
134+
135+
There is also `npm run generate:proto` script that uses protoc to populate the generated code directory `proto_ts` based on `*.proto` files in src. Don't forget to run this step before `build` any time you make a change to any of the `*.proto` files.
136+
137+
### Test
138+
139+
To run all tests:
140+
141+
```shell
142+
npm test
143+
```
144+
145+
To run tests for Chome only:
146+
147+
```shell
148+
npm run test:chrome
149+
```
150+
151+
To run tests for Firefox only:
152+
153+
```shell
154+
npm run test:firefox
155+
```
156+
102157
### Lint
103158
Aegir is also used to lint the code, which follows the [Standard](https://github.com/standard/standard) JS linter.
104159
The VS Code plugin for this standard is located at https://marketplace.visualstudio.com/items?itemName=standard.vscode-standard.

examples/README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# Examples
2+
3+
* [Browser to Server Echo](browser-to-server/README.md): connect to a go-libp2p-webrtc server with a browser
4+
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# js-libp2p-webrtc Browser to Server
2+
3+
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.
4+
5+
## Running the Go Server
6+
7+
To run the Go LibP2P WebRTC server:
8+
9+
```shell
10+
npm run go-libp2p-server
11+
```
12+
13+
Copy the multiaddress in the output.
14+
15+
## Running the Example
16+
17+
In a separate console tab, install dependencies and start the Vite server:
18+
19+
```shell
20+
npm i && npm run start
21+
```
22+
23+
The browser window will automatically open.
24+
Using the copied multiaddress from the Go server, paste it into the `Server MultiAddress` input and click the `Connect` button.
25+
Once the peer is connected, click the message section will appear. Enter a message and click the `Send` button.
26+
27+
The output should look like:
28+
29+
```text
30+
Dialing /ip4/10.0.1.5/udp/54375/webrtc/certhash/uEiADy8JubdWrAzseyzfXFyCpdRN02eWZg86tjCrTCA5dbQ/p2p/12D3KooWEG7N4bnZfFBNZE7WG6xm2P4Sr6sonMwyD4HCAqApEthb
31+
Peer connected '/ip4/10.0.1.5/udp/54375/webrtc/certhash/uEiADy8JubdWrAzseyzfXFyCpdRN02eWZg86tjCrTCA5dbQ/p2p/12D3KooWEG7N4bnZfFBNZE7WG6xm2P4Sr6sonMwyD4HCAqApEthb'
32+
Sending message 'hello'
33+
Received message 'hello'
34+
```
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
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 WebRTC</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+
<div id="app">
27+
<div>
28+
<label for="peer">Server MultiAddress:</label>
29+
<input type="text" id="peer" />
30+
<button id="connect">Connect</button>
31+
</div>
32+
<div id="send-section">
33+
<label for="message">Message:</label>
34+
<input type="text" id="message" value="hello" />
35+
<button id="send">Send</button>
36+
</div>
37+
<div id="output"></div>
38+
</div>
39+
<script type="module" src="./index.js"></script>
40+
</body>
41+
</html>
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import { createLibp2p } from 'libp2p'
2+
import { Noise } from '@chainsafe/libp2p-noise'
3+
import { multiaddr } from '@multiformats/multiaddr'
4+
import first from "it-first";
5+
import { pipe } from "it-pipe";
6+
import { fromString, toString } from "uint8arrays";
7+
import { webRTC } from 'js-libp2p-webrtc'
8+
9+
let stream;
10+
const output = document.getElementById('output')
11+
const sendSection = document.getElementById('send-section')
12+
const appendOutput = (line) => output.innerText += `${line}\n`
13+
const clean = (line) => line.replaceAll('\n', '')
14+
15+
const node = await createLibp2p({
16+
transports: [webRTC()],
17+
connectionEncryption: [() => new Noise()],
18+
});
19+
20+
await node.start()
21+
22+
node.connectionManager.addEventListener('peer:connect', (connection) => {
23+
appendOutput(`Peer connected '${node.getConnections().map(c => c.remoteAddr.toString())}'`)
24+
sendSection.style.display = 'block'
25+
})
26+
27+
window.connect.onclick = async () => {
28+
const ma = multiaddr(window.peer.value)
29+
appendOutput(`Dialing ${ma}`)
30+
stream = await node.dialProtocol(ma, ['/echo/1.0.0'])
31+
}
32+
33+
window.send.onclick = async () => {
34+
const message = `${window.message.value}\n`
35+
appendOutput(`Sending message '${clean(message)}'`)
36+
const response = await pipe([fromString(message)], stream, async (source) => await first(source))
37+
const responseDecoded = toString(response.slice(0, response.length));
38+
appendOutput(`Received message '${clean(responseDecoded)}'`)
39+
}

0 commit comments

Comments
 (0)