From 7fb23cd340789041587a073975a88d8c5a327fd8 Mon Sep 17 00:00:00 2001 From: Alex Potsides Date: Wed, 28 Jun 2023 07:27:28 +0200 Subject: [PATCH] chore: make examples self-contained (#1859) - Adds a package.json to each example with dependencies for that example. - Configures each example as a monorepo project This ensures that the examples will use the dependency versions from the monorepo instead of downloading them from npm. Closes #1759 --- .github/workflows/main.yml | 32 +---- README.md | 13 ++ examples/auto-relay/LICENSE | 4 + examples/auto-relay/LICENSE-APACHE | 5 + examples/auto-relay/LICENSE-MIT | 19 +++ examples/auto-relay/README.md | 31 ++++- examples/auto-relay/dialer.js | 8 +- examples/auto-relay/listener.js | 8 +- examples/auto-relay/package.json | 46 +++++++ examples/auto-relay/relay.js | 10 +- examples/auto-relay/test.js | 122 +++++++++--------- examples/chat/LICENSE | 4 + examples/chat/LICENSE-APACHE | 5 + examples/chat/LICENSE-MIT | 19 +++ examples/chat/README.md | 31 ++++- examples/chat/package.json | 52 ++++++++ examples/chat/src/dialer.js | 4 +- examples/chat/src/libp2p.js | 8 +- examples/chat/src/listener.js | 4 +- examples/chat/src/peer-id-dialer.js | 6 +- examples/chat/src/peer-id-listener.js | 6 +- examples/chat/src/stream.js | 6 +- examples/chat/test.js | 106 ++++++++------- examples/connection-encryption/1.js | 12 +- examples/connection-encryption/LICENSE | 4 + examples/connection-encryption/LICENSE-APACHE | 5 + examples/connection-encryption/LICENSE-MIT | 19 +++ examples/connection-encryption/README.md | 30 ++++- examples/connection-encryption/package.json | 45 +++++++ examples/connection-encryption/test.js | 13 +- examples/delegated-routing/LICENSE | 4 + examples/delegated-routing/LICENSE-APACHE | 5 + examples/delegated-routing/LICENSE-MIT | 19 +++ examples/delegated-routing/README.md | 46 +++++-- examples/delegated-routing/package.json | 63 ++++++--- examples/delegated-routing/src/App.js | 106 +++++++-------- examples/delegated-routing/src/index.js | 2 +- .../delegated-routing/src/libp2p-bundle.js | 51 -------- examples/discovery-mechanisms/1.js | 10 +- examples/discovery-mechanisms/2.js | 10 +- examples/discovery-mechanisms/3.js | 10 +- examples/discovery-mechanisms/LICENSE | 4 + examples/discovery-mechanisms/LICENSE-APACHE | 5 + examples/discovery-mechanisms/LICENSE-MIT | 19 +++ examples/discovery-mechanisms/README.md | 33 ++++- .../discovery-mechanisms/bootstrappers.js | 2 +- examples/discovery-mechanisms/package.json | 50 +++++++ examples/discovery-mechanisms/test-1.js | 2 +- examples/discovery-mechanisms/test-2.js | 2 +- examples/discovery-mechanisms/test-3.js | 2 +- examples/discovery-mechanisms/test.js | 8 +- examples/echo/LICENSE | 4 + examples/echo/LICENSE-APACHE | 5 + examples/echo/LICENSE-MIT | 19 +++ examples/echo/README.md | 31 ++++- examples/echo/package.json | 50 +++++++ examples/echo/src/dialer.js | 12 +- examples/echo/src/id-d.js | 6 +- examples/echo/src/id-l.js | 6 +- examples/echo/src/libp2p.js | 8 +- examples/echo/src/listener.js | 6 +- examples/echo/test.js | 92 +++++++------ examples/libp2p-in-the-browser/LICENSE | 4 + examples/libp2p-in-the-browser/LICENSE-APACHE | 5 + examples/libp2p-in-the-browser/LICENSE-MIT | 19 +++ examples/libp2p-in-the-browser/README.md | 46 +++++-- examples/libp2p-in-the-browser/index.js | 18 +-- examples/libp2p-in-the-browser/package.json | 51 ++++++-- examples/libp2p-in-the-browser/test.js | 62 ++++----- examples/libp2p-in-the-browser/vite.config.js | 2 +- examples/package.json | 27 ---- examples/peer-and-content-routing/1.js | 10 +- examples/peer-and-content-routing/2.js | 14 +- examples/peer-and-content-routing/LICENSE | 4 + .../peer-and-content-routing/LICENSE-APACHE | 5 + examples/peer-and-content-routing/LICENSE-MIT | 19 +++ examples/peer-and-content-routing/README.md | 38 +++++- .../peer-and-content-routing/package.json | 47 +++++++ examples/peer-and-content-routing/test-1.js | 2 +- examples/peer-and-content-routing/test-2.js | 2 +- examples/peer-and-content-routing/test.js | 6 +- examples/pnet/.gitignore | 1 - examples/pnet/LICENSE | 4 + examples/pnet/LICENSE-APACHE | 5 + examples/pnet/LICENSE-MIT | 19 +++ examples/pnet/README.md | 38 +++++- examples/pnet/index.js | 4 +- examples/pnet/libp2p-node.js | 10 +- examples/pnet/package.json | 45 +++++++ examples/pnet/test.js | 11 +- examples/protocol-and-stream-muxing/1.js | 10 +- examples/protocol-and-stream-muxing/2.js | 10 +- examples/protocol-and-stream-muxing/3.js | 8 +- examples/protocol-and-stream-muxing/LICENSE | 4 + .../protocol-and-stream-muxing/LICENSE-APACHE | 5 + .../protocol-and-stream-muxing/LICENSE-MIT | 19 +++ examples/protocol-and-stream-muxing/README.md | 59 ++++++--- .../protocol-and-stream-muxing/package.json | 45 +++++++ examples/protocol-and-stream-muxing/test-1.js | 2 +- examples/protocol-and-stream-muxing/test-2.js | 2 +- examples/protocol-and-stream-muxing/test-3.js | 2 +- examples/protocol-and-stream-muxing/test.js | 8 +- examples/pubsub/1.js | 10 +- examples/pubsub/LICENSE | 4 + examples/pubsub/LICENSE-APACHE | 5 + examples/pubsub/LICENSE-MIT | 19 +++ examples/pubsub/README.md | 54 +++++--- examples/pubsub/package.json | 46 +++++++ examples/pubsub/test-1.js | 2 +- examples/pubsub/test.js | 8 +- examples/test-all.js | 35 ----- examples/test.js | 97 -------------- examples/transports/1.js | 6 +- examples/transports/2.js | 10 +- examples/transports/3.js | 16 +-- examples/transports/4.js | 14 +- examples/transports/LICENSE | 4 + examples/transports/LICENSE-APACHE | 5 + examples/transports/LICENSE-MIT | 19 +++ examples/transports/README.md | 35 ++++- examples/transports/package.json | 47 +++++++ examples/transports/test-1.js | 2 +- examples/transports/test-2.js | 2 +- examples/transports/test-3.js | 2 +- examples/transports/test-4.js | 2 +- examples/transports/test.js | 10 +- examples/utils.js | 58 --------- interop/LICENSE | 4 + interop/LICENSE-APACHE | 5 + interop/LICENSE-MIT | 19 +++ interop/README.md | 36 ++++++ interop/package.json | 56 +++++--- interop/tsconfig.json | 38 ++++-- package.json | 5 +- packages/kad-dht/README.md | 4 +- packages/kad-dht/package.json | 4 +- packages/libp2p/package.json | 4 +- packages/logger/package.json | 2 +- packages/peer-discovery-mdns/package.json | 2 +- packages/pubsub-floodsub/package.json | 2 +- packages/pubsub/package.json | 2 +- packages/transport-tcp/package.json | 2 +- packages/transport-websockets/package.json | 4 +- packages/utils/package.json | 2 +- 144 files changed, 1879 insertions(+), 885 deletions(-) create mode 100644 examples/auto-relay/LICENSE create mode 100644 examples/auto-relay/LICENSE-APACHE create mode 100644 examples/auto-relay/LICENSE-MIT create mode 100644 examples/auto-relay/package.json create mode 100644 examples/chat/LICENSE create mode 100644 examples/chat/LICENSE-APACHE create mode 100644 examples/chat/LICENSE-MIT create mode 100644 examples/chat/package.json create mode 100644 examples/connection-encryption/LICENSE create mode 100644 examples/connection-encryption/LICENSE-APACHE create mode 100644 examples/connection-encryption/LICENSE-MIT create mode 100644 examples/connection-encryption/package.json create mode 100644 examples/delegated-routing/LICENSE create mode 100644 examples/delegated-routing/LICENSE-APACHE create mode 100644 examples/delegated-routing/LICENSE-MIT delete mode 100644 examples/delegated-routing/src/libp2p-bundle.js create mode 100644 examples/discovery-mechanisms/LICENSE create mode 100644 examples/discovery-mechanisms/LICENSE-APACHE create mode 100644 examples/discovery-mechanisms/LICENSE-MIT create mode 100644 examples/discovery-mechanisms/package.json create mode 100644 examples/echo/LICENSE create mode 100644 examples/echo/LICENSE-APACHE create mode 100644 examples/echo/LICENSE-MIT create mode 100644 examples/echo/package.json create mode 100644 examples/libp2p-in-the-browser/LICENSE create mode 100644 examples/libp2p-in-the-browser/LICENSE-APACHE create mode 100644 examples/libp2p-in-the-browser/LICENSE-MIT delete mode 100644 examples/package.json create mode 100644 examples/peer-and-content-routing/LICENSE create mode 100644 examples/peer-and-content-routing/LICENSE-APACHE create mode 100644 examples/peer-and-content-routing/LICENSE-MIT create mode 100644 examples/peer-and-content-routing/package.json delete mode 100644 examples/pnet/.gitignore create mode 100644 examples/pnet/LICENSE create mode 100644 examples/pnet/LICENSE-APACHE create mode 100644 examples/pnet/LICENSE-MIT create mode 100644 examples/pnet/package.json create mode 100644 examples/protocol-and-stream-muxing/LICENSE create mode 100644 examples/protocol-and-stream-muxing/LICENSE-APACHE create mode 100644 examples/protocol-and-stream-muxing/LICENSE-MIT create mode 100644 examples/protocol-and-stream-muxing/package.json create mode 100644 examples/pubsub/LICENSE create mode 100644 examples/pubsub/LICENSE-APACHE create mode 100644 examples/pubsub/LICENSE-MIT create mode 100644 examples/pubsub/package.json delete mode 100644 examples/test-all.js delete mode 100644 examples/test.js create mode 100644 examples/transports/LICENSE create mode 100644 examples/transports/LICENSE-APACHE create mode 100644 examples/transports/LICENSE-MIT create mode 100644 examples/transports/package.json delete mode 100644 examples/utils.js create mode 100644 interop/LICENSE create mode 100644 interop/LICENSE-APACHE create mode 100644 interop/LICENSE-MIT create mode 100644 interop/README.md diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 2ca956b835..07419917cc 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -167,42 +167,16 @@ jobs: - uses: ipfs/aegir/actions/cache-node-modules@master - run: npm run test:interop -- --bail - test-example: + test-examples: needs: build runs-on: ubuntu-latest - strategy: - matrix: - example: [ - chat, - connection-encryption, - discovery-mechanisms, - echo, - libp2p-in-the-browser, - peer-and-content-routing, - pnet, - protocol-and-stream-muxing, - pubsub, - transports - ] - fail-fast: true steps: - uses: actions/checkout@v3 - uses: actions/setup-node@v3 with: node-version: lts/* - uses: ipfs/aegir/actions/cache-node-modules@master - with: - directories: | - ./examples/node_modules - ~/.cache - build: | - cd examples - npm i - npx playwright install - cache_name: cache-examples - - run: | - cd examples - npm run test -- ${{ matrix.example }} + - run: npm run --if-present test:example multidim-interop: needs: build @@ -238,7 +212,7 @@ jobs: test-electron-main, test-electron-renderer, test-interop, - test-example, + test-examples, multidim-interop ] if: github.event_name == 'push' && github.ref == 'refs/heads/master' diff --git a/README.md b/README.md index 87690568e5..1f7f4beed4 100644 --- a/README.md +++ b/README.md @@ -31,6 +31,19 @@ ## Structure +- [`/examples/auto-relay`](./examples/auto-relay) Shows how to configure relayed connections +- [`/examples/chat`](./examples/chat) An example chat app using libp2p +- [`/examples/connection-encryption`](./examples/connection-encryption) An example of how to configure connection encrypters +- [`/examples/delegated-routing`](./examples/delegated-routing) How to configure libp2p delegated routers +- [`/examples/discovery-mechanisms`](./examples/discovery-mechanisms) How to configure peer discovery mechanisms +- [`/examples/echo`](./examples/echo) An example echo app +- [`/examples/libp2p-in-the-browser`](./examples/libp2p-in-the-browser) A libp2p node running in the browser +- [`/examples/peer-and-content-routing`](./examples/peer-and-content-routing) How to use peer and content routing +- [`/examples/pnet`](./examples/pnet) How to configure a libp2p private network +- [`/examples/protocol-and-stream-muxing`](./examples/protocol-and-stream-muxing) How to use multiplex protocols streams +- [`/examples/pubsub`](./examples/pubsub) An example using libp2p pubsub +- [`/examples/transports`](./examples/transports) An example using different types of libp2p transport +- [`/interop`](./interop) Multidimension Interop Test - [`/packages/crypto`](./packages/crypto) Crypto primitives for libp2p - [`/packages/interface`](./packages/interface) The interface implemented by a libp2p node - [`/packages/interface-compliance-tests`](./packages/interface-compliance-tests) Compliance tests for JS libp2p interfaces diff --git a/examples/auto-relay/LICENSE b/examples/auto-relay/LICENSE new file mode 100644 index 0000000000..20ce483c86 --- /dev/null +++ b/examples/auto-relay/LICENSE @@ -0,0 +1,4 @@ +This project is dual licensed under MIT and Apache-2.0. + +MIT: https://www.opensource.org/licenses/mit +Apache-2.0: https://www.apache.org/licenses/license-2.0 diff --git a/examples/auto-relay/LICENSE-APACHE b/examples/auto-relay/LICENSE-APACHE new file mode 100644 index 0000000000..14478a3b60 --- /dev/null +++ b/examples/auto-relay/LICENSE-APACHE @@ -0,0 +1,5 @@ +Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. diff --git a/examples/auto-relay/LICENSE-MIT b/examples/auto-relay/LICENSE-MIT new file mode 100644 index 0000000000..72dc60d84b --- /dev/null +++ b/examples/auto-relay/LICENSE-MIT @@ -0,0 +1,19 @@ +The MIT License (MIT) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/examples/auto-relay/README.md b/examples/auto-relay/README.md index 3e987685fa..a4479a22dc 100644 --- a/examples/auto-relay/README.md +++ b/examples/auto-relay/README.md @@ -1,7 +1,21 @@ -# Auto relay +# @libp2p/example-auto-relay -Auto Relay enables libp2p nodes to dynamically find and bind to relays on the network. Once binding (listening) is done, the node can and should advertise its addresses on the network, allowing any other node to dial it over its bound relay(s). -While direct connections to nodes are preferable, it's not always possible to do so due to NATs or browser limitations. +[![libp2p.io](https://img.shields.io/badge/project-libp2p-yellow.svg?style=flat-square)](http://libp2p.io/) +[![Discuss](https://img.shields.io/discourse/https/discuss.libp2p.io/posts.svg?style=flat-square)](https://discuss.libp2p.io) +[![codecov](https://img.shields.io/codecov/c/github/libp2p/js-libp2p.svg?style=flat-square)](https://codecov.io/gh/libp2p/js-libp2p) +[![CI](https://img.shields.io/github/actions/workflow/status/libp2p/js-libp2p/main.yml?branch=master\&style=flat-square)](https://github.com/libp2p/js-libp2p/actions/workflows/main.yml?query=branch%3Amaster) + +> Shows how to configure relayed connections + +## Table of contents + +- [0. Setup the example](#0-setup-the-example) +- [1. Set up a relay node](#1-set-up-a-relay-node) +- [2. Set up a listener node with Auto Relay Enabled](#2-set-up-a-listener-node-with-auto-relay-enabled) +- [3. Set up a dialer node for testing connectivity](#3-set-up-a-dialer-node-for-testing-connectivity) +- [4. What is next?](#4-what-is-next) +- [License](#license) +- [Contribution](#contribution) ## 0. Setup the example @@ -173,3 +187,14 @@ As you can see from the output, the remote address of the established connection Before moving into production, there are a few things that you should take into account. A relay node should not advertise its private address in a real world scenario, as the node would not be reachable by others. You should provide an array of public addresses in the libp2p `addresses.announce` option. If you are using websockets, bear in mind that due to browser’s security policies you cannot establish unencrypted connection from secure context. The simplest solution is to setup SSL with nginx and proxy to the node and setup a domain name for the certificate. + +## License + +Licensed under either of + +- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) +- MIT ([LICENSE-MIT](LICENSE-MIT) / ) + +## Contribution + +Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/examples/auto-relay/dialer.js b/examples/auto-relay/dialer.js index 5cfabfe83c..b797da4283 100644 --- a/examples/auto-relay/dialer.js +++ b/examples/auto-relay/dialer.js @@ -1,9 +1,11 @@ -import { createLibp2p } from 'libp2p' -import { webSockets } from '@libp2p/websockets' +/* eslint-disable no-console */ + import { noise } from '@chainsafe/libp2p-noise' +import { yamux } from '@chainsafe/libp2p-yamux' import { mplex } from '@libp2p/mplex' +import { webSockets } from '@libp2p/websockets' import { multiaddr } from '@multiformats/multiaddr' -import { yamux } from '@chainsafe/libp2p-yamux' +import { createLibp2p } from 'libp2p' import { circuitRelayTransport } from 'libp2p/circuit-relay' import { identifyService } from 'libp2p/identify' diff --git a/examples/auto-relay/listener.js b/examples/auto-relay/listener.js index 22b20a4cb8..5ee0967372 100644 --- a/examples/auto-relay/listener.js +++ b/examples/auto-relay/listener.js @@ -1,9 +1,11 @@ -import { createLibp2p } from 'libp2p' -import { webSockets } from '@libp2p/websockets' +/* eslint-disable no-console */ + import { noise } from '@chainsafe/libp2p-noise' +import { yamux } from '@chainsafe/libp2p-yamux' import { mplex } from '@libp2p/mplex' +import { webSockets } from '@libp2p/websockets' import { multiaddr } from '@multiformats/multiaddr' -import { yamux } from '@chainsafe/libp2p-yamux' +import { createLibp2p } from 'libp2p' import { circuitRelayTransport } from 'libp2p/circuit-relay' import { identifyService } from 'libp2p/identify' diff --git a/examples/auto-relay/package.json b/examples/auto-relay/package.json new file mode 100644 index 0000000000..d0a2ade9f8 --- /dev/null +++ b/examples/auto-relay/package.json @@ -0,0 +1,46 @@ +{ + "name": "@libp2p/example-auto-relay", + "version": "0.0.0", + "description": "Shows how to configure relayed connections", + "license": "Apache-2.0 OR MIT", + "homepage": "https://github.com/libp2p/js-libp2p/tree/master/examples/auto-relay#readme", + "repository": { + "type": "git", + "url": "git+https://github.com/libp2p/js-libp2p.git" + }, + "bugs": { + "url": "https://github.com/libp2p/js-libp2p/issues" + }, + "type": "module", + "files": [ + "src", + "dist", + "!dist/test", + "!**/*.tsbuildinfo" + ], + "eslintConfig": { + "extends": "ipfs", + "parserOptions": { + "sourceType": "module" + } + }, + "scripts": { + "lint": "aegir lint", + "test:example": "node test.js" + }, + "dependencies": { + "@chainsafe/libp2p-noise": "^12.0.1", + "@chainsafe/libp2p-yamux": "^4.0.2", + "@libp2p/mplex": "^8.0.0", + "@libp2p/websockets": "^6.0.0", + "@multiformats/multiaddr": "^12.1.3", + "libp2p": "^0.45.0" + }, + "devDependencies": { + "aegir": "^39.0.10", + "execa": "^7.1.1", + "p-defer": "^4.0.0", + "uint8arrays": "^4.0.4" + }, + "private": true +} diff --git a/examples/auto-relay/relay.js b/examples/auto-relay/relay.js index de0400ab49..17c0053e49 100644 --- a/examples/auto-relay/relay.js +++ b/examples/auto-relay/relay.js @@ -1,8 +1,10 @@ -import { createLibp2p } from 'libp2p' -import { webSockets } from '@libp2p/websockets' +/* eslint-disable no-console */ + import { noise } from '@chainsafe/libp2p-noise' -import { mplex } from '@libp2p/mplex' import { yamux } from '@chainsafe/libp2p-yamux' +import { mplex } from '@libp2p/mplex' +import { webSockets } from '@libp2p/websockets' +import { createLibp2p } from 'libp2p' import { circuitRelayServer } from 'libp2p/circuit-relay' import { identifyService } from 'libp2p/identify' @@ -20,7 +22,7 @@ async function main () { noise() ], streamMuxers: [ - yamux(),mplex() + yamux(), mplex() ], services: { identify: identifyService(), diff --git a/examples/auto-relay/test.js b/examples/auto-relay/test.js index 646dbce2b3..e0372f6f69 100644 --- a/examples/auto-relay/test.js +++ b/examples/auto-relay/test.js @@ -1,8 +1,8 @@ import path from 'path' +import { fileURLToPath } from 'url' import { execa } from 'execa' import pDefer from 'p-defer' import { toString as uint8ArrayToString } from 'uint8arrays/to-string' -import { fileURLToPath } from 'url' const __dirname = path.dirname(fileURLToPath(import.meta.url)) @@ -13,81 +13,79 @@ function startProcess (name, args = []) { }) } -export async function test () { - let output1 = '' - let output2 = '' - let output3 = '' - let relayAddr - let autoRelayAddr +let output1 = '' +let output2 = '' +let output3 = '' +let relayAddr +let autoRelayAddr - const proc1Ready = pDefer() - const proc2Ready = pDefer() +const proc1Ready = pDefer() +const proc2Ready = pDefer() - // Step 1 process - process.stdout.write('relay.js\n') +// Step 1 process +process.stdout.write('relay.js\n') - const proc1 = startProcess('relay.js') - proc1.all.on('data', async (data) => { - process.stdout.write(data) +const proc1 = startProcess('relay.js') +proc1.all.on('data', async (data) => { + process.stdout.write(data) - output1 += uint8ArrayToString(data) + output1 += uint8ArrayToString(data) - if (output1.includes('Listening on:') && output1.includes('/p2p/')) { - relayAddr = output1.trim().split('Listening on:\n')[1].split('\n')[0] - proc1Ready.resolve() - } - }) + if (output1.includes('Listening on:') && output1.includes('/p2p/')) { + relayAddr = output1.trim().split('Listening on:\n')[1].split('\n')[0] + proc1Ready.resolve() + } +}) - await proc1Ready.promise - process.stdout.write('==================================================================\n') +await proc1Ready.promise +process.stdout.write('==================================================================\n') - // Step 2 process - process.stdout.write('listener.js\n') +// Step 2 process +process.stdout.write('listener.js\n') - const proc2 = startProcess('listener.js', [relayAddr]) - proc2.all.on('data', async (data) => { - process.stdout.write(data) +const proc2 = startProcess('listener.js', [relayAddr]) +proc2.all.on('data', async (data) => { + process.stdout.write(data) - output2 += uint8ArrayToString(data) + output2 += uint8ArrayToString(data) - if (output2.includes('Advertising with a relay address of') && output2.includes('/p2p/')) { - autoRelayAddr = output2.trim().split('Advertising with a relay address of ')[1].trim() - proc2Ready.resolve() - } - }) + if (output2.includes('Advertising with a relay address of') && output2.includes('/p2p/')) { + autoRelayAddr = output2.trim().split('Advertising with a relay address of ')[1].trim() + proc2Ready.resolve() + } +}) - await proc2Ready.promise - process.stdout.write('==================================================================\n') +await proc2Ready.promise +process.stdout.write('==================================================================\n') - // Step 3 process - process.stdout.write('dialer.js\n') +// Step 3 process +process.stdout.write('dialer.js\n') - const proc3 = startProcess('dialer.js', [autoRelayAddr]) - proc3.all.on('data', async (data) => { - process.stdout.write(data) +const proc3 = startProcess('dialer.js', [autoRelayAddr]) +proc3.all.on('data', async (data) => { + process.stdout.write(data) - output3 += uint8ArrayToString(data) + output3 += uint8ArrayToString(data) - if (output3.includes('Connected to the auto relay node via')) { - const remoteAddr = output3.trim().split('Connected to the auto relay node via ')[1] + if (output3.includes('Connected to the auto relay node via')) { + const remoteAddr = output3.trim().split('Connected to the auto relay node via ')[1] - if (remoteAddr === autoRelayAddr) { - proc3.kill() - proc2.kill() - proc1.kill() - } else { - throw new Error('dialer did not dial through the relay') - } + if (remoteAddr === autoRelayAddr) { + proc3.kill() + proc2.kill() + proc1.kill() + } else { + throw new Error('dialer did not dial through the relay') } - }) - - await Promise.all([ - proc1, - proc2, - proc3 - ]).catch((err) => { - if (err.signal !== 'SIGTERM') { - throw err - } - }) -} + } +}) + +await Promise.all([ + proc1, + proc2, + proc3 +]).catch((err) => { + if (err.signal !== 'SIGTERM') { + throw err + } +}) diff --git a/examples/chat/LICENSE b/examples/chat/LICENSE new file mode 100644 index 0000000000..20ce483c86 --- /dev/null +++ b/examples/chat/LICENSE @@ -0,0 +1,4 @@ +This project is dual licensed under MIT and Apache-2.0. + +MIT: https://www.opensource.org/licenses/mit +Apache-2.0: https://www.apache.org/licenses/license-2.0 diff --git a/examples/chat/LICENSE-APACHE b/examples/chat/LICENSE-APACHE new file mode 100644 index 0000000000..14478a3b60 --- /dev/null +++ b/examples/chat/LICENSE-APACHE @@ -0,0 +1,5 @@ +Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. diff --git a/examples/chat/LICENSE-MIT b/examples/chat/LICENSE-MIT new file mode 100644 index 0000000000..72dc60d84b --- /dev/null +++ b/examples/chat/LICENSE-MIT @@ -0,0 +1,19 @@ +The MIT License (MIT) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/examples/chat/README.md b/examples/chat/README.md index 02f5690629..0115da0620 100644 --- a/examples/chat/README.md +++ b/examples/chat/README.md @@ -1,13 +1,38 @@ -# Chat example with libp2p +# @libp2p/example-chat -This example creates a simple chat app in your terminal. +[![libp2p.io](https://img.shields.io/badge/project-libp2p-yellow.svg?style=flat-square)](http://libp2p.io/) +[![Discuss](https://img.shields.io/discourse/https/discuss.libp2p.io/posts.svg?style=flat-square)](https://discuss.libp2p.io) +[![codecov](https://img.shields.io/codecov/c/github/libp2p/js-libp2p.svg?style=flat-square)](https://codecov.io/gh/libp2p/js-libp2p) +[![CI](https://img.shields.io/github/actions/workflow/status/libp2p/js-libp2p/main.yml?branch=master\&style=flat-square)](https://github.com/libp2p/js-libp2p/actions/workflows/main.yml?query=branch%3Amaster) + +> An example chat app using libp2p + +## Table of contents + +- [Setup](#setup) +- [Running](#running) +- [License](#license) +- [Contribution](#contribution) ## Setup + 1. Install the modules in the libp2p root directory, `npm install` and `npm run build`. 2. Open 2 terminal windows in the `./examples/chat/src` directory. ## Running + 1. Run the listener in window 1, `node listener.js` 2. Run the dialer in window 2, `node dialer.js` -3. Type a message in either window and hit _enter_ +3. Type a message in either window and hit *enter* 4. Tell yourself secrets to your hearts content! + +## License + +Licensed under either of + +- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) +- MIT ([LICENSE-MIT](LICENSE-MIT) / ) + +## Contribution + +Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/examples/chat/package.json b/examples/chat/package.json new file mode 100644 index 0000000000..92d614b3aa --- /dev/null +++ b/examples/chat/package.json @@ -0,0 +1,52 @@ +{ + "name": "@libp2p/example-chat", + "version": "0.0.0", + "description": "An example chat app using libp2p", + "license": "Apache-2.0 OR MIT", + "homepage": "https://github.com/libp2p/js-libp2p/tree/master/examples/chat#readme", + "repository": { + "type": "git", + "url": "git+https://github.com/libp2p/js-libp2p.git" + }, + "bugs": { + "url": "https://github.com/libp2p/js-libp2p/issues" + }, + "type": "module", + "files": [ + "src", + "dist", + "!dist/test", + "!**/*.tsbuildinfo" + ], + "eslintConfig": { + "extends": "ipfs", + "parserOptions": { + "sourceType": "module" + } + }, + "scripts": { + "lint": "aegir lint", + "test:example": "node test.js" + }, + "dependencies": { + "@chainsafe/libp2p-noise": "^12.0.1", + "@chainsafe/libp2p-yamux": "^4.0.2", + "@libp2p/mplex": "^8.0.0", + "@libp2p/peer-id-factory": "^2.0.0", + "@libp2p/tcp": "^7.0.0", + "@libp2p/websockets": "^6.0.0", + "@multiformats/multiaddr": "^12.1.3", + "@nodeutils/defaults-deep": "^1.1.0", + "it-length-prefixed": "^9.0.1", + "it-map": "^3.0.3", + "it-pipe": "^3.0.1", + "libp2p": "^0.45.0", + "uint8arrays": "^4.0.4" + }, + "devDependencies": { + "aegir": "^39.0.10", + "execa": "^7.1.1", + "p-defer": "^4.0.0" + }, + "private": true +} diff --git a/examples/chat/src/dialer.js b/examples/chat/src/dialer.js index a878a1dbc9..956492dbe4 100644 --- a/examples/chat/src/dialer.js +++ b/examples/chat/src/dialer.js @@ -1,11 +1,11 @@ /* eslint-disable no-console */ +import { createFromJSON } from '@libp2p/peer-id-factory' import { multiaddr } from '@multiformats/multiaddr' import { createLibp2p } from './libp2p.js' -import { stdinToStream, streamToConsole } from './stream.js' -import { createFromJSON } from '@libp2p/peer-id-factory' import peerIdDialerJson from './peer-id-dialer.js' import peerIdListenerJson from './peer-id-listener.js' +import { stdinToStream, streamToConsole } from './stream.js' async function run () { const [idDialer, idListener] = await Promise.all([ diff --git a/examples/chat/src/libp2p.js b/examples/chat/src/libp2p.js index 09b31e8e54..5a244b59b5 100644 --- a/examples/chat/src/libp2p.js +++ b/examples/chat/src/libp2p.js @@ -1,8 +1,8 @@ +import { noise } from '@chainsafe/libp2p-noise' +import { yamux } from '@chainsafe/libp2p-yamux' +import { mplex } from '@libp2p/mplex' import { tcp } from '@libp2p/tcp' import { webSockets } from '@libp2p/websockets' -import { mplex } from '@libp2p/mplex' -import { yamux } from '@chainsafe/libp2p-yamux' -import { noise } from '@chainsafe/libp2p-noise' import defaultsDeep from '@nodeutils/defaults-deep' import { createLibp2p as create } from 'libp2p' @@ -13,7 +13,7 @@ export async function createLibp2p (_options) { webSockets() ], streamMuxers: [ - yamux(),mplex() + yamux(), mplex() ], connectionEncryption: [ noise() diff --git a/examples/chat/src/listener.js b/examples/chat/src/listener.js index e3bb355ebf..7397695424 100644 --- a/examples/chat/src/listener.js +++ b/examples/chat/src/listener.js @@ -1,9 +1,9 @@ /* eslint-disable no-console */ -import { createLibp2p } from './libp2p.js' -import { stdinToStream, streamToConsole } from './stream.js' import { createFromJSON } from '@libp2p/peer-id-factory' +import { createLibp2p } from './libp2p.js' import peerIdListenerJson from './peer-id-listener.js' +import { stdinToStream, streamToConsole } from './stream.js' async function run () { // Create a new libp2p node with the given multi-address diff --git a/examples/chat/src/peer-id-dialer.js b/examples/chat/src/peer-id-dialer.js index 4c5f00dedb..79d31007f2 100644 --- a/examples/chat/src/peer-id-dialer.js +++ b/examples/chat/src/peer-id-dialer.js @@ -1,5 +1,5 @@ export default { - "id": "Qma3GsJmB47xYuyahPZPSadh1avvxfyYQwk8R3UnFrQ6aP", - "privKey": "CAASpwkwggSjAgEAAoIBAQCaNSDOjPz6T8HZsf7LDpxiQRiN2OjeyIHUS05p8QWOr3EFUCFsC31R4moihE5HN+FxNalUyyFZU//yjf1pdnlMJqrVByJSMa+y2y4x2FucpoCAO97Tx+iWzwlZ2UXEUXM1Y81mhPbeWXy+wP2xElTgIER0Tsn/thoA0SD2u9wJuVvM7dB7cBcHYmqV6JH+KWCedRTum6O1BssqP/4Lbm2+rkrbZ4+oVRoU2DRLoFhKqwqLtylrbuj4XOI3XykMXV5+uQXz1JzubNOB9lsc6K+eRC+w8hhhDuFMgzkZ4qomCnx3uhO67KaICd8yqqBa6PJ/+fBM5Xk4hjyR40bwcf41AgMBAAECggEAZnrCJ6IYiLyyRdr9SbKXCNDb4YByGYPEi/HT1aHgIJfFE1PSMjxcdytxfyjP4JJpVtPjiT9JFVU2ddoYu5qJN6tGwjVwgJEWg1UXmPaAw1T/drjS94kVsAs82qICtFmwp52Apg3dBZ0Qwq/8qE1XbG7lLyohIbfCBiL0tiPYMfkcsN9gnFT/kFCX0LVs2pa9fHCRMY9rqCc4/rWJa1w8sMuQ23y4lDaxKF9OZVvOHFQkbBDrkquWHE4r55fchCz/rJklkPJUNENuncBRu0/2X+p4IKFD1DnttXNwb8j4LPiSlLro1T0hiUr5gO2QmdYwXFF63Q3mjQy0+5I4eNbjjQKBgQDZvZy3gUKS/nQNkYfq9za80uLbIj/cWbO+ZZjXCsj0fNIcQFJcKMBoA7DjJvu2S/lf86/41YHkPdmrLAEQAkJ+5BBNOycjYK9minTEjIMMmZDTXXugZ62wnU6F46uLkgEChTqEP57Y6xwwV+JaEDFEsW5N1eE9lEVX9nGIr4phMwKBgQC1TazLuEt1WBx/iUT83ita7obXqoKNzwsS/MWfY2innzYZKDOqeSYZzLtt9uTtp4X4uLyPbYs0qFYhXLsUYMoGHNN8+NdjoyxCjQRJRBkMtaNR0lc5lVDWl3bTuJovjFCgAr9uqJrmI5OHcCIk/cDpdWb3nWaMihVlePmiTcTy9wKBgQCU0u7c1jKkudqks4XM6a+2HAYGdUBk4cLjLhnrUWnNAcuyl5wzdX8dGPi8KZb+IKuQE8WBNJ2VXVj7kBYh1QmSJVunDflQSvNYCOaKuOeRoxzD+y9Wkca74qkbBmPn/6FFEb7PSZTO+tPHjyodGNgz9XpJJRjQuBk1aDJtlF3m1QKBgE5SAr5ym65SZOU3UGUIOKRsfDW4Q/OsqDUImvpywCgBICaX9lHDShFFHwau7FA52ScL7vDquoMB4UtCOtLfyQYA9995w9oYCCurrVlVIJkb8jSLcADBHw3EmqF1kq3NqJqm9TmBfoDCh52vdCCUufxgKh33kfBOSlXuf7B8dgMbAoGAZ3r0/mBQX6S+s5+xCETMTSNv7TQzxgtURIpVs+ZVr2cMhWhiv+n0Omab9X9Z50se8cWl5lkvx8vn3D/XHHIPrMF6qk7RAXtvReb+PeitNvm0odqjFv0J2qki6fDs0HKwq4kojAXI1Md8Th0eobNjsy21fEEJT7uKMJdovI/SErI=", - "pubKey": "CAASpgIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCaNSDOjPz6T8HZsf7LDpxiQRiN2OjeyIHUS05p8QWOr3EFUCFsC31R4moihE5HN+FxNalUyyFZU//yjf1pdnlMJqrVByJSMa+y2y4x2FucpoCAO97Tx+iWzwlZ2UXEUXM1Y81mhPbeWXy+wP2xElTgIER0Tsn/thoA0SD2u9wJuVvM7dB7cBcHYmqV6JH+KWCedRTum6O1BssqP/4Lbm2+rkrbZ4+oVRoU2DRLoFhKqwqLtylrbuj4XOI3XykMXV5+uQXz1JzubNOB9lsc6K+eRC+w8hhhDuFMgzkZ4qomCnx3uhO67KaICd8yqqBa6PJ/+fBM5Xk4hjyR40bwcf41AgMBAAE=" + id: 'Qma3GsJmB47xYuyahPZPSadh1avvxfyYQwk8R3UnFrQ6aP', + privKey: 'CAASpwkwggSjAgEAAoIBAQCaNSDOjPz6T8HZsf7LDpxiQRiN2OjeyIHUS05p8QWOr3EFUCFsC31R4moihE5HN+FxNalUyyFZU//yjf1pdnlMJqrVByJSMa+y2y4x2FucpoCAO97Tx+iWzwlZ2UXEUXM1Y81mhPbeWXy+wP2xElTgIER0Tsn/thoA0SD2u9wJuVvM7dB7cBcHYmqV6JH+KWCedRTum6O1BssqP/4Lbm2+rkrbZ4+oVRoU2DRLoFhKqwqLtylrbuj4XOI3XykMXV5+uQXz1JzubNOB9lsc6K+eRC+w8hhhDuFMgzkZ4qomCnx3uhO67KaICd8yqqBa6PJ/+fBM5Xk4hjyR40bwcf41AgMBAAECggEAZnrCJ6IYiLyyRdr9SbKXCNDb4YByGYPEi/HT1aHgIJfFE1PSMjxcdytxfyjP4JJpVtPjiT9JFVU2ddoYu5qJN6tGwjVwgJEWg1UXmPaAw1T/drjS94kVsAs82qICtFmwp52Apg3dBZ0Qwq/8qE1XbG7lLyohIbfCBiL0tiPYMfkcsN9gnFT/kFCX0LVs2pa9fHCRMY9rqCc4/rWJa1w8sMuQ23y4lDaxKF9OZVvOHFQkbBDrkquWHE4r55fchCz/rJklkPJUNENuncBRu0/2X+p4IKFD1DnttXNwb8j4LPiSlLro1T0hiUr5gO2QmdYwXFF63Q3mjQy0+5I4eNbjjQKBgQDZvZy3gUKS/nQNkYfq9za80uLbIj/cWbO+ZZjXCsj0fNIcQFJcKMBoA7DjJvu2S/lf86/41YHkPdmrLAEQAkJ+5BBNOycjYK9minTEjIMMmZDTXXugZ62wnU6F46uLkgEChTqEP57Y6xwwV+JaEDFEsW5N1eE9lEVX9nGIr4phMwKBgQC1TazLuEt1WBx/iUT83ita7obXqoKNzwsS/MWfY2innzYZKDOqeSYZzLtt9uTtp4X4uLyPbYs0qFYhXLsUYMoGHNN8+NdjoyxCjQRJRBkMtaNR0lc5lVDWl3bTuJovjFCgAr9uqJrmI5OHcCIk/cDpdWb3nWaMihVlePmiTcTy9wKBgQCU0u7c1jKkudqks4XM6a+2HAYGdUBk4cLjLhnrUWnNAcuyl5wzdX8dGPi8KZb+IKuQE8WBNJ2VXVj7kBYh1QmSJVunDflQSvNYCOaKuOeRoxzD+y9Wkca74qkbBmPn/6FFEb7PSZTO+tPHjyodGNgz9XpJJRjQuBk1aDJtlF3m1QKBgE5SAr5ym65SZOU3UGUIOKRsfDW4Q/OsqDUImvpywCgBICaX9lHDShFFHwau7FA52ScL7vDquoMB4UtCOtLfyQYA9995w9oYCCurrVlVIJkb8jSLcADBHw3EmqF1kq3NqJqm9TmBfoDCh52vdCCUufxgKh33kfBOSlXuf7B8dgMbAoGAZ3r0/mBQX6S+s5+xCETMTSNv7TQzxgtURIpVs+ZVr2cMhWhiv+n0Omab9X9Z50se8cWl5lkvx8vn3D/XHHIPrMF6qk7RAXtvReb+PeitNvm0odqjFv0J2qki6fDs0HKwq4kojAXI1Md8Th0eobNjsy21fEEJT7uKMJdovI/SErI=', + pubKey: 'CAASpgIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCaNSDOjPz6T8HZsf7LDpxiQRiN2OjeyIHUS05p8QWOr3EFUCFsC31R4moihE5HN+FxNalUyyFZU//yjf1pdnlMJqrVByJSMa+y2y4x2FucpoCAO97Tx+iWzwlZ2UXEUXM1Y81mhPbeWXy+wP2xElTgIER0Tsn/thoA0SD2u9wJuVvM7dB7cBcHYmqV6JH+KWCedRTum6O1BssqP/4Lbm2+rkrbZ4+oVRoU2DRLoFhKqwqLtylrbuj4XOI3XykMXV5+uQXz1JzubNOB9lsc6K+eRC+w8hhhDuFMgzkZ4qomCnx3uhO67KaICd8yqqBa6PJ/+fBM5Xk4hjyR40bwcf41AgMBAAE=' } diff --git a/examples/chat/src/peer-id-listener.js b/examples/chat/src/peer-id-listener.js index 722f95ebf9..8e5acb76c0 100644 --- a/examples/chat/src/peer-id-listener.js +++ b/examples/chat/src/peer-id-listener.js @@ -1,5 +1,5 @@ export default { - "id": "QmcrQZ6RJdpYuGvZqD5QEHAv6qX4BrQLJLQPQUrTrzdcgm", - "privKey": "CAASqAkwggSkAgEAAoIBAQDLZZcGcbe4urMBVlcHgN0fpBymY+xcr14ewvamG70QZODJ1h9sljlExZ7byLiqRB3SjGbfpZ1FweznwNxWtWpjHkQjTVXeoM4EEgDSNO/Cg7KNlU0EJvgPJXeEPycAZX9qASbVJ6EECQ40VR/7+SuSqsdL1hrmG1phpIju+D64gLyWpw9WEALfzMpH5I/KvdYDW3N4g6zOD2mZNp5y1gHeXINHWzMF596O72/6cxwyiXV1eJ000k1NVnUyrPjXtqWdVLRk5IU1LFpoQoXZU5X1hKj1a2qt/lZfH5eOrF/ramHcwhrYYw1txf8JHXWO/bbNnyemTHAvutZpTNrsWATfAgMBAAECggEAQj0obPnVyjxLFZFnsFLgMHDCv9Fk5V5bOYtmxfvcm50us6ye+T8HEYWGUa9RrGmYiLweuJD34gLgwyzE1RwptHPj3tdNsr4NubefOtXwixlWqdNIjKSgPlaGULQ8YF2tm/kaC2rnfifwz0w1qVqhPReO5fypL+0ShyANVD3WN0Fo2ugzrniCXHUpR2sHXSg6K+2+qWdveyjNWog34b7CgpV73Ln96BWae6ElU8PR5AWdMnRaA9ucA+/HWWJIWB3Fb4+6uwlxhu2L50Ckq1gwYZCtGw63q5L4CglmXMfIKnQAuEzazq9T4YxEkp+XDnVZAOgnQGUBYpetlgMmkkh9qQKBgQDvsEs0ThzFLgnhtC2Jy//ZOrOvIAKAZZf/mS08AqWH3L0/Rjm8ZYbLsRcoWU78sl8UFFwAQhMRDBP9G+RPojWVahBL/B7emdKKnFR1NfwKjFdDVaoX5uNvZEKSl9UubbC4WZJ65u/cd5jEnj+w3ir9G8n+P1gp/0yBz02nZXFgSwKBgQDZPQr4HBxZL7Kx7D49ormIlB7CCn2i7mT11Cppn5ifUTrp7DbFJ2t9e8UNk6tgvbENgCKXvXWsmflSo9gmMxeEOD40AgAkO8Pn2R4OYhrwd89dECiKM34HrVNBzGoB5+YsAno6zGvOzLKbNwMG++2iuNXqXTk4uV9GcI8OnU5ZPQKBgCZUGrKSiyc85XeiSGXwqUkjifhHNh8yH8xPwlwGUFIZimnD4RevZI7OEtXw8iCWpX2gg9XGuyXOuKORAkF5vvfVriV4e7c9Ad4Igbj8mQFWz92EpV6NHXGCpuKqRPzXrZrNOA9PPqwSs+s9IxI1dMpk1zhBCOguWx2m+NP79NVhAoGBAI6WSoTfrpu7ewbdkVzTWgQTdLzYNe6jmxDf2ZbKclrf7lNr/+cYIK2Ud5qZunsdBwFdgVcnu/02czeS42TvVBgs8mcgiQc/Uy7yi4/VROlhOnJTEMjlU2umkGc3zLzDgYiRd7jwRDLQmMrYKNyEr02HFKFn3w8kXSzW5I8rISnhAoGBANhchHVtJd3VMYvxNcQb909FiwTnT9kl9pkjhwivx+f8/K8pDfYCjYSBYCfPTM5Pskv5dXzOdnNuCj6Y2H/9m2SsObukBwF0z5Qijgu1DsxvADVIKZ4rzrGb4uSEmM6200qjJ/9U98fVM7rvOraakrhcf9gRwuspguJQnSO9cLj6", - "pubKey": "CAASpgIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDLZZcGcbe4urMBVlcHgN0fpBymY+xcr14ewvamG70QZODJ1h9sljlExZ7byLiqRB3SjGbfpZ1FweznwNxWtWpjHkQjTVXeoM4EEgDSNO/Cg7KNlU0EJvgPJXeEPycAZX9qASbVJ6EECQ40VR/7+SuSqsdL1hrmG1phpIju+D64gLyWpw9WEALfzMpH5I/KvdYDW3N4g6zOD2mZNp5y1gHeXINHWzMF596O72/6cxwyiXV1eJ000k1NVnUyrPjXtqWdVLRk5IU1LFpoQoXZU5X1hKj1a2qt/lZfH5eOrF/ramHcwhrYYw1txf8JHXWO/bbNnyemTHAvutZpTNrsWATfAgMBAAE=" + id: 'QmcrQZ6RJdpYuGvZqD5QEHAv6qX4BrQLJLQPQUrTrzdcgm', + privKey: 'CAASqAkwggSkAgEAAoIBAQDLZZcGcbe4urMBVlcHgN0fpBymY+xcr14ewvamG70QZODJ1h9sljlExZ7byLiqRB3SjGbfpZ1FweznwNxWtWpjHkQjTVXeoM4EEgDSNO/Cg7KNlU0EJvgPJXeEPycAZX9qASbVJ6EECQ40VR/7+SuSqsdL1hrmG1phpIju+D64gLyWpw9WEALfzMpH5I/KvdYDW3N4g6zOD2mZNp5y1gHeXINHWzMF596O72/6cxwyiXV1eJ000k1NVnUyrPjXtqWdVLRk5IU1LFpoQoXZU5X1hKj1a2qt/lZfH5eOrF/ramHcwhrYYw1txf8JHXWO/bbNnyemTHAvutZpTNrsWATfAgMBAAECggEAQj0obPnVyjxLFZFnsFLgMHDCv9Fk5V5bOYtmxfvcm50us6ye+T8HEYWGUa9RrGmYiLweuJD34gLgwyzE1RwptHPj3tdNsr4NubefOtXwixlWqdNIjKSgPlaGULQ8YF2tm/kaC2rnfifwz0w1qVqhPReO5fypL+0ShyANVD3WN0Fo2ugzrniCXHUpR2sHXSg6K+2+qWdveyjNWog34b7CgpV73Ln96BWae6ElU8PR5AWdMnRaA9ucA+/HWWJIWB3Fb4+6uwlxhu2L50Ckq1gwYZCtGw63q5L4CglmXMfIKnQAuEzazq9T4YxEkp+XDnVZAOgnQGUBYpetlgMmkkh9qQKBgQDvsEs0ThzFLgnhtC2Jy//ZOrOvIAKAZZf/mS08AqWH3L0/Rjm8ZYbLsRcoWU78sl8UFFwAQhMRDBP9G+RPojWVahBL/B7emdKKnFR1NfwKjFdDVaoX5uNvZEKSl9UubbC4WZJ65u/cd5jEnj+w3ir9G8n+P1gp/0yBz02nZXFgSwKBgQDZPQr4HBxZL7Kx7D49ormIlB7CCn2i7mT11Cppn5ifUTrp7DbFJ2t9e8UNk6tgvbENgCKXvXWsmflSo9gmMxeEOD40AgAkO8Pn2R4OYhrwd89dECiKM34HrVNBzGoB5+YsAno6zGvOzLKbNwMG++2iuNXqXTk4uV9GcI8OnU5ZPQKBgCZUGrKSiyc85XeiSGXwqUkjifhHNh8yH8xPwlwGUFIZimnD4RevZI7OEtXw8iCWpX2gg9XGuyXOuKORAkF5vvfVriV4e7c9Ad4Igbj8mQFWz92EpV6NHXGCpuKqRPzXrZrNOA9PPqwSs+s9IxI1dMpk1zhBCOguWx2m+NP79NVhAoGBAI6WSoTfrpu7ewbdkVzTWgQTdLzYNe6jmxDf2ZbKclrf7lNr/+cYIK2Ud5qZunsdBwFdgVcnu/02czeS42TvVBgs8mcgiQc/Uy7yi4/VROlhOnJTEMjlU2umkGc3zLzDgYiRd7jwRDLQmMrYKNyEr02HFKFn3w8kXSzW5I8rISnhAoGBANhchHVtJd3VMYvxNcQb909FiwTnT9kl9pkjhwivx+f8/K8pDfYCjYSBYCfPTM5Pskv5dXzOdnNuCj6Y2H/9m2SsObukBwF0z5Qijgu1DsxvADVIKZ4rzrGb4uSEmM6200qjJ/9U98fVM7rvOraakrhcf9gRwuspguJQnSO9cLj6', + pubKey: 'CAASpgIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDLZZcGcbe4urMBVlcHgN0fpBymY+xcr14ewvamG70QZODJ1h9sljlExZ7byLiqRB3SjGbfpZ1FweznwNxWtWpjHkQjTVXeoM4EEgDSNO/Cg7KNlU0EJvgPJXeEPycAZX9qASbVJ6EECQ40VR/7+SuSqsdL1hrmG1phpIju+D64gLyWpw9WEALfzMpH5I/KvdYDW3N4g6zOD2mZNp5y1gHeXINHWzMF596O72/6cxwyiXV1eJ000k1NVnUyrPjXtqWdVLRk5IU1LFpoQoXZU5X1hKj1a2qt/lZfH5eOrF/ramHcwhrYYw1txf8JHXWO/bbNnyemTHAvutZpTNrsWATfAgMBAAE=' } diff --git a/examples/chat/src/stream.js b/examples/chat/src/stream.js index f04357f678..194a9c1da0 100644 --- a/examples/chat/src/stream.js +++ b/examples/chat/src/stream.js @@ -1,12 +1,12 @@ /* eslint-disable no-console */ -import { pipe } from 'it-pipe' import * as lp from 'it-length-prefixed' import map from 'it-map' +import { pipe } from 'it-pipe' import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string' import { toString as uint8ArrayToString } from 'uint8arrays/to-string' -export function stdinToStream(stream) { +export function stdinToStream (stream) { // Read utf-8 from stdin process.stdin.setEncoding('utf8') pipe( @@ -21,7 +21,7 @@ export function stdinToStream(stream) { ) } -export function streamToConsole(stream) { +export function streamToConsole (stream) { pipe( // Read from the stream (the source) stream.source, diff --git a/examples/chat/test.js b/examples/chat/test.js index 179bf3ead6..28ca41dc1e 100644 --- a/examples/chat/test.js +++ b/examples/chat/test.js @@ -1,76 +1,74 @@ import path from 'path' +import { fileURLToPath } from 'url' import { execa } from 'execa' import pDefer from 'p-defer' import { toString as uint8ArrayToString } from 'uint8arrays/to-string' -import { fileURLToPath } from 'url' const __dirname = path.dirname(fileURLToPath(import.meta.url)) -function startProcess(name) { +function startProcess (name) { return execa('node', [path.join(__dirname, name)], { cwd: path.resolve(__dirname), all: true }) } -export async function test () { - const message = 'test message' - let listenerOutput = '' - let dialerOutput = '' +const message = 'test message' +let listenerOutput = '' +let dialerOutput = '' - let isListening = false - let messageSent = false - const listenerReady = pDefer() - const dialerReady = pDefer() - const messageReceived = pDefer() +let isListening = false +let messageSent = false +const listenerReady = pDefer() +const dialerReady = pDefer() +const messageReceived = pDefer() - // Step 1 process - process.stdout.write('node listener.js\n') - const listenerProc = startProcess('src/listener.js') - listenerProc.all.on('data', async (data) => { - process.stdout.write(data) +// Step 1 process +process.stdout.write('node listener.js\n') +const listenerProc = startProcess('./src/listener.js') +listenerProc.all.on('data', async (data) => { + process.stdout.write(data) - listenerOutput += uint8ArrayToString(data) + listenerOutput += uint8ArrayToString(data) - if (!isListening && listenerOutput.includes('Listener ready, listening on')) { - listenerReady.resolve() - isListening = true - } else if (isListening && listenerOutput.includes(message)) { - messageReceived.resolve() - } - }) + if (!isListening && listenerOutput.includes('Listener ready, listening on')) { + listenerReady.resolve() + isListening = true + } else if (isListening && listenerOutput.includes(message)) { + messageReceived.resolve() + } +}) - await listenerReady.promise - process.stdout.write('==================================================================\n') +await listenerReady.promise +process.stdout.write('==================================================================\n') - // Step 2 process - process.stdout.write('node dialer.js\n') - const dialerProc = startProcess('src/dialer.js') - dialerProc.all.on('data', async (data) => { - process.stdout.write(data) - dialerOutput += uint8ArrayToString(data) +// Step 2 process +process.stdout.write('node dialer.js\n') +const dialerProc = startProcess('./src/dialer.js') +dialerProc.all.on('data', async (data) => { + process.stdout.write(data) + dialerOutput += uint8ArrayToString(data) - if (!messageSent && dialerOutput.includes('Type a message and see what happens')) { - dialerReady.resolve() - dialerProc.stdin.write(message) - dialerProc.stdin.write('\n') - messageSent = true - } - }) + if (!messageSent && dialerOutput.includes('Type a message and see what happens')) { + dialerReady.resolve() + dialerProc.stdin.write(message) + dialerProc.stdin.write('\n') + messageSent = true + } +}) - await dialerReady.promise - process.stdout.write('==================================================================\n') - await messageReceived.promise - process.stdout.write('chat message received\n') +await dialerReady.promise +process.stdout.write('==================================================================\n') +await messageReceived.promise +process.stdout.write('chat message received\n') - listenerProc.kill() - dialerProc.kill() - await Promise.all([ - listenerProc, - dialerProc - ]).catch((err) => { - if (err.signal !== 'SIGTERM') { - throw err - } - }) -} +listenerProc.kill() +dialerProc.kill() +await Promise.all([ + listenerProc, + dialerProc +]).catch((err) => { + if (err.signal !== 'SIGTERM') { + throw err + } +}) diff --git a/examples/connection-encryption/1.js b/examples/connection-encryption/1.js index 4c1a777fc4..44e1982b2a 100644 --- a/examples/connection-encryption/1.js +++ b/examples/connection-encryption/1.js @@ -1,11 +1,13 @@ -import { createLibp2p } from '../../packages/libp2p/dist/src/index.js' -import { tcp } from '@libp2p/tcp' -import { mplex } from '@libp2p/mplex' -import { yamux } from '@chainsafe/libp2p-yamux' +/* eslint-disable no-console */ + import { noise } from '@chainsafe/libp2p-noise' +import { yamux } from '@chainsafe/libp2p-yamux' +import { mplex } from '@libp2p/mplex' +import { tcp } from '@libp2p/tcp' import { pipe } from 'it-pipe' -import { toString as uint8ArrayToString } from 'uint8arrays/to-string' +import { createLibp2p } from 'libp2p' import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string' +import { toString as uint8ArrayToString } from 'uint8arrays/to-string' const createNode = async () => { const node = await createLibp2p({ diff --git a/examples/connection-encryption/LICENSE b/examples/connection-encryption/LICENSE new file mode 100644 index 0000000000..20ce483c86 --- /dev/null +++ b/examples/connection-encryption/LICENSE @@ -0,0 +1,4 @@ +This project is dual licensed under MIT and Apache-2.0. + +MIT: https://www.opensource.org/licenses/mit +Apache-2.0: https://www.apache.org/licenses/license-2.0 diff --git a/examples/connection-encryption/LICENSE-APACHE b/examples/connection-encryption/LICENSE-APACHE new file mode 100644 index 0000000000..14478a3b60 --- /dev/null +++ b/examples/connection-encryption/LICENSE-APACHE @@ -0,0 +1,5 @@ +Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. diff --git a/examples/connection-encryption/LICENSE-MIT b/examples/connection-encryption/LICENSE-MIT new file mode 100644 index 0000000000..72dc60d84b --- /dev/null +++ b/examples/connection-encryption/LICENSE-MIT @@ -0,0 +1,19 @@ +The MIT License (MIT) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/examples/connection-encryption/README.md b/examples/connection-encryption/README.md index 5af36a474b..a37291f7e7 100644 --- a/examples/connection-encryption/README.md +++ b/examples/connection-encryption/README.md @@ -1,12 +1,23 @@ -# Connection Encryption +# @libp2p/example-connection-encryption -libp2p can leverage the encrypted communications from the transports it uses (i.e WebRTC). To ensure that every connection is encrypted, independently of how it was set up, libp2p also supports a set of modules that encrypt every communication established. +[![libp2p.io](https://img.shields.io/badge/project-libp2p-yellow.svg?style=flat-square)](http://libp2p.io/) +[![Discuss](https://img.shields.io/discourse/https/discuss.libp2p.io/posts.svg?style=flat-square)](https://discuss.libp2p.io) +[![codecov](https://img.shields.io/codecov/c/github/libp2p/js-libp2p.svg?style=flat-square)](https://codecov.io/gh/libp2p/js-libp2p) +[![CI](https://img.shields.io/github/actions/workflow/status/libp2p/js-libp2p/main.yml?branch=master\&style=flat-square)](https://github.com/libp2p/js-libp2p/actions/workflows/main.yml?query=branch%3Amaster) -We call this usage a _connection upgrade_ where given a connection between peer A to peer B, a protocol handshake can be performed that gives that connection new properties. +> An example of how to configure connection encrypters + +## Table of contents + +- [Set up encrypted communications](#set-up-encrypted-communications) +- [License](#license) +- [Contribution](#contribution) + +We call this usage a *connection upgrade* where given a connection between peer A to peer B, a protocol handshake can be performed that gives that connection new properties. A byproduct of having these encrypted communications modules is that we can authenticate the peers we are dialing to. You might have noticed that every time we dial to a peer in libp2p space, we always use its PeerId at the end (e.g /ip4/127.0.0.1/tcp/89765/p2p/QmWCbVw1XZ8hiYBwwshPce2yaTDYTqTaP7GCHGpry3ykWb), this PeerId is generated by hashing the Public Key of the peer. With this, we can create a crypto challenge when dialing to another peer and prove that peer is the owner of a PrivateKey that matches the Public Key we know. -# 1. Set up encrypted communications +## Set up encrypted communications We will build this example on top of example for [Protocol and Stream Multiplexing](../protocol-and-stream-multiplexing). You will need the `@chainsafe/libp2p-noise` module to complete it, go ahead and `npm install @chainsafe/libp2p-noise`. @@ -30,3 +41,14 @@ const createNode = async () => { ``` And that's it, from now on, all your libp2p communications are encrypted. Try running the example [1.js](./1.js) to see it working. + +## License + +Licensed under either of + +- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) +- MIT ([LICENSE-MIT](LICENSE-MIT) / ) + +## Contribution + +Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/examples/connection-encryption/package.json b/examples/connection-encryption/package.json new file mode 100644 index 0000000000..77c1249b29 --- /dev/null +++ b/examples/connection-encryption/package.json @@ -0,0 +1,45 @@ +{ + "name": "@libp2p/example-connection-encryption", + "version": "0.0.0", + "description": "An example of how to configure connection encrypters", + "license": "Apache-2.0 OR MIT", + "homepage": "https://github.com/libp2p/js-libp2p/tree/master/examples/connection-encryption#readme", + "repository": { + "type": "git", + "url": "git+https://github.com/libp2p/js-libp2p.git" + }, + "bugs": { + "url": "https://github.com/libp2p/js-libp2p/issues" + }, + "type": "module", + "files": [ + "src", + "dist", + "!dist/test", + "!**/*.tsbuildinfo" + ], + "eslintConfig": { + "extends": "ipfs", + "parserOptions": { + "sourceType": "module" + } + }, + "scripts": { + "lint": "aegir lint", + "test:example": "node test.js" + }, + "dependencies": { + "@chainsafe/libp2p-noise": "^12.0.1", + "@chainsafe/libp2p-yamux": "^4.0.2", + "@libp2p/mplex": "^8.0.0", + "@libp2p/tcp": "^7.0.0", + "it-pipe": "^3.0.1", + "libp2p": "^0.45.0", + "uint8arrays": "^4.0.4" + }, + "devDependencies": { + "aegir": "^39.0.10", + "test-ipfs-example": "^1.0.0" + }, + "private": true +} diff --git a/examples/connection-encryption/test.js b/examples/connection-encryption/test.js index 8111be9c1e..1bba4c3bf2 100644 --- a/examples/connection-encryption/test.js +++ b/examples/connection-encryption/test.js @@ -1,14 +1,11 @@ - import path from 'path' -import { waitForOutput } from '../utils.js' import { fileURLToPath } from 'url' +import { waitForOutput } from 'test-ipfs-example/node' const __dirname = path.dirname(fileURLToPath(import.meta.url)) -export async function test () { - process.stdout.write('1.js\n') +process.stdout.write('1.js\n') - await waitForOutput('This information is sent out encrypted to the other peer', 'node', [path.join(__dirname, '1.js')], { - cwd: __dirname - }) -} +await waitForOutput('This information is sent out encrypted to the other peer', 'node', [path.join(__dirname, '1.js')], { + cwd: __dirname +}) diff --git a/examples/delegated-routing/LICENSE b/examples/delegated-routing/LICENSE new file mode 100644 index 0000000000..20ce483c86 --- /dev/null +++ b/examples/delegated-routing/LICENSE @@ -0,0 +1,4 @@ +This project is dual licensed under MIT and Apache-2.0. + +MIT: https://www.opensource.org/licenses/mit +Apache-2.0: https://www.apache.org/licenses/license-2.0 diff --git a/examples/delegated-routing/LICENSE-APACHE b/examples/delegated-routing/LICENSE-APACHE new file mode 100644 index 0000000000..14478a3b60 --- /dev/null +++ b/examples/delegated-routing/LICENSE-APACHE @@ -0,0 +1,5 @@ +Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. diff --git a/examples/delegated-routing/LICENSE-MIT b/examples/delegated-routing/LICENSE-MIT new file mode 100644 index 0000000000..72dc60d84b --- /dev/null +++ b/examples/delegated-routing/LICENSE-MIT @@ -0,0 +1,19 @@ +The MIT License (MIT) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/examples/delegated-routing/README.md b/examples/delegated-routing/README.md index 7bc0a8a04e..bebbe9dcf1 100644 --- a/examples/delegated-routing/README.md +++ b/examples/delegated-routing/README.md @@ -1,6 +1,20 @@ -# Delegated Routing with Libp2p and IPFS +# @libp2p/example-delegated-routing-example -This example shows how to use delegated peer and content routing. The [Peer and Content Routing Example](../peer-and-content-routing) focuses on the DHT implementation. This example takes that a step further and introduces delegated routing. Delegated routing is especially useful when your libp2p node will have limited resources, making running a DHT impractical. It's also highly useful if your node is generating content, but can't reliably be on the network. You can use delegate nodes to provide content on your behalf. +[![libp2p.io](https://img.shields.io/badge/project-libp2p-yellow.svg?style=flat-square)](http://libp2p.io/) +[![Discuss](https://img.shields.io/discourse/https/discuss.libp2p.io/posts.svg?style=flat-square)](https://discuss.libp2p.io) +[![codecov](https://img.shields.io/codecov/c/github/libp2p/js-libp2p.svg?style=flat-square)](https://codecov.io/gh/libp2p/js-libp2p) +[![CI](https://img.shields.io/github/actions/workflow/status/libp2p/js-libp2p/main.yml?branch=master\&style=flat-square)](https://github.com/libp2p/js-libp2p/actions/workflows/main.yml?query=branch%3Amaster) + +> How to configure libp2p delegated routers + +## Table of contents + +- [Prerequisite](#prerequisite) +- [Running this example](#running-this-example) + - [Finding Content via the Delegate](#finding-content-via-the-delegate) + - [Finding Peers via the Delegate](#finding-peers-via-the-delegate) +- [License](#license) +- [Contribution](#contribution) The starting [Libp2p Bundle](./src/libp2p-bundle.js) in this example starts by disabling the DHT and adding the Delegated Peer and Content Routers. Once you've completed the example, you should try enabled the DHT and see what kind of results you get! You can also enable the various Peer Discovery modules and see the impact it has on your Peer count. @@ -14,8 +28,10 @@ This example uses a publicly known delegated routing node. This aims to ease exp 1. Install IPFS locally if you dont already have it. [Install Guide](https://docs.ipfs.tech/install/) 2. Run the IPFS daemon: `ipfs daemon` 3. In another window output the addresses of the node: `ipfs id`. Make note of the websocket address, it will contain `/ws/` in the address. - - If there is no websocket address, you will need to add it in the ipfs config file (`~/.ipfs/config`) - - Add to Swarm Addresses something like: `"/ip4/127.0.0.1/tcp/4010/ws"` + +- If there is no websocket address, you will need to add it in the ipfs config file (`~/.ipfs/config`) +- Add to Swarm Addresses something like: `"/ip4/127.0.0.1/tcp/4010/ws"` + 4. In `./src/App.js` replace `BootstrapNode` with your nodes Websocket address from the step above. 5. Start this example @@ -24,22 +40,36 @@ npm install npm start ``` -This should open your browser to http://localhost:3000. If it does not, go ahead and do that now. +This should open your browser to . If it does not, go ahead and do that now. 6. Your browser should show you connected to at least 1 peer. ### Finding Content via the Delegate + 1. Add a file to your IPFS node. From this example root you can do `ipfs add ./README.md` to add the example readme. 2. Copy the hash from line 5, it will look something like *Qmf33vz4HJFkqgH7XPP1uA6atYKTX1BWQEQthzpKcAdeyZ*. 3. In the browser, paste the hash into the *Hash* field and hit `Find`. The readme contents should display. This will do a few things: -* The delegate nodes api will be queried to find providers of the content -* The content will be fetched from the providers -* Since we now have the content, we tell the delegate node to fetch the content from us and become a provider + +- The delegate nodes api will be queried to find providers of the content +- The content will be fetched from the providers +- Since we now have the content, we tell the delegate node to fetch the content from us and become a provider ### Finding Peers via the Delegate + 1. Get a list of your delegate nodes peer by querying the IPFS daemon: `ipfs swarm peers` 2. Copy one of the CIDs from the list of peer addresses, this will be the last portion of the address and will look something like `QmdoG8DpzYUZMVP5dGmgmigZwR1RE8Cf6SxMPg1SBXJAQ8`. 3. In your browser, paste the CID into the *Peer* field and hit `Find`. 4. You should see information about the peer including its addresses. + +## License + +Licensed under either of + +- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) +- MIT ([LICENSE-MIT](LICENSE-MIT) / ) + +## Contribution + +Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/examples/delegated-routing/package.json b/examples/delegated-routing/package.json index af15656731..9a430143c7 100644 --- a/examples/delegated-routing/package.json +++ b/examples/delegated-routing/package.json @@ -1,29 +1,58 @@ { - "name": "delegated-routing-example", - "version": "0.1.0", - "private": true, + "name": "@libp2p/example-delegated-routing-example", + "version": "0.0.0", + "description": "How to configure libp2p delegated routers", + "license": "Apache-2.0 OR MIT", + "homepage": "https://github.com/libp2p/js-libp2p/tree/master/examples/delegated-routing#readme", + "repository": { + "type": "git", + "url": "git+https://github.com/libp2p/js-libp2p.git" + }, + "bugs": { + "url": "https://github.com/libp2p/js-libp2p/issues" + }, + "type": "module", + "files": [ + "src", + "dist", + "!dist/test", + "!**/*.tsbuildinfo" + ], + "eslintConfig": { + "extends": "ipfs", + "parserOptions": { + "sourceType": "module", + "parserOptions": { + "sourceType": "module" + } + } + }, + "scripts": { + "lint": "aegir lint", + "start": "react-scripts start" + }, "dependencies": { - "@chainsafe/libp2p-noise": "^12.0.0", - "ipfs-core": "^0.15.4", - "ipfs-http-client": "^58.0.1", - "libp2p": "file:../../packages/libp2p", + "@chainsafe/libp2p-noise": "^12.0.1", + "@libp2p/bootstrap": "^8.0.0", "@libp2p/delegated-content-routing": "^4.0.0", "@libp2p/delegated-peer-routing": "^4.0.0", - "@libp2p/kad-dht": "^9.2.0", - "@libp2p/mplex": "^8.0.1", - "@libp2p/webrtc-star": "^7.0.0", - "@libp2p/websockets": "^6.0.1", - "react": "^17.0.2", - "react-dom": "^17.0.2", - "react-scripts": "5.0.0" + "@libp2p/kad-dht": "^9.0.0", + "@libp2p/mplex": "^8.0.0", + "@libp2p/websockets": "^6.0.0", + "kubo-rpc-client": "^3.0.1", + "libp2p": "^0.45.0", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "react-scripts": "^5.0.1" }, - "scripts": { - "start": "react-scripts start" + "devDependencies": { + "aegir": "^39.0.10" }, "browserslist": [ ">0.2%", "not dead", "not ie <= 11", "not op_mini all" - ] + ], + "private": true } diff --git a/examples/delegated-routing/src/App.js b/examples/delegated-routing/src/App.js index 830fd758c1..c092081d55 100644 --- a/examples/delegated-routing/src/App.js +++ b/examples/delegated-routing/src/App.js @@ -1,9 +1,19 @@ // eslint-disable-next-line 'use strict' +import { noise } from '@chainsafe/libp2p-noise' +import { yamux } from '@chainsafe/libp2p-yamux' +import { bootstrap } from '@libp2p/bootstrap' +import { delegatedContentRouting } from '@libp2p/delegated-content-routing' +import { delegatedPeerRouting } from '@libp2p/delegated-peer-routing' +import { mplex } from '@libp2p/mplex' +import { webSockets } from '@libp2p/websockets' +import { create as createKuboRpcClient } from 'kubo-rpc-client' +import { createLibp2p } from 'libp2p' +import { circuitRelayTransport } from 'libp2p/circuit-relay' +import { CID } from 'multiformats/cid' import React from 'react' -import Ipfs from 'ipfs-core' -import libp2pBundle from './libp2p-bundle' + const Component = React.Component const BootstrapNode = '/ip4/127.0.0.1/tcp/8081/ws/p2p/QmdoG8DpzYUZMVP5dGmgmigZwR1RE8Cf6SxMPg1SBXJAQ8' @@ -32,84 +42,76 @@ class App extends Component { hash: event.target.value }) } + handlePeerChange (event) { this.setState({ peer: event.target.value }) } - handleHashSubmit (event) { + async handleHashSubmit (event) { event.preventDefault() this.setState({ isLoading: this.state.isLoading + 1 }) - this.ipfs.cat(this.state.hash, (err, data) => { - if (err) console.log('Error', err) + const providers = [] + + for await (const provider of this.libp2p.contentRouting.findProviders(CID.parse(this.state.hash))) { + providers.push(provider) this.setState({ - response: data.toString(), + response: providers.toString(), isLoading: this.state.isLoading - 1 }) - }) + } } - handlePeerSubmit (event) { + + async handlePeerSubmit (event) { event.preventDefault() this.setState({ isLoading: this.state.isLoading + 1 }) - this.ipfs.dht.findpeer(this.state.peer, (err, results) => { - if (err) console.log('Error', err) + const peerInfo = await this.libp2p.peerRouting.findPeer(this.state.peer) - this.setState({ - response: JSON.stringify(results, null, 2), - isLoading: this.state.isLoading - 1 - }) + this.setState({ + response: JSON.stringify(peerInfo, null, 2), + isLoading: this.state.isLoading - 1 }) } - componentDidMount () { - window.ipfs = this.ipfs = Ipfs.create({ - config: { - Addresses: { - Swarm: [] - }, - Discovery: { - MDNS: { - Enabled: false - }, - webRTCStar: { - Enabled: false - } - }, - Bootstrap: [ - BootstrapNode - ] - }, - preload: { - enabled: false - }, - libp2p: libp2pBundle + async componentDidMount () { + const client = createKuboRpcClient({ + host: '0.0.0.0', + protocol: 'http', + port: '8080' }) - this.ipfs.on('ready', () => { - if (this.peerInterval) { - clearInterval(this.peerInterval) - } - - this.ipfs.swarm.connect(BootstrapNode, (err) => { - if (err) { - console.log('Error connecting to the node', err) - } - console.log('Connected!') - }) - this.peerInterval = setInterval(() => { - this.ipfs.swarm.peers((err, peers) => { - if (err) console.log(err) - if (peers) this.setState({peers: peers.length}) + window.libp2p = this.libp2p = await createLibp2p({ + contentRouting: [ + delegatedPeerRouting(client) + ], + peerRouting: [ + delegatedContentRouting(client) + ], + peerDiscovery: [ + bootstrap({ + list: { + BootstrapNode + } }) - }, 2500) + ], + transports: [ + webSockets(), + circuitRelayTransport() + ], + streamMuxers: [ + yamux(), mplex() + ], + connectionEncryption: [ + noise() + ] }) } diff --git a/examples/delegated-routing/src/index.js b/examples/delegated-routing/src/index.js index c41a66a325..03b5425104 100644 --- a/examples/delegated-routing/src/index.js +++ b/examples/delegated-routing/src/index.js @@ -3,6 +3,6 @@ import React from 'react' // eslint-disable-line no-unused-vars import ReactDOM from 'react-dom' -import App from './App' // eslint-disable-line no-unused-vars +import App from './App.js' // eslint-disable-line no-unused-vars ReactDOM.render(, document.getElementById('root')) diff --git a/examples/delegated-routing/src/libp2p-bundle.js b/examples/delegated-routing/src/libp2p-bundle.js deleted file mode 100644 index fa57b412fe..0000000000 --- a/examples/delegated-routing/src/libp2p-bundle.js +++ /dev/null @@ -1,51 +0,0 @@ -// eslint-disable-next-line -'use strict' - -import { createLibp2p } from 'libp2p' -import { webSockets } from '@libp2p/websockets' -import { webRTCStar } from '@libp2p/webrtc-star' -import { mplex } from '@libp2p/mplex' -import { yamux } from '@chainsafe/libp2p-yamux' -import { noise } from '@chainsafe/libp2p-noise' -import { delegatedPeerRouting } from '@libp2p/delegated-peer-routing' -import { delegatedContentRouting } from '@libp2p/delegated-content-routing' -import { create as createIpfsHttpClient } from 'ipfs-http-client' -import { circuitRelayTransport } from 'libp2p/circuit-relay' - -export default function Libp2pBundle ({ peerInfo, peerBook }) { - const wrtcstar = new webRTCStar() - const client = createIpfsHttpClient({ - host: '0.0.0.0', - protocol: 'http', - port: '8080' - }) - - return createLibp2p({ - peerInfo, - peerBook, - // Let's limit the number of connections the connection managers can have - connectionManager: { - maxConnections: 10 - }, - contentRouting: [ - delegatedPeerRouting(client) - ], - peerRouting: [ - delegatedContentRouting(client) - ], - transports: [ - wrtcstar.transport, - webSockets(), - circuitRelayTransport() - ], - streamMuxers: [ - yamux(), mplex() - ], - peerDiscovery: [ - wrtcstar.discovery - ], - connectionEncryption: [ - noise() - ] - }) -} diff --git a/examples/discovery-mechanisms/1.js b/examples/discovery-mechanisms/1.js index 8291da4d51..a653285945 100644 --- a/examples/discovery-mechanisms/1.js +++ b/examples/discovery-mechanisms/1.js @@ -1,11 +1,11 @@ /* eslint-disable no-console */ -import { createLibp2p } from 'libp2p' -import { tcp } from '@libp2p/tcp' -import { mplex } from '@libp2p/mplex' -import { yamux } from '@chainsafe/libp2p-yamux' import { noise } from '@chainsafe/libp2p-noise' +import { yamux } from '@chainsafe/libp2p-yamux' import { bootstrap } from '@libp2p/bootstrap' +import { mplex } from '@libp2p/mplex' +import { tcp } from '@libp2p/tcp' +import { createLibp2p } from 'libp2p' import bootstrappers from './bootstrappers.js' (async () => { @@ -25,7 +25,7 @@ import bootstrappers from './bootstrappers.js' node.addEventListener('peer:connect', (evt) => { const peerId = evt.detail - console.log('Connection established to:', peerId.toString()) // Emitted when a peer has been found + console.log('Connection established to:', peerId.toString()) // Emitted when a peer has been found }) node.addEventListener('peer:discovery', (evt) => { diff --git a/examples/discovery-mechanisms/2.js b/examples/discovery-mechanisms/2.js index bcc2ddf320..3a80cd5aeb 100644 --- a/examples/discovery-mechanisms/2.js +++ b/examples/discovery-mechanisms/2.js @@ -1,11 +1,11 @@ /* eslint-disable no-console */ -import { createLibp2p } from 'libp2p' -import { tcp } from '@libp2p/tcp' -import { mplex } from '@libp2p/mplex' -import { yamux } from '@chainsafe/libp2p-yamux' import { noise } from '@chainsafe/libp2p-noise' +import { yamux } from '@chainsafe/libp2p-yamux' import { mdns } from '@libp2p/mdns' +import { mplex } from '@libp2p/mplex' +import { tcp } from '@libp2p/tcp' +import { createLibp2p } from 'libp2p' const createNode = async () => { const node = await createLibp2p({ @@ -16,7 +16,7 @@ const createNode = async () => { tcp() ], streamMuxers: [ - yamux(),mplex() + yamux(), mplex() ], connectionEncryption: [ noise() diff --git a/examples/discovery-mechanisms/3.js b/examples/discovery-mechanisms/3.js index e0452f7c73..93078517d2 100644 --- a/examples/discovery-mechanisms/3.js +++ b/examples/discovery-mechanisms/3.js @@ -1,13 +1,13 @@ /* eslint-disable no-console */ -import { createLibp2p } from 'libp2p' -import { tcp } from '@libp2p/tcp' -import { mplex } from '@libp2p/mplex' -import { yamux } from '@chainsafe/libp2p-yamux' import { noise } from '@chainsafe/libp2p-noise' -import { floodsub } from '@libp2p/floodsub' +import { yamux } from '@chainsafe/libp2p-yamux' import { bootstrap } from '@libp2p/bootstrap' +import { floodsub } from '@libp2p/floodsub' +import { mplex } from '@libp2p/mplex' import { pubsubPeerDiscovery } from '@libp2p/pubsub-peer-discovery' +import { tcp } from '@libp2p/tcp' +import { createLibp2p } from 'libp2p' import { circuitRelayTransport, circuitRelayServer } from 'libp2p/circuit-relay' import { identifyService } from 'libp2p/identify' diff --git a/examples/discovery-mechanisms/LICENSE b/examples/discovery-mechanisms/LICENSE new file mode 100644 index 0000000000..20ce483c86 --- /dev/null +++ b/examples/discovery-mechanisms/LICENSE @@ -0,0 +1,4 @@ +This project is dual licensed under MIT and Apache-2.0. + +MIT: https://www.opensource.org/licenses/mit +Apache-2.0: https://www.apache.org/licenses/license-2.0 diff --git a/examples/discovery-mechanisms/LICENSE-APACHE b/examples/discovery-mechanisms/LICENSE-APACHE new file mode 100644 index 0000000000..14478a3b60 --- /dev/null +++ b/examples/discovery-mechanisms/LICENSE-APACHE @@ -0,0 +1,5 @@ +Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. diff --git a/examples/discovery-mechanisms/LICENSE-MIT b/examples/discovery-mechanisms/LICENSE-MIT new file mode 100644 index 0000000000..72dc60d84b --- /dev/null +++ b/examples/discovery-mechanisms/LICENSE-MIT @@ -0,0 +1,19 @@ +The MIT License (MIT) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/examples/discovery-mechanisms/README.md b/examples/discovery-mechanisms/README.md index b11f13d48f..59af433297 100644 --- a/examples/discovery-mechanisms/README.md +++ b/examples/discovery-mechanisms/README.md @@ -1,6 +1,20 @@ -# Peer Discovery Mechanisms +# @libp2p/example-discovery-mechanisms -A Peer Discovery module enables libp2p to find peers to connect to. Think of these mechanisms as ways to join the rest of the network, as railing points. +[![libp2p.io](https://img.shields.io/badge/project-libp2p-yellow.svg?style=flat-square)](http://libp2p.io/) +[![Discuss](https://img.shields.io/discourse/https/discuss.libp2p.io/posts.svg?style=flat-square)](https://discuss.libp2p.io) +[![codecov](https://img.shields.io/codecov/c/github/libp2p/js-libp2p.svg?style=flat-square)](https://codecov.io/gh/libp2p/js-libp2p) +[![CI](https://img.shields.io/github/actions/workflow/status/libp2p/js-libp2p/main.yml?branch=master\&style=flat-square)](https://github.com/libp2p/js-libp2p/actions/workflows/main.yml?query=branch%3Amaster) + +> How to configure peer discovery mechanisms + +## Table of contents + +- [1. Bootstrap list of Peers when booting a node](#1-bootstrap-list-of-peers-when-booting-a-node) +- [2. MulticastDNS to find other peers in the network](#2-multicastdns-to-find-other-peers-in-the-network) +- [3. Pubsub based Peer Discovery](#3-pubsub-based-peer-discovery) +- [4. Where to find other Peer Discovery Mechanisms](#4-where-to-find-other-peer-discovery-mechanisms) +- [License](#license) +- [Contribution](#contribution) With this system, a libp2p node can both have a set of nodes to always connect on boot (bootstraper nodes), discover nodes through locality (e.g connected in the same LAN) or through serendipity (random walks on a DHT). @@ -40,7 +54,7 @@ const node = await createLibp2p({ }) ``` -In this configuration, we use a `bootstrappers` array listing peers to connect _on boot_. Here is the list used by js-ipfs and go-ipfs. +In this configuration, we use a `bootstrappers` array listing peers to connect *on boot*. Here is the list used by js-ipfs and go-ipfs. ```JavaScript const bootstrapers = [ @@ -287,5 +301,16 @@ This is really useful when running libp2p in constrained environments like a bro There are plenty more Peer Discovery Mechanisms out there, you can: - Find one in [@libp2p/webrtc-star](https://github.com/libp2p/js-libp2p-webrtc-star). Yes, a transport with discovery capabilities! This happens because WebRTC requires a rendezvous point for peers to exchange [SDP](https://tools.ietf.org/html/rfc4317) offer, which means we have one or more points that can introduce peers to each other. Think of it as MulticastDNS for the Web, as in MulticastDNS only works in LAN. -- Any DHT will offer you a discovery capability. You can simple _random-walk_ the routing tables to find other peers to connect to. For example [@libp2p/kad-dht](https://github.com/libp2p/js-libp2p-kad-dht) can be used for peer discovery. An example of how to configure it to enable random walks can be found [here](https://github.com/libp2p/js-libp2p/blob/v0.28.4/doc/CONFIGURATION.md#customizing-dht). +- Any DHT will offer you a discovery capability. You can simple *random-walk* the routing tables to find other peers to connect to. For example [@libp2p/kad-dht](https://github.com/libp2p/js-libp2p-kad-dht) can be used for peer discovery. An example of how to configure it to enable random walks can be found [here](https://github.com/libp2p/js-libp2p/blob/v0.28.4/doc/CONFIGURATION.md#customizing-dht). - You can create your own Discovery service, a registry, a list, a radio beacon, you name it! + +## License + +Licensed under either of + +- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) +- MIT ([LICENSE-MIT](LICENSE-MIT) / ) + +## Contribution + +Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/examples/discovery-mechanisms/bootstrappers.js b/examples/discovery-mechanisms/bootstrappers.js index 7f88820eb3..85c5e73151 100644 --- a/examples/discovery-mechanisms/bootstrappers.js +++ b/examples/discovery-mechanisms/bootstrappers.js @@ -5,5 +5,5 @@ export default [ '/dnsaddr/bootstrap.libp2p.io/p2p/QmbLHAnMoJPWSCR5Zhtx6BHJX9KiKNN6tpvbUcqanj75Nb', '/dnsaddr/bootstrap.libp2p.io/p2p/QmZa1sAxajnQjVM8WjWXoMbmPd7NsWhfKsPkErzpm9wGkp', '/dnsaddr/bootstrap.libp2p.io/p2p/QmQCU2EcMqAqQPR2i9bChDtGNJchTbq5TbXJJ16u19uLTa', - '/dnsaddr/bootstrap.libp2p.io/p2p/QmcZf59bWwK5XFi76CZX8cbJ4BhTzzA3gU1ZjYZcYW3dwt', + '/dnsaddr/bootstrap.libp2p.io/p2p/QmcZf59bWwK5XFi76CZX8cbJ4BhTzzA3gU1ZjYZcYW3dwt' ] diff --git a/examples/discovery-mechanisms/package.json b/examples/discovery-mechanisms/package.json new file mode 100644 index 0000000000..b6c42890fe --- /dev/null +++ b/examples/discovery-mechanisms/package.json @@ -0,0 +1,50 @@ +{ + "name": "@libp2p/example-discovery-mechanisms", + "version": "0.0.0", + "description": "How to configure peer discovery mechanisms", + "license": "Apache-2.0 OR MIT", + "homepage": "https://github.com/libp2p/js-libp2p/tree/master/examples/discovery-mechanisms#readme", + "repository": { + "type": "git", + "url": "git+https://github.com/libp2p/js-libp2p.git" + }, + "bugs": { + "url": "https://github.com/libp2p/js-libp2p/issues" + }, + "type": "module", + "files": [ + "src", + "dist", + "!dist/test", + "!**/*.tsbuildinfo" + ], + "eslintConfig": { + "extends": "ipfs", + "parserOptions": { + "sourceType": "module" + } + }, + "scripts": { + "lint": "aegir lint", + "start": "react-scripts start", + "test:example": "node test.js" + }, + "dependencies": { + "@chainsafe/libp2p-noise": "^12.0.1", + "@chainsafe/libp2p-yamux": "^4.0.2", + "@libp2p/bootstrap": "^8.0.0", + "@libp2p/floodsub": "^7.0.0", + "@libp2p/mdns": "^8.0.0", + "@libp2p/mplex": "^8.0.0", + "@libp2p/pubsub-peer-discovery": "^8.0.4", + "@libp2p/tcp": "^7.0.0", + "libp2p": "^0.45.0" + }, + "devDependencies": { + "aegir": "^39.0.10", + "execa": "^7.1.1", + "p-wait-for": "^5.0.2", + "uint8arrays": "^4.0.4" + }, + "private": true +} diff --git a/examples/discovery-mechanisms/test-1.js b/examples/discovery-mechanisms/test-1.js index 554f2c2e04..e8570adb48 100644 --- a/examples/discovery-mechanisms/test-1.js +++ b/examples/discovery-mechanisms/test-1.js @@ -1,6 +1,6 @@ import path from 'path' -import { waitForOutput } from '../utils.js' import { fileURLToPath } from 'url' +import { waitForOutput } from 'test-ipfs-example/node' const __dirname = path.dirname(fileURLToPath(import.meta.url)) diff --git a/examples/discovery-mechanisms/test-2.js b/examples/discovery-mechanisms/test-2.js index fefb7e43f5..24f3a0b476 100644 --- a/examples/discovery-mechanisms/test-2.js +++ b/examples/discovery-mechanisms/test-2.js @@ -1,8 +1,8 @@ import path from 'path' +import { fileURLToPath } from 'url' import { execa } from 'execa' import pWaitFor from 'p-wait-for' import { toString as uint8ArrayToString } from 'uint8arrays/to-string' -import { fileURLToPath } from 'url' const __dirname = path.dirname(fileURLToPath(import.meta.url)) diff --git a/examples/discovery-mechanisms/test-3.js b/examples/discovery-mechanisms/test-3.js index 650b4db0e1..cd7e58a5d6 100644 --- a/examples/discovery-mechanisms/test-3.js +++ b/examples/discovery-mechanisms/test-3.js @@ -1,8 +1,8 @@ import path from 'path' +import { fileURLToPath } from 'url' import { execa } from 'execa' import pWaitFor from 'p-wait-for' import { toString as uint8ArrayToString } from 'uint8arrays/to-string' -import { fileURLToPath } from 'url' const __dirname = path.dirname(fileURLToPath(import.meta.url)) diff --git a/examples/discovery-mechanisms/test.js b/examples/discovery-mechanisms/test.js index 79f41f9457..fd441b83ed 100644 --- a/examples/discovery-mechanisms/test.js +++ b/examples/discovery-mechanisms/test.js @@ -2,8 +2,6 @@ import { test as test1 } from './test-1.js' import { test as test2 } from './test-2.js' import { test as test3 } from './test-3.js' -export async function test () { - await test1() - await test2() - await test3() -} +await test1() +await test2() +await test3() diff --git a/examples/echo/LICENSE b/examples/echo/LICENSE new file mode 100644 index 0000000000..20ce483c86 --- /dev/null +++ b/examples/echo/LICENSE @@ -0,0 +1,4 @@ +This project is dual licensed under MIT and Apache-2.0. + +MIT: https://www.opensource.org/licenses/mit +Apache-2.0: https://www.apache.org/licenses/license-2.0 diff --git a/examples/echo/LICENSE-APACHE b/examples/echo/LICENSE-APACHE new file mode 100644 index 0000000000..14478a3b60 --- /dev/null +++ b/examples/echo/LICENSE-APACHE @@ -0,0 +1,5 @@ +Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. diff --git a/examples/echo/LICENSE-MIT b/examples/echo/LICENSE-MIT new file mode 100644 index 0000000000..72dc60d84b --- /dev/null +++ b/examples/echo/LICENSE-MIT @@ -0,0 +1,19 @@ +The MIT License (MIT) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/examples/echo/README.md b/examples/echo/README.md index 2cea61df40..098e613025 100644 --- a/examples/echo/README.md +++ b/examples/echo/README.md @@ -1,13 +1,38 @@ -# Echo example with libp2p +# @libp2p/example-echo -This example performs a simple echo from the listener to the dialer. +[![libp2p.io](https://img.shields.io/badge/project-libp2p-yellow.svg?style=flat-square)](http://libp2p.io/) +[![Discuss](https://img.shields.io/discourse/https/discuss.libp2p.io/posts.svg?style=flat-square)](https://discuss.libp2p.io) +[![codecov](https://img.shields.io/codecov/c/github/libp2p/js-libp2p.svg?style=flat-square)](https://codecov.io/gh/libp2p/js-libp2p) +[![CI](https://img.shields.io/github/actions/workflow/status/libp2p/js-libp2p/main.yml?branch=master\&style=flat-square)](https://github.com/libp2p/js-libp2p/actions/workflows/main.yml?query=branch%3Amaster) + +> An example echo app + +## Table of contents + +- [Setup](#setup) +- [Running](#running) +- [License](#license) +- [Contribution](#contribution) ## Setup + 1. Install the modules from libp2p root, `npm install` and `npm run build`. 2. Open 2 terminal windows in the `./src` directory. ## Running + 1. Run the listener in window 1, `node listener.js` 2. Run the dialer in window 2, `node dialer.js` -3. You should see console logs showing the dial, and the received echo of _hey_ +3. You should see console logs showing the dial, and the received echo of *hey* 4. If you look at the listener window, you will see it receiving the dial + +## License + +Licensed under either of + +- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) +- MIT ([LICENSE-MIT](LICENSE-MIT) / ) + +## Contribution + +Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/examples/echo/package.json b/examples/echo/package.json new file mode 100644 index 0000000000..f595e0136e --- /dev/null +++ b/examples/echo/package.json @@ -0,0 +1,50 @@ +{ + "name": "@libp2p/example-echo", + "version": "0.0.0", + "description": "An example echo app", + "license": "Apache-2.0 OR MIT", + "homepage": "https://github.com/libp2p/js-libp2p/tree/master/examples/echo#readme", + "repository": { + "type": "git", + "url": "git+https://github.com/libp2p/js-libp2p.git" + }, + "bugs": { + "url": "https://github.com/libp2p/js-libp2p/issues" + }, + "type": "module", + "files": [ + "src", + "dist", + "!dist/test", + "!**/*.tsbuildinfo" + ], + "eslintConfig": { + "extends": "ipfs", + "parserOptions": { + "sourceType": "module" + } + }, + "scripts": { + "lint": "aegir lint", + "test:example": "node test.js" + }, + "dependencies": { + "@chainsafe/libp2p-noise": "^12.0.1", + "@chainsafe/libp2p-yamux": "^4.0.2", + "@libp2p/mplex": "^8.0.0", + "@libp2p/peer-id-factory": "^2.0.0", + "@libp2p/tcp": "^7.0.0", + "@libp2p/websockets": "^6.0.0", + "@multiformats/multiaddr": "^12.1.3", + "@nodeutils/defaults-deep": "^1.1.0", + "it-pipe": "^3.0.1", + "libp2p": "^0.45.0", + "uint8arrays": "^4.0.4" + }, + "devDependencies": { + "aegir": "^39.0.10", + "execa": "^7.1.1", + "p-defer": "^4.0.0" + }, + "private": true +} diff --git a/examples/echo/src/dialer.js b/examples/echo/src/dialer.js index 13d0cf3a57..07eb3d1584 100644 --- a/examples/echo/src/dialer.js +++ b/examples/echo/src/dialer.js @@ -4,16 +4,16 @@ * Dialer Node */ -import { createLibp2p } from './libp2p.js' +import { createFromJSON } from '@libp2p/peer-id-factory' +import { multiaddr } from '@multiformats/multiaddr' import { pipe } from 'it-pipe' +import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string' +import { toString as uint8ArrayToString } from 'uint8arrays/to-string' import idd from './id-d.js' import idl from './id-l.js' -import { createFromJSON } from '@libp2p/peer-id-factory' -import { toString as uint8ArrayToString } from 'uint8arrays/to-string' -import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string' -import { multiaddr } from '@multiformats/multiaddr' +import { createLibp2p } from './libp2p.js' -async function run() { +async function run () { const [dialerId, listenerId] = await Promise.all([ createFromJSON(idd), createFromJSON(idl) diff --git a/examples/echo/src/id-d.js b/examples/echo/src/id-d.js index 4c5f00dedb..79d31007f2 100644 --- a/examples/echo/src/id-d.js +++ b/examples/echo/src/id-d.js @@ -1,5 +1,5 @@ export default { - "id": "Qma3GsJmB47xYuyahPZPSadh1avvxfyYQwk8R3UnFrQ6aP", - "privKey": "CAASpwkwggSjAgEAAoIBAQCaNSDOjPz6T8HZsf7LDpxiQRiN2OjeyIHUS05p8QWOr3EFUCFsC31R4moihE5HN+FxNalUyyFZU//yjf1pdnlMJqrVByJSMa+y2y4x2FucpoCAO97Tx+iWzwlZ2UXEUXM1Y81mhPbeWXy+wP2xElTgIER0Tsn/thoA0SD2u9wJuVvM7dB7cBcHYmqV6JH+KWCedRTum6O1BssqP/4Lbm2+rkrbZ4+oVRoU2DRLoFhKqwqLtylrbuj4XOI3XykMXV5+uQXz1JzubNOB9lsc6K+eRC+w8hhhDuFMgzkZ4qomCnx3uhO67KaICd8yqqBa6PJ/+fBM5Xk4hjyR40bwcf41AgMBAAECggEAZnrCJ6IYiLyyRdr9SbKXCNDb4YByGYPEi/HT1aHgIJfFE1PSMjxcdytxfyjP4JJpVtPjiT9JFVU2ddoYu5qJN6tGwjVwgJEWg1UXmPaAw1T/drjS94kVsAs82qICtFmwp52Apg3dBZ0Qwq/8qE1XbG7lLyohIbfCBiL0tiPYMfkcsN9gnFT/kFCX0LVs2pa9fHCRMY9rqCc4/rWJa1w8sMuQ23y4lDaxKF9OZVvOHFQkbBDrkquWHE4r55fchCz/rJklkPJUNENuncBRu0/2X+p4IKFD1DnttXNwb8j4LPiSlLro1T0hiUr5gO2QmdYwXFF63Q3mjQy0+5I4eNbjjQKBgQDZvZy3gUKS/nQNkYfq9za80uLbIj/cWbO+ZZjXCsj0fNIcQFJcKMBoA7DjJvu2S/lf86/41YHkPdmrLAEQAkJ+5BBNOycjYK9minTEjIMMmZDTXXugZ62wnU6F46uLkgEChTqEP57Y6xwwV+JaEDFEsW5N1eE9lEVX9nGIr4phMwKBgQC1TazLuEt1WBx/iUT83ita7obXqoKNzwsS/MWfY2innzYZKDOqeSYZzLtt9uTtp4X4uLyPbYs0qFYhXLsUYMoGHNN8+NdjoyxCjQRJRBkMtaNR0lc5lVDWl3bTuJovjFCgAr9uqJrmI5OHcCIk/cDpdWb3nWaMihVlePmiTcTy9wKBgQCU0u7c1jKkudqks4XM6a+2HAYGdUBk4cLjLhnrUWnNAcuyl5wzdX8dGPi8KZb+IKuQE8WBNJ2VXVj7kBYh1QmSJVunDflQSvNYCOaKuOeRoxzD+y9Wkca74qkbBmPn/6FFEb7PSZTO+tPHjyodGNgz9XpJJRjQuBk1aDJtlF3m1QKBgE5SAr5ym65SZOU3UGUIOKRsfDW4Q/OsqDUImvpywCgBICaX9lHDShFFHwau7FA52ScL7vDquoMB4UtCOtLfyQYA9995w9oYCCurrVlVIJkb8jSLcADBHw3EmqF1kq3NqJqm9TmBfoDCh52vdCCUufxgKh33kfBOSlXuf7B8dgMbAoGAZ3r0/mBQX6S+s5+xCETMTSNv7TQzxgtURIpVs+ZVr2cMhWhiv+n0Omab9X9Z50se8cWl5lkvx8vn3D/XHHIPrMF6qk7RAXtvReb+PeitNvm0odqjFv0J2qki6fDs0HKwq4kojAXI1Md8Th0eobNjsy21fEEJT7uKMJdovI/SErI=", - "pubKey": "CAASpgIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCaNSDOjPz6T8HZsf7LDpxiQRiN2OjeyIHUS05p8QWOr3EFUCFsC31R4moihE5HN+FxNalUyyFZU//yjf1pdnlMJqrVByJSMa+y2y4x2FucpoCAO97Tx+iWzwlZ2UXEUXM1Y81mhPbeWXy+wP2xElTgIER0Tsn/thoA0SD2u9wJuVvM7dB7cBcHYmqV6JH+KWCedRTum6O1BssqP/4Lbm2+rkrbZ4+oVRoU2DRLoFhKqwqLtylrbuj4XOI3XykMXV5+uQXz1JzubNOB9lsc6K+eRC+w8hhhDuFMgzkZ4qomCnx3uhO67KaICd8yqqBa6PJ/+fBM5Xk4hjyR40bwcf41AgMBAAE=" + id: 'Qma3GsJmB47xYuyahPZPSadh1avvxfyYQwk8R3UnFrQ6aP', + privKey: 'CAASpwkwggSjAgEAAoIBAQCaNSDOjPz6T8HZsf7LDpxiQRiN2OjeyIHUS05p8QWOr3EFUCFsC31R4moihE5HN+FxNalUyyFZU//yjf1pdnlMJqrVByJSMa+y2y4x2FucpoCAO97Tx+iWzwlZ2UXEUXM1Y81mhPbeWXy+wP2xElTgIER0Tsn/thoA0SD2u9wJuVvM7dB7cBcHYmqV6JH+KWCedRTum6O1BssqP/4Lbm2+rkrbZ4+oVRoU2DRLoFhKqwqLtylrbuj4XOI3XykMXV5+uQXz1JzubNOB9lsc6K+eRC+w8hhhDuFMgzkZ4qomCnx3uhO67KaICd8yqqBa6PJ/+fBM5Xk4hjyR40bwcf41AgMBAAECggEAZnrCJ6IYiLyyRdr9SbKXCNDb4YByGYPEi/HT1aHgIJfFE1PSMjxcdytxfyjP4JJpVtPjiT9JFVU2ddoYu5qJN6tGwjVwgJEWg1UXmPaAw1T/drjS94kVsAs82qICtFmwp52Apg3dBZ0Qwq/8qE1XbG7lLyohIbfCBiL0tiPYMfkcsN9gnFT/kFCX0LVs2pa9fHCRMY9rqCc4/rWJa1w8sMuQ23y4lDaxKF9OZVvOHFQkbBDrkquWHE4r55fchCz/rJklkPJUNENuncBRu0/2X+p4IKFD1DnttXNwb8j4LPiSlLro1T0hiUr5gO2QmdYwXFF63Q3mjQy0+5I4eNbjjQKBgQDZvZy3gUKS/nQNkYfq9za80uLbIj/cWbO+ZZjXCsj0fNIcQFJcKMBoA7DjJvu2S/lf86/41YHkPdmrLAEQAkJ+5BBNOycjYK9minTEjIMMmZDTXXugZ62wnU6F46uLkgEChTqEP57Y6xwwV+JaEDFEsW5N1eE9lEVX9nGIr4phMwKBgQC1TazLuEt1WBx/iUT83ita7obXqoKNzwsS/MWfY2innzYZKDOqeSYZzLtt9uTtp4X4uLyPbYs0qFYhXLsUYMoGHNN8+NdjoyxCjQRJRBkMtaNR0lc5lVDWl3bTuJovjFCgAr9uqJrmI5OHcCIk/cDpdWb3nWaMihVlePmiTcTy9wKBgQCU0u7c1jKkudqks4XM6a+2HAYGdUBk4cLjLhnrUWnNAcuyl5wzdX8dGPi8KZb+IKuQE8WBNJ2VXVj7kBYh1QmSJVunDflQSvNYCOaKuOeRoxzD+y9Wkca74qkbBmPn/6FFEb7PSZTO+tPHjyodGNgz9XpJJRjQuBk1aDJtlF3m1QKBgE5SAr5ym65SZOU3UGUIOKRsfDW4Q/OsqDUImvpywCgBICaX9lHDShFFHwau7FA52ScL7vDquoMB4UtCOtLfyQYA9995w9oYCCurrVlVIJkb8jSLcADBHw3EmqF1kq3NqJqm9TmBfoDCh52vdCCUufxgKh33kfBOSlXuf7B8dgMbAoGAZ3r0/mBQX6S+s5+xCETMTSNv7TQzxgtURIpVs+ZVr2cMhWhiv+n0Omab9X9Z50se8cWl5lkvx8vn3D/XHHIPrMF6qk7RAXtvReb+PeitNvm0odqjFv0J2qki6fDs0HKwq4kojAXI1Md8Th0eobNjsy21fEEJT7uKMJdovI/SErI=', + pubKey: 'CAASpgIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCaNSDOjPz6T8HZsf7LDpxiQRiN2OjeyIHUS05p8QWOr3EFUCFsC31R4moihE5HN+FxNalUyyFZU//yjf1pdnlMJqrVByJSMa+y2y4x2FucpoCAO97Tx+iWzwlZ2UXEUXM1Y81mhPbeWXy+wP2xElTgIER0Tsn/thoA0SD2u9wJuVvM7dB7cBcHYmqV6JH+KWCedRTum6O1BssqP/4Lbm2+rkrbZ4+oVRoU2DRLoFhKqwqLtylrbuj4XOI3XykMXV5+uQXz1JzubNOB9lsc6K+eRC+w8hhhDuFMgzkZ4qomCnx3uhO67KaICd8yqqBa6PJ/+fBM5Xk4hjyR40bwcf41AgMBAAE=' } diff --git a/examples/echo/src/id-l.js b/examples/echo/src/id-l.js index 722f95ebf9..8e5acb76c0 100644 --- a/examples/echo/src/id-l.js +++ b/examples/echo/src/id-l.js @@ -1,5 +1,5 @@ export default { - "id": "QmcrQZ6RJdpYuGvZqD5QEHAv6qX4BrQLJLQPQUrTrzdcgm", - "privKey": "CAASqAkwggSkAgEAAoIBAQDLZZcGcbe4urMBVlcHgN0fpBymY+xcr14ewvamG70QZODJ1h9sljlExZ7byLiqRB3SjGbfpZ1FweznwNxWtWpjHkQjTVXeoM4EEgDSNO/Cg7KNlU0EJvgPJXeEPycAZX9qASbVJ6EECQ40VR/7+SuSqsdL1hrmG1phpIju+D64gLyWpw9WEALfzMpH5I/KvdYDW3N4g6zOD2mZNp5y1gHeXINHWzMF596O72/6cxwyiXV1eJ000k1NVnUyrPjXtqWdVLRk5IU1LFpoQoXZU5X1hKj1a2qt/lZfH5eOrF/ramHcwhrYYw1txf8JHXWO/bbNnyemTHAvutZpTNrsWATfAgMBAAECggEAQj0obPnVyjxLFZFnsFLgMHDCv9Fk5V5bOYtmxfvcm50us6ye+T8HEYWGUa9RrGmYiLweuJD34gLgwyzE1RwptHPj3tdNsr4NubefOtXwixlWqdNIjKSgPlaGULQ8YF2tm/kaC2rnfifwz0w1qVqhPReO5fypL+0ShyANVD3WN0Fo2ugzrniCXHUpR2sHXSg6K+2+qWdveyjNWog34b7CgpV73Ln96BWae6ElU8PR5AWdMnRaA9ucA+/HWWJIWB3Fb4+6uwlxhu2L50Ckq1gwYZCtGw63q5L4CglmXMfIKnQAuEzazq9T4YxEkp+XDnVZAOgnQGUBYpetlgMmkkh9qQKBgQDvsEs0ThzFLgnhtC2Jy//ZOrOvIAKAZZf/mS08AqWH3L0/Rjm8ZYbLsRcoWU78sl8UFFwAQhMRDBP9G+RPojWVahBL/B7emdKKnFR1NfwKjFdDVaoX5uNvZEKSl9UubbC4WZJ65u/cd5jEnj+w3ir9G8n+P1gp/0yBz02nZXFgSwKBgQDZPQr4HBxZL7Kx7D49ormIlB7CCn2i7mT11Cppn5ifUTrp7DbFJ2t9e8UNk6tgvbENgCKXvXWsmflSo9gmMxeEOD40AgAkO8Pn2R4OYhrwd89dECiKM34HrVNBzGoB5+YsAno6zGvOzLKbNwMG++2iuNXqXTk4uV9GcI8OnU5ZPQKBgCZUGrKSiyc85XeiSGXwqUkjifhHNh8yH8xPwlwGUFIZimnD4RevZI7OEtXw8iCWpX2gg9XGuyXOuKORAkF5vvfVriV4e7c9Ad4Igbj8mQFWz92EpV6NHXGCpuKqRPzXrZrNOA9PPqwSs+s9IxI1dMpk1zhBCOguWx2m+NP79NVhAoGBAI6WSoTfrpu7ewbdkVzTWgQTdLzYNe6jmxDf2ZbKclrf7lNr/+cYIK2Ud5qZunsdBwFdgVcnu/02czeS42TvVBgs8mcgiQc/Uy7yi4/VROlhOnJTEMjlU2umkGc3zLzDgYiRd7jwRDLQmMrYKNyEr02HFKFn3w8kXSzW5I8rISnhAoGBANhchHVtJd3VMYvxNcQb909FiwTnT9kl9pkjhwivx+f8/K8pDfYCjYSBYCfPTM5Pskv5dXzOdnNuCj6Y2H/9m2SsObukBwF0z5Qijgu1DsxvADVIKZ4rzrGb4uSEmM6200qjJ/9U98fVM7rvOraakrhcf9gRwuspguJQnSO9cLj6", - "pubKey": "CAASpgIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDLZZcGcbe4urMBVlcHgN0fpBymY+xcr14ewvamG70QZODJ1h9sljlExZ7byLiqRB3SjGbfpZ1FweznwNxWtWpjHkQjTVXeoM4EEgDSNO/Cg7KNlU0EJvgPJXeEPycAZX9qASbVJ6EECQ40VR/7+SuSqsdL1hrmG1phpIju+D64gLyWpw9WEALfzMpH5I/KvdYDW3N4g6zOD2mZNp5y1gHeXINHWzMF596O72/6cxwyiXV1eJ000k1NVnUyrPjXtqWdVLRk5IU1LFpoQoXZU5X1hKj1a2qt/lZfH5eOrF/ramHcwhrYYw1txf8JHXWO/bbNnyemTHAvutZpTNrsWATfAgMBAAE=" + id: 'QmcrQZ6RJdpYuGvZqD5QEHAv6qX4BrQLJLQPQUrTrzdcgm', + privKey: 'CAASqAkwggSkAgEAAoIBAQDLZZcGcbe4urMBVlcHgN0fpBymY+xcr14ewvamG70QZODJ1h9sljlExZ7byLiqRB3SjGbfpZ1FweznwNxWtWpjHkQjTVXeoM4EEgDSNO/Cg7KNlU0EJvgPJXeEPycAZX9qASbVJ6EECQ40VR/7+SuSqsdL1hrmG1phpIju+D64gLyWpw9WEALfzMpH5I/KvdYDW3N4g6zOD2mZNp5y1gHeXINHWzMF596O72/6cxwyiXV1eJ000k1NVnUyrPjXtqWdVLRk5IU1LFpoQoXZU5X1hKj1a2qt/lZfH5eOrF/ramHcwhrYYw1txf8JHXWO/bbNnyemTHAvutZpTNrsWATfAgMBAAECggEAQj0obPnVyjxLFZFnsFLgMHDCv9Fk5V5bOYtmxfvcm50us6ye+T8HEYWGUa9RrGmYiLweuJD34gLgwyzE1RwptHPj3tdNsr4NubefOtXwixlWqdNIjKSgPlaGULQ8YF2tm/kaC2rnfifwz0w1qVqhPReO5fypL+0ShyANVD3WN0Fo2ugzrniCXHUpR2sHXSg6K+2+qWdveyjNWog34b7CgpV73Ln96BWae6ElU8PR5AWdMnRaA9ucA+/HWWJIWB3Fb4+6uwlxhu2L50Ckq1gwYZCtGw63q5L4CglmXMfIKnQAuEzazq9T4YxEkp+XDnVZAOgnQGUBYpetlgMmkkh9qQKBgQDvsEs0ThzFLgnhtC2Jy//ZOrOvIAKAZZf/mS08AqWH3L0/Rjm8ZYbLsRcoWU78sl8UFFwAQhMRDBP9G+RPojWVahBL/B7emdKKnFR1NfwKjFdDVaoX5uNvZEKSl9UubbC4WZJ65u/cd5jEnj+w3ir9G8n+P1gp/0yBz02nZXFgSwKBgQDZPQr4HBxZL7Kx7D49ormIlB7CCn2i7mT11Cppn5ifUTrp7DbFJ2t9e8UNk6tgvbENgCKXvXWsmflSo9gmMxeEOD40AgAkO8Pn2R4OYhrwd89dECiKM34HrVNBzGoB5+YsAno6zGvOzLKbNwMG++2iuNXqXTk4uV9GcI8OnU5ZPQKBgCZUGrKSiyc85XeiSGXwqUkjifhHNh8yH8xPwlwGUFIZimnD4RevZI7OEtXw8iCWpX2gg9XGuyXOuKORAkF5vvfVriV4e7c9Ad4Igbj8mQFWz92EpV6NHXGCpuKqRPzXrZrNOA9PPqwSs+s9IxI1dMpk1zhBCOguWx2m+NP79NVhAoGBAI6WSoTfrpu7ewbdkVzTWgQTdLzYNe6jmxDf2ZbKclrf7lNr/+cYIK2Ud5qZunsdBwFdgVcnu/02czeS42TvVBgs8mcgiQc/Uy7yi4/VROlhOnJTEMjlU2umkGc3zLzDgYiRd7jwRDLQmMrYKNyEr02HFKFn3w8kXSzW5I8rISnhAoGBANhchHVtJd3VMYvxNcQb909FiwTnT9kl9pkjhwivx+f8/K8pDfYCjYSBYCfPTM5Pskv5dXzOdnNuCj6Y2H/9m2SsObukBwF0z5Qijgu1DsxvADVIKZ4rzrGb4uSEmM6200qjJ/9U98fVM7rvOraakrhcf9gRwuspguJQnSO9cLj6', + pubKey: 'CAASpgIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDLZZcGcbe4urMBVlcHgN0fpBymY+xcr14ewvamG70QZODJ1h9sljlExZ7byLiqRB3SjGbfpZ1FweznwNxWtWpjHkQjTVXeoM4EEgDSNO/Cg7KNlU0EJvgPJXeEPycAZX9qASbVJ6EECQ40VR/7+SuSqsdL1hrmG1phpIju+D64gLyWpw9WEALfzMpH5I/KvdYDW3N4g6zOD2mZNp5y1gHeXINHWzMF596O72/6cxwyiXV1eJ000k1NVnUyrPjXtqWdVLRk5IU1LFpoQoXZU5X1hKj1a2qt/lZfH5eOrF/ramHcwhrYYw1txf8JHXWO/bbNnyemTHAvutZpTNrsWATfAgMBAAE=' } diff --git a/examples/echo/src/libp2p.js b/examples/echo/src/libp2p.js index a639019ddc..85b569490a 100644 --- a/examples/echo/src/libp2p.js +++ b/examples/echo/src/libp2p.js @@ -1,8 +1,8 @@ +import { noise } from '@chainsafe/libp2p-noise' +import { yamux } from '@chainsafe/libp2p-yamux' +import { mplex } from '@libp2p/mplex' import { tcp } from '@libp2p/tcp' import { webSockets } from '@libp2p/websockets' -import { mplex } from '@libp2p/mplex' -import { yamux } from '@chainsafe/libp2p-yamux' -import { noise } from '@chainsafe/libp2p-noise' import defaultsDeep from '@nodeutils/defaults-deep' import { createLibp2p as createNode } from 'libp2p' @@ -13,7 +13,7 @@ export async function createLibp2p (_options) { webSockets() ], streamMuxers: [ - yamux(),mplex() + yamux(), mplex() ], connectionEncryption: [ noise() diff --git a/examples/echo/src/listener.js b/examples/echo/src/listener.js index 86a65e1be7..1ff193cf33 100644 --- a/examples/echo/src/listener.js +++ b/examples/echo/src/listener.js @@ -4,12 +4,12 @@ * Listener Node */ -import { createLibp2p } from './libp2p.js' -import { pipe } from 'it-pipe' import { createFromJSON } from '@libp2p/peer-id-factory' +import { pipe } from 'it-pipe' import idl from './id-l.js' +import { createLibp2p } from './libp2p.js' -async function run() { +async function run () { const listenerId = await createFromJSON(idl) // Listener libp2p node diff --git a/examples/echo/test.js b/examples/echo/test.js index 2fbae5c111..5bdb55c3a6 100644 --- a/examples/echo/test.js +++ b/examples/echo/test.js @@ -1,60 +1,58 @@ import path from 'path' +import { fileURLToPath } from 'url' import { execa } from 'execa' import pDefer from 'p-defer' import { toString as uint8ArrayToString } from 'uint8arrays/to-string' -import { fileURLToPath } from 'url' const __dirname = path.dirname(fileURLToPath(import.meta.url)) -function startProcess(name) { +function startProcess (name) { return execa('node', [path.join(__dirname, name)], { cwd: path.resolve(__dirname), all: true }) } -export async function test () { - const listenerReady = pDefer() - const messageReceived = pDefer() - - // Step 1 process - process.stdout.write('node listener.js\n') - const listenerProc = startProcess('src/listener.js') - listenerProc.all.on('data', async (data) => { - process.stdout.write(data) - const s = uint8ArrayToString(data) - - if (s.includes('Listener ready, listening on:')) { - listenerReady.resolve() - } - }) - - await listenerReady.promise - process.stdout.write('==================================================================\n') - - // Step 2 process - process.stdout.write('node dialer.js\n') - const dialerProc = startProcess('src/dialer.js') - dialerProc.all.on('data', async (data) => { - process.stdout.write(data) - const s = uint8ArrayToString(data) - - if (s.includes('received echo:')) { - messageReceived.resolve() - } - }) - - await messageReceived.promise - process.stdout.write('echo message received\n') - - listenerProc.kill() - dialerProc.kill() - await Promise.all([ - listenerProc, - dialerProc - ]).catch((err) => { - if (err.signal !== 'SIGTERM') { - throw err - } - }) -} +const listenerReady = pDefer() +const messageReceived = pDefer() + +// Step 1 process +process.stdout.write('node src/listener.js\n') +const listenerProc = startProcess('src/listener.js') +listenerProc.all.on('data', async (data) => { + process.stdout.write(data) + const s = uint8ArrayToString(data) + + if (s.includes('Listener ready, listening on:')) { + listenerReady.resolve() + } +}) + +await listenerReady.promise +process.stdout.write('==================================================================\n') + +// Step 2 process +process.stdout.write('node src/dialer.js\n') +const dialerProc = startProcess('src/dialer.js') +dialerProc.all.on('data', async (data) => { + process.stdout.write(data) + const s = uint8ArrayToString(data) + + if (s.includes('received echo:')) { + messageReceived.resolve() + } +}) + +await messageReceived.promise +process.stdout.write('echo message received\n') + +listenerProc.kill() +dialerProc.kill() +await Promise.all([ + listenerProc, + dialerProc +]).catch((err) => { + if (err.signal !== 'SIGTERM') { + throw err + } +}) diff --git a/examples/libp2p-in-the-browser/LICENSE b/examples/libp2p-in-the-browser/LICENSE new file mode 100644 index 0000000000..20ce483c86 --- /dev/null +++ b/examples/libp2p-in-the-browser/LICENSE @@ -0,0 +1,4 @@ +This project is dual licensed under MIT and Apache-2.0. + +MIT: https://www.opensource.org/licenses/mit +Apache-2.0: https://www.apache.org/licenses/license-2.0 diff --git a/examples/libp2p-in-the-browser/LICENSE-APACHE b/examples/libp2p-in-the-browser/LICENSE-APACHE new file mode 100644 index 0000000000..14478a3b60 --- /dev/null +++ b/examples/libp2p-in-the-browser/LICENSE-APACHE @@ -0,0 +1,5 @@ +Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. diff --git a/examples/libp2p-in-the-browser/LICENSE-MIT b/examples/libp2p-in-the-browser/LICENSE-MIT new file mode 100644 index 0000000000..72dc60d84b --- /dev/null +++ b/examples/libp2p-in-the-browser/LICENSE-MIT @@ -0,0 +1,19 @@ +The MIT License (MIT) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/examples/libp2p-in-the-browser/README.md b/examples/libp2p-in-the-browser/README.md index 5c8454eb4d..3d58dd6956 100644 --- a/examples/libp2p-in-the-browser/README.md +++ b/examples/libp2p-in-the-browser/README.md @@ -1,6 +1,19 @@ -# libp2p in the browser +# @libp2p/example-libp2p-in-the-browser -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. +[![libp2p.io](https://img.shields.io/badge/project-libp2p-yellow.svg?style=flat-square)](http://libp2p.io/) +[![Discuss](https://img.shields.io/discourse/https/discuss.libp2p.io/posts.svg?style=flat-square)](https://discuss.libp2p.io) +[![codecov](https://img.shields.io/codecov/c/github/libp2p/js-libp2p.svg?style=flat-square)](https://codecov.io/gh/libp2p/js-libp2p) +[![CI](https://img.shields.io/github/actions/workflow/status/libp2p/js-libp2p/main.yml?branch=master\&style=flat-square)](https://github.com/libp2p/js-libp2p/actions/workflows/main.yml?query=branch%3Amaster) + +> A libp2p node running in the browser + +## Table of contents + +- [Setup](#setup) +- [Running the examples](#running-the-examples) +- [Going to production?](#going-to-production) +- [License](#license) +- [Contribution](#contribution) ## Setup @@ -9,20 +22,18 @@ In order to run the example: - Install dependencey at the root of the js-libp2p repository (if not already done), - then, install the dependencies from same directory as this README: -``` -npm install -npm run build -cd ./examples/libp2p-in-the-browser -npm install -``` + + + npm install + npm run build + cd ./examples/libp2p-in-the-browser + npm install ## Running the examples Start by running the vite server: -``` -npm start -``` + npm start The output should look something like this: @@ -36,7 +47,7 @@ Server running at http://localhost:1234 ✨ Built in 1000ms. ``` -This will compile the code and start a server listening on port [http://localhost:1234](http://localhost:1234). Now open your browser to `http://localhost:1234`. You should see a log of your node's Peer ID, the discovered peers from the Bootstrap module, and connections to those peers as they are created. +This will compile the code and start a server listening on port . Now open your browser to `http://localhost:1234`. You should see a log of your node's Peer ID, the discovered peers from the Bootstrap module, and connections to those peers as they are created. Now, if you open a second browser tab to `http://localhost:1234`, you should discover your node from the previous tab. This is due to the fact that the `libp2p-webrtc-star` transport also acts as a Peer Discovery interface. Your node will be notified of any peer that connects to the same signaling server you are connected to. Once libp2p discovers this new peer, it will attempt to establish a direct WebRTC connection. @@ -49,3 +60,14 @@ This example uses public `libp2p-webrtc-star` servers. These servers should be u You can see how to deploy your own signaling server in [libp2p/js-libp2p-webrtc-star/DEPLOYMENT.md](https://github.com/libp2p/js-libp2p-webrtc-star/blob/master/packages/webrtc-star-signalling-server/DEPLOYMENT.md). Once you have your own server running, you should add its listen address in your libp2p node configuration. + +## License + +Licensed under either of + +- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) +- MIT ([LICENSE-MIT](LICENSE-MIT) / ) + +## Contribution + +Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/examples/libp2p-in-the-browser/index.js b/examples/libp2p-in-the-browser/index.js index 945a5b6e50..0662d405ec 100644 --- a/examples/libp2p-in-the-browser/index.js +++ b/examples/libp2p-in-the-browser/index.js @@ -1,14 +1,16 @@ -import { createLibp2p } from 'libp2p' -import { circuitRelayTransport } from 'libp2p/circuit-relay' -import { identifyService } from 'libp2p/identify' -import { kadDHT } from '@libp2p/kad-dht' -import { webSockets } from '@libp2p/websockets' -import { webTransport } from '@libp2p/webtransport' -import { webRTCDirect, webRTC } from '@libp2p/webrtc' +/* eslint-disable no-console */ + import { noise } from '@chainsafe/libp2p-noise' -import { mplex } from '@libp2p/mplex' import { yamux } from '@chainsafe/libp2p-yamux' import { bootstrap } from '@libp2p/bootstrap' +import { kadDHT } from '@libp2p/kad-dht' +import { mplex } from '@libp2p/mplex' +import { webRTCDirect, webRTC } from '@libp2p/webrtc' +import { webSockets } from '@libp2p/websockets' +import { webTransport } from '@libp2p/webtransport' +import { createLibp2p } from 'libp2p' +import { circuitRelayTransport } from 'libp2p/circuit-relay' +import { identifyService } from 'libp2p/identify' document.addEventListener('DOMContentLoaded', async () => { // Create our libp2p node diff --git a/examples/libp2p-in-the-browser/package.json b/examples/libp2p-in-the-browser/package.json index b00b0dfd22..76ece312a4 100644 --- a/examples/libp2p-in-the-browser/package.json +++ b/examples/libp2p-in-the-browser/package.json @@ -1,26 +1,51 @@ { - "name": "libp2p-in-browser", + "name": "@libp2p/example-libp2p-in-the-browser", "version": "1.0.0", "description": "A libp2p node running in the browser", + "license": "Apache-2.0 OR MIT", + "homepage": "https://github.com/libp2p/js-libp2p/tree/master/examples/libp2p-in-the-browser#readme", + "repository": { + "type": "git", + "url": "git+https://github.com/libp2p/js-libp2p.git" + }, + "bugs": { + "url": "https://github.com/libp2p/js-libp2p/issues" + }, "type": "module", + "files": [ + "src", + "dist", + "!dist/test", + "!**/*.tsbuildinfo" + ], + "eslintConfig": { + "extends": "ipfs", + "parserOptions": { + "sourceType": "module" + } + }, "scripts": { - "test": "echo \"Error: no test specified\" && exit 1", - "start": "vite" + "lint": "aegir lint", + "start": "vite", + "test:example": "node test.js" }, - "license": "ISC", "dependencies": { "@chainsafe/libp2p-gossipsub": "^8.0.0", - "@chainsafe/libp2p-noise": "^12.0.0", - "@chainsafe/libp2p-yamux": "^4.0.1", + "@chainsafe/libp2p-noise": "^12.0.1", + "@chainsafe/libp2p-yamux": "^4.0.2", "@libp2p/bootstrap": "^8.0.0", - "@libp2p/kad-dht": "^9.3.3", - "@libp2p/mplex": "^8.0.1", - "@libp2p/webrtc": "^1.2.0", - "@libp2p/websockets": "^6.0.1", - "@libp2p/webtransport": "^2.0.1", - "libp2p": "file:../../packages/libp2p" + "@libp2p/kad-dht": "^9.0.0", + "@libp2p/mplex": "^8.0.0", + "@libp2p/webrtc": "^2.0.0", + "@libp2p/websockets": "^6.0.0", + "@libp2p/webtransport": "^2.0.0", + "libp2p": "^0.45.0" }, "devDependencies": { + "aegir": "^39.0.10", + "execa": "^7.1.1", + "playwright": "^1.35.1", "vite": "^2.8.6" - } + }, + "private": true } diff --git a/examples/libp2p-in-the-browser/test.js b/examples/libp2p-in-the-browser/test.js index 75e1b7e2c5..4e639cc419 100644 --- a/examples/libp2p-in-the-browser/test.js +++ b/examples/libp2p-in-the-browser/test.js @@ -1,40 +1,40 @@ -import { execa } from 'execa' -import { chromium } from 'playwright' +/* eslint-disable no-console */ + import path from 'path' import { fileURLToPath } from 'url' +import { execa } from 'execa' +import { chromium } from 'playwright' const __dirname = path.dirname(fileURLToPath(import.meta.url)) -export async function test () { - let url = 'http://localhost:3000' +const url = 'http://localhost:3000' - const proc = execa('vite', [], { - preferLocal: true, - localDir: __dirname, - cwd: __dirname, - all: true - }) +const proc = execa('vite', [], { + preferLocal: true, + localDir: __dirname, + cwd: __dirname, + all: true +}) - proc.all.on('data', async (chunk) => { - /**@type {string} */ - const out = chunk.toString() +proc.all.on('data', async (chunk) => { + /** @type {string} */ + const out = chunk.toString() - if (out.includes('ready in')) { - try { - const browser = await chromium.launch(); - const page = await browser.newPage(); - await page.goto(url); - await page.waitForFunction(selector => document.querySelector(selector).innerText === 'libp2p started!', '#status') - await page.waitForFunction(selector => document.querySelector(selector).innerText.includes('libp2p id is'), '#output') - await page.waitForFunction(selector => document.querySelector(selector).innerText.includes('Found peer'), '#output') - await page.waitForFunction(selector => document.querySelector(selector).innerText.includes('Connected to'), '#output') - await browser.close() - } catch (err) { - console.error(err) - process.exit(1) - } finally { - proc.cancel() - } + if (out.includes('ready in')) { + try { + const browser = await chromium.launch() + const page = await browser.newPage() + await page.goto(url) + await page.waitForFunction(selector => document.querySelector(selector).innerText === 'libp2p started!', '#status') + await page.waitForFunction(selector => document.querySelector(selector).innerText.includes('libp2p id is'), '#output') + await page.waitForFunction(selector => document.querySelector(selector).innerText.includes('Found peer'), '#output') + await page.waitForFunction(selector => document.querySelector(selector).innerText.includes('Connected to'), '#output') + await browser.close() + } catch (err) { + console.error(err) + process.exit(1) + } finally { + proc.cancel() } - }) -} + } +}) diff --git a/examples/libp2p-in-the-browser/vite.config.js b/examples/libp2p-in-the-browser/vite.config.js index 04ae6bed00..b40b89518d 100644 --- a/examples/libp2p-in-the-browser/vite.config.js +++ b/examples/libp2p-in-the-browser/vite.config.js @@ -2,4 +2,4 @@ export default { build: { target: 'es2020' } -} \ No newline at end of file +} diff --git a/examples/package.json b/examples/package.json deleted file mode 100644 index d297e6b98b..0000000000 --- a/examples/package.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "name": "libp2p-examples", - "version": "1.0.0", - "description": "Examples of how to use libp2p", - "type": "module", - "scripts": { - "test": "node ./test.js", - "test:all": "node ./test-all.js" - }, - "license": "MIT", - "dependencies": { - "@libp2p/floodsub": "^7.0.1", - "@libp2p/pubsub-peer-discovery": "^8.0.4", - "@nodeutils/defaults-deep": "^1.1.0", - "execa": "^6.1.0", - "fs-extra": "^10.1.0", - "it-to-buffer": "^3.0.1", - "libp2p": "file:../packages/libp2p", - "p-defer": "^4.0.0", - "uint8arrays": "^4.0.0", - "which": "^2.0.1" - }, - "devDependencies": { - "https": "^1.0.0", - "playwright": "^1.7.1" - } -} diff --git a/examples/peer-and-content-routing/1.js b/examples/peer-and-content-routing/1.js index dfd2a18c88..6edd96b356 100644 --- a/examples/peer-and-content-routing/1.js +++ b/examples/peer-and-content-routing/1.js @@ -1,13 +1,13 @@ /* eslint-disable no-console */ -import { createLibp2p } from 'libp2p' -import { identifyService } from 'libp2p/identify' -import { tcp } from '@libp2p/tcp' -import { mplex } from '@libp2p/mplex' -import { yamux } from '@chainsafe/libp2p-yamux' import { noise } from '@chainsafe/libp2p-noise' +import { yamux } from '@chainsafe/libp2p-yamux' import { kadDHT } from '@libp2p/kad-dht' +import { mplex } from '@libp2p/mplex' +import { tcp } from '@libp2p/tcp' import delay from 'delay' +import { createLibp2p } from 'libp2p' +import { identifyService } from 'libp2p/identify' const createNode = async () => { const node = await createLibp2p({ diff --git a/examples/peer-and-content-routing/2.js b/examples/peer-and-content-routing/2.js index efd52525dd..7c7c2ab643 100644 --- a/examples/peer-and-content-routing/2.js +++ b/examples/peer-and-content-routing/2.js @@ -1,15 +1,15 @@ /* eslint-disable no-console */ -import { createLibp2p } from 'libp2p' -import { identifyService } from 'libp2p/identify' -import { tcp } from '@libp2p/tcp' -import { mplex } from '@libp2p/mplex' -import { yamux } from '@chainsafe/libp2p-yamux' import { noise } from '@chainsafe/libp2p-noise' -import { CID } from 'multiformats/cid' +import { yamux } from '@chainsafe/libp2p-yamux' import { kadDHT } from '@libp2p/kad-dht' -import all from 'it-all' +import { mplex } from '@libp2p/mplex' +import { tcp } from '@libp2p/tcp' import delay from 'delay' +import all from 'it-all' +import { createLibp2p } from 'libp2p' +import { identifyService } from 'libp2p/identify' +import { CID } from 'multiformats/cid' const createNode = async () => { const node = await createLibp2p({ diff --git a/examples/peer-and-content-routing/LICENSE b/examples/peer-and-content-routing/LICENSE new file mode 100644 index 0000000000..20ce483c86 --- /dev/null +++ b/examples/peer-and-content-routing/LICENSE @@ -0,0 +1,4 @@ +This project is dual licensed under MIT and Apache-2.0. + +MIT: https://www.opensource.org/licenses/mit +Apache-2.0: https://www.apache.org/licenses/license-2.0 diff --git a/examples/peer-and-content-routing/LICENSE-APACHE b/examples/peer-and-content-routing/LICENSE-APACHE new file mode 100644 index 0000000000..14478a3b60 --- /dev/null +++ b/examples/peer-and-content-routing/LICENSE-APACHE @@ -0,0 +1,5 @@ +Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. diff --git a/examples/peer-and-content-routing/LICENSE-MIT b/examples/peer-and-content-routing/LICENSE-MIT new file mode 100644 index 0000000000..72dc60d84b --- /dev/null +++ b/examples/peer-and-content-routing/LICENSE-MIT @@ -0,0 +1,19 @@ +The MIT License (MIT) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/examples/peer-and-content-routing/README.md b/examples/peer-and-content-routing/README.md index a2364d34a1..ce482db5bf 100644 --- a/examples/peer-and-content-routing/README.md +++ b/examples/peer-and-content-routing/README.md @@ -1,12 +1,25 @@ -# Peer and Content Routing +# @libp2p/example-peer-and-content-routing -DHTs (Distributed Hash Tables) are one of the most common building blocks used when creating P2P networks. However, the name doesn't make justice to all the benefits it brings and putting the whole set of features in one box has proven to be limiting when we want to integrate multiple pieces together. With this in mind, we've come up with a new definition for what a DHT offers: Peer Routing and Content Routing. +[![libp2p.io](https://img.shields.io/badge/project-libp2p-yellow.svg?style=flat-square)](http://libp2p.io/) +[![Discuss](https://img.shields.io/discourse/https/discuss.libp2p.io/posts.svg?style=flat-square)](https://discuss.libp2p.io) +[![codecov](https://img.shields.io/codecov/c/github/libp2p/js-libp2p.svg?style=flat-square)](https://codecov.io/gh/libp2p/js-libp2p) +[![CI](https://img.shields.io/github/actions/workflow/status/libp2p/js-libp2p/main.yml?branch=master\&style=flat-square)](https://github.com/libp2p/js-libp2p/actions/workflows/main.yml?query=branch%3Amaster) + +> How to use peer and content routing + +## Table of contents + +- [1. Using Peer Routing to find other peers](#1-using-peer-routing-to-find-other-peers) +- [2. Using Content Routing to find providers of content](#2-using-content-routing-to-find-providers-of-content) +- [3. Future Work](#3-future-work) +- [License](#license) +- [Contribution](#contribution) Peer Routing is the category of modules that offer a way to find other peers in the network by intentionally issuing queries, iterative or recursive, until a Peer is found or the closest Peers, given the Peer Routing algorithm strategy are found. Content Routing is the category of modules that offer a way to find where content lives in the network, it works in two steps: 1) Peers provide (announce) to the network that they are holders of specific content (multihashes) and 2) Peers issue queries to find where that content lives. A Content Routing mechanism could be as complex as a Kademlia DHT or a simple registry somewhere in the network. -# 1. Using Peer Routing to find other peers +## 1. Using Peer Routing to find other peers This example builds on top of the [Protocol and Stream Muxing](../protocol-and-stream-muxing). We need to install `@libp2p/kad-dht`, go ahead and `npm install @libp2p/kad-dht`. If you want to see the final version, open [1.js](./1.js). @@ -28,7 +41,9 @@ const createNode = async () => { transports: [tcp()], streamMuxers: [yamux(), mplex()], connectionEncryption: [noise()], - dht: kadDHT() + services: { + dht: kadDHT() + } }) return node @@ -76,7 +91,7 @@ Found it, multiaddrs are: You have successfully used Peer Routing to find a peer that you were not directly connected. Now all you have to do is to dial to the multiaddrs you discovered. -# 2. Using Content Routing to find providers of content +## 2. Using Content Routing to find providers of content With Content Routing, you can create records that are stored in multiple points in the network, these records can be resolved by you or other peers and they act as memos or rendezvous points. A great usage of this feature is to support discovery of content, where one node holds a file and instead of using a centralized tracker to inform other nodes that it holds that file, it simply puts a record in the network that can be resolved by other peers. Peer Routing and Content Routing are commonly known as Distributed Hash Tables, DHT. @@ -108,10 +123,21 @@ Found provider: QmSsmVPoTy3WpzwiNPnsKmonBaZjK2HitFs2nWUvwK31Pz That's it, now you know how to find peers that have pieces of information that interest you! -# 3. Future Work +## 3. Future Work Currently, the only mechanisms for Peer and Content Routing come from the DHT, however we do have the intention to support: - Multiple Peer Routing Mechanisms, including ones that do recursive searches (i.e [webrtc-explorer](http://daviddias.me/blog/webrtc-explorer-2-0-0-alpha-release/) like packet switching or [CJDNS](https://github.com/cjdelisle/cjdns) path finder) - Content Routing via PubSub - Content Routing via centralized index (i.e a tracker) + +## License + +Licensed under either of + +- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) +- MIT ([LICENSE-MIT](LICENSE-MIT) / ) + +## Contribution + +Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/examples/peer-and-content-routing/package.json b/examples/peer-and-content-routing/package.json new file mode 100644 index 0000000000..8419f6a218 --- /dev/null +++ b/examples/peer-and-content-routing/package.json @@ -0,0 +1,47 @@ +{ + "name": "@libp2p/example-peer-and-content-routing", + "version": "0.0.0", + "description": "How to use peer and content routing", + "license": "Apache-2.0 OR MIT", + "homepage": "https://github.com/libp2p/js-libp2p/tree/master/examples/peer-and-content-routing#readme", + "repository": { + "type": "git", + "url": "git+https://github.com/libp2p/js-libp2p.git" + }, + "bugs": { + "url": "https://github.com/libp2p/js-libp2p/issues" + }, + "type": "module", + "files": [ + "src", + "dist", + "!dist/test", + "!**/*.tsbuildinfo" + ], + "eslintConfig": { + "extends": "ipfs", + "parserOptions": { + "sourceType": "module" + } + }, + "scripts": { + "lint": "aegir lint", + "test:example": "node test.js" + }, + "dependencies": { + "@chainsafe/libp2p-noise": "^12.0.1", + "@chainsafe/libp2p-yamux": "^4.0.2", + "@libp2p/kad-dht": "^9.0.0", + "@libp2p/mplex": "^8.0.0", + "@libp2p/tcp": "^7.0.0", + "delay": "^6.0.0", + "it-all": "^3.0.2", + "libp2p": "^0.45.0", + "multiformats": "^12.0.1" + }, + "devDependencies": { + "aegir": "^39.0.10", + "test-ipfs-example": "^1.0.0" + }, + "private": true +} diff --git a/examples/peer-and-content-routing/test-1.js b/examples/peer-and-content-routing/test-1.js index 8a234f4d28..3d9fd4e220 100644 --- a/examples/peer-and-content-routing/test-1.js +++ b/examples/peer-and-content-routing/test-1.js @@ -1,6 +1,6 @@ import path from 'path' -import { waitForOutput } from '../utils.js' import { fileURLToPath } from 'url' +import { waitForOutput } from 'test-ipfs-example/node' const __dirname = path.dirname(fileURLToPath(import.meta.url)) diff --git a/examples/peer-and-content-routing/test-2.js b/examples/peer-and-content-routing/test-2.js index 68b41f6572..1c73889e6f 100644 --- a/examples/peer-and-content-routing/test-2.js +++ b/examples/peer-and-content-routing/test-2.js @@ -1,6 +1,6 @@ import path from 'path' -import { waitForOutput } from '../utils.js' import { fileURLToPath } from 'url' +import { waitForOutput } from 'test-ipfs-example/node' const __dirname = path.dirname(fileURLToPath(import.meta.url)) diff --git a/examples/peer-and-content-routing/test.js b/examples/peer-and-content-routing/test.js index 622a7dfce2..07acb00823 100644 --- a/examples/peer-and-content-routing/test.js +++ b/examples/peer-and-content-routing/test.js @@ -1,7 +1,5 @@ import { test as test1 } from './test-1.js' import { test as test2 } from './test-2.js' -export async function test() { - await test1() - await test2() -} +await test1() +await test2() diff --git a/examples/pnet/.gitignore b/examples/pnet/.gitignore deleted file mode 100644 index c036379422..0000000000 --- a/examples/pnet/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tmp/ \ No newline at end of file diff --git a/examples/pnet/LICENSE b/examples/pnet/LICENSE new file mode 100644 index 0000000000..20ce483c86 --- /dev/null +++ b/examples/pnet/LICENSE @@ -0,0 +1,4 @@ +This project is dual licensed under MIT and Apache-2.0. + +MIT: https://www.opensource.org/licenses/mit +Apache-2.0: https://www.apache.org/licenses/license-2.0 diff --git a/examples/pnet/LICENSE-APACHE b/examples/pnet/LICENSE-APACHE new file mode 100644 index 0000000000..14478a3b60 --- /dev/null +++ b/examples/pnet/LICENSE-APACHE @@ -0,0 +1,5 @@ +Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. diff --git a/examples/pnet/LICENSE-MIT b/examples/pnet/LICENSE-MIT new file mode 100644 index 0000000000..72dc60d84b --- /dev/null +++ b/examples/pnet/LICENSE-MIT @@ -0,0 +1,19 @@ +The MIT License (MIT) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/examples/pnet/README.md b/examples/pnet/README.md index 2f59721724..2e3104fef9 100644 --- a/examples/pnet/README.md +++ b/examples/pnet/README.md @@ -1,17 +1,33 @@ -# Private Networking -This example shows how to set up a private network of libp2p nodes. +# @libp2p/example-pnet + +[![libp2p.io](https://img.shields.io/badge/project-libp2p-yellow.svg?style=flat-square)](http://libp2p.io/) +[![Discuss](https://img.shields.io/discourse/https/discuss.libp2p.io/posts.svg?style=flat-square)](https://discuss.libp2p.io) +[![codecov](https://img.shields.io/codecov/c/github/libp2p/js-libp2p.svg?style=flat-square)](https://codecov.io/gh/libp2p/js-libp2p) +[![CI](https://img.shields.io/github/actions/workflow/status/libp2p/js-libp2p/main.yml?branch=master\&style=flat-square)](https://github.com/libp2p/js-libp2p/actions/workflows/main.yml?query=branch%3Amaster) + +> How to configure a libp2p private network + +## Table of contents + +- [Setup](#setup) +- [Run](#run) + - [Using different keys](#using-different-keys) + - [Exploring the repos](#exploring-the-repos) +- [License](#license) +- [Contribution](#contribution) ## Setup + 1. Install the modules in the libp2p root directory, `npm install` and `npm run build`. ## Run + Running the example will cause two nodes with the same swarm key to be started and exchange basic information. -``` -node index.js -``` + node index.js ### Using different keys + This example includes `TASK` comments that can be used to try the example with different swarm keys. This will allow you to see how nodes will fail to connect if they are on different private networks and try to connect to one another. @@ -20,6 +36,18 @@ To change the swarm key of one of the nodes, look through `index.js` for comment where lines are that pertain to changing the swarm key of node 2. ### Exploring the repos + Once you've run the example you can take a look at the repos in the `./tmp` directory to see how they differ, including the swarm keys. You should see a `swarm.key` file in each of the repos and when the nodes are on the same private network this contents of the `swarm.key` files should be the same. + +## License + +Licensed under either of + +- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) +- MIT ([LICENSE-MIT](LICENSE-MIT) / ) + +## Contribution + +Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/examples/pnet/index.js b/examples/pnet/index.js index cdc04825b3..115d7f1792 100644 --- a/examples/pnet/index.js +++ b/examples/pnet/index.js @@ -1,10 +1,10 @@ /* eslint no-console: ["off"] */ -import { generateKey } from 'libp2p/pnet' -import { privateLibp2pNode } from './libp2p-node.js' import { pipe } from 'it-pipe' +import { generateKey } from 'libp2p/pnet' import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string' import { toString as uint8ArrayToString } from 'uint8arrays/to-string' +import { privateLibp2pNode } from './libp2p-node.js' // Create a Uint8Array and write the swarm key to it const swarmKey = new Uint8Array(95) diff --git a/examples/pnet/libp2p-node.js b/examples/pnet/libp2p-node.js index f1e08aa714..8b6b5e817f 100644 --- a/examples/pnet/libp2p-node.js +++ b/examples/pnet/libp2p-node.js @@ -1,15 +1,15 @@ -import { createLibp2p } from 'libp2p' -import { tcp } from '@libp2p/tcp' -import { mplex } from '@libp2p/mplex' -import { yamux } from '@chainsafe/libp2p-yamux' import { noise } from '@chainsafe/libp2p-noise' +import { yamux } from '@chainsafe/libp2p-yamux' +import { mplex } from '@libp2p/mplex' +import { tcp } from '@libp2p/tcp' +import { createLibp2p } from 'libp2p' import { preSharedKey } from 'libp2p/pnet' /** * privateLibp2pNode returns a libp2p node function that will use the swarm * key with the given `swarmKey` to create the Protector * - * @param swarmKey + * @param {any} swarmKey */ export async function privateLibp2pNode (swarmKey) { const node = await createLibp2p({ diff --git a/examples/pnet/package.json b/examples/pnet/package.json new file mode 100644 index 0000000000..a82e2dc8bc --- /dev/null +++ b/examples/pnet/package.json @@ -0,0 +1,45 @@ +{ + "name": "@libp2p/example-pnet", + "version": "0.0.0", + "description": "How to configure a libp2p private network", + "license": "Apache-2.0 OR MIT", + "homepage": "https://github.com/libp2p/js-libp2p/tree/master/examples/pnet#readme", + "repository": { + "type": "git", + "url": "git+https://github.com/libp2p/js-libp2p.git" + }, + "bugs": { + "url": "https://github.com/libp2p/js-libp2p/issues" + }, + "type": "module", + "files": [ + "src", + "dist", + "!dist/test", + "!**/*.tsbuildinfo" + ], + "eslintConfig": { + "extends": "ipfs", + "parserOptions": { + "sourceType": "module" + } + }, + "scripts": { + "lint": "aegir lint", + "test:example": "node test.js" + }, + "dependencies": { + "@chainsafe/libp2p-noise": "^12.0.1", + "@chainsafe/libp2p-yamux": "^4.0.2", + "@libp2p/mplex": "^8.0.0", + "@libp2p/tcp": "^7.0.0", + "it-pipe": "^3.0.1", + "libp2p": "^0.45.0", + "uint8arrays": "^4.0.4" + }, + "devDependencies": { + "aegir": "^39.0.10", + "test-ipfs-example": "^1.0.0" + }, + "private": true +} diff --git a/examples/pnet/test.js b/examples/pnet/test.js index 33696e95ef..eb78f5a6f9 100644 --- a/examples/pnet/test.js +++ b/examples/pnet/test.js @@ -1,12 +1,9 @@ import path from 'path' -import { waitForOutput } from '../utils.js' import { fileURLToPath } from 'url' +import { waitForOutput } from 'test-ipfs-example/node' const __dirname = path.dirname(fileURLToPath(import.meta.url)) -export async function test () { - await waitForOutput('This message is sent on a private network', 'node', [path.join(__dirname, 'index.js')], { - cwd: __dirname - }) -} - +await waitForOutput('This message is sent on a private network', 'node', [path.join(__dirname, 'index.js')], { + cwd: __dirname +}) diff --git a/examples/protocol-and-stream-muxing/1.js b/examples/protocol-and-stream-muxing/1.js index e40daba690..0b3bf5b1e7 100644 --- a/examples/protocol-and-stream-muxing/1.js +++ b/examples/protocol-and-stream-muxing/1.js @@ -1,9 +1,11 @@ -import { createLibp2p } from 'libp2p' -import { tcp } from '@libp2p/tcp' -import { mplex } from '@libp2p/mplex' -import { yamux } from '@chainsafe/libp2p-yamux' +/* eslint-disable no-console */ + import { noise } from '@chainsafe/libp2p-noise' +import { yamux } from '@chainsafe/libp2p-yamux' +import { mplex } from '@libp2p/mplex' +import { tcp } from '@libp2p/tcp' import { pipe } from 'it-pipe' +import { createLibp2p } from 'libp2p' import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string' import { toString as uint8ArrayToString } from 'uint8arrays/to-string' diff --git a/examples/protocol-and-stream-muxing/2.js b/examples/protocol-and-stream-muxing/2.js index 791552a2eb..57e86294d4 100644 --- a/examples/protocol-and-stream-muxing/2.js +++ b/examples/protocol-and-stream-muxing/2.js @@ -1,9 +1,11 @@ -import { createLibp2p } from 'libp2p' -import { tcp } from '@libp2p/tcp' -import { mplex } from '@libp2p/mplex' -import { yamux } from '@chainsafe/libp2p-yamux' +/* eslint-disable no-console */ + import { noise } from '@chainsafe/libp2p-noise' +import { yamux } from '@chainsafe/libp2p-yamux' +import { mplex } from '@libp2p/mplex' +import { tcp } from '@libp2p/tcp' import { pipe } from 'it-pipe' +import { createLibp2p } from 'libp2p' import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string' import { toString as uint8ArrayToString } from 'uint8arrays/to-string' diff --git a/examples/protocol-and-stream-muxing/3.js b/examples/protocol-and-stream-muxing/3.js index a034f32ba2..eb88137a42 100644 --- a/examples/protocol-and-stream-muxing/3.js +++ b/examples/protocol-and-stream-muxing/3.js @@ -1,11 +1,11 @@ /* eslint-disable no-console */ -import { createLibp2p } from 'libp2p' -import { tcp } from '@libp2p/tcp' -import { mplex } from '@libp2p/mplex' -import { yamux } from '@chainsafe/libp2p-yamux' import { noise } from '@chainsafe/libp2p-noise' +import { yamux } from '@chainsafe/libp2p-yamux' +import { mplex } from '@libp2p/mplex' +import { tcp } from '@libp2p/tcp' import { pipe } from 'it-pipe' +import { createLibp2p } from 'libp2p' import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string' import { toString as uint8ArrayToString } from 'uint8arrays/to-string' diff --git a/examples/protocol-and-stream-muxing/LICENSE b/examples/protocol-and-stream-muxing/LICENSE new file mode 100644 index 0000000000..20ce483c86 --- /dev/null +++ b/examples/protocol-and-stream-muxing/LICENSE @@ -0,0 +1,4 @@ +This project is dual licensed under MIT and Apache-2.0. + +MIT: https://www.opensource.org/licenses/mit +Apache-2.0: https://www.apache.org/licenses/license-2.0 diff --git a/examples/protocol-and-stream-muxing/LICENSE-APACHE b/examples/protocol-and-stream-muxing/LICENSE-APACHE new file mode 100644 index 0000000000..14478a3b60 --- /dev/null +++ b/examples/protocol-and-stream-muxing/LICENSE-APACHE @@ -0,0 +1,5 @@ +Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. diff --git a/examples/protocol-and-stream-muxing/LICENSE-MIT b/examples/protocol-and-stream-muxing/LICENSE-MIT new file mode 100644 index 0000000000..72dc60d84b --- /dev/null +++ b/examples/protocol-and-stream-muxing/LICENSE-MIT @@ -0,0 +1,19 @@ +The MIT License (MIT) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/examples/protocol-and-stream-muxing/README.md b/examples/protocol-and-stream-muxing/README.md index 902b3ef5c1..82558e0ce9 100644 --- a/examples/protocol-and-stream-muxing/README.md +++ b/examples/protocol-and-stream-muxing/README.md @@ -1,12 +1,25 @@ -# Protocol and Stream Multiplexing (aka muxing) +# @libp2p/example-protocol-and-stream-muxing -One of the specialties of libp2p is solving the bane of protocol discovery and handshake between machines. Before libp2p, you would have to assign a listener to a port and then through some process of formal specification you would assign ports to special protocols so that other hosts would know before hand which port to dial (e.g ssh (22), http (80), https (443), ftp (21), etc). With libp2p you don't need to do that anymore, not only you don't have to assign ports before hand, you don't even need to think about ports at all since all the protocol handshaking happens in the wire! +[![libp2p.io](https://img.shields.io/badge/project-libp2p-yellow.svg?style=flat-square)](http://libp2p.io/) +[![Discuss](https://img.shields.io/discourse/https/discuss.libp2p.io/posts.svg?style=flat-square)](https://discuss.libp2p.io) +[![codecov](https://img.shields.io/codecov/c/github/libp2p/js-libp2p.svg?style=flat-square)](https://codecov.io/gh/libp2p/js-libp2p) +[![CI](https://img.shields.io/github/actions/workflow/status/libp2p/js-libp2p/main.yml?branch=master\&style=flat-square)](https://github.com/libp2p/js-libp2p/actions/workflows/main.yml?query=branch%3Amaster) -The feature of agreeing on a protocol over an established connection is what we call _protocol multiplexing_ and it is possible through [multistream-select](https://github.com/multiformats/multistream), another protocol that lets you agree per connection (or stream) which protocol is going to be talked over that connection (select), it also enables you to request the other end to tell you which protocols it supports (ls). You can learn more about multistream-select at its [specification repo](https://github.com/multiformats/multistream). +> How to use multiplex protocols streams -# 1. Handle multiple protocols +## Table of contents -Let's see _protocol multiplexing_ in action! You will need the following modules for this example: `libp2p`, `@libp2p/tcp`, `@libp2p/peer-id`, `it-pipe`, `it-buffer` and `streaming-iterables`. This example reuses the base left by the [Transports](../transports) example. You can see the complete solution at [1.js](./1.js). +- [1. Handle multiple protocols](#1-handle-multiple-protocols) +- [2. Reuse existing connection](#2-reuse-existing-connection) +- [3. Bidirectional connections](#3-bidirectional-connections) +- [License](#license) +- [Contribution](#contribution) + +The feature of agreeing on a protocol over an established connection is what we call *protocol multiplexing* and it is possible through [multistream-select](https://github.com/multiformats/multistream), another protocol that lets you agree per connection (or stream) which protocol is going to be talked over that connection (select), it also enables you to request the other end to tell you which protocols it supports (ls). You can learn more about multistream-select at its [specification repo](https://github.com/multiformats/multistream). + +## 1. Handle multiple protocols + +Let's see *protocol multiplexing* in action! You will need the following modules for this example: `libp2p`, `@libp2p/tcp`, `@libp2p/peer-id`, `it-pipe`, `it-buffer` and `streaming-iterables`. This example reuses the base left by the [Transports](../transports) example. You can see the complete solution at [1.js](./1.js). After creating the nodes, we need to tell libp2p which protocols to handle. @@ -43,7 +56,7 @@ node2.handle('/your-protocol', ({ stream }) => { }) ``` -After the protocol is _handled_, now we can dial to it. +After the protocol is *handled*, now we can dial to it. ```JavaScript const stream = await node1.dialProtocol(node2.peerId, ['/your-protocol']) @@ -99,9 +112,9 @@ node2.handle(['/another-protocol/1.0.0', '/another-protocol/2.0.0'], ({ stream } Try all of this out by executing [1.js](./1.js). -# 2. Reuse existing connection +## 2. Reuse existing connection -The examples above would require a node to create a whole new connection for every time it dials in one of the protocols, this is a waste of resources and also it might be simply not possible (e.g lack of file descriptors, not enough ports being open, etc). What we really want is to dial a connection once and then multiplex several virtual connections (stream) over a single connection, this is where _stream multiplexing_ comes into play. +The examples above would require a node to create a whole new connection for every time it dials in one of the protocols, this is a waste of resources and also it might be simply not possible (e.g lack of file descriptors, not enough ports being open, etc). What we really want is to dial a connection once and then multiplex several virtual connections (stream) over a single connection, this is where *stream multiplexing* comes into play. Stream multiplexing is an old concept, in fact it happens in many of the layers of the [OSI System](https://en.wikipedia.org/wiki/OSI_model). In libp2p, we make this feature to our avail by letting the user pick which module for stream multiplexing to use. @@ -163,22 +176,21 @@ await pipe( By running [2.js](./2.js) you should see the following result: -``` -> node 2.js -from: /a, msg: protocol (a) -from: /b, msg: protocol (b) -from: /b, msg: another stream on protocol (b) -``` + > node 2.js + from: /a, msg: protocol (a) + from: /b, msg: protocol (b) + from: /b, msg: another stream on protocol (b) -# 3. Bidirectional connections +## 3. Bidirectional connections -There is one last trick on _protocol and stream multiplexing_ that libp2p uses to make everyone's life easier and that is _bidirectional connection_. +There is one last trick on *protocol and stream multiplexing* that libp2p uses to make everyone's life easier and that is *bidirectional connection*. With the aid of both mechanisms, we can reuse an incomming connection to dial streams out too, this is specially useful when you are behind tricky NAT, firewalls or if you are running in a browser, where you can't have listening addrs, but you can dial out. By dialing out, you enable other peers to talk with you in Protocols that they want, simply by opening a new multiplexed stream. You can see this working on example [3.js](./3.js). As we've seen earlier, we can create our node with this createNode function. + ```js const createNode = async () => { const node = await createLibp2p({ @@ -195,6 +207,7 @@ const createNode = async () => { ``` We can now create our two nodes for this example. + ```js const [node1, node2] = await Promise.all([ createNode(), @@ -203,6 +216,7 @@ const [node1, node2] = await Promise.all([ ``` Since, we want to connect these nodes `node1` & `node2`, we add our `node2` multiaddr in key-value pair in `node1` peer store. + ```js await node1.peerStore.patch(node2.peerId, { multiaddrs: node2.getMultiaddrs() @@ -212,6 +226,7 @@ await node1.peerStore.patch(node2.peerId, { You may notice that we are only adding `node2` to `node1` peer store. This is because we want to dial up a bidirectional connection between these two nodes. Finally, let's create protocols for `node1` & `node2` and dial those protocols. + ```js node1.handle('/node-1', ({ stream }) => { pipe( @@ -261,6 +276,7 @@ from 2 to 1 So, we have successfully set up a bidirectional connection with protocol muxing. But you should be aware that we were able to dial from `node2` to `node1` even we haven't added the `node1` peerId to node2 address book is because we dialed node2 from node1 first. Then, we just dialed back our stream out from `node2` to `node1`. So, if we dial from `node2` to `node1` before dialing from `node1` to `node2` we will get an error. The code below will result into an error as `the dial address is not valid`. + ```js // Dialing from node2 to node1 const stream2 = await node2.dialProtocol(node1.peerId, ['/node-1']) @@ -276,3 +292,14 @@ await pipe( stream1 ) ``` + +## License + +Licensed under either of + +- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) +- MIT ([LICENSE-MIT](LICENSE-MIT) / ) + +## Contribution + +Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/examples/protocol-and-stream-muxing/package.json b/examples/protocol-and-stream-muxing/package.json new file mode 100644 index 0000000000..c0ec6d46b2 --- /dev/null +++ b/examples/protocol-and-stream-muxing/package.json @@ -0,0 +1,45 @@ +{ + "name": "@libp2p/example-protocol-and-stream-muxing", + "version": "0.0.0", + "description": "How to use multiplex protocols streams", + "license": "Apache-2.0 OR MIT", + "homepage": "https://github.com/libp2p/js-libp2p/tree/master/examples/protocol-and-stream-muxing#readme", + "repository": { + "type": "git", + "url": "git+https://github.com/libp2p/js-libp2p.git" + }, + "bugs": { + "url": "https://github.com/libp2p/js-libp2p/issues" + }, + "type": "module", + "files": [ + "src", + "dist", + "!dist/test", + "!**/*.tsbuildinfo" + ], + "eslintConfig": { + "extends": "ipfs", + "parserOptions": { + "sourceType": "module" + } + }, + "scripts": { + "lint": "aegir lint", + "test:example": "node test.js" + }, + "dependencies": { + "@chainsafe/libp2p-noise": "^12.0.1", + "@chainsafe/libp2p-yamux": "^4.0.2", + "@libp2p/mplex": "^8.0.0", + "@libp2p/tcp": "^7.0.0", + "it-pipe": "^3.0.1", + "libp2p": "^0.45.0", + "uint8arrays": "^4.0.4" + }, + "devDependencies": { + "aegir": "^39.0.10", + "test-ipfs-example": "^1.0.0" + }, + "private": true +} diff --git a/examples/protocol-and-stream-muxing/test-1.js b/examples/protocol-and-stream-muxing/test-1.js index d11e42e4f8..5e13eb6ed2 100644 --- a/examples/protocol-and-stream-muxing/test-1.js +++ b/examples/protocol-and-stream-muxing/test-1.js @@ -1,6 +1,6 @@ import path from 'path' -import { waitForOutput } from '../utils.js' import { fileURLToPath } from 'url' +import { waitForOutput } from 'test-ipfs-example/node' const __dirname = path.dirname(fileURLToPath(import.meta.url)) diff --git a/examples/protocol-and-stream-muxing/test-2.js b/examples/protocol-and-stream-muxing/test-2.js index cf6dc60665..885d54117b 100644 --- a/examples/protocol-and-stream-muxing/test-2.js +++ b/examples/protocol-and-stream-muxing/test-2.js @@ -1,6 +1,6 @@ import path from 'path' -import { waitForOutput } from '../utils.js' import { fileURLToPath } from 'url' +import { waitForOutput } from 'test-ipfs-example/node' const __dirname = path.dirname(fileURLToPath(import.meta.url)) diff --git a/examples/protocol-and-stream-muxing/test-3.js b/examples/protocol-and-stream-muxing/test-3.js index bcd4aa1547..0748b259db 100644 --- a/examples/protocol-and-stream-muxing/test-3.js +++ b/examples/protocol-and-stream-muxing/test-3.js @@ -1,6 +1,6 @@ import path from 'path' -import { waitForOutput } from '../utils.js' import { fileURLToPath } from 'url' +import { waitForOutput } from 'test-ipfs-example/node' const __dirname = path.dirname(fileURLToPath(import.meta.url)) diff --git a/examples/protocol-and-stream-muxing/test.js b/examples/protocol-and-stream-muxing/test.js index 8f209bdddb..fd441b83ed 100644 --- a/examples/protocol-and-stream-muxing/test.js +++ b/examples/protocol-and-stream-muxing/test.js @@ -2,8 +2,6 @@ import { test as test1 } from './test-1.js' import { test as test2 } from './test-2.js' import { test as test3 } from './test-3.js' -export async function test() { - await test1() - await test2() - await test3() -} +await test1() +await test2() +await test3() diff --git a/examples/pubsub/1.js b/examples/pubsub/1.js index dd0ffff9bc..0e15e87ddb 100644 --- a/examples/pubsub/1.js +++ b/examples/pubsub/1.js @@ -1,12 +1,12 @@ /* eslint-disable no-console */ -import { createLibp2p } from 'libp2p' -import { identifyService } from 'libp2p/identify' -import { tcp } from '@libp2p/tcp' -import { mplex } from '@libp2p/mplex' -import { yamux } from '@chainsafe/libp2p-yamux' import { noise } from '@chainsafe/libp2p-noise' +import { yamux } from '@chainsafe/libp2p-yamux' import { floodsub } from '@libp2p/floodsub' +import { mplex } from '@libp2p/mplex' +import { tcp } from '@libp2p/tcp' +import { createLibp2p } from 'libp2p' +import { identifyService } from 'libp2p/identify' import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string' import { toString as uint8ArrayToString } from 'uint8arrays/to-string' diff --git a/examples/pubsub/LICENSE b/examples/pubsub/LICENSE new file mode 100644 index 0000000000..20ce483c86 --- /dev/null +++ b/examples/pubsub/LICENSE @@ -0,0 +1,4 @@ +This project is dual licensed under MIT and Apache-2.0. + +MIT: https://www.opensource.org/licenses/mit +Apache-2.0: https://www.apache.org/licenses/license-2.0 diff --git a/examples/pubsub/LICENSE-APACHE b/examples/pubsub/LICENSE-APACHE new file mode 100644 index 0000000000..14478a3b60 --- /dev/null +++ b/examples/pubsub/LICENSE-APACHE @@ -0,0 +1,5 @@ +Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. diff --git a/examples/pubsub/LICENSE-MIT b/examples/pubsub/LICENSE-MIT new file mode 100644 index 0000000000..72dc60d84b --- /dev/null +++ b/examples/pubsub/LICENSE-MIT @@ -0,0 +1,19 @@ +The MIT License (MIT) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/examples/pubsub/README.md b/examples/pubsub/README.md index ee8b5779ad..538e3c5dbd 100644 --- a/examples/pubsub/README.md +++ b/examples/pubsub/README.md @@ -1,6 +1,19 @@ -# Publish Subscribe +# @libp2p/example-pubsub -Publish Subscribe is also included on the stack. Currently, we have two PubSub implementation available [@libp2p/floodsub](https://github.com/libp2p/js-libp2p-floodsub) and [@chainsafe/libp2p-gossipsub](https://github.com/ChainSafe/js-libp2p-gossipsub), with many more being researched at [research-pubsub](https://github.com/libp2p/research-pubsub). +[![libp2p.io](https://img.shields.io/badge/project-libp2p-yellow.svg?style=flat-square)](http://libp2p.io/) +[![Discuss](https://img.shields.io/discourse/https/discuss.libp2p.io/posts.svg?style=flat-square)](https://discuss.libp2p.io) +[![codecov](https://img.shields.io/codecov/c/github/libp2p/js-libp2p.svg?style=flat-square)](https://codecov.io/gh/libp2p/js-libp2p) +[![CI](https://img.shields.io/github/actions/workflow/status/libp2p/js-libp2p/main.yml?branch=master\&style=flat-square)](https://github.com/libp2p/js-libp2p/actions/workflows/main.yml?query=branch%3Amaster) + +> An example using libp2p pubsub + +## Table of contents + +- [0. Set up the example](#0-set-up-the-example) +- [1. Setting up a simple PubSub network on top of libp2p](#1-setting-up-a-simple-pubsub-network-on-top-of-libp2p) +- [2. Future work](#2-future-work) +- [License](#license) +- [Contribution](#contribution) We've seen many interesting use cases appear with this, here are some highlights: @@ -86,12 +99,10 @@ setInterval(() => { The output of the program should look like: -``` -> node 1.js -connected to QmWpvkKm6qHLhoxpWrTswY6UMNWDyn8hN265Qp9ZYvgS82 -node1 received: Bird bird bird, bird is the word! -node1 received: Bird bird bird, bird is the word! -``` + > node 1.js + connected to QmWpvkKm6qHLhoxpWrTswY6UMNWDyn8hN265Qp9ZYvgS82 + node1 received: Bird bird bird, bird is the word! + node1 received: Bird bird bird, bird is the word! You can change the pubsub `emitSelf` option if you want the publishing node to receive its own messages. @@ -101,14 +112,12 @@ gossipsub({ allowPublishToZeroPeers: true, emitSelf: true }) The output of the program should look like: -``` -> node 1.js -connected to QmWpvkKm6qHLhoxpWrTswY6UMNWDyn8hN265Qp9ZYvgS82 -node1 received: Bird bird bird, bird is the word! -node2 received: Bird bird bird, bird is the word! -node1 received: Bird bird bird, bird is the word! -node2 received: Bird bird bird, bird is the word! -``` + > node 1.js + connected to QmWpvkKm6qHLhoxpWrTswY6UMNWDyn8hN265Qp9ZYvgS82 + node1 received: Bird bird bird, bird is the word! + node2 received: Bird bird bird, bird is the word! + node1 received: Bird bird bird, bird is the word! + node2 received: Bird bird bird, bird is the word! ## 2. Future work @@ -116,5 +125,16 @@ libp2p/IPFS PubSub is enabling a whole set of Distributed Real Time applications - [PubSub Room](https://github.com/ipfs-labs/ipfs-pubsub-room) - [Live DB - A always in Sync DB using CRDT](https://github.com/ipfs-labs/ipfs-live-db) -- [IIIF Annotations over IPFS, CRDT and libp2p](https://www.youtube.com/watch?v=hmAniA6g9D0&feature=youtu.be&t=10m40s) +- [IIIF Annotations over IPFS, CRDT and libp2p](https://www.youtube.com/watch?v=hmAniA6g9D0\&feature=youtu.be\&t=10m40s) - [orbit.chat - p2p chat application, fully running in the browser with js-ipfs, js-libp2p and orbit-db](http://orbit.chat/) + +## License + +Licensed under either of + +- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) +- MIT ([LICENSE-MIT](LICENSE-MIT) / ) + +## Contribution + +Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/examples/pubsub/package.json b/examples/pubsub/package.json new file mode 100644 index 0000000000..2ccf1ff085 --- /dev/null +++ b/examples/pubsub/package.json @@ -0,0 +1,46 @@ +{ + "name": "@libp2p/example-pubsub", + "version": "0.0.0", + "description": "An example using libp2p pubsub", + "license": "Apache-2.0 OR MIT", + "homepage": "https://github.com/libp2p/js-libp2p/tree/master/examples/pubsub#readme", + "repository": { + "type": "git", + "url": "git+https://github.com/libp2p/js-libp2p.git" + }, + "bugs": { + "url": "https://github.com/libp2p/js-libp2p/issues" + }, + "type": "module", + "files": [ + "src", + "dist", + "!dist/test", + "!**/*.tsbuildinfo" + ], + "eslintConfig": { + "extends": "ipfs", + "parserOptions": { + "sourceType": "module" + } + }, + "scripts": { + "lint": "aegir lint", + "test:example": "node test.js" + }, + "dependencies": { + "@chainsafe/libp2p-noise": "^12.0.1", + "@chainsafe/libp2p-yamux": "^4.0.2", + "@libp2p/floodsub": "^7.0.0", + "@libp2p/mplex": "^8.0.0", + "@libp2p/tcp": "^7.0.0", + "libp2p": "^0.45.0", + "uint8arrays": "^4.0.4" + }, + "devDependencies": { + "aegir": "^39.0.10", + "execa": "^7.1.1", + "p-defer": "^4.0.0" + }, + "private": true +} diff --git a/examples/pubsub/test-1.js b/examples/pubsub/test-1.js index e863307154..064f4aecf6 100644 --- a/examples/pubsub/test-1.js +++ b/examples/pubsub/test-1.js @@ -1,8 +1,8 @@ import path from 'path' +import { fileURLToPath } from 'url' import { execa } from 'execa' import pDefer from 'p-defer' import { toString as uint8ArrayToString } from 'uint8arrays/to-string' -import { fileURLToPath } from 'url' const __dirname = path.dirname(fileURLToPath(import.meta.url)) diff --git a/examples/pubsub/test.js b/examples/pubsub/test.js index 2848f4b0b5..1e35941f74 100644 --- a/examples/pubsub/test.js +++ b/examples/pubsub/test.js @@ -1,7 +1,5 @@ -import { test as test1 } from './test-1.js' import { test as testMessageFiltering } from './message-filtering/test.js' +import { test as test1 } from './test-1.js' -export async function test() { - await test1() - await testMessageFiltering() -} +await test1() +await testMessageFiltering() diff --git a/examples/test-all.js b/examples/test-all.js deleted file mode 100644 index bce01ac71c..0000000000 --- a/examples/test-all.js +++ /dev/null @@ -1,35 +0,0 @@ - -process.on('unhandedRejection', (err) => { - console.error(err) - - process.exit(1) -}) - -import path from 'path' -import fs from 'fs' -import { - waitForOutput -} from './utils.js' -import { fileURLToPath } from 'url' - -const __dirname = path.dirname(fileURLToPath(import.meta.url)) - -async function testAll () { - for (const dir of fs.readdirSync(__dirname)) { - if (dir === 'node_modules' || dir === 'tests_output') { - continue - } - - const stats = fs.statSync(path.join(__dirname, dir)) - - if (!stats.isDirectory()) { - continue - } - - await waitForOutput('npm info ok', 'npm', ['--loglevel', 'info', 'run', 'test', '--', dir], { - cwd: __dirname - }) - } -} - -testAll() diff --git a/examples/test.js b/examples/test.js deleted file mode 100644 index e6d625c8be..0000000000 --- a/examples/test.js +++ /dev/null @@ -1,97 +0,0 @@ -process.env.NODE_ENV = 'test' -process.env.CI = true // needed for some "clever" build tools - -import fs from 'fs-extra' -import path from 'path' -import { execa } from 'execa' -import { fileURLToPath } from 'url' - -const __dirname = path.dirname(fileURLToPath(import.meta.url)) -const dir = path.join(__dirname, process.argv[2]) - -testExample(dir) - .then(() => {}, (err) => { - if (err.exitCode) { - process.exit(err.exitCode) - } - - console.error(err) - process.exit(1) - }) - -async function testExample (dir) { - await installDeps(dir) - await build(dir) - await runTest(dir) -} - -async function installDeps (dir) { - if (!fs.existsSync(path.join(dir, 'package.json'))) { - console.info('Nothing to install in', dir) - return - } - - if (fs.existsSync(path.join(dir, 'node_modules'))) { - console.info('Dependencies already installed in', dir) - return - } - - const proc = execa('npm', ['install'], { - all: true, - cwd: dir - }) - proc.all.on('data', (data) => { - process.stdout.write(data) - }) - - await proc -} - -async function build (dir) { - const pkgJson = path.join(dir, 'package.json') - - if (!fs.existsSync(pkgJson)) { - console.info('Nothing to build in', dir) - return - } - - const pkg = JSON.parse(fs.readFileSync(pkgJson)) - let build - - if (pkg.scripts.bundle) { - build = 'bundle' - } - - if (pkg.scripts.build) { - build = 'build' - } - - if (!build) { - console.info('No "build" or "bundle" script in', pkgJson) - return - } - - const proc = execa('npm', ['run', build], { - all: true, - cwd: dir - }) - proc.all.on('data', (data) => { - process.stdout.write(data) - }) - - await proc -} - -async function runTest (dir) { - console.info('Running node tests in', dir) - const testFile = path.join(dir, 'test.js') - - if (!fs.existsSync(testFile)) { - console.info('Nothing to test in', dir) - return - } - - const { test } = await import(testFile) - - await test() -} diff --git a/examples/transports/1.js b/examples/transports/1.js index 859bade949..0ca98ea875 100644 --- a/examples/transports/1.js +++ b/examples/transports/1.js @@ -1,8 +1,8 @@ /* eslint-disable no-console */ -import { createLibp2p } from 'libp2p' -import { tcp } from '@libp2p/tcp' import { noise } from '@chainsafe/libp2p-noise' +import { tcp } from '@libp2p/tcp' +import { createLibp2p } from 'libp2p' const createNode = async () => { const node = await createLibp2p({ @@ -30,4 +30,4 @@ const createNode = async () => { console.log('node has started (true/false):', node.isStarted()) console.log('listening on:') node.getMultiaddrs().forEach((ma) => console.log(ma.toString())) -})(); +})() diff --git a/examples/transports/2.js b/examples/transports/2.js index 0ddcf58c5b..9cc39cfc85 100644 --- a/examples/transports/2.js +++ b/examples/transports/2.js @@ -1,14 +1,14 @@ /* eslint-disable no-console */ -import { createLibp2p } from 'libp2p' -import { tcp } from '@libp2p/tcp' import { noise } from '@chainsafe/libp2p-noise' -import { mplex } from '@libp2p/mplex' import { yamux } from '@chainsafe/libp2p-yamux' -import { toString as uint8ArrayToString } from 'uint8arrays/to-string' -import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string' +import { mplex } from '@libp2p/mplex' +import { tcp } from '@libp2p/tcp' import { pipe } from 'it-pipe' import toBuffer from 'it-to-buffer' +import { createLibp2p } from 'libp2p' +import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string' +import { toString as uint8ArrayToString } from 'uint8arrays/to-string' const createNode = async () => { const node = await createLibp2p({ diff --git a/examples/transports/3.js b/examples/transports/3.js index 4d4392e759..4663b5563e 100644 --- a/examples/transports/3.js +++ b/examples/transports/3.js @@ -1,14 +1,14 @@ /* eslint-disable no-console */ -import { createLibp2p } from 'libp2p' -import { tcp } from '@libp2p/tcp' -import { webSockets } from '@libp2p/websockets' import { noise } from '@chainsafe/libp2p-noise' -import { mplex } from '@libp2p/mplex' import { yamux } from '@chainsafe/libp2p-yamux' +import { mplex } from '@libp2p/mplex' +import { tcp } from '@libp2p/tcp' +import { webSockets } from '@libp2p/websockets' import { pipe } from 'it-pipe' -import { toString as uint8ArrayToString } from 'uint8arrays/to-string' +import { createLibp2p } from 'libp2p' import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string' +import { toString as uint8ArrayToString } from 'uint8arrays/to-string' const createNode = async (transports, addresses = []) => { if (!Array.isArray(addresses)) { @@ -19,7 +19,7 @@ const createNode = async (transports, addresses = []) => { addresses: { listen: addresses }, - transports: transports, + transports, connectionEncryption: [noise()], streamMuxers: [yamux(), mplex()] }) @@ -27,7 +27,7 @@ const createNode = async (transports, addresses = []) => { return node } -function printAddrs(node, number) { +function printAddrs (node, number) { console.log('node %s is listening on:', number) node.getMultiaddrs().forEach((ma) => console.log(ma.toString())) } @@ -88,4 +88,4 @@ function print ({ stream }) { } catch (err) { console.log('node 3 failed to dial to node 1 with:', err.message) } -})(); +})() diff --git a/examples/transports/4.js b/examples/transports/4.js index 76695006bd..6ce792e669 100644 --- a/examples/transports/4.js +++ b/examples/transports/4.js @@ -1,16 +1,16 @@ /* eslint-disable no-console */ -import { createLibp2p } from 'libp2p' -import { tcp } from '@libp2p/tcp' -import { webSockets } from '@libp2p/websockets' -import { noise } from '@chainsafe/libp2p-noise' -import { mplex } from '@libp2p/mplex' -import { yamux } from '@chainsafe/libp2p-yamux' import fs from 'fs' import https from 'https' +import { noise } from '@chainsafe/libp2p-noise' +import { yamux } from '@chainsafe/libp2p-yamux' +import { mplex } from '@libp2p/mplex' +import { tcp } from '@libp2p/tcp' +import { webSockets } from '@libp2p/websockets' import { pipe } from 'it-pipe' -import { toString as uint8ArrayToString } from 'uint8arrays/to-string' +import { createLibp2p } from 'libp2p' import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string' +import { toString as uint8ArrayToString } from 'uint8arrays/to-string' const httpServer = https.createServer({ cert: fs.readFileSync('./test_certs/cert.pem'), diff --git a/examples/transports/LICENSE b/examples/transports/LICENSE new file mode 100644 index 0000000000..20ce483c86 --- /dev/null +++ b/examples/transports/LICENSE @@ -0,0 +1,4 @@ +This project is dual licensed under MIT and Apache-2.0. + +MIT: https://www.opensource.org/licenses/mit +Apache-2.0: https://www.apache.org/licenses/license-2.0 diff --git a/examples/transports/LICENSE-APACHE b/examples/transports/LICENSE-APACHE new file mode 100644 index 0000000000..14478a3b60 --- /dev/null +++ b/examples/transports/LICENSE-APACHE @@ -0,0 +1,5 @@ +Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. diff --git a/examples/transports/LICENSE-MIT b/examples/transports/LICENSE-MIT new file mode 100644 index 0000000000..72dc60d84b --- /dev/null +++ b/examples/transports/LICENSE-MIT @@ -0,0 +1,19 @@ +The MIT License (MIT) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/examples/transports/README.md b/examples/transports/README.md index 7da2d2c086..eac5a5009a 100644 --- a/examples/transports/README.md +++ b/examples/transports/README.md @@ -1,6 +1,20 @@ -# [Transports](http://libp2p.io/implementations/#transports) +# @libp2p/example-transports -libp2p doesn't make assumptions for you, instead, it enables you as the developer of the application to pick the modules you need to run your application, which can vary depending on the runtime you are executing. A libp2p node can use one or more Transports to dial and listen for Connections. These transports are modules that offer a clean interface for dialing and listening, defined by the [interface-transport] specification. Some examples of possible transports are: TCP, UTP, WebRTC, QUIC, HTTP, Pigeon and so on. +[![libp2p.io](https://img.shields.io/badge/project-libp2p-yellow.svg?style=flat-square)](http://libp2p.io/) +[![Discuss](https://img.shields.io/discourse/https/discuss.libp2p.io/posts.svg?style=flat-square)](https://discuss.libp2p.io) +[![codecov](https://img.shields.io/codecov/c/github/libp2p/js-libp2p.svg?style=flat-square)](https://codecov.io/gh/libp2p/js-libp2p) +[![CI](https://img.shields.io/github/actions/workflow/status/libp2p/js-libp2p/main.yml?branch=master\&style=flat-square)](https://github.com/libp2p/js-libp2p/actions/workflows/main.yml?query=branch%3Amaster) + +> An example using different types of libp2p transport + +## Table of contents + +- [1. Creating a libp2p node with TCP](#1-creating-a-libp2p-node-with-tcp) +- [2. Dialing from one node to another node](#2-dialing-from-one-node-to-another-node) +- [3. Using multiple transports](#3-using-multiple-transports) +- [4. How to create a new libp2p transport](#4-how-to-create-a-new-libp2p-transport) +- [License](#license) +- [Contribution](#contribution) A more complete definition of what is a transport can be found on the [interface-transport] specification. A way to recognize a candidate transport is through the badge: @@ -92,6 +106,7 @@ import all from 'it-all' ``` We are going to reuse the `createNode` function from step 1, but this time add a stream multiplexer from `libp2p-mplex`. + ```js const createNode = async () => { const node = await createLibp2p({ @@ -108,6 +123,7 @@ const createNode = async () => { return node } ``` + We will also make things simpler by creating another function to print the multiaddresses to avoid duplicating code. ```JavaScript @@ -149,6 +165,7 @@ await pipe( stream ) ``` + For more information refer to the [docs](https://github.com/libp2p/js-libp2p/blob/master/doc/API.md). The result should look like: @@ -299,7 +316,21 @@ If you decide to implement a transport yourself, please consider adding to the l Hope this tutorial was useful. We are always looking to improve it, so contributions are welcome! +## License + +Licensed under either of + +- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) +- MIT ([LICENSE-MIT](LICENSE-MIT) / ) + +## Contribution + +Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. + [interface-transport]: https://github.com/libp2p/js-libp2p-interfaces/tree/master/packages/libp2p-interfaces/src/transport + [interface-transport badge]: https://raw.githubusercontent.com/libp2p/js-libp2p-interfaces/master/packages/libp2p-interfaces/src/transport/img/badge.png + [interface-transport implementations]: https://github.com/libp2p/js-libp2p-interfaces/tree/master/packages/libp2p-interfaces/src/transport#modules-that-implement-the-interface + [interface-transport api]: https://github.com/libp2p/js-libp2p-interfaces/tree/master/packages/libp2p-interfaces/src/transport#api diff --git a/examples/transports/package.json b/examples/transports/package.json new file mode 100644 index 0000000000..b4250a678f --- /dev/null +++ b/examples/transports/package.json @@ -0,0 +1,47 @@ +{ + "name": "@libp2p/example-transports", + "version": "0.0.0", + "description": "An example using different types of libp2p transport", + "license": "Apache-2.0 OR MIT", + "homepage": "https://github.com/libp2p/js-libp2p/tree/master/examples/transports#readme", + "repository": { + "type": "git", + "url": "git+https://github.com/libp2p/js-libp2p.git" + }, + "bugs": { + "url": "https://github.com/libp2p/js-libp2p/issues" + }, + "type": "module", + "files": [ + "src", + "dist", + "!dist/test", + "!**/*.tsbuildinfo" + ], + "eslintConfig": { + "extends": "ipfs", + "parserOptions": { + "sourceType": "module" + } + }, + "scripts": { + "lint": "aegir lint", + "test:example": "node test.js" + }, + "dependencies": { + "@chainsafe/libp2p-noise": "^12.0.1", + "@chainsafe/libp2p-yamux": "^4.0.2", + "@libp2p/mplex": "^8.0.0", + "@libp2p/tcp": "^7.0.0", + "@libp2p/websockets": "^6.0.0", + "it-pipe": "^3.0.1", + "it-to-buffer": "^4.0.2", + "libp2p": "^0.45.0", + "uint8arrays": "^4.0.4" + }, + "devDependencies": { + "aegir": "^39.0.10", + "test-ipfs-example": "^1.0.0" + }, + "private": true +} diff --git a/examples/transports/test-1.js b/examples/transports/test-1.js index 81c1721d94..d94544ce17 100644 --- a/examples/transports/test-1.js +++ b/examples/transports/test-1.js @@ -1,6 +1,6 @@ import path from 'path' -import { waitForOutput } from '../utils.js' import { fileURLToPath } from 'url' +import { waitForOutput } from 'test-ipfs-example/node' const __dirname = path.dirname(fileURLToPath(import.meta.url)) diff --git a/examples/transports/test-2.js b/examples/transports/test-2.js index 4c9714781b..f254851cb9 100644 --- a/examples/transports/test-2.js +++ b/examples/transports/test-2.js @@ -1,6 +1,6 @@ import path from 'path' -import { waitForOutput } from '../utils.js' import { fileURLToPath } from 'url' +import { waitForOutput } from 'test-ipfs-example/node' const __dirname = path.dirname(fileURLToPath(import.meta.url)) diff --git a/examples/transports/test-3.js b/examples/transports/test-3.js index acc1e27def..242af9a737 100644 --- a/examples/transports/test-3.js +++ b/examples/transports/test-3.js @@ -1,6 +1,6 @@ import path from 'path' -import { waitForOutput } from '../utils.js' import { fileURLToPath } from 'url' +import { waitForOutput } from 'test-ipfs-example/node' const __dirname = path.dirname(fileURLToPath(import.meta.url)) diff --git a/examples/transports/test-4.js b/examples/transports/test-4.js index 7a5953b0da..6c4850e08b 100644 --- a/examples/transports/test-4.js +++ b/examples/transports/test-4.js @@ -1,6 +1,6 @@ import path from 'path' -import { waitForOutput } from '../utils.js' import { fileURLToPath } from 'url' +import { waitForOutput } from 'test-ipfs-example/node' const __dirname = path.dirname(fileURLToPath(import.meta.url)) diff --git a/examples/transports/test.js b/examples/transports/test.js index 1b0f8f949a..bc53a61f46 100644 --- a/examples/transports/test.js +++ b/examples/transports/test.js @@ -3,9 +3,7 @@ import { test as test2 } from './test-2.js' import { test as test3 } from './test-3.js' import { test as test4 } from './test-4.js' -export async function test() { - await test1() - await test2() - await test3() - await test4() -} +await test1() +await test2() +await test3() +await test4() diff --git a/examples/utils.js b/examples/utils.js deleted file mode 100644 index e6118cc5bb..0000000000 --- a/examples/utils.js +++ /dev/null @@ -1,58 +0,0 @@ -import { execa } from 'execa' -import fs from 'fs-extra' -import which from 'which' - -async function isExecutable (command) { - try { - await fs.access(command, fs.constants.X_OK) - - return true - } catch (err) { - if (err.code === 'ENOENT') { - return isExecutable(await which(command)) - } - - if (err.code === 'EACCES') { - return false - } - - throw err - } -} - -export async function waitForOutput (expectedOutput, command, args = [], opts = {}) { - if (!await isExecutable(command)) { - args.unshift(command) - command = 'node' - } - - const proc = execa(command, args, { - ...opts, - all: true - }) - let output = '' - let time = 600000 - - let timeout = setTimeout(() => { - throw new Error(`Did not see "${expectedOutput}" in output from "${[command].concat(args).join(' ')}" after ${time/1000}s`) - }, time) - - proc.all.on('data', (data) => { - process.stdout.write(data) - - output += data.toString('utf8') - - if (output.includes(expectedOutput)) { - clearTimeout(timeout) - proc.kill() - } - }) - - try { - await proc - } catch (err) { - if (!err.killed) { - throw err - } - } -} diff --git a/interop/LICENSE b/interop/LICENSE new file mode 100644 index 0000000000..20ce483c86 --- /dev/null +++ b/interop/LICENSE @@ -0,0 +1,4 @@ +This project is dual licensed under MIT and Apache-2.0. + +MIT: https://www.opensource.org/licenses/mit +Apache-2.0: https://www.apache.org/licenses/license-2.0 diff --git a/interop/LICENSE-APACHE b/interop/LICENSE-APACHE new file mode 100644 index 0000000000..14478a3b60 --- /dev/null +++ b/interop/LICENSE-APACHE @@ -0,0 +1,5 @@ +Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. diff --git a/interop/LICENSE-MIT b/interop/LICENSE-MIT new file mode 100644 index 0000000000..72dc60d84b --- /dev/null +++ b/interop/LICENSE-MIT @@ -0,0 +1,19 @@ +The MIT License (MIT) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/interop/README.md b/interop/README.md new file mode 100644 index 0000000000..a10c19924b --- /dev/null +++ b/interop/README.md @@ -0,0 +1,36 @@ +# multidim-interop + +[![libp2p.io](https://img.shields.io/badge/project-libp2p-yellow.svg?style=flat-square)](http://libp2p.io/) +[![Discuss](https://img.shields.io/discourse/https/discuss.libp2p.io/posts.svg?style=flat-square)](https://discuss.libp2p.io) +[![codecov](https://img.shields.io/codecov/c/github/libp2p/js-libp2p.svg?style=flat-square)](https://codecov.io/gh/libp2p/js-libp2p) +[![CI](https://img.shields.io/github/actions/workflow/status/libp2p/js-libp2p/main.yml?branch=master\&style=flat-square)](https://github.com/libp2p/js-libp2p/actions/workflows/main.yml?query=branch%3Amaster) + +> Multidimension Interop Test + +## Table of contents + +- [Install](#install) +- [API Docs](#api-docs) +- [License](#license) +- [Contribution](#contribution) + +## Install + +```console +$ npm i multidim-interop +``` + +## API Docs + +- + +## License + +Licensed under either of + +- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) +- MIT ([LICENSE-MIT](LICENSE-MIT) / ) + +## Contribution + +Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/interop/package.json b/interop/package.json index 917c4fdfc7..91553f83bd 100644 --- a/interop/package.json +++ b/interop/package.json @@ -1,34 +1,60 @@ { "name": "multidim-interop", - "private": true, "version": "1.0.0", "description": "Multidimension Interop Test", - "type": "module", - "main": "index.js", "author": "Glen De Cauwsemaecker / @marcopolo", - "license": "MIT", + "license": "Apache-2.0 OR MIT", + "homepage": "https://github.com/libp2p/js-libp2p/tree/master/interop#readme", + "repository": { + "type": "git", + "url": "git+https://github.com/libp2p/js-libp2p.git" + }, + "bugs": { + "url": "https://github.com/libp2p/js-libp2p/issues" + }, + "type": "module", + "types": "./dist/src/index.d.ts", + "files": [ + "src", + "dist", + "!dist/test", + "!**/*.tsbuildinfo" + ], + "exports": { + ".": { + "types": "./dist/src/index.d.ts", + "import": "./dist/src/index.js" + } + }, + "eslintConfig": { + "extends": "ipfs", + "parserOptions": { + "sourceType": "module" + } + }, "scripts": { "start": "node index.js", "build": "aegir build", "test:interop:multidim": "aegir test" }, "dependencies": { - "@chainsafe/libp2p-noise": "^12.0.0", - "@chainsafe/libp2p-yamux": "^4.0.1", - "@libp2p/mplex": "^8.0.1", - "@libp2p/tcp": "^7.0.1", - "@libp2p/webrtc": "^2.0.7", - "@libp2p/websockets": "^6.0.1", - "@libp2p/webtransport": "^2.0.1", + "@chainsafe/libp2p-noise": "^12.0.1", + "@chainsafe/libp2p-yamux": "^4.0.2", + "@libp2p/mplex": "^8.0.0", + "@libp2p/tcp": "^7.0.0", + "@libp2p/webrtc": "^2.0.0", + "@libp2p/websockets": "^6.0.0", + "@libp2p/webtransport": "^2.0.0", "@multiformats/mafmt": "^12.1.2", "@multiformats/multiaddr": "^12.1.3", - "libp2p": "../packages/libp2p", + "libp2p": "^0.45.0", "redis": "4.5.1" }, + "devDependencies": { + "aegir": "^39.0.10" + }, "browser": { "@libp2p/tcp": false }, - "devDependencies": { - "aegir": "^39.0.5" - } + "private": true } diff --git a/interop/tsconfig.json b/interop/tsconfig.json index 55b334a3e5..5be3797bc7 100644 --- a/interop/tsconfig.json +++ b/interop/tsconfig.json @@ -1,10 +1,30 @@ { - "extends": "aegir/src/config/tsconfig.aegir.json", - "compilerOptions": { - "outDir": "dist" - }, - "include": [ - "src", - "test" - ] -} \ No newline at end of file + "extends": "aegir/src/config/tsconfig.aegir.json", + "compilerOptions": { + "outDir": "dist" + }, + "include": [ + "src", + "test" + ], + "references": [ + { + "path": "../packages/libp2p" + }, + { + "path": "../packages/stream-multiplexer-mplex" + }, + { + "path": "../packages/transport-tcp" + }, + { + "path": "../packages/transport-webrtc" + }, + { + "path": "../packages/transport-websockets" + }, + { + "path": "../packages/transport-webtransport" + } + ] +} diff --git a/package.json b/package.json index 4aab9ff0e1..f354e3162b 100644 --- a/package.json +++ b/package.json @@ -24,7 +24,7 @@ "test:external": "aegir run test:external", "test:cli": "aegir run test:cli", "test:interop": "aegir run test:interop", - "test:examples": "cd examples && npm run test:all", + "test:example": "aegir run test:example", "coverage": "aegir run coverage", "build": "aegir run build", "clean": "aegir run clean", @@ -46,6 +46,7 @@ }, "workspaces": [ "packages/*", - "interop" + "interop", + "examples/*" ] } diff --git a/packages/kad-dht/README.md b/packages/kad-dht/README.md index d0cb29462c..bd231f8c1d 100644 --- a/packages/kad-dht/README.md +++ b/packages/kad-dht/README.md @@ -59,7 +59,9 @@ import { createLibp2pNode } from 'libp2p' import { kadDHT } from '@libp2p/kad-dht' const node = await createLibp2pNode({ - dht: kadDHT() + services: { + dht: kadDHT() + } //... other config }) await node.start() diff --git a/packages/kad-dht/package.json b/packages/kad-dht/package.json index 1f4bbce183..83236ca8d5 100644 --- a/packages/kad-dht/package.json +++ b/packages/kad-dht/package.json @@ -98,13 +98,13 @@ "aegir": "^39.0.10", "datastore-level": "^10.0.0", "delay": "^6.0.0", - "execa": "^7.0.0", + "execa": "^7.1.1", "it-filter": "^3.0.1", "it-last": "^3.0.1", "lodash.random": "^3.2.0", "lodash.range": "^3.2.0", "p-retry": "^5.0.0", - "p-wait-for": "^5.0.0", + "p-wait-for": "^5.0.2", "protons": "^7.0.2", "sinon": "^15.1.2", "ts-sinon": "^2.0.2", diff --git a/packages/libp2p/package.json b/packages/libp2p/package.json index 54c179d0df..ce64a297a6 100644 --- a/packages/libp2p/package.json +++ b/packages/libp2p/package.json @@ -178,14 +178,14 @@ "@types/xsalsa20": "^1.1.0", "aegir": "^39.0.10", "delay": "^6.0.0", - "execa": "^7.0.0", + "execa": "^7.1.1", "go-libp2p": "^1.1.1", "it-pushable": "^3.0.0", "it-to-buffer": "^4.0.1", "npm-run-all": "^4.1.5", "p-event": "^6.0.0", "p-times": "^4.0.0", - "p-wait-for": "^5.0.0", + "p-wait-for": "^5.0.2", "protons": "^7.0.2", "sinon": "^15.1.2", "sinon-ts": "^1.0.0" diff --git a/packages/logger/package.json b/packages/logger/package.json index f7d269eecf..db09b9fc21 100644 --- a/packages/logger/package.json +++ b/packages/logger/package.json @@ -59,7 +59,7 @@ "@types/debug": "^4.1.7", "aegir": "^39.0.10", "sinon": "^15.1.2", - "uint8arrays": "^4.0.3" + "uint8arrays": "^4.0.4" }, "typedoc": { "entryPoint": "./src/index.ts" diff --git a/packages/peer-discovery-mdns/package.json b/packages/peer-discovery-mdns/package.json index 23fe0fa314..5dd2ed9966 100644 --- a/packages/peer-discovery-mdns/package.json +++ b/packages/peer-discovery-mdns/package.json @@ -57,7 +57,7 @@ "@libp2p/interface-internal": "~0.0.1", "@libp2p/peer-id-factory": "^2.0.0", "aegir": "^39.0.10", - "p-wait-for": "^5.0.0", + "p-wait-for": "^5.0.2", "ts-sinon": "^2.0.2" }, "typedoc": { diff --git a/packages/pubsub-floodsub/package.json b/packages/pubsub-floodsub/package.json index 4127b381e5..536d57e180 100644 --- a/packages/pubsub-floodsub/package.json +++ b/packages/pubsub-floodsub/package.json @@ -72,7 +72,7 @@ "@types/sinon": "^10.0.15", "aegir": "^39.0.10", "multiformats": "^12.0.1", - "p-wait-for": "^5.0.0", + "p-wait-for": "^5.0.2", "protons": "^7.0.2", "sinon": "^15.1.2" }, diff --git a/packages/pubsub/package.json b/packages/pubsub/package.json index 255e8a3a87..0bb883d352 100644 --- a/packages/pubsub/package.json +++ b/packages/pubsub/package.json @@ -109,7 +109,7 @@ "delay": "^6.0.0", "it-pair": "^2.0.6", "p-defer": "^4.0.0", - "p-wait-for": "^5.0.0", + "p-wait-for": "^5.0.2", "protons": "^7.0.2", "protons-runtime": "^5.0.0", "sinon": "^15.1.2" diff --git a/packages/transport-tcp/package.json b/packages/transport-tcp/package.json index f855e5e9c1..4a2e43ab6c 100644 --- a/packages/transport-tcp/package.json +++ b/packages/transport-tcp/package.json @@ -65,7 +65,7 @@ "it-pipe": "^3.0.1", "p-defer": "^4.0.0", "sinon": "^15.1.2", - "uint8arrays": "^4.0.3" + "uint8arrays": "^4.0.4" }, "typedoc": { "entryPoint": "./src/index.ts" diff --git a/packages/transport-websockets/package.json b/packages/transport-websockets/package.json index 6bfc33e43b..3287ae719d 100644 --- a/packages/transport-websockets/package.json +++ b/packages/transport-websockets/package.json @@ -91,9 +91,9 @@ "it-goodbye": "^4.0.1", "it-pipe": "^3.0.1", "it-stream-types": "^2.0.1", - "p-wait-for": "^5.0.0", + "p-wait-for": "^5.0.2", "uint8arraylist": "^2.3.2", - "uint8arrays": "^4.0.3" + "uint8arrays": "^4.0.4" }, "browser": { "./dist/src/listener.js": "./dist/src/listener.browser.js" diff --git a/packages/utils/package.json b/packages/utils/package.json index 07eb025c33..42d13959af 100644 --- a/packages/utils/package.json +++ b/packages/utils/package.json @@ -100,7 +100,7 @@ "it-all": "^3.0.1", "it-pair": "^2.0.6", "it-pipe": "^3.0.1", - "uint8arrays": "^4.0.3" + "uint8arrays": "^4.0.4" }, "typedoc": { "entryPoint": "./src/index.ts"