├── .github ├── dependabot.yml ├── pull_request_template.md └── workflows │ ├── ci.yml │ ├── generated-pr.yml │ ├── semantic-pull-request.yml │ └── stale.yml ├── .gitignore ├── CONTRIBUTING.md ├── LICENSE ├── LICENSE-APACHE ├── LICENSE-MIT ├── README.md ├── examples ├── js-libp2p-example-auto-tls │ ├── .github │ │ ├── pull_request_template.md │ │ └── workflows │ │ │ └── sync.yml │ ├── LICENSE │ ├── LICENSE-APACHE │ ├── LICENSE-MIT │ ├── README.md │ ├── auto-confirm.js │ ├── package.json │ └── trust-free.js ├── js-libp2p-example-browser-pubsub │ ├── .github │ │ ├── pull_request_template.md │ │ └── workflows │ │ │ └── sync.yml │ ├── LICENSE │ ├── LICENSE-APACHE │ ├── LICENSE-MIT │ ├── README.md │ ├── index.html │ ├── index.js │ ├── package.json │ ├── relay.js │ ├── test │ │ └── index.spec.js │ └── vite.config.js ├── js-libp2p-example-chat │ ├── .github │ │ ├── pull_request_template.md │ │ └── workflows │ │ │ └── sync.yml │ ├── LICENSE │ ├── LICENSE-APACHE │ ├── LICENSE-MIT │ ├── README.md │ ├── package.json │ ├── src │ │ ├── dialer.js │ │ ├── libp2p.js │ │ ├── listener.js │ │ └── stream.js │ └── test │ │ └── index.spec.js ├── js-libp2p-example-circuit-relay │ ├── .github │ │ ├── pull_request_template.md │ │ └── workflows │ │ │ └── sync.yml │ ├── LICENSE │ ├── LICENSE-APACHE │ ├── LICENSE-MIT │ ├── README.md │ ├── dialer.js │ ├── listener.js │ ├── package.json │ ├── relay.js │ └── test │ │ └── index.spec.js ├── js-libp2p-example-connection-encryption │ ├── .github │ │ ├── pull_request_template.md │ │ └── workflows │ │ │ └── sync.yml │ ├── LICENSE │ ├── LICENSE-APACHE │ ├── LICENSE-MIT │ ├── README.md │ ├── noise.js │ ├── package.json │ ├── plaintext.js │ └── test │ │ └── index.spec.js ├── js-libp2p-example-custom-protocols │ ├── .github │ │ ├── pull_request_template.md │ │ └── workflows │ │ │ └── sync.yml │ ├── 1-echo.js │ ├── 2-request-response.js │ ├── LICENSE │ ├── LICENSE-APACHE │ ├── LICENSE-MIT │ ├── README.md │ ├── package.json │ └── test │ │ ├── 1-echo.spec.js │ │ └── 2-request-response.spec.js ├── js-libp2p-example-delegated-routing │ ├── .github │ │ ├── pull_request_template.md │ │ └── workflows │ │ │ └── sync.yml │ ├── LICENSE │ ├── LICENSE-APACHE │ ├── LICENSE-MIT │ ├── README.md │ ├── package.json │ ├── server.js │ ├── src │ │ ├── App.js │ │ ├── index.html │ │ ├── index.js │ │ ├── libp2p.js │ │ └── main.css │ ├── test │ │ └── index.spec.js │ └── vite.config.js ├── js-libp2p-example-discovery-mechanisms │ ├── .github │ │ ├── pull_request_template.md │ │ └── workflows │ │ │ └── sync.yml │ ├── 1-dht.js │ ├── 2-mdns.js │ ├── 3-pubsub.js │ ├── LICENSE │ ├── LICENSE-APACHE │ ├── LICENSE-MIT │ ├── README.md │ ├── bootstrappers.js │ ├── package.json │ └── test │ │ ├── test-1-dht.spec.js │ │ ├── test-2-mdns.spec.js │ │ └── test-3-pubsub.spec.js ├── js-libp2p-example-peer-and-content-routing │ ├── .github │ │ ├── pull_request_template.md │ │ └── workflows │ │ │ └── sync.yml │ ├── 1.js │ ├── 2.js │ ├── LICENSE │ ├── LICENSE-APACHE │ ├── LICENSE-MIT │ ├── README.md │ ├── package.json │ └── test │ │ ├── index.js │ │ ├── test-1.js │ │ └── test-2.js ├── js-libp2p-example-pnet │ ├── .github │ │ ├── pull_request_template.md │ │ └── workflows │ │ │ └── sync.yml │ ├── LICENSE │ ├── LICENSE-APACHE │ ├── LICENSE-MIT │ ├── README.md │ ├── index.js │ ├── libp2p-node.js │ ├── package.json │ └── test │ │ └── index.js ├── js-libp2p-example-protocol-and-stream-muxing │ ├── .github │ │ ├── pull_request_template.md │ │ └── workflows │ │ │ └── sync.yml │ ├── 1.js │ ├── 2.js │ ├── 3.js │ ├── LICENSE │ ├── LICENSE-APACHE │ ├── LICENSE-MIT │ ├── README.md │ ├── package.json │ └── test │ │ ├── test-1.js │ │ ├── test-2.js │ │ ├── test-3.js │ │ └── test.js ├── js-libp2p-example-pubsub │ ├── .github │ │ ├── pull_request_template.md │ │ └── workflows │ │ │ └── sync.yml │ ├── 1.js │ ├── 2.js │ ├── LICENSE │ ├── LICENSE-APACHE │ ├── LICENSE-MIT │ ├── README.md │ ├── package.json │ └── test │ │ ├── test-1.js │ │ ├── test-2.js │ │ └── test.js ├── js-libp2p-example-transports │ ├── .github │ │ ├── pull_request_template.md │ │ └── workflows │ │ │ └── sync.yml │ ├── 1.js │ ├── 2.js │ ├── 3.js │ ├── 4.js │ ├── LICENSE │ ├── LICENSE-APACHE │ ├── LICENSE-MIT │ ├── README.md │ ├── package.json │ ├── test │ │ ├── test-1.js │ │ ├── test-2.js │ │ ├── test-3.js │ │ ├── test-4.js │ │ └── test.js │ └── test_certs │ │ ├── cert.pem │ │ └── key.pem └── js-libp2p-example-webrtc-private-to-private │ ├── .github │ ├── pull_request_template.md │ └── workflows │ │ └── sync.yml │ ├── LICENSE │ ├── LICENSE-APACHE │ ├── LICENSE-MIT │ ├── README.md │ ├── index.html │ ├── index.js │ ├── package.json │ ├── relay.js │ ├── test │ └── index.spec.js │ └── vite.config.js └── package.json /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: npm 4 | directory: "/" 5 | schedule: 6 | interval: daily 7 | time: "11:00" 8 | open-pull-requests-limit: 50 9 | -------------------------------------------------------------------------------- /.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | ## Title 2 | 8 | 9 | ## Description 10 | 11 | 17 | 18 | ## Notes & open questions 19 | 20 | 23 | 24 | ## Change checklist 25 | 26 | - [ ] I have performed a self-review of my own code 27 | - [ ] I have made corresponding changes to the documentation if necessary (this includes comments as well) 28 | - [ ] I have added tests that prove my fix is effective or that my feature works -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | pull_request: 8 | branches: 9 | - '**' 10 | 11 | concurrency: 12 | group: ${{ github.head_ref || github.ref_name }} 13 | cancel-in-progress: true 14 | 15 | jobs: 16 | examples: 17 | runs-on: ubuntu-latest 18 | name: Test ${{ matrix.project }} 19 | strategy: 20 | fail-fast: false 21 | matrix: 22 | project: 23 | - js-libp2p-example-auto-tls 24 | - js-libp2p-example-browser-pubsub 25 | - js-libp2p-example-chat 26 | - js-libp2p-example-circuit-relay 27 | - js-libp2p-example-connection-encryption 28 | - js-libp2p-example-custom-protocols 29 | - js-libp2p-example-delegated-routing 30 | - js-libp2p-example-discovery-mechanisms 31 | - js-libp2p-example-peer-and-content-routing 32 | - js-libp2p-example-pnet 33 | - js-libp2p-example-protocol-and-stream-muxing 34 | - js-libp2p-example-pubsub 35 | - js-libp2p-example-transports 36 | - js-libp2p-example-webrtc-private-to-private 37 | defaults: 38 | run: 39 | working-directory: examples/${{ matrix.project }} 40 | steps: 41 | - uses: actions/checkout@v3 42 | - uses: actions/setup-node@v3 43 | with: 44 | node-version: lts/* 45 | - name: Install dependencies 46 | run: npm install 47 | - name: Install Playwright 48 | run: npx -y playwright install --with-deps 49 | - name: Run tests 50 | run: npm run test 51 | env: 52 | CI: true 53 | 54 | monorepo: 55 | runs-on: ubuntu-latest 56 | name: Test monorepo 57 | steps: 58 | - uses: actions/checkout@v3 59 | - uses: actions/setup-node@v3 60 | with: 61 | node-version: lts/* 62 | - name: Install dependencies 63 | run: npm install 64 | - name: Install Playwright 65 | run: npx -y playwright install --with-deps 66 | - name: Run linting 67 | run: npm run lint 68 | env: 69 | CI: true 70 | - name: Run tests 71 | run: npm run test 72 | env: 73 | CI: true 74 | 75 | push-changes: 76 | name: Push changes 77 | runs-on: ubuntu-latest 78 | needs: [monorepo, examples] 79 | if: github.event_name == 'push' && github.ref == 'refs/heads/main' 80 | strategy: 81 | fail-fast: true 82 | matrix: 83 | project: 84 | - js-libp2p-example-auto-tls 85 | - js-libp2p-example-browser-pubsub 86 | - js-libp2p-example-chat 87 | - js-libp2p-example-circuit-relay 88 | - js-libp2p-example-connection-encryption 89 | - js-libp2p-example-custom-protocols 90 | - js-libp2p-example-delegated-routing 91 | - js-libp2p-example-discovery-mechanisms 92 | - js-libp2p-example-peer-and-content-routing 93 | - js-libp2p-example-pnet 94 | - js-libp2p-example-protocol-and-stream-muxing 95 | - js-libp2p-example-pubsub 96 | - js-libp2p-example-transports 97 | - js-libp2p-example-webrtc-private-to-private 98 | steps: 99 | - uses: convictional/trigger-workflow-and-wait@f69fa9eedd3c62a599220f4d5745230e237904be 100 | with: 101 | owner: libp2p 102 | repo: ${{ matrix.project }} 103 | github_token: ${{ secrets.REPO_PULL_TOKEN }} 104 | workflow_file_name: sync.yml 105 | -------------------------------------------------------------------------------- /.github/workflows/generated-pr.yml: -------------------------------------------------------------------------------- 1 | name: Close Generated PRs 2 | 3 | on: 4 | schedule: 5 | - cron: '0 0 * * *' 6 | workflow_dispatch: 7 | 8 | permissions: 9 | issues: write 10 | pull-requests: write 11 | 12 | jobs: 13 | stale: 14 | uses: ipdxco/unified-github-workflows/.github/workflows/reusable-generated-pr.yml@v1 15 | -------------------------------------------------------------------------------- /.github/workflows/semantic-pull-request.yml: -------------------------------------------------------------------------------- 1 | name: Semantic PR 2 | 3 | on: 4 | pull_request_target: 5 | types: 6 | - opened 7 | - edited 8 | - synchronize 9 | 10 | jobs: 11 | main: 12 | uses: ipdxco/unified-github-workflows/.github/workflows/reusable-semantic-pull-request.yml@v1 13 | -------------------------------------------------------------------------------- /.github/workflows/stale.yml: -------------------------------------------------------------------------------- 1 | name: Close Stale Issues 2 | 3 | on: 4 | schedule: 5 | - cron: '0 0 * * *' 6 | workflow_dispatch: 7 | 8 | permissions: 9 | issues: write 10 | pull-requests: write 11 | 12 | jobs: 13 | stale: 14 | uses: ipdxco/unified-github-workflows/.github/workflows/reusable-stale-issue.yml@v1 15 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | build 3 | dist 4 | .docs 5 | .coverage 6 | node_modules 7 | package-lock.json 8 | yarn.lock 9 | .DS_Store 10 | .next 11 | .vscode 12 | test-results 13 | playwright-report 14 | .parcel-cache 15 | .envrc 16 | .tool-versions 17 | db 18 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | Contributions are what make the open source community such an amazing place to be learn, inspire, and create. Any contributions you make are **greatly appreciated**. 4 | 5 | ## Table of Contents 6 | 7 | - [Howto](#howto) 8 | - [How to add a new example](#how-to-add-a-new-example) 9 | - [Examples must](#examples-must) 10 | - [Update `js-libp2p` to run tests against the repo](#update-js-libp2p-to-run-tests-against-the-repo) 11 | 12 | 13 | ## Howto 14 | 15 | 1. Fork the IPFS Examples Project (`https://github.com/libp2p/js-libp2p-examples`) 16 | 2. Create your Feature Branch (`git checkout -b feature/amazing-feature`) 17 | 3. Commit your Changes (`git commit -a -m 'feat: add some amazing feature'`) 18 | 4. Push to the Branch (`git push origin feature/amazing-feature`) 19 | 5. Open a Pull Request 20 | 21 | ## How to add a new example 22 | 23 | 1. Decide on a pithy folder name for your example, it should start with `js-libp2p-example-` and ideally be one or two words that describe what it's about - e.g. `js-libp2p-example-transfer-files` 24 | 1. Create a folder in this repo under `examples`, eg. `./examples/js-libp2p-example-transfer-files` 25 | 1. Add the files and tests that make up the example 26 | 1. Add the folder name to the `project-list` lists in the `examples` and `push-changes` jobs in this repositories `./github/ci.yml` 27 | 1. Create a PR to https://github.com/libp2p/github-mgmt similar to https://github.com/libp2p/github-mgmt/pull/22 to facilitate the addition of your project as an isolated repo. 28 | 29 | ## Examples must 30 | 31 | - Live inside the `/examples/` folder 32 | - Have tests and should make use of `test-ipfs-example` library 33 | - Implement the following scripts: 34 | - `clean`: used to clean all the unnecessary code (e.g.: files generated by bundlers and package managers) 35 | - `build`: used to build the example 36 | - `start`: used to start the example 37 | - `test`: used to test the example 38 | - The `README.md` must have (see example inside `example-template`): 39 | - Link to `Codesandbox.com` for one-click running demonstration 40 | - References for documentation/tutorials used to build the example 41 | - _Optional:_ Screenshots, gifs, etc... under `img/` folder 42 | - Update the CI to run the tests of the new example as standalone 43 | - Edit `github/workflows/ci.yml` 44 | - Add the test name to `project` under `matrix` 45 | 46 | ## Update `js-libp2p` to run tests against the repo 47 | 48 | Open a PR to the [libp2p/js-libp2p](https://github.com/libp2p/js-libp2p) project that edits the `.github/workflows/examples.yml` in order to make sure a libp2p release does not break your new example. 49 | 50 | Search `.github/workflows/test.yml` for the `test-examples` section and add a block at the end of the `example` matrix key similar to: 51 | 52 | ```yml 53 | - name: my super fun new example 54 | repo: https://github.com/libp2p/js-libp2p-my-super-fun-new-example.git 55 | deps: libp2p@$PWD/packages/libp2p/dist 56 | ``` 57 | 58 | The value of the `deps` key will vary depending on which modules from Helia your example uses. Above we override the `helia` module, but your example may different deps. 59 | 60 | Please see the existing setup in `.github/workflows/test.yml` for how to ensure you are overriding the correct modules. 61 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | This project is dual licensed under MIT and Apache-2.0. 2 | 3 | MIT: https://www.opensource.org/licenses/mit 4 | Apache-2.0: https://www.apache.org/licenses/license-2.0 5 | -------------------------------------------------------------------------------- /LICENSE-APACHE: -------------------------------------------------------------------------------- 1 | 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 2 | 3 | http://www.apache.org/licenses/LICENSE-2.0 4 | 5 | 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. 6 | -------------------------------------------------------------------------------- /LICENSE-MIT: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | libp2p hex logo 4 | 5 |

6 | 7 |

A collection of js-libp2p examples

8 | 9 |

10 | 11 |
12 | Explore the docs 13 | · 14 | Report Bug 15 | · 16 | Request Feature/Example 17 |

18 | 19 | ## Table of Contents 20 | 21 | - [About The Project](#about-the-project) 22 | - [Getting Started](#getting-started) 23 | - [Prerequisites](#prerequisites) 24 | - [Understanding how libp2p works](#understanding-how-libp2p-works) 25 | - [Other examples](#other-examples) 26 | - [Contribute](#contribute) 27 | - [License](#license) 28 | 29 | ## About The Project 30 | 31 | - Read the [js-libp2p documentation](https://github.com/libp2p/js-libp2p/tree/main/doc) 32 | - Check out the [js-libp2p API docs](https://libp2p.github.io/js-libp2p/) 33 | - Check out the [general libp2p documentation](https://docs.libp2p.io) for tips, how-tos and more 34 | - Read the [libp2p specs](https://github.com/libp2p/specs) 35 | - See https://blog.libp2p.io for news and more 36 | - Head over to https://proto.school to take interactive tutorials that cover core libp2p APIs 37 | - Need help? Visit the discussion board: https://github.com/libp2p/js-libp2p/discussions 38 | 39 | ## Getting Started 40 | 41 | Feel free to jump directly into the examples, however going through the following sections will help build context and background knowledge. 42 | 43 | ### Prerequisites 44 | 45 | Make sure you have installed all of the following prerequisites on your development machine: 46 | 47 | - Git - [Download & Install Git](https://git-scm.com/downloads). OSX and Linux machines typically have this already installed. 48 | - Node.js - [Download & Install Node.js](https://nodejs.org/en/download/) and the npm package manager. 49 | 50 | ### Understanding how libp2p works 51 | 52 | - [Circuit Relay](https://github.com/libp2p/js-libp2p-example-circuit-relay) - configuring Circuit Relay connections 53 | - [Connection Encryption](https://github.com/libp2p/js-libp2p-example-connection-encryption) - how to encrypt connection between libp2p nodes 54 | - [Delegated routing](https://github.com/libp2p/js-libp2p-example-delegated-routing) - how to offload network operations and queries onto more capable nodes 55 | - [Discovery mechanisms](https://github.com/libp2p/js-libp2p-example-discovery-mechanisms) - how libp2p discovers other peers on the network 56 | - [Custom protocols](https://github.com/libp2p/js-libp2p-example-custom-protocols) - how to create a custom protocol for your application 57 | - [Transports](https://github.com/libp2p/js-libp2p-example-transports) - how to connect peers together via different transports 58 | - [WebRTC](https://github.com/libp2p/js-libp2p-example-webrtc-private-to-private) - a special transport for connecting browsers together 59 | 60 | ### Other examples 61 | 62 | These are demo apps or examples that showcase specific modules or services: 63 | 64 | - [Chat](https://github.com/libp2p/js-libp2p-example-chat) - a simple chat app 65 | - [Browser Pub/Sub](https://github.com/libp2p/js-libp2p-example-browser-pubsub) - Using Pub/Sub between browsers 66 | 67 | There is also [universal connectivity](https://github.com/libp2p/universal-connectivity/tree/main) demo that shows of how many different libp2p implementations can be connected together. 68 | 69 | ## Contribute 70 | 71 | See [CONTRIBUTING.md](https://github.com/libp2p/js-libp2p-examples/blob/main/CONTRIBUTING.md). 72 | 73 | ## License 74 | 75 | Licensed under either of 76 | 77 | - Apache 2.0, ([LICENSE-APACHE](https://github.com/libp2p/js-libp2p-examples/blob/main/LICENSE-APACHE) / ) 78 | - MIT ([LICENSE-MIT](https://github.com/libp2p/js-libp2p-examples/blob/main/LICENSE-MIT) / ) 79 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-auto-tls/.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | # ⚠️ IMPORTANT ⚠️ 2 | 3 | # Please do not create a Pull Request for this repository 4 | 5 | The contents of this repository are automatically synced from the parent [js-libp2p Examples Project](https://github.com/libp2p/js-libp2p-examples) so any changes made to the standalone repository will be lost after the next sync. 6 | 7 | Please open a PR against [js-libp2p Examples](https://github.com/libp2p/js-libp2p-examples) instead. 8 | 9 | ## Contributing 10 | 11 | Contributions are what make the open source community such an amazing place to be learn, inspire, and create. Any contributions you make are **greatly appreciated**. 12 | 13 | 1. Fork the [js-libp2p Examples Project](https://github.com/libp2p/js-libp2p-examples) 14 | 2. Create your Feature Branch (`git checkout -b feature/amazing-example`) 15 | 3. Commit your Changes (`git commit -a -m 'feat: add some amazing example'`) 16 | 4. Push to the Branch (`git push origin feature/amazing-example`) 17 | 5. Open a Pull Request 18 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-auto-tls/.github/workflows/sync.yml: -------------------------------------------------------------------------------- 1 | name: pull 2 | 3 | on: 4 | workflow_dispatch 5 | 6 | jobs: 7 | sync: 8 | runs-on: ubuntu-latest 9 | steps: 10 | - uses: actions/checkout@v2 11 | - name: Pull from another repository 12 | uses: ipfs-examples/actions-pull-directory-from-repo@main 13 | with: 14 | source-repo: libp2p/js-libp2p-examples 15 | source-folder-path: examples/${{ github.event.repository.name }} 16 | source-branch: main 17 | target-branch: main 18 | git-username: github-actions 19 | git-email: github-actions@github.com 20 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-auto-tls/LICENSE: -------------------------------------------------------------------------------- 1 | This project is dual licensed under MIT and Apache-2.0. 2 | 3 | MIT: https://www.opensource.org/licenses/mit 4 | Apache-2.0: https://www.apache.org/licenses/license-2.0 5 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-auto-tls/LICENSE-APACHE: -------------------------------------------------------------------------------- 1 | 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 2 | 3 | http://www.apache.org/licenses/LICENSE-2.0 4 | 5 | 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. 6 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-auto-tls/LICENSE-MIT: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-auto-tls/auto-confirm.js: -------------------------------------------------------------------------------- 1 | /* eslint no-console: ["off"] */ 2 | 3 | /* eslint-env mocha */ 4 | 5 | import { noise } from '@chainsafe/libp2p-noise' 6 | import { yamux } from '@chainsafe/libp2p-yamux' 7 | import { autoTLS } from '@ipshipyard/libp2p-auto-tls' 8 | import { loadOrCreateSelfKey } from '@libp2p/config' 9 | import { identify, identifyPush } from '@libp2p/identify' 10 | import { keychain } from '@libp2p/keychain' 11 | import { uPnPNAT } from '@libp2p/upnp-nat' 12 | import { webSockets } from '@libp2p/websockets' 13 | import { WebSocketsSecure } from '@multiformats/multiaddr-matcher' 14 | import { LevelDatastore } from 'datastore-level' 15 | import { createLibp2p } from 'libp2p' 16 | 17 | const datastore = new LevelDatastore('./db') 18 | await datastore.open() 19 | 20 | const privateKey = await loadOrCreateSelfKey(datastore) 21 | 22 | const libp2p = await createLibp2p({ 23 | privateKey, 24 | datastore, 25 | addresses: { 26 | listen: [ 27 | '/ip4/0.0.0.0/tcp/0/ws', 28 | '/ip6/::/tcp/0/ws' 29 | ] 30 | }, 31 | transports: [ 32 | webSockets() 33 | ], 34 | connectionEncrypters: [ 35 | noise() 36 | ], 37 | streamMuxers: [ 38 | yamux() 39 | ], 40 | services: { 41 | // needed to run KAD-DHT and to be contacted by libp2p.direct 42 | identify: identify(), 43 | identifyPush: identifyPush(), 44 | 45 | // used to securely store the certificate for use after a restart 46 | keychain: keychain(), 47 | 48 | // requests a certificate and makes it available to libp2p, trusts that 49 | // `libp2p.direct` will answer DNS requests successfully 50 | autoTLS: autoTLS({ 51 | autoConfirmAddress: true 52 | }), 53 | 54 | // opens ports on your router to allow libp2p.direct to dial us back - N.b 55 | // uPNP must be enabled for this to work. Trusts that network traffic will 56 | // reach us after this is done. 57 | uPnPNAT: uPnPNAT({ 58 | autoConfirmAddress: true 59 | }) 60 | } 61 | }) 62 | 63 | libp2p.addEventListener('certificate:provision', () => { 64 | console.info('A TLS certificate was provisioned') 65 | 66 | const interval = setInterval(() => { 67 | const mas = libp2p 68 | .getMultiaddrs() 69 | .filter(ma => WebSocketsSecure.exactMatch(ma) && ma.toString().includes('/sni/')) 70 | .map(ma => ma.toString()) 71 | 72 | if (mas.length > 0) { 73 | console.info('addresses:') 74 | console.info(mas.join('\n')) 75 | clearInterval(interval) 76 | } 77 | }, 1_000) 78 | }) 79 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-auto-tls/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@libp2p/example-auto-tls", 3 | "version": "0.0.0", 4 | "description": "How to get a TLS certificate automatically", 5 | "license": "Apache-2.0 OR MIT", 6 | "homepage": "https://github.com/libp2p/js-libp2p-examples/tree/master/examples/js-libp2p-example-pnet#readme", 7 | "repository": { 8 | "type": "git", 9 | "url": "git+https://github.com/libp2p/js-libp2p-examples.git" 10 | }, 11 | "bugs": { 12 | "url": "https://github.com/libp2p/js-libp2p-examples/issues" 13 | }, 14 | "scripts": { 15 | "test": "echo 'Cannot test in CI'" 16 | }, 17 | "type": "module", 18 | "dependencies": { 19 | "@chainsafe/libp2p-noise": "^16.0.0", 20 | "@chainsafe/libp2p-yamux": "^7.0.0", 21 | "@ipshipyard/libp2p-auto-tls": "^1.0.0", 22 | "@libp2p/autonat": "^2.0.13", 23 | "@libp2p/bootstrap": "^11.0.14", 24 | "@libp2p/config": "^1.0.0", 25 | "@libp2p/identify": "^3.0.13", 26 | "@libp2p/kad-dht": "^15.0.0", 27 | "@libp2p/keychain": "^5.0.11", 28 | "@libp2p/ping": "^2.0.27", 29 | "@libp2p/upnp-nat": "^3.0.1", 30 | "@libp2p/websockets": "^9.1.0", 31 | "@multiformats/multiaddr-matcher": "^1.6.0", 32 | "datastore-level": "^11.0.1", 33 | "libp2p": "^2.0.0" 34 | }, 35 | "private": true 36 | } 37 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-auto-tls/trust-free.js: -------------------------------------------------------------------------------- 1 | /* eslint no-console: ["off"] */ 2 | 3 | /* eslint-env mocha */ 4 | 5 | import { noise } from '@chainsafe/libp2p-noise' 6 | import { yamux } from '@chainsafe/libp2p-yamux' 7 | import { autoTLS } from '@ipshipyard/libp2p-auto-tls' 8 | import { autoNAT } from '@libp2p/autonat' 9 | import { bootstrap } from '@libp2p/bootstrap' 10 | import { loadOrCreateSelfKey } from '@libp2p/config' 11 | import { identify, identifyPush } from '@libp2p/identify' 12 | import { kadDHT, removePrivateAddressesMapper } from '@libp2p/kad-dht' 13 | import { keychain } from '@libp2p/keychain' 14 | import { ping } from '@libp2p/ping' 15 | import { tcp } from '@libp2p/tcp' 16 | import { uPnPNAT } from '@libp2p/upnp-nat' 17 | import { webSockets } from '@libp2p/websockets' 18 | import { WebSocketsSecure } from '@multiformats/multiaddr-matcher' 19 | import { LevelDatastore } from 'datastore-level' 20 | import { createLibp2p } from 'libp2p' 21 | 22 | const datastore = new LevelDatastore('./db') 23 | await datastore.open() 24 | 25 | const privateKey = await loadOrCreateSelfKey(datastore) 26 | 27 | const libp2p = await createLibp2p({ 28 | privateKey, 29 | datastore, 30 | addresses: { 31 | listen: [ 32 | '/ip4/0.0.0.0/tcp/0/ws', 33 | '/ip6/::/tcp/0/ws' 34 | ] 35 | }, 36 | transports: [ 37 | webSockets(), 38 | tcp() 39 | ], 40 | connectionEncrypters: [ 41 | noise() 42 | ], 43 | streamMuxers: [ 44 | yamux() 45 | ], 46 | services: { 47 | // needed to run KAD-DHT and to be contacted by libp2p.direct 48 | identify: identify(), 49 | identifyPush: identifyPush(), 50 | ping: ping(), 51 | 52 | // used to securely store the certificate for use after a restart 53 | keychain: keychain(), 54 | 55 | // requests a certificate and makes it available to libp2p 56 | autoTLS: autoTLS(), 57 | 58 | // opens ports on your router to allow libp2p.direct to dial us back - N.b 59 | // uPNP must be enabled for this to work 60 | uPnPNAT: uPnPNAT(), 61 | 62 | // verifies that our reported public addresses are dialable 63 | autoNAT: autoNAT(), 64 | 65 | // used to find peers to run AutoNAT 66 | aminoDHT: kadDHT({ 67 | protocol: '/ipfs/kad/1.0.0', 68 | peerInfoMapper: removePrivateAddressesMapper 69 | }), 70 | 71 | // these peers help us fill our DHT routing table 72 | bootstrap: bootstrap({ 73 | list: [ 74 | '/dnsaddr/bootstrap.libp2p.io/p2p/QmNnooDu7bfjPFoTZYxMNLWUQJyrVwtbZg5gBMjTezGAJN', 75 | '/dnsaddr/bootstrap.libp2p.io/p2p/QmbLHAnMoJPWSCR5Zhtx6BHJX9KiKNN6tpvbUcqanj75Nb', 76 | '/dnsaddr/bootstrap.libp2p.io/p2p/QmcZf59bWwK5XFi76CZX8cbJ4BhTzzA3gU1ZjYZcYW3dwt', 77 | '/dnsaddr/va1.bootstrap.libp2p.io/p2p/12D3KooWKnDdG3iXw9eTFijk3EWSunZcFi54Zka4wmtqtt6rPxc8', 78 | '/ip4/104.131.131.82/tcp/4001/p2p/QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ' 79 | ] 80 | }) 81 | } 82 | }) 83 | 84 | libp2p.addEventListener('certificate:provision', () => { 85 | console.info('A TLS certificate was provisioned') 86 | 87 | const interval = setInterval(() => { 88 | const mas = libp2p 89 | .getMultiaddrs() 90 | .filter(ma => WebSocketsSecure.exactMatch(ma) && ma.toString().includes('/sni/')) 91 | .map(ma => ma.toString()) 92 | 93 | if (mas.length > 0) { 94 | console.info('addresses:') 95 | console.info(mas.join('\n')) 96 | clearInterval(interval) 97 | } 98 | }, 1_000) 99 | }) 100 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-browser-pubsub/.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | # ⚠️ IMPORTANT ⚠️ 2 | 3 | # Please do not create a Pull Request for this repository 4 | 5 | The contents of this repository are automatically synced from the parent [js-libp2p Examples Project](https://github.com/libp2p/js-libp2p-examples) so any changes made to the standalone repository will be lost after the next sync. 6 | 7 | Please open a PR against [js-libp2p Examples](https://github.com/libp2p/js-libp2p-examples) instead. 8 | 9 | ## Contributing 10 | 11 | Contributions are what make the open source community such an amazing place to be learn, inspire, and create. Any contributions you make are **greatly appreciated**. 12 | 13 | 1. Fork the [js-libp2p Examples Project](https://github.com/libp2p/js-libp2p-examples) 14 | 2. Create your Feature Branch (`git checkout -b feature/amazing-example`) 15 | 3. Commit your Changes (`git commit -a -m 'feat: add some amazing example'`) 16 | 4. Push to the Branch (`git push origin feature/amazing-example`) 17 | 5. Open a Pull Request 18 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-browser-pubsub/.github/workflows/sync.yml: -------------------------------------------------------------------------------- 1 | name: pull 2 | 3 | on: 4 | workflow_dispatch 5 | 6 | jobs: 7 | sync: 8 | runs-on: ubuntu-latest 9 | steps: 10 | - uses: actions/checkout@v2 11 | - name: Pull from another repository 12 | uses: ipfs-examples/actions-pull-directory-from-repo@main 13 | with: 14 | source-repo: libp2p/js-libp2p-examples 15 | source-folder-path: examples/${{ github.event.repository.name }} 16 | source-branch: main 17 | target-branch: main 18 | git-username: github-actions 19 | git-email: github-actions@github.com 20 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-browser-pubsub/LICENSE: -------------------------------------------------------------------------------- 1 | This project is dual licensed under MIT and Apache-2.0. 2 | 3 | MIT: https://www.opensource.org/licenses/mit 4 | Apache-2.0: https://www.apache.org/licenses/license-2.0 5 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-browser-pubsub/LICENSE-APACHE: -------------------------------------------------------------------------------- 1 | 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 2 | 3 | http://www.apache.org/licenses/LICENSE-2.0 4 | 5 | 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. 6 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-browser-pubsub/LICENSE-MIT: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-browser-pubsub/README.md: -------------------------------------------------------------------------------- 1 | # @libp2p/example-browser-pubsub 2 | 3 | [![libp2p.io](https://img.shields.io/badge/project-libp2p-yellow.svg?style=flat-square)](http://libp2p.io/) 4 | [![Discuss](https://img.shields.io/discourse/https/discuss.libp2p.io/posts.svg?style=flat-square)](https://discuss.libp2p.io) 5 | [![codecov](https://img.shields.io/codecov/c/github/libp2p/js-libp2p-examples.svg?style=flat-square)](https://codecov.io/gh/libp2p/js-libp2p-examples) 6 | [![CI](https://img.shields.io/github/actions/workflow/status/libp2p/js-libp2p-examples/ci.yml?branch=main\&style=flat-square)](https://github.com/libp2p/js-libp2p-examples/actions/workflows/ci.yml?query=branch%3Amain) 7 | 8 | > User libp2p pubsub in browsers 9 | 10 | This example leverages the [vite bundler](https://vitejs.dev/) to compile and serve the libp2p code in the browser. You can use other bundlers such as Webpack, but we will not be covering them here. 11 | 12 | ## Table of contents 13 | 14 | - [Setup](#setup) 15 | - [Running](#running) 16 | - [Why do I need a Relay Server?](#why-do-i-need-a-relay-server) 17 | - [Start the Relay Server](#start-the-relay-server) 18 | - [Running the Example](#running-the-example) 19 | - [Need help?](#need-help) 20 | - [License](#license) 21 | - [Contribution](#contribution) 22 | 23 | ## Setup 24 | 25 | 1. Install example dependencies 26 | ```console 27 | $ npm install 28 | ``` 29 | 2. Open 2 terminal windows in the `./src` directory. 30 | 31 | ## Running 32 | 33 | This example has three components. Two browser windows which will send pubsub messages and a relay server that they will use to establish the initial connection. 34 | 35 | ### Why do I need a Relay Server? 36 | 37 | The only transport available to browser nodes that lets them be dialed by remote peers is the [WebRTC](https://www.npmjs.com/package/@libp2p/webrtc) transport. 38 | 39 | This transport requires an initial [handshake](https://en.wikipedia.org/wiki/Session_Description_Protocol) to be done out-of-band, during which the two peers exchange their capabilities, addresses and open ports. 40 | 41 | We use a [Circuit Relay](https://docs.libp2p.io/concepts/nat/circuit-relay/) server to establish an initial communication channel between the two browsers for this process, after which they will have negotiated a peer-to-peer connection and the relay will no longer be used. 42 | 43 | ```mermaid 44 | sequenceDiagram 45 | Browser A->>Relay: Create reservation 46 | activate Relay 47 | Browser B->>Relay: Dial Browser A 48 | Relay->>Browser A: Relayed dial from Browser B 49 | Browser B->>Relay: WebRTC handshake request 50 | Relay->>Browser A: Relayed WebRTC handshake request 51 | Browser A->>Relay: WebRTC handshake response 52 | Relay->>Browser B: Relayed WebRTC handshake response 53 | deactivate Relay 54 | Browser B->>Browser A: WebRTC connection 55 | ``` 56 | 57 | ### Start the Relay Server 58 | 59 | For browsers to communicate, we first need to run the libp2p relay server: 60 | 61 | ```console 62 | $ npm run relay 63 | ``` 64 | 65 | Copy one of the multiaddresses in the output. 66 | 67 | ### Running the Example 68 | 69 | Start the Vite server: 70 | 71 | ```console 72 | $ npm start 73 | ``` 74 | 75 | A browser window will automatically open. Let's call this `Browser A`. 76 | 77 | 1. Paste the copied multiaddress from the relay server, paste it into the `Dial MultiAddr` input and click the `Connect` button 78 | 2. `Browser A` is now connected to the relay server 79 | 3. Copy the multiaddress located after the `Listening on` message 80 | 81 | Now open a second browser with the url `http://localhost:5173/`. Let's call this `Browser B`. 82 | 83 | 1. Using the copied multiaddress from `Listening on` section in `Browser A`, paste it into the `Remote MultiAddress` input and click the `Connect` button 84 | 2. `Browser B` is now connected to `Browser A` 85 | 86 | You can now shut down the relay server if you wish. 87 | 88 | 1. In both `Browser A` and `Browser B`, enter the same topic name in the "Subscribe to topic" input and click the "Subscribe" button 89 | 2. In either browser, enter a message in the `Send Message to Topic` field and click "Send" 90 | 91 | You should see the message appear in the output section towards the bottom of the other browser window. 92 | 93 | ## Need help? 94 | 95 | - Read the [js-libp2p documentation](https://github.com/libp2p/js-libp2p/tree/main/doc) 96 | - Check out the [js-libp2p API docs](https://libp2p.github.io/js-libp2p/) 97 | - Check out the [general libp2p documentation](https://docs.libp2p.io) for tips, how-tos and more 98 | - Read the [libp2p specs](https://github.com/libp2p/specs) 99 | - Ask a question on the [js-libp2p discussion board](https://github.com/libp2p/js-libp2p/discussions) 100 | 101 | ## License 102 | 103 | Licensed under either of 104 | 105 | - Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) 106 | - MIT ([LICENSE-MIT](LICENSE-MIT) / ) 107 | 108 | ## Contribution 109 | 110 | Unless you explicitly state otherwise, any contribution intentionally submitted 111 | for inclusion in the work by you, as defined in the Apache-2.0 license, shall be 112 | dual licensed as above, without any additional terms or conditions. 113 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-browser-pubsub/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | js-libp2p browser pubsub 7 | 24 | 25 | 26 |

libp2p Browser PubSub example

27 |

This example demonstrates the pubsub API running in a browser

28 |
    29 |
  1. Start a relay using the command line:
    $ node ./relay.js
    30 | Relay listening on multiaddr(s):  [
    31 |   '${multiaddr}'
    32 | ]
    33 |       
  2. 34 |
  3. Copy the relay's multiaddr and use the "Dial Multaddr" section to dial the relay
  4. 35 |
  5. Wait for a WebRTC address to appear in the "Listening Addresses" area
  6. 36 |
  7. Open the same page in another browser window
  8. 37 |
  9. Use the "Dial Multiaddr" section in the second window to dial the WebRTC address from the first
  10. 38 |
  11. Subscribe both windows to the same topic using the "PubSub" section
  12. 39 |
  13. Send messages between the windows using the "PubSub" section
  14. 40 |
41 |
42 |
43 |

Node

44 | 45 | 46 | 47 | 48 |

PeerId

49 |

50 | 51 |

Listening Addresses

52 |
    53 |
  • None
  • 54 |
55 | 56 |

Connected Peers

57 |
    58 |
  • None
  • 59 |
60 |
61 |
62 |
63 |

PubSub

64 | 65 | 66 | 67 | 68 |

Topic Peers

69 |
    70 |
  • None
  • 71 |
72 | 73 | 74 | 75 | 76 |
77 |
78 |
79 |

Output

80 |

81 |     
82 | 83 | 84 | 85 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-browser-pubsub/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@libp2p/example-browser-pubsub", 3 | "version": "1.0.0", 4 | "description": "How to use libp2p pubsub in browsers", 5 | "license": "Apache-2.0 OR MIT", 6 | "homepage": "https://github.com/libp2p/js-libp2p-example-browser-pubsub#readme", 7 | "repository": { 8 | "type": "git", 9 | "url": "git+https://github.com/libp2p/js-libp2p-examples.git" 10 | }, 11 | "bugs": { 12 | "url": "https://github.com/libp2p/js-libp2p-examples/issues" 13 | }, 14 | "type": "module", 15 | "scripts": { 16 | "start": "vite", 17 | "build": "vite build", 18 | "relay": "node relay.js", 19 | "test:firefox": "npm run build && playwright test --browser=firefox test", 20 | "test:chrome": "npm run build && playwright test test", 21 | "test": "npm run build && test-browser-example test" 22 | }, 23 | "dependencies": { 24 | "@chainsafe/libp2p-gossipsub": "^14.0.0", 25 | "@chainsafe/libp2p-noise": "^16.0.0", 26 | "@chainsafe/libp2p-yamux": "^7.0.0", 27 | "@libp2p/circuit-relay-v2": "^3.0.0", 28 | "@libp2p/dcutr": "^2.0.0", 29 | "@libp2p/identify": "^3.0.0", 30 | "@libp2p/webrtc": "^5.0.0", 31 | "@libp2p/websockets": "^9.0.0", 32 | "@multiformats/multiaddr": "^12.3.1", 33 | "libp2p": "^2.0.0", 34 | "vite": "^6.0.3" 35 | }, 36 | "devDependencies": { 37 | "test-ipfs-example": "^1.0.0" 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-browser-pubsub/relay.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | 3 | import { noise } from '@chainsafe/libp2p-noise' 4 | import { yamux } from '@chainsafe/libp2p-yamux' 5 | import { circuitRelayServer } from '@libp2p/circuit-relay-v2' 6 | import { identify } from '@libp2p/identify' 7 | import { webSockets } from '@libp2p/websockets' 8 | import * as filters from '@libp2p/websockets/filters' 9 | import { createLibp2p } from 'libp2p' 10 | 11 | const server = await createLibp2p({ 12 | addresses: { 13 | listen: ['/ip4/127.0.0.1/tcp/0/ws'] 14 | }, 15 | transports: [ 16 | webSockets({ 17 | filter: filters.all 18 | }) 19 | ], 20 | connectionEncrypters: [noise()], 21 | streamMuxers: [yamux()], 22 | services: { 23 | identify: identify(), 24 | relay: circuitRelayServer({ 25 | reservations: { 26 | maxReservations: Infinity 27 | } 28 | }) 29 | } 30 | }) 31 | 32 | console.log('Relay listening on multiaddr(s): ', server.getMultiaddrs().map((ma) => ma.toString())) 33 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-browser-pubsub/test/index.spec.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | import { noise } from '@chainsafe/libp2p-noise' 3 | import { yamux } from '@chainsafe/libp2p-yamux' 4 | import { circuitRelayServer } from '@libp2p/circuit-relay-v2' 5 | import { identify } from '@libp2p/identify' 6 | import { webSockets } from '@libp2p/websockets' 7 | import * as filters from '@libp2p/websockets/filters' 8 | import { createLibp2p } from 'libp2p' 9 | import { setup, expect } from 'test-ipfs-example/browser' 10 | 11 | // Setup 12 | const test = setup() 13 | 14 | // DOM 15 | const connectBtn = '#dial-multiaddr-button' 16 | const connectAddr = '#dial-multiaddr-input' 17 | const sendMessageInput = '#send-topic-message-input' 18 | const sendMessageBtn = '#send-topic-message-button' 19 | const output = '#output' 20 | const listeningAddresses = '#listening-addresses' 21 | const subscribeInput = '#subscribe-topic-input' 22 | const subscribeBtn = '#subscribe-topic-button' 23 | const topicPeers = '#topic-peers' 24 | const peerId = '#peer-id' 25 | 26 | let url 27 | 28 | // we spawn a js libp2p relay 29 | async function spawnRelay () { 30 | const relayNode = await createLibp2p({ 31 | addresses: { 32 | listen: ['/ip4/127.0.0.1/tcp/0/ws'] 33 | }, 34 | transports: [ 35 | webSockets({ 36 | filter: filters.all 37 | }) 38 | ], 39 | connectionEncrypters: [noise()], 40 | streamMuxers: [yamux()], 41 | services: { 42 | identify: identify(), 43 | relay: circuitRelayServer() 44 | } 45 | }) 46 | 47 | const relayNodeAddr = relayNode.getMultiaddrs()[0].toString() 48 | 49 | return { relayNode, relayNodeAddr } 50 | } 51 | 52 | test.describe('pubsub browser example:', () => { 53 | let relayNode 54 | let relayNodeAddr 55 | 56 | // eslint-disable-next-line no-empty-pattern 57 | test.beforeAll(async ({ servers }, testInfo) => { 58 | testInfo.setTimeout(5 * 60_000) 59 | const r = await spawnRelay() 60 | relayNode = r.relayNode 61 | relayNodeAddr = r.relayNodeAddr 62 | url = servers[0].url 63 | }, {}) 64 | 65 | test.afterAll(() => { 66 | relayNode.stop() 67 | }) 68 | 69 | test.beforeEach(async ({ page }) => { 70 | await page.goto(url) 71 | }) 72 | 73 | test('should connect via a relay node', async ({ page: pageA, context }) => { 74 | // load second page 75 | const pageB = await context.newPage() 76 | await pageB.goto(url) 77 | 78 | // load page peer ids 79 | const pageAPeerId = await pageA.textContent(peerId) 80 | const pageBPeerId = await pageB.textContent(peerId) 81 | 82 | // connect the first page to the relay 83 | const webRTCAddressA = await dialRelay(pageA, relayNodeAddr) 84 | 85 | // dial first page from second page over relay 86 | await dialPeerOverRelay(pageB, webRTCAddressA) 87 | 88 | // stop the relay 89 | await relayNode.stop() 90 | 91 | const topicName = `topic-${Date.now()}` 92 | 93 | // subscribe to pubsub topic 94 | await subscribeToTopic(pageA, topicName) 95 | await subscribeToTopic(pageB, topicName) 96 | 97 | // wait for peers to appear in topic peers 98 | await waitForTopicPeers(pageA, pageBPeerId) 99 | await waitForTopicPeers(pageB, pageAPeerId) 100 | 101 | // send a message from one to the other 102 | await sendMessage(pageA, 'hello A', pageB) 103 | }) 104 | }) 105 | 106 | async function subscribeToTopic (page, topic) { 107 | // subscribe to the topic 108 | await page.fill(subscribeInput, topic) 109 | await page.click(subscribeBtn) 110 | 111 | // check the message was echoed back 112 | const outputLocator = page.locator(output) 113 | await expect(outputLocator).toContainText(`Subscribing to '${topic}'`) 114 | } 115 | 116 | async function waitForTopicPeers (page, otherPeer) { 117 | const outputLocator = page.locator(topicPeers) 118 | await expect(outputLocator).toContainText(otherPeer) 119 | } 120 | 121 | async function sendMessage (pageA, message, pageB) { 122 | // subscribe to the topic 123 | await pageA.fill(sendMessageInput, message) 124 | await pageA.click(sendMessageBtn) 125 | 126 | // check the message was received 127 | const outputLocator = pageB.locator(output) 128 | await expect(outputLocator).toContainText(message) 129 | } 130 | 131 | async function dialRelay (page, address) { 132 | // add the relay multiaddr to the input field and submit 133 | await page.fill(connectAddr, address) 134 | await page.click(connectBtn) 135 | 136 | const outputLocator = page.locator(output) 137 | await expect(outputLocator).toContainText(`Dialing '${address}'`) 138 | await expect(outputLocator).toContainText(`Connected to '${address}'`) 139 | 140 | const multiaddrsLocator = page.locator(listeningAddresses) 141 | await expect(multiaddrsLocator).toHaveText(/webrtc/) 142 | 143 | const multiaddrs = await page.textContent(listeningAddresses) 144 | const addr = multiaddrs.split(address).filter(str => str.includes('webrtc')).pop() 145 | 146 | return address + addr 147 | } 148 | 149 | async function dialPeerOverRelay (page, address) { 150 | // add the go libp2p multiaddr to the input field and submit 151 | await page.fill(connectAddr, address) 152 | await page.click(connectBtn) 153 | 154 | const outputLocator = page.locator(output) 155 | await expect(outputLocator).toContainText(`Dialing '${address}'`) 156 | await expect(outputLocator).toContainText(`Connected to '${address}'`) 157 | } 158 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-browser-pubsub/vite.config.js: -------------------------------------------------------------------------------- 1 | export default { 2 | build: { 3 | target: 'es2022' 4 | }, 5 | optimizeDeps: { 6 | esbuildOptions: { target: 'es2022', supported: { bigint: true } } 7 | }, 8 | server: { 9 | open: true 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-chat/.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | # ⚠️ IMPORTANT ⚠️ 2 | 3 | # Please do not create a Pull Request for this repository 4 | 5 | The contents of this repository are automatically synced from the parent [js-libp2p Examples Project](https://github.com/libp2p/js-libp2p-examples) so any changes made to the standalone repository will be lost after the next sync. 6 | 7 | Please open a PR against [js-libp2p Examples](https://github.com/libp2p/js-libp2p-examples) instead. 8 | 9 | ## Contributing 10 | 11 | Contributions are what make the open source community such an amazing place to be learn, inspire, and create. Any contributions you make are **greatly appreciated**. 12 | 13 | 1. Fork the [js-libp2p Examples Project](https://github.com/libp2p/js-libp2p-examples) 14 | 2. Create your Feature Branch (`git checkout -b feature/amazing-example`) 15 | 3. Commit your Changes (`git commit -a -m 'feat: add some amazing example'`) 16 | 4. Push to the Branch (`git push origin feature/amazing-example`) 17 | 5. Open a Pull Request 18 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-chat/.github/workflows/sync.yml: -------------------------------------------------------------------------------- 1 | name: pull 2 | 3 | on: 4 | workflow_dispatch 5 | 6 | jobs: 7 | sync: 8 | runs-on: ubuntu-latest 9 | steps: 10 | - uses: actions/checkout@v2 11 | - name: Pull from another repository 12 | uses: ipfs-examples/actions-pull-directory-from-repo@main 13 | with: 14 | source-repo: libp2p/js-libp2p-examples 15 | source-folder-path: examples/${{ github.event.repository.name }} 16 | source-branch: main 17 | target-branch: main 18 | git-username: github-actions 19 | git-email: github-actions@github.com 20 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-chat/LICENSE: -------------------------------------------------------------------------------- 1 | This project is dual licensed under MIT and Apache-2.0. 2 | 3 | MIT: https://www.opensource.org/licenses/mit 4 | Apache-2.0: https://www.apache.org/licenses/license-2.0 5 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-chat/LICENSE-APACHE: -------------------------------------------------------------------------------- 1 | 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 2 | 3 | http://www.apache.org/licenses/LICENSE-2.0 4 | 5 | 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. 6 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-chat/LICENSE-MIT: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-chat/README.md: -------------------------------------------------------------------------------- 1 | # @libp2p/example-chat 2 | 3 | [![libp2p.io](https://img.shields.io/badge/project-libp2p-yellow.svg?style=flat-square)](http://libp2p.io/) 4 | [![Discuss](https://img.shields.io/discourse/https/discuss.libp2p.io/posts.svg?style=flat-square)](https://discuss.libp2p.io) 5 | [![codecov](https://img.shields.io/codecov/c/github/libp2p/js-libp2p-examples.svg?style=flat-square)](https://codecov.io/gh/libp2p/js-libp2p-examples) 6 | [![CI](https://img.shields.io/github/actions/workflow/status/libp2p/js-libp2p-examples/ci.yml?branch=main\&style=flat-square)](https://github.com/libp2p/js-libp2p-examples/actions/workflows/ci.yml?query=branch%3Amain) 7 | 8 | > An example chat app using libp2p 9 | 10 | ## Table of contents 11 | 12 | - [Setup](#setup) 13 | - [Running](#running) 14 | - [Need help?](#need-help) 15 | - [License](#license) 16 | - [Contribution](#contribution) 17 | 18 | ## Setup 19 | 20 | 1. Install example dependencies 21 | ```console 22 | $ npm install 23 | ``` 24 | 2. Open 2 terminal windows in the `./src` directory. 25 | 26 | ## Running 27 | 28 | 1. Run the listener in window 1, `node listener.js` 29 | 2. Run the dialer in window 2, `node dialer.js` 30 | 3. Wait until the two peers discover each other 31 | 4. Type a message in either window and hit *enter* 32 | 5. Tell yourself secrets to your hearts content! 33 | 34 | ## Need help? 35 | 36 | - Read the [js-libp2p documentation](https://github.com/libp2p/js-libp2p/tree/main/doc) 37 | - Check out the [js-libp2p API docs](https://libp2p.github.io/js-libp2p/) 38 | - Check out the [general libp2p documentation](https://docs.libp2p.io) for tips, how-tos and more 39 | - Read the [libp2p specs](https://github.com/libp2p/specs) 40 | - Ask a question on the [js-libp2p discussion board](https://github.com/libp2p/js-libp2p/discussions) 41 | 42 | ## License 43 | 44 | Licensed under either of 45 | 46 | - Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) 47 | - MIT ([LICENSE-MIT](LICENSE-MIT) / ) 48 | 49 | ## Contribution 50 | 51 | Unless you explicitly state otherwise, any contribution intentionally submitted 52 | for inclusion in the work by you, as defined in the Apache-2.0 license, shall be 53 | dual licensed as above, without any additional terms or conditions. 54 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-chat/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@libp2p/example-chat", 3 | "version": "0.0.0", 4 | "description": "An example chat app using libp2p", 5 | "license": "Apache-2.0 OR MIT", 6 | "homepage": "https://github.com/libp2p/js-libp2p-example-chat#readme", 7 | "repository": { 8 | "type": "git", 9 | "url": "git+https://github.com/libp2p/js-libp2p-examples.git" 10 | }, 11 | "bugs": { 12 | "url": "https://github.com/libp2p/js-libp2p-examples/issues" 13 | }, 14 | "type": "module", 15 | "scripts": { 16 | "test": "test-node-example test/*" 17 | }, 18 | "dependencies": { 19 | "@chainsafe/libp2p-noise": "^16.0.0", 20 | "@chainsafe/libp2p-yamux": "^7.0.0", 21 | "@libp2p/mdns": "^11.0.1", 22 | "@libp2p/tcp": "^10.0.0", 23 | "@libp2p/websockets": "^9.0.0", 24 | "@multiformats/multiaddr": "^12.3.1", 25 | "@nodeutils/defaults-deep": "^1.1.0", 26 | "it-length-prefixed": "^10.0.1", 27 | "it-map": "^3.0.3", 28 | "it-pipe": "^3.0.1", 29 | "libp2p": "^2.0.0", 30 | "p-defer": "^4.0.0", 31 | "uint8arrays": "^5.1.0" 32 | }, 33 | "devDependencies": { 34 | "test-ipfs-example": "^1.1.0" 35 | }, 36 | "private": true 37 | } 38 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-chat/src/dialer.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | 3 | import { createLibp2p } from './libp2p.js' 4 | import { stdinToStream, streamToConsole } from './stream.js' 5 | 6 | async function run () { 7 | // Create a new libp2p node on localhost with a randomly chosen port 8 | const dialer = await createLibp2p({ 9 | addresses: { 10 | listen: ['/ip4/0.0.0.0/tcp/0'] 11 | } 12 | }) 13 | 14 | // Output this node's address 15 | console.log('Dialer ready, listening on:') 16 | dialer.getMultiaddrs().forEach((ma) => { 17 | console.log(ma.toString()) 18 | }) 19 | 20 | dialer.addEventListener('peer:discovery', (evt) => { 21 | console.info('peer:discovery', evt.detail) 22 | 23 | // Dial to the remote peer (the "listener") 24 | dialer.dialProtocol(evt.detail.multiaddrs, '/chat/1.0.0') 25 | .then(stream => { 26 | console.log('Dialer dialed to listener on protocol: /chat/1.0.0') 27 | console.log('Type a message and see what happens') 28 | 29 | // Send stdin to the stream 30 | stdinToStream(stream) 31 | // Read the stream and output to console 32 | streamToConsole(stream) 33 | }) 34 | }) 35 | } 36 | 37 | run() 38 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-chat/src/libp2p.js: -------------------------------------------------------------------------------- 1 | import { noise } from '@chainsafe/libp2p-noise' 2 | import { yamux } from '@chainsafe/libp2p-yamux' 3 | import { mdns } from '@libp2p/mdns' 4 | import { tcp } from '@libp2p/tcp' 5 | import { webSockets } from '@libp2p/websockets' 6 | import defaultsDeep from '@nodeutils/defaults-deep' 7 | import { createLibp2p as create } from 'libp2p' 8 | 9 | export async function createLibp2p (_options) { 10 | const defaults = { 11 | transports: [ 12 | tcp(), 13 | webSockets() 14 | ], 15 | streamMuxers: [ 16 | yamux() 17 | ], 18 | connectionEncrypters: [ 19 | noise() 20 | ], 21 | peerDiscovery: [ 22 | mdns() 23 | ] 24 | } 25 | 26 | return create(defaultsDeep(_options, defaults)) 27 | } 28 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-chat/src/listener.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | 3 | import { createLibp2p } from './libp2p.js' 4 | import { stdinToStream, streamToConsole } from './stream.js' 5 | 6 | async function run () { 7 | // Create a new libp2p node with the given multi-address 8 | const listener = await createLibp2p({ 9 | addresses: { 10 | listen: ['/ip4/0.0.0.0/tcp/10333'] 11 | } 12 | }) 13 | 14 | // Log a message when a remote peer connects to us 15 | listener.addEventListener('peer:connect', (evt) => { 16 | const remotePeer = evt.detail 17 | console.log('connected to: ', remotePeer.toString()) 18 | }) 19 | 20 | // Handle messages for the protocol 21 | await listener.handle('/chat/1.0.0', async ({ stream }) => { 22 | // Send stdin to the stream 23 | stdinToStream(stream) 24 | // Read the stream and output to console 25 | streamToConsole(stream) 26 | }) 27 | 28 | // Output listen addresses to the console 29 | console.log('Listener ready, listening on:') 30 | listener.getMultiaddrs().forEach((ma) => { 31 | console.log(ma.toString()) 32 | }) 33 | } 34 | 35 | run() 36 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-chat/src/stream.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | 3 | import * as lp from 'it-length-prefixed' 4 | import map from 'it-map' 5 | import { pipe } from 'it-pipe' 6 | import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string' 7 | import { toString as uint8ArrayToString } from 'uint8arrays/to-string' 8 | 9 | export function stdinToStream (stream) { 10 | // Read utf-8 from stdin 11 | process.stdin.setEncoding('utf8') 12 | pipe( 13 | // Read from stdin (the source) 14 | process.stdin, 15 | // Turn strings into buffers 16 | (source) => map(source, (string) => uint8ArrayFromString(string)), 17 | // Encode with length prefix (so receiving side knows how much data is coming) 18 | (source) => lp.encode(source), 19 | // Write to the stream (the sink) 20 | stream.sink 21 | ) 22 | } 23 | 24 | export function streamToConsole (stream) { 25 | pipe( 26 | // Read from the stream (the source) 27 | stream.source, 28 | // Decode length-prefixed data 29 | (source) => lp.decode(source), 30 | // Turn buffers into strings 31 | (source) => map(source, (buf) => uint8ArrayToString(buf.subarray())), 32 | // Sink function 33 | async function (source) { 34 | // For each chunk of data 35 | for await (const msg of source) { 36 | // Output the data as a utf8 string 37 | console.log('> ' + msg.toString().replace('\n', '')) 38 | } 39 | } 40 | ) 41 | } 42 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-chat/test/index.spec.js: -------------------------------------------------------------------------------- 1 | import path from 'path' 2 | import { fileURLToPath } from 'url' 3 | import pDefer from 'p-defer' 4 | import { matchOutput } from 'test-ipfs-example/node' 5 | 6 | const __dirname = path.dirname(fileURLToPath(import.meta.url)) 7 | 8 | const messageReceived = pDefer() 9 | const message = 'test message' 10 | 11 | // Step 1 process 12 | process.stdout.write('node listener.js\n') 13 | 14 | const { 15 | process: listener 16 | } = await matchOutput(/Listener ready, listening on/g, 'node', [path.resolve(__dirname, '../src/listener.js')]) 17 | 18 | // receive message 19 | listener.stdout.addListener('data', (buf) => { 20 | if (buf.toString().includes(message)) { 21 | messageReceived.resolve() 22 | } 23 | }) 24 | 25 | process.stdout.write('==================================================================\n') 26 | 27 | // Step 2 process 28 | process.stdout.write('node dialer.js\n') 29 | 30 | const { 31 | process: dialer 32 | } = await matchOutput(/Type a message and see what happens/g, 'node', [path.resolve(__dirname, '../src/dialer.js')]) 33 | 34 | // send message 35 | dialer.stdin.write(message) 36 | dialer.stdin.write('\n') 37 | 38 | process.stdout.write('==================================================================\n') 39 | 40 | await messageReceived.promise 41 | 42 | process.stdout.write('chat message received\n') 43 | 44 | dialer.kill() 45 | listener.kill() 46 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-circuit-relay/.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | # ⚠️ IMPORTANT ⚠️ 2 | 3 | # Please do not create a Pull Request for this repository 4 | 5 | The contents of this repository are automatically synced from the parent [js-libp2p Examples Project](https://github.com/libp2p/js-libp2p-examples) so any changes made to the standalone repository will be lost after the next sync. 6 | 7 | Please open a PR against [js-libp2p Examples](https://github.com/libp2p/js-libp2p-examples) instead. 8 | 9 | ## Contributing 10 | 11 | Contributions are what make the open source community such an amazing place to be learn, inspire, and create. Any contributions you make are **greatly appreciated**. 12 | 13 | 1. Fork the [js-libp2p Examples Project](https://github.com/libp2p/js-libp2p-examples) 14 | 2. Create your Feature Branch (`git checkout -b feature/amazing-example`) 15 | 3. Commit your Changes (`git commit -a -m 'feat: add some amazing example'`) 16 | 4. Push to the Branch (`git push origin feature/amazing-example`) 17 | 5. Open a Pull Request 18 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-circuit-relay/.github/workflows/sync.yml: -------------------------------------------------------------------------------- 1 | name: pull 2 | 3 | on: 4 | workflow_dispatch 5 | 6 | jobs: 7 | sync: 8 | runs-on: ubuntu-latest 9 | steps: 10 | - uses: actions/checkout@v2 11 | - name: Pull from another repository 12 | uses: ipfs-examples/actions-pull-directory-from-repo@main 13 | with: 14 | source-repo: libp2p/js-libp2p-examples 15 | source-folder-path: examples/${{ github.event.repository.name }} 16 | source-branch: main 17 | target-branch: main 18 | git-username: github-actions 19 | git-email: github-actions@github.com 20 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-circuit-relay/LICENSE: -------------------------------------------------------------------------------- 1 | This project is dual licensed under MIT and Apache-2.0. 2 | 3 | MIT: https://www.opensource.org/licenses/mit 4 | Apache-2.0: https://www.apache.org/licenses/license-2.0 5 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-circuit-relay/LICENSE-APACHE: -------------------------------------------------------------------------------- 1 | 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 2 | 3 | http://www.apache.org/licenses/LICENSE-2.0 4 | 5 | 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. 6 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-circuit-relay/LICENSE-MIT: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-circuit-relay/dialer.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | 3 | import { noise } from '@chainsafe/libp2p-noise' 4 | import { yamux } from '@chainsafe/libp2p-yamux' 5 | import { circuitRelayTransport } from '@libp2p/circuit-relay-v2' 6 | import { identify } from '@libp2p/identify' 7 | import { webSockets } from '@libp2p/websockets' 8 | import { multiaddr } from '@multiformats/multiaddr' 9 | import { createLibp2p } from 'libp2p' 10 | 11 | async function main () { 12 | const listenNodeAddr = process.argv[2] 13 | if (!listenNodeAddr) { 14 | throw new Error('The listening node address needs to be specified') 15 | } 16 | 17 | const node = await createLibp2p({ 18 | transports: [ 19 | webSockets(), 20 | circuitRelayTransport() 21 | ], 22 | connectionEncrypters: [ 23 | noise() 24 | ], 25 | streamMuxers: [ 26 | yamux() 27 | ], 28 | services: { 29 | identify: identify() 30 | } 31 | }) 32 | 33 | console.log(`Node started with id ${node.peerId.toString()}`) 34 | 35 | const ma = multiaddr(listenNodeAddr) 36 | const conn = await node.dial(ma, { 37 | signal: AbortSignal.timeout(10_000) 38 | }) 39 | console.log(`Connected to the listening node via ${conn.remoteAddr.toString()}`) 40 | } 41 | 42 | main() 43 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-circuit-relay/listener.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | 3 | import { noise } from '@chainsafe/libp2p-noise' 4 | import { yamux } from '@chainsafe/libp2p-yamux' 5 | import { circuitRelayTransport } from '@libp2p/circuit-relay-v2' 6 | import { identify } from '@libp2p/identify' 7 | import { webSockets } from '@libp2p/websockets' 8 | import { multiaddr } from '@multiformats/multiaddr' 9 | import { createLibp2p } from 'libp2p' 10 | 11 | async function main () { 12 | const relayAddr = process.argv[2] 13 | if (!relayAddr) { 14 | throw new Error('the relay address needs to be specified as a parameter') 15 | } 16 | 17 | const node = await createLibp2p({ 18 | addresses: { 19 | listen: [ 20 | '/p2p-circuit' 21 | ] 22 | }, 23 | transports: [ 24 | webSockets(), 25 | circuitRelayTransport() 26 | ], 27 | connectionEncrypters: [ 28 | noise() 29 | ], 30 | streamMuxers: [ 31 | yamux() 32 | ], 33 | services: { 34 | identify: identify() 35 | } 36 | }) 37 | 38 | console.log(`Node started with id ${node.peerId.toString()}`) 39 | 40 | const conn = await node.dial(multiaddr(relayAddr)) 41 | 42 | console.log(`Connected to the relay ${conn.remotePeer.toString()}`) 43 | 44 | // Wait for connection and relay to be bind for the example purpose 45 | node.addEventListener('self:peer:update', (evt) => { 46 | // Updated self multiaddrs? 47 | console.log(`Listening on a relay address of ${node.getMultiaddrs()[0].toString()}`) 48 | }) 49 | } 50 | 51 | main() 52 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-circuit-relay/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@libp2p/example-circuit-relay", 3 | "version": "0.0.0", 4 | "description": "How to use Circuit Relay to connect two nodes", 5 | "license": "Apache-2.0 OR MIT", 6 | "homepage": "https://github.com/libp2p/js-libp2p-example-circuit-relay#readme", 7 | "repository": { 8 | "type": "git", 9 | "url": "git+https://github.com/libp2p/js-libp2p-examples.git" 10 | }, 11 | "bugs": { 12 | "url": "https://github.com/libp2p/js-libp2p-examples/issues" 13 | }, 14 | "type": "module", 15 | "scripts": { 16 | "test": "test-node-example test/*" 17 | }, 18 | "dependencies": { 19 | "@chainsafe/libp2p-noise": "^16.0.0", 20 | "@chainsafe/libp2p-yamux": "^7.0.0", 21 | "@libp2p/circuit-relay-v2": "^3.0.0", 22 | "@libp2p/identify": "^3.0.0", 23 | "@libp2p/websockets": "^9.0.0", 24 | "@multiformats/multiaddr": "^12.3.1", 25 | "libp2p": "^2.0.0" 26 | }, 27 | "devDependencies": { 28 | "test-ipfs-example": "^1.1.0" 29 | }, 30 | "private": true 31 | } 32 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-circuit-relay/relay.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | 3 | import { noise } from '@chainsafe/libp2p-noise' 4 | import { yamux } from '@chainsafe/libp2p-yamux' 5 | import { circuitRelayServer } from '@libp2p/circuit-relay-v2' 6 | import { identify } from '@libp2p/identify' 7 | import { webSockets } from '@libp2p/websockets' 8 | import { createLibp2p } from 'libp2p' 9 | 10 | async function main () { 11 | const node = await createLibp2p({ 12 | addresses: { 13 | listen: ['/ip4/0.0.0.0/tcp/0/ws'] 14 | // TODO check "What is next?" section 15 | }, 16 | transports: [ 17 | webSockets() 18 | ], 19 | connectionEncrypters: [ 20 | noise() 21 | ], 22 | streamMuxers: [ 23 | yamux() 24 | ], 25 | services: { 26 | identify: identify(), 27 | relay: circuitRelayServer() 28 | } 29 | }) 30 | 31 | console.log(`Node started with id ${node.peerId.toString()}`) 32 | console.log('Listening on:') 33 | node.getMultiaddrs().forEach((ma) => console.log(ma.toString())) 34 | } 35 | 36 | main() 37 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-circuit-relay/test/index.spec.js: -------------------------------------------------------------------------------- 1 | import path from 'path' 2 | import { fileURLToPath } from 'url' 3 | import { matchOutput, waitForOutput } from 'test-ipfs-example/node' 4 | 5 | const __dirname = path.dirname(fileURLToPath(import.meta.url)) 6 | 7 | // Step 1 process 8 | process.stdout.write('relay.js\n') 9 | 10 | const { 11 | process: relay, 12 | matches: [relayAddress] 13 | } = await matchOutput(/^(\/ip4\/.*)$/m, 'node', [path.resolve(__dirname, '../relay.js')]) 14 | 15 | process.stdout.write('==================================================================\n') 16 | 17 | // Step 2 process 18 | process.stdout.write('listener.js\n') 19 | 20 | const { 21 | process: listener, 22 | matches: [, autoRelayAddr] 23 | } = await matchOutput(/^Listening on a relay address of (\/ip4\/.*)$/m, 'node', [path.resolve(__dirname, '../listener.js'), relayAddress]) 24 | 25 | process.stdout.write('==================================================================\n') 26 | 27 | // Step 3 process 28 | process.stdout.write('dialer.js\n') 29 | 30 | await waitForOutput(`Connected to the listening node via ${autoRelayAddr}`, 'node', [path.resolve(__dirname, '../dialer.js'), autoRelayAddr]) 31 | 32 | listener.kill() 33 | relay.kill() 34 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-connection-encryption/.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | # ⚠️ IMPORTANT ⚠️ 2 | 3 | # Please do not create a Pull Request for this repository 4 | 5 | The contents of this repository are automatically synced from the parent [js-libp2p Examples Project](https://github.com/libp2p/js-libp2p-examples) so any changes made to the standalone repository will be lost after the next sync. 6 | 7 | Please open a PR against [js-libp2p Examples](https://github.com/libp2p/js-libp2p-examples) instead. 8 | 9 | ## Contributing 10 | 11 | Contributions are what make the open source community such an amazing place to be learn, inspire, and create. Any contributions you make are **greatly appreciated**. 12 | 13 | 1. Fork the [js-libp2p Examples Project](https://github.com/libp2p/js-libp2p-examples) 14 | 2. Create your Feature Branch (`git checkout -b feature/amazing-example`) 15 | 3. Commit your Changes (`git commit -a -m 'feat: add some amazing example'`) 16 | 4. Push to the Branch (`git push origin feature/amazing-example`) 17 | 5. Open a Pull Request 18 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-connection-encryption/.github/workflows/sync.yml: -------------------------------------------------------------------------------- 1 | name: pull 2 | 3 | on: 4 | workflow_dispatch 5 | 6 | jobs: 7 | sync: 8 | runs-on: ubuntu-latest 9 | steps: 10 | - uses: actions/checkout@v2 11 | - name: Pull from another repository 12 | uses: ipfs-examples/actions-pull-directory-from-repo@main 13 | with: 14 | source-repo: libp2p/js-libp2p-examples 15 | source-folder-path: examples/${{ github.event.repository.name }} 16 | source-branch: main 17 | target-branch: main 18 | git-username: github-actions 19 | git-email: github-actions@github.com 20 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-connection-encryption/LICENSE: -------------------------------------------------------------------------------- 1 | This project is dual licensed under MIT and Apache-2.0. 2 | 3 | MIT: https://www.opensource.org/licenses/mit 4 | Apache-2.0: https://www.apache.org/licenses/license-2.0 5 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-connection-encryption/LICENSE-APACHE: -------------------------------------------------------------------------------- 1 | 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 2 | 3 | http://www.apache.org/licenses/LICENSE-2.0 4 | 5 | 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. 6 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-connection-encryption/LICENSE-MIT: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-connection-encryption/README.md: -------------------------------------------------------------------------------- 1 | # @libp2p/example-connection-encryption 2 | 3 | [![libp2p.io](https://img.shields.io/badge/project-libp2p-yellow.svg?style=flat-square)](http://libp2p.io/) 4 | [![Discuss](https://img.shields.io/discourse/https/discuss.libp2p.io/posts.svg?style=flat-square)](https://discuss.libp2p.io) 5 | [![codecov](https://img.shields.io/codecov/c/github/libp2p/js-libp2p-examples.svg?style=flat-square)](https://codecov.io/gh/libp2p/js-libp2p-examples) 6 | [![CI](https://img.shields.io/github/actions/workflow/status/libp2p/js-libp2p-examples/ci.yml?branch=main\&style=flat-square)](https://github.com/libp2p/js-libp2p-examples/actions/workflows/ci.yml?query=branch%3Amain) 7 | 8 | > An example of how to configure connection encrypters 9 | 10 | ## Table of contents 11 | 12 | - [Set up encrypted communications](#set-up-encrypted-communications) 13 | - [Need help?](#need-help) 14 | - [License](#license) 15 | - [Contribution](#contribution) 16 | 17 | All traffic sent over connections between two libp2p nodes is encrypted. This gives us peace of mind that the node we are talking to is the node we think we are talking to, and that no-one is able to eavesdrop or interfere with the data we are exchanging. 18 | 19 | You may have noticed that every time we dial the [multiaddr](https://multiformats.io/multiaddr) of a peer in libp2p space, we include the [PeerId](https://docs.libp2p.io/concepts/fundamentals/peers/#peer-id) at the end: 20 | 21 | ``` 22 | /ip4/127.0.0.1/tcp/89765/p2p/12D3Foo 23 | ``` 24 | 25 | For some types of `PeerID`, it is the public key of the remote node (Ed25519 and secp256k1) or, when the public key is too large to embed in a string, it can be the a hash of the public key (RSA). 26 | 27 | Including the `PeerID` in the multiaddr allows us to authenticate the remote peer by creating a crypto challenge that allows them to prove they hold the the private key that matches the public key we know. 28 | 29 | Once authenticated in this fashion we can proceed to encrypt/decrypt all traffic sent over the connection. 30 | 31 | There are several strategies for performing encryption, the most common uses the [Noise Protocol Framework](http://www.noiseprotocol.org/). 32 | 33 | js-libp2p also supports a plaintext "encryption" implementation that should not be used in production but is sometimes useful for testing. 34 | 35 | ## Set up encrypted communications 36 | 37 | To add them to your libp2p configuration, all you have to do is: 38 | 39 | ```JavaScript 40 | import { noise } from '@chainsafe/libp2p-noise' 41 | import { yamux } from '@chainsafe/libp2p-yamux' 42 | import { tcp } from '@libp2p/tcp' 43 | import { createLibp2p } from 'libp2p' 44 | 45 | const createNode = async () => { 46 | return await createLibp2p({ 47 | transports: [ tcp() ], 48 | streamMuxers: [ yamux() ], 49 | // Attach noise as the crypto channel to use 50 | connectionEncrypters: [ noise() ] 51 | }) 52 | } 53 | ``` 54 | 55 | And that's it, from now on, all your libp2p communications are encrypted. Try running the example [noise.js](./noise.js) to see it working. 56 | 57 | To experiment with the plaintext implementation, run [plaintext.js](./plaintext.js). 58 | 59 | ## Need help? 60 | 61 | - Read the [js-libp2p documentation](https://github.com/libp2p/js-libp2p/tree/main/doc) 62 | - Check out the [js-libp2p API docs](https://libp2p.github.io/js-libp2p/) 63 | - Check out the [general libp2p documentation](https://docs.libp2p.io) for tips, how-tos and more 64 | - Read the [libp2p specs](https://github.com/libp2p/specs) 65 | - Ask a question on the [js-libp2p discussion board](https://github.com/libp2p/js-libp2p/discussions) 66 | 67 | ## License 68 | 69 | Licensed under either of 70 | 71 | - Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) 72 | - MIT ([LICENSE-MIT](LICENSE-MIT) / ) 73 | 74 | ## Contribution 75 | 76 | 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. 77 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-connection-encryption/noise.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | 3 | import { noise } from '@chainsafe/libp2p-noise' 4 | import { yamux } from '@chainsafe/libp2p-yamux' 5 | import { tcp } from '@libp2p/tcp' 6 | import { pipe } from 'it-pipe' 7 | import { createLibp2p } from 'libp2p' 8 | import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string' 9 | import { toString as uint8ArrayToString } from 'uint8arrays/to-string' 10 | 11 | const createNode = async () => { 12 | const node = await createLibp2p({ 13 | addresses: { 14 | listen: ['/ip4/0.0.0.0/tcp/0'] 15 | }, 16 | transports: [tcp()], 17 | streamMuxers: [yamux()], 18 | connectionEncrypters: [noise()] 19 | }) 20 | 21 | return node 22 | } 23 | 24 | const node1 = await createNode() 25 | const node2 = await createNode() 26 | 27 | node2.handle('/a-protocol', ({ stream }) => { 28 | pipe( 29 | stream, 30 | async function (source) { 31 | for await (const msg of source) { 32 | console.log(uint8ArrayToString(msg.subarray())) 33 | } 34 | } 35 | ) 36 | }) 37 | 38 | const stream = await node1.dialProtocol(node2.getMultiaddrs(), '/a-protocol') 39 | 40 | await pipe( 41 | [uint8ArrayFromString('This information is sent out encrypted to the other peer')], 42 | stream 43 | ) 44 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-connection-encryption/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@libp2p/example-connection-encryption", 3 | "version": "0.0.0", 4 | "description": "An example of how to configure connection encryption", 5 | "license": "Apache-2.0 OR MIT", 6 | "homepage": "https://github.com/libp2p/js-libp2p-example-connection-encryption#readme", 7 | "repository": { 8 | "type": "git", 9 | "url": "git+https://github.com/libp2p/js-libp2p-examples.git" 10 | }, 11 | "bugs": { 12 | "url": "https://github.com/libp2p/js-libp2p-examples/issues" 13 | }, 14 | "type": "module", 15 | "scripts": { 16 | "test": "test-node-example test/*" 17 | }, 18 | "dependencies": { 19 | "@chainsafe/libp2p-noise": "^16.0.0", 20 | "@chainsafe/libp2p-yamux": "^7.0.0", 21 | "@libp2p/plaintext": "^2.0.0", 22 | "@libp2p/tcp": "^10.0.0", 23 | "it-pipe": "^3.0.1", 24 | "libp2p": "^2.0.0", 25 | "uint8arrays": "^5.1.0" 26 | }, 27 | "devDependencies": { 28 | "test-ipfs-example": "^1.0.0" 29 | }, 30 | "private": true 31 | } 32 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-connection-encryption/plaintext.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | 3 | import { yamux } from '@chainsafe/libp2p-yamux' 4 | import { plaintext } from '@libp2p/plaintext' 5 | import { tcp } from '@libp2p/tcp' 6 | import { pipe } from 'it-pipe' 7 | import { createLibp2p } from 'libp2p' 8 | import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string' 9 | import { toString as uint8ArrayToString } from 'uint8arrays/to-string' 10 | 11 | const createNode = async () => { 12 | const node = await createLibp2p({ 13 | addresses: { 14 | listen: ['/ip4/0.0.0.0/tcp/0'] 15 | }, 16 | transports: [tcp()], 17 | streamMuxers: [yamux()], 18 | connectionEncrypters: [plaintext()] 19 | }) 20 | 21 | return node 22 | } 23 | 24 | const node1 = await createNode() 25 | const node2 = await createNode() 26 | 27 | node2.handle('/a-protocol', ({ stream }) => { 28 | pipe( 29 | stream, 30 | async function (source) { 31 | for await (const msg of source) { 32 | console.log(uint8ArrayToString(msg.subarray())) 33 | } 34 | } 35 | ) 36 | }) 37 | 38 | const stream = await node1.dialProtocol(node2.getMultiaddrs(), '/a-protocol') 39 | 40 | await pipe( 41 | [uint8ArrayFromString('This information is sent out encrypted to the other peer')], 42 | stream 43 | ) 44 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-connection-encryption/test/index.spec.js: -------------------------------------------------------------------------------- 1 | import path from 'path' 2 | import { fileURLToPath } from 'url' 3 | import { waitForOutput } from 'test-ipfs-example/node' 4 | 5 | const __dirname = path.dirname(fileURLToPath(import.meta.url)) 6 | 7 | process.stdout.write('noise.js\n') 8 | 9 | await waitForOutput('This information is sent out encrypted to the other peer', 'node', [path.join(__dirname, '../noise.js')], { 10 | cwd: __dirname 11 | }) 12 | 13 | process.stdout.write('plaintext.js\n') 14 | 15 | await waitForOutput('This information is sent out encrypted to the other peer', 'node', [path.join(__dirname, '../plaintext.js')], { 16 | cwd: __dirname 17 | }) 18 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-custom-protocols/.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | # ⚠️ IMPORTANT ⚠️ 2 | 3 | # Please do not create a Pull Request for this repository 4 | 5 | The contents of this repository are automatically synced from the parent [js-libp2p Examples Project](https://github.com/libp2p/js-libp2p-examples) so any changes made to the standalone repository will be lost after the next sync. 6 | 7 | Please open a PR against [js-libp2p Examples](https://github.com/libp2p/js-libp2p-examples) instead. 8 | 9 | ## Contributing 10 | 11 | Contributions are what make the open source community such an amazing place to be learn, inspire, and create. Any contributions you make are **greatly appreciated**. 12 | 13 | 1. Fork the [js-libp2p Examples Project](https://github.com/libp2p/js-libp2p-examples) 14 | 2. Create your Feature Branch (`git checkout -b feature/amazing-example`) 15 | 3. Commit your Changes (`git commit -a -m 'feat: add some amazing example'`) 16 | 4. Push to the Branch (`git push origin feature/amazing-example`) 17 | 5. Open a Pull Request 18 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-custom-protocols/.github/workflows/sync.yml: -------------------------------------------------------------------------------- 1 | name: pull 2 | 3 | on: 4 | workflow_dispatch 5 | 6 | jobs: 7 | sync: 8 | runs-on: ubuntu-latest 9 | steps: 10 | - uses: actions/checkout@v2 11 | - name: Pull from another repository 12 | uses: ipfs-examples/actions-pull-directory-from-repo@main 13 | with: 14 | source-repo: libp2p/js-libp2p-examples 15 | source-folder-path: examples/${{ github.event.repository.name }} 16 | source-branch: main 17 | target-branch: main 18 | git-username: github-actions 19 | git-email: github-actions@github.com 20 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-custom-protocols/1-echo.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | 3 | import { noise } from '@chainsafe/libp2p-noise' 4 | import { yamux } from '@chainsafe/libp2p-yamux' 5 | import { tcp } from '@libp2p/tcp' 6 | import { pipe } from 'it-pipe' 7 | import { createLibp2p } from 'libp2p' 8 | 9 | async function createNode () { 10 | return await createLibp2p({ 11 | addresses: { 12 | listen: [ 13 | '/ip4/0.0.0.0/tcp/0' 14 | ] 15 | }, 16 | connectionEncrypters: [ 17 | noise() 18 | ], 19 | streamMuxers: [ 20 | yamux() 21 | ], 22 | transports: [ 23 | tcp() 24 | ] 25 | }) 26 | } 27 | 28 | // create two nodes 29 | const remote = await createNode() 30 | const local = await createNode() 31 | 32 | // this is our protocol id 33 | const ECHO_PROTOCOL = '/echo/1.0.0' 34 | 35 | // the remote will handle incoming streams opened on the protocol 36 | await remote.handle(ECHO_PROTOCOL, ({ stream }) => { 37 | // pipe the stream output back to the stream input 38 | pipe(stream, stream) 39 | }) 40 | 41 | // the local will dial the remote on the protocol stream 42 | const stream = await local.dialProtocol(remote.getMultiaddrs(), ECHO_PROTOCOL) 43 | 44 | // now it will write some data and read it back 45 | const output = await pipe( 46 | async function * () { 47 | // the stream input must be bytes 48 | yield new TextEncoder().encode('hello world') 49 | }, 50 | stream, 51 | async (source) => { 52 | let string = '' 53 | const decoder = new TextDecoder() 54 | 55 | for await (const buf of source) { 56 | // buf is a `Uint8ArrayList` so we must turn it into a `Uint8Array` 57 | // before decoding it 58 | string += decoder.decode(buf.subarray()) 59 | } 60 | 61 | return string 62 | } 63 | ) 64 | 65 | console.info(`Echoed back to us: "${output}"`) 66 | 67 | await remote.stop() 68 | await local.stop() 69 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-custom-protocols/2-request-response.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | 3 | import { noise } from '@chainsafe/libp2p-noise' 4 | import { yamux } from '@chainsafe/libp2p-yamux' 5 | import { tcp } from '@libp2p/tcp' 6 | import { lpStream } from 'it-length-prefixed-stream' 7 | import { createLibp2p } from 'libp2p' 8 | 9 | async function createNode () { 10 | return await createLibp2p({ 11 | addresses: { 12 | listen: [ 13 | '/ip4/0.0.0.0/tcp/0' 14 | ] 15 | }, 16 | connectionEncrypters: [ 17 | noise() 18 | ], 19 | streamMuxers: [ 20 | yamux() 21 | ], 22 | transports: [ 23 | tcp() 24 | ] 25 | }) 26 | } 27 | 28 | // create two nodes 29 | const remote = await createNode() 30 | const local = await createNode() 31 | 32 | // this is our protocol id 33 | const REQ_RESP_PROTOCOL = '/request-response/1.0.0' 34 | 35 | // the remote will handle incoming streams opened on the protocol 36 | await remote.handle(REQ_RESP_PROTOCOL, ({ stream }) => { 37 | Promise.resolve().then(async () => { 38 | // lpStream lets us read/write in a predetermined order 39 | const lp = lpStream(stream) 40 | 41 | // read the incoming request 42 | const req = await lp.read() 43 | 44 | // deserialize the query 45 | const query = JSON.parse(new TextDecoder().decode(req.subarray())) 46 | 47 | if (query.question === 'What is the air-speed velocity of an unladen swallow?') { 48 | // write the response 49 | await lp.write(new TextEncoder().encode(JSON.stringify({ 50 | answer: 'Is that an African or a European swallow?' 51 | }))) 52 | } else { 53 | // write the response 54 | await lp.write(new TextEncoder().encode(JSON.stringify({ 55 | error: "What? I don't know?!" 56 | }))) 57 | } 58 | }) 59 | .catch(err => { 60 | stream.abort(err) 61 | }) 62 | }) 63 | 64 | // the local will dial the remote on the protocol stream 65 | const stream = await local.dialProtocol(remote.getMultiaddrs(), REQ_RESP_PROTOCOL) 66 | 67 | // lpStream lets us read/write in a predetermined order 68 | const lp = lpStream(stream) 69 | 70 | // send the query 71 | await lp.write(new TextEncoder().encode(JSON.stringify({ 72 | question: 'What is the air-speed velocity of an unladen swallow?' 73 | }))) 74 | 75 | // read the response 76 | const res = await lp.read() 77 | const output = JSON.parse(new TextDecoder().decode(res.subarray())) 78 | 79 | console.info(`The answer is: "${output.answer}"`) 80 | 81 | await remote.stop() 82 | await local.stop() 83 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-custom-protocols/LICENSE: -------------------------------------------------------------------------------- 1 | This project is dual licensed under MIT and Apache-2.0. 2 | 3 | MIT: https://www.opensource.org/licenses/mit 4 | Apache-2.0: https://www.apache.org/licenses/license-2.0 5 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-custom-protocols/LICENSE-APACHE: -------------------------------------------------------------------------------- 1 | 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 2 | 3 | http://www.apache.org/licenses/LICENSE-2.0 4 | 5 | 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. 6 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-custom-protocols/LICENSE-MIT: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-custom-protocols/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@libp2p/example-custom-protocols", 3 | "version": "0.0.0", 4 | "description": "How to create custom protocols for your app", 5 | "license": "Apache-2.0 OR MIT", 6 | "homepage": "https://github.com/libp2p/js-libp2p-example-custom-protocols#readme", 7 | "repository": { 8 | "type": "git", 9 | "url": "git+https://github.com/libp2p/js-libp2p-examples.git" 10 | }, 11 | "bugs": { 12 | "url": "https://github.com/libp2p/js-libp2p-examples/issues" 13 | }, 14 | "type": "module", 15 | "scripts": { 16 | "test": "test-node-example test/*" 17 | }, 18 | "dependencies": { 19 | "@chainsafe/libp2p-noise": "^16.0.0", 20 | "@chainsafe/libp2p-yamux": "^7.0.0", 21 | "@libp2p/tcp": "^10.0.0", 22 | "@libp2p/websockets": "^9.0.0", 23 | "@multiformats/multiaddr": "^12.1.5", 24 | "@nodeutils/defaults-deep": "^1.1.0", 25 | "it-length-prefixed-stream": "^1.1.4", 26 | "it-pipe": "^3.0.1", 27 | "libp2p": "^2.0.0", 28 | "uint8arrays": "^5.1.0" 29 | }, 30 | "devDependencies": { 31 | "test-ipfs-example": "^1.1.0" 32 | }, 33 | "private": true 34 | } 35 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-custom-protocols/test/1-echo.spec.js: -------------------------------------------------------------------------------- 1 | import path from 'path' 2 | import { fileURLToPath } from 'url' 3 | import { waitForOutput } from 'test-ipfs-example/node' 4 | 5 | const __dirname = path.dirname(fileURLToPath(import.meta.url)) 6 | 7 | process.stdout.write('1-echo.js\n') 8 | 9 | await waitForOutput('Echoed back to us: "hello world"', 'node', [path.join(__dirname, '..', '1-echo.js')], { 10 | cwd: __dirname 11 | }) 12 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-custom-protocols/test/2-request-response.spec.js: -------------------------------------------------------------------------------- 1 | import path from 'path' 2 | import { fileURLToPath } from 'url' 3 | import { waitForOutput } from 'test-ipfs-example/node' 4 | 5 | const __dirname = path.dirname(fileURLToPath(import.meta.url)) 6 | 7 | process.stdout.write('2-request-response.js\n') 8 | 9 | await waitForOutput('The answer is: "Is that an African or a European swallow?"', 'node', [path.join(__dirname, '..', '2-request-response.js')], { 10 | cwd: __dirname 11 | }) 12 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-delegated-routing/.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | # ⚠️ IMPORTANT ⚠️ 2 | 3 | # Please do not create a Pull Request for this repository 4 | 5 | The contents of this repository are automatically synced from the parent [js-libp2p Examples Project](https://github.com/libp2p/js-libp2p-examples) so any changes made to the standalone repository will be lost after the next sync. 6 | 7 | Please open a PR against [js-libp2p Examples](https://github.com/libp2p/js-libp2p-examples) instead. 8 | 9 | ## Contributing 10 | 11 | Contributions are what make the open source community such an amazing place to be learn, inspire, and create. Any contributions you make are **greatly appreciated**. 12 | 13 | 1. Fork the [js-libp2p Examples Project](https://github.com/libp2p/js-libp2p-examples) 14 | 2. Create your Feature Branch (`git checkout -b feature/amazing-example`) 15 | 3. Commit your Changes (`git commit -a -m 'feat: add some amazing example'`) 16 | 4. Push to the Branch (`git push origin feature/amazing-example`) 17 | 5. Open a Pull Request 18 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-delegated-routing/.github/workflows/sync.yml: -------------------------------------------------------------------------------- 1 | name: pull 2 | 3 | on: 4 | workflow_dispatch 5 | 6 | jobs: 7 | sync: 8 | runs-on: ubuntu-latest 9 | steps: 10 | - uses: actions/checkout@v2 11 | - name: Pull from another repository 12 | uses: ipfs-examples/actions-pull-directory-from-repo@main 13 | with: 14 | source-repo: libp2p/js-libp2p-examples 15 | source-folder-path: examples/${{ github.event.repository.name }} 16 | source-branch: main 17 | target-branch: main 18 | git-username: github-actions 19 | git-email: github-actions@github.com 20 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-delegated-routing/LICENSE: -------------------------------------------------------------------------------- 1 | This project is dual licensed under MIT and Apache-2.0. 2 | 3 | MIT: https://www.opensource.org/licenses/mit 4 | Apache-2.0: https://www.apache.org/licenses/license-2.0 5 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-delegated-routing/LICENSE-APACHE: -------------------------------------------------------------------------------- 1 | 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 2 | 3 | http://www.apache.org/licenses/LICENSE-2.0 4 | 5 | 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. 6 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-delegated-routing/LICENSE-MIT: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-delegated-routing/README.md: -------------------------------------------------------------------------------- 1 | # @libp2p/example-delegated-routing-example 2 | 3 | [![libp2p.io](https://img.shields.io/badge/project-libp2p-yellow.svg?style=flat-square)](http://libp2p.io/) 4 | [![Discuss](https://img.shields.io/discourse/https/discuss.libp2p.io/posts.svg?style=flat-square)](https://discuss.libp2p.io) 5 | [![codecov](https://img.shields.io/codecov/c/github/libp2p/js-libp2p-examples.svg?style=flat-square)](https://codecov.io/gh/libp2p/js-libp2p-examples) 6 | [![CI](https://img.shields.io/github/actions/workflow/status/libp2p/js-libp2p-examples/ci.yml?branch=main\&style=flat-square)](https://github.com/libp2p/js-libp2p-examples/actions/workflows/ci.yml?query=branch%3Amain) 7 | 8 | > How to configure libp2p delegated routers 9 | 10 | ## Table of contents 11 | 12 | - [Running this example](#running-this-example) 13 | - [Finding Content Providers via the Delegate](#finding-content-providers-via-the-delegate) 14 | - [Finding Peers via the Delegate](#finding-peers-via-the-delegate) 15 | - [Need help?](#need-help) 16 | - [License](#license) 17 | - [Contribution](#contribution) 18 | 19 | Delegated routing allows a libp2p node running in a constrained environment (for example a browser) to offload network operations and queries to a more capable node running elsewhere. 20 | 21 | The [libp2p node](./src/libp2p.js) created by this app has no transports, connection encrypters or muxers - it uses only a [Delegated Routing V1 HTTP API client](https://specs.ipfs.tech/routing/http-routing-v1/) to look up CID providers and Peer Info from a more capable libp2p node running in a separate process. 22 | 23 | ## Running this example 24 | 25 | 1. Install the example dependencies 26 | ```console 27 | $ npm i 28 | ``` 29 | 2. Start the Helia node in `./server.js` - this is the node we will delegate operations to 30 | ```console 31 | $ node ./server.js 32 | ``` 33 | 3. Start the lightweight browser libp2p node 34 | ```console 35 | $ npm start 36 | ``` 37 | 38 | This should open your browser to . If it does not, go ahead and do that now. 39 | 40 | ### Finding Content Providers via the Delegate 41 | 42 | 1. Enter the CID of the block you wish to find providers for, one is pre-filled for your convenience 43 | 2. Click "Find Providers" 44 | 3. If any exist, provders will start to appear in the box beneath the input fields 45 | 46 | ### Finding Peers via the Delegate 47 | 48 | 1. Enter the PeerId of the peer you wish to find, one is pre-filled for your convenience 49 | 2. Click "Find PeerInfo" 50 | 3. If found, multiaddrs for the peer will appear in the box beneath the input fields 51 | 52 | ## Need help? 53 | 54 | - Read the [js-libp2p documentation](https://github.com/libp2p/js-libp2p/tree/main/doc) 55 | - Check out the [js-libp2p API docs](https://libp2p.github.io/js-libp2p/) 56 | - Check out the [general libp2p documentation](https://docs.libp2p.io) for tips, how-tos and more 57 | - Read the [libp2p specs](https://github.com/libp2p/specs) 58 | - Ask a question on the [js-libp2p discussion board](https://github.com/libp2p/js-libp2p/discussions) 59 | 60 | ## License 61 | 62 | Licensed under either of 63 | 64 | - Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) 65 | - MIT ([LICENSE-MIT](LICENSE-MIT) / ) 66 | 67 | ## Contribution 68 | 69 | 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. 70 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-delegated-routing/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@libp2p/example-delegated-routing-example", 3 | "version": "0.0.0", 4 | "description": "How to use other libp2p nodes to perform delegated routing", 5 | "license": "Apache-2.0 OR MIT", 6 | "homepage": "https://github.com/libp2p/js-libp2p-examples/tree/main/examples/js-libp2p-example-delegated-routing#readme", 7 | "repository": { 8 | "type": "git", 9 | "url": "git+https://github.com/libp2p/js-libp2p-examples.git" 10 | }, 11 | "bugs": { 12 | "url": "https://github.com/libp2p/js-libp2p-examples/issues" 13 | }, 14 | "type": "module", 15 | "scripts": { 16 | "start": "vite", 17 | "build": "vite build", 18 | "server": "node ./server.js", 19 | "test:firefox": "npm run build && playwright test --browser=firefox test", 20 | "test:chrome": "npm run build && playwright test test", 21 | "test": "npm run build && test-browser-example test" 22 | }, 23 | "dependencies": { 24 | "@helia/delegated-routing-v1-http-api-client": "^4.0.0", 25 | "@helia/delegated-routing-v1-http-api-server": "^4.0.0", 26 | "libp2p": "^2.0.0", 27 | "react": "^18.3.1", 28 | "react-dom": "^18.3.1", 29 | "vite": "^6.0.3" 30 | }, 31 | "devDependencies": { 32 | "@libp2p/peer-id": "^5.0.4", 33 | "eslint-config-ipfs": "^7.0.2", 34 | "helia": "^5.0.0", 35 | "test-ipfs-example": "^1.0.0" 36 | }, 37 | "private": true 38 | } 39 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-delegated-routing/server.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | import { createDelegatedRoutingV1HttpApiServer } from '@helia/delegated-routing-v1-http-api-server' 3 | import { createHelia } from 'helia' 4 | 5 | const helia = await createHelia() 6 | 7 | const fastify = await createDelegatedRoutingV1HttpApiServer(helia, { 8 | listen: { 9 | host: '127.0.0.1', 10 | port: 9832, 11 | listenTextResolver: (address) => { return `server is listening at ${address}` } 12 | } 13 | }) 14 | 15 | console.info(`Server listening on http://${fastify.server.address().address}:${fastify.server.address().port}`) 16 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-delegated-routing/src/App.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | // eslint-disable-next-line 3 | 'use strict' 4 | 5 | import { peerIdFromString } from '@libp2p/peer-id' 6 | import { CID } from 'multiformats/cid' 7 | import React from 'react' 8 | import { configureLibp2p } from './libp2p.js' 9 | 10 | const Component = React.Component 11 | 12 | class App extends Component { 13 | constructor (props) { 14 | super(props) 15 | this.state = { 16 | // This hash is the 'hello world' string 17 | hash: 'bafkreifzjut3te2nhyekklss27nh3k72ysco7y32koao5eei66wof36n5e', 18 | // This peer is one of the Bootstrap nodes for Helia 19 | peer: 'QmNnooDu7bfjPFoTZYxMNLWUQJyrVwtbZg5gBMjTezGAJN', 20 | isLoading: 0 21 | } 22 | this.peerInterval = null 23 | 24 | this.handleHashChange = this.handleHashChange.bind(this) 25 | this.handleHashSubmit = this.handleHashSubmit.bind(this) 26 | this.handlePeerChange = this.handlePeerChange.bind(this) 27 | this.handlePeerSubmit = this.handlePeerSubmit.bind(this) 28 | } 29 | 30 | handleHashChange (event) { 31 | this.setState({ 32 | hash: event.target.value 33 | }) 34 | } 35 | 36 | handlePeerChange (event) { 37 | this.setState({ 38 | peer: event.target.value 39 | }) 40 | } 41 | 42 | async handleHashSubmit (event) { 43 | event.preventDefault() 44 | this.setState({ 45 | isLoading: this.state.isLoading + 1 46 | }) 47 | 48 | const providers = [] 49 | 50 | for await (const provider of this.libp2p.contentRouting.findProviders(CID.parse(this.state.hash))) { 51 | providers.push(provider) 52 | 53 | this.setState({ 54 | response: JSON.stringify(providers, null, 2), 55 | isLoading: this.state.isLoading - 1 56 | }) 57 | } 58 | 59 | this.setState({ 60 | response: JSON.stringify(providers, null, 2), 61 | isLoading: this.state.isLoading - 1 62 | }) 63 | } 64 | 65 | async handlePeerSubmit (event) { 66 | event.preventDefault() 67 | this.setState({ 68 | isLoading: this.state.isLoading + 1 69 | }) 70 | 71 | try { 72 | const peerInfo = await this.libp2p.peerRouting.findPeer(peerIdFromString(this.state.peer)) 73 | 74 | this.setState({ 75 | response: JSON.stringify(peerInfo, null, 2), 76 | isLoading: this.state.isLoading - 1 77 | }) 78 | } catch (err) { 79 | this.setState({ 80 | response: `Error finding peer: ${err.message}`, 81 | isLoading: this.state.isLoading - 1 82 | }) 83 | } 84 | } 85 | 86 | async componentDidMount () { 87 | window.libp2p = this.libp2p = await configureLibp2p() 88 | } 89 | 90 | render () { 91 | return ( 92 |
93 |
94 |

Delegated Routing

95 |
96 |
97 |
98 | 103 |
104 |
105 | 110 |
111 |
112 |
0 ? 'loading' : '', 'loader'].join(' ')}> 113 |
114 |
115 |
116 |
117 |             {this.state.response}
118 |           
119 |
120 |
121 | ) 122 | } 123 | } 124 | 125 | export default App 126 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-delegated-routing/src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Delegated Routing 8 | 9 | 10 | 11 |
12 |
13 |

Delegated Routing

14 |
15 |
16 |
17 | 22 |
23 |
24 | 29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |         
37 |
38 |
39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-delegated-routing/src/index.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | 3 | import { createDelegatedRoutingV1HttpApiClient } from '@helia/delegated-routing-v1-http-api-client' 4 | import { peerIdFromString } from '@libp2p/peer-id' 5 | import { createLibp2p } from 'libp2p' 6 | import { CID } from 'multiformats/cid' 7 | 8 | const DOM = { 9 | findProvidersInput: () => document.getElementById('find-providers-input'), 10 | findProvidersButton: () => document.getElementById('find-providers-button'), 11 | 12 | findPeerInput: () => document.getElementById('find-peer-input'), 13 | findPeerButton: () => document.getElementById('find-peer-button'), 14 | 15 | loadingNotificationElement: () => document.getElementById('loading-notification'), 16 | 17 | output: () => document.getElementById('output') 18 | } 19 | 20 | const libp2p = await createLibp2p({ 21 | services: { 22 | delegatedRouting: () => createDelegatedRoutingV1HttpApiClient('http://127.0.0.1:9832') 23 | } 24 | }) 25 | 26 | // find providers 27 | DOM.findProvidersButton().onclick = async (event) => { 28 | event.preventDefault() 29 | DOM.loadingNotificationElement().className = 'loading' 30 | 31 | try { 32 | const cid = CID.parse(DOM.findProvidersInput().value) 33 | const providers = [] 34 | DOM.output().innerText = '' 35 | 36 | for await (const provider of libp2p.contentRouting.findProviders(cid)) { 37 | providers.push(provider) 38 | 39 | DOM.output().innerText = JSON.stringify(providers, null, 2) 40 | } 41 | } finally { 42 | DOM.loadingNotificationElement().className = '' 43 | } 44 | } 45 | 46 | // find peer 47 | DOM.findPeerButton().onclick = async (event) => { 48 | event.preventDefault() 49 | DOM.loadingNotificationElement().className = 'loading' 50 | 51 | try { 52 | const peerId = peerIdFromString(DOM.findPeerInput().value) 53 | DOM.output().innerText = '' 54 | const peerInfo = await libp2p.peerRouting.findPeer(peerId) 55 | 56 | DOM.output().innerText = JSON.stringify(peerInfo, null, 2) 57 | } finally { 58 | DOM.loadingNotificationElement().className = '' 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-delegated-routing/src/libp2p.js: -------------------------------------------------------------------------------- 1 | import { createDelegatedRoutingV1HttpApiClient } from '@helia/delegated-routing-v1-http-api-client' 2 | import { createLibp2p } from 'libp2p' 3 | 4 | /** 5 | * Creates a basic libp2p node - it will only perform peer/content routing via 6 | * the configured delegated routing v1 http api client 7 | */ 8 | export async function configureLibp2p () { 9 | return await createLibp2p({ 10 | services: { 11 | delegatedRouting: () => createDelegatedRoutingV1HttpApiClient('http://127.0.0.1:9832') 12 | } 13 | }) 14 | } 15 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-delegated-routing/src/main.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | padding: 0; 4 | font-family: sans-serif; 5 | } 6 | 7 | section * { 8 | margin: 10px; 9 | } 10 | 11 | header { 12 | background-color: #222; 13 | height: 150px; 14 | padding: 20px; 15 | color: white; 16 | } 17 | 18 | .center { 19 | text-align: center; 20 | } 21 | 22 | pre { 23 | background-color: bisque; 24 | min-height: 100px; 25 | margin: 0px; 26 | padding: 10px; 27 | } 28 | 29 | .loader { 30 | text-align: center; 31 | height: 64px; 32 | margin-bottom: -64px; 33 | } 34 | 35 | .loading .lds-ripple { 36 | display: inline-block; 37 | position: relative; 38 | width: 64px; 39 | height: 64px; 40 | } 41 | .loading .lds-ripple div { 42 | position: absolute; 43 | border: 4px solid #000; 44 | opacity: 1; 45 | border-radius: 50%; 46 | animation: lds-ripple 1s cubic-bezier(0, 0.2, 0.8, 1) infinite; 47 | margin: auto; 48 | } 49 | .loading .lds-ripple div:nth-child(2) { 50 | animation-delay: -0.5s; 51 | } 52 | @keyframes lds-ripple { 53 | 0% { 54 | top: 28px; 55 | left: 28px; 56 | width: 0; 57 | height: 0; 58 | opacity: 1; 59 | } 60 | 100% { 61 | top: -1px; 62 | left: -1px; 63 | width: 58px; 64 | height: 58px; 65 | opacity: 0; 66 | } 67 | } -------------------------------------------------------------------------------- /examples/js-libp2p-example-delegated-routing/test/index.spec.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | import { createDelegatedRoutingV1HttpApiServer } from '@helia/delegated-routing-v1-http-api-server' 3 | import { peerIdFromString } from '@libp2p/peer-id' 4 | import { createHelia, libp2pDefaults } from 'helia' 5 | import { setup, expect } from 'test-ipfs-example/browser' 6 | 7 | // Setup 8 | const test = setup() 9 | 10 | // DOM 11 | const findProvidersInput = '#find-providers-input' 12 | const findProvidersBtn = '#find-providers-button' 13 | const findPeerInput = '#find-peer-input' 14 | const findPeerBtn = '#find-peer-button' 15 | const output = '#output' 16 | 17 | let url 18 | 19 | // start a libp2p node to delegate to 20 | async function spawnServer () { 21 | const libp2p = libp2pDefaults() 22 | 23 | if (process.env.CI != null) { 24 | // do not use UPnP service in CI 25 | delete libp2p.services.upnp 26 | } 27 | 28 | const helia = await createHelia({ 29 | routers: [{ 30 | // dummy router that always finds providers 31 | findProviders: async function * () { 32 | yield { 33 | id: peerIdFromString('QmNnooDu7bfjPFoTZYxMNLWUQJyrVwtbZg5gBMjTezGAJN'), 34 | multiaddrs: [], 35 | protocols: [] 36 | } 37 | }, 38 | findPeer: async function () { 39 | return { 40 | id: peerIdFromString('QmNnooDu7bfjPFoTZYxMNLWUQJyrVwtbZg5gBMjTezGAJN'), 41 | multiaddrs: [] 42 | } 43 | } 44 | }], 45 | libp2p 46 | }) 47 | const fastify = await createDelegatedRoutingV1HttpApiServer(helia, { 48 | listen: { 49 | host: '127.0.0.1', 50 | port: 9832, 51 | listenTextResolver: (address) => { return `server is listening at ${address}` } 52 | } 53 | }) 54 | 55 | return { helia, fastify } 56 | } 57 | 58 | test.describe('delegated routing example:', () => { 59 | let helia 60 | let fastify 61 | 62 | // eslint-disable-next-line no-empty-pattern 63 | test.beforeAll(async ({ servers }, testInfo) => { 64 | testInfo.setTimeout(5 * 60_000) 65 | const r = await spawnServer() 66 | helia = r.helia 67 | fastify = r.fastify 68 | url = servers[0].url 69 | }, {}) 70 | 71 | test.afterAll(async () => { 72 | await fastify?.close() 73 | await helia?.stop() 74 | }) 75 | 76 | test.beforeEach(async ({ page }) => { 77 | await page.goto(url) 78 | }) 79 | 80 | test('should find providers using the delegate', async ({ page, context }) => { 81 | // add the empty directory CID to the input field and submit 82 | await page.fill(findProvidersInput, 'bafybeiczsscdsbs7ffqz55asqdf3smv6klcw3gofszvwlyarci47bgf354') 83 | await page.click(findProvidersBtn) 84 | 85 | const outputLocator = page.locator(output) 86 | await expect(outputLocator).toContainText('[') 87 | }) 88 | 89 | test('should find peer using the delegate', async ({ page, context }) => { 90 | // add the relay multiaddr to the input field and submit 91 | await page.fill(findPeerInput, 'QmNnooDu7bfjPFoTZYxMNLWUQJyrVwtbZg5gBMjTezGAJN') 92 | await page.click(findPeerBtn) 93 | 94 | const outputLocator = page.locator(output) 95 | await expect(outputLocator).toContainText('multiaddrs":') 96 | }) 97 | }) 98 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-delegated-routing/vite.config.js: -------------------------------------------------------------------------------- 1 | export default { 2 | build: { 3 | target: 'es2022', 4 | outDir: '../dist', 5 | emptyOutDir: true 6 | }, 7 | optimizeDeps: { 8 | esbuildOptions: { target: 'es2022', supported: { bigint: true } } 9 | }, 10 | server: { 11 | open: true 12 | }, 13 | root: './src' 14 | } 15 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-discovery-mechanisms/.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | # ⚠️ IMPORTANT ⚠️ 2 | 3 | # Please do not create a Pull Request for this repository 4 | 5 | The contents of this repository are automatically synced from the parent [js-libp2p Examples Project](https://github.com/libp2p/js-libp2p-examples) so any changes made to the standalone repository will be lost after the next sync. 6 | 7 | Please open a PR against [js-libp2p Examples](https://github.com/libp2p/js-libp2p-examples) instead. 8 | 9 | ## Contributing 10 | 11 | Contributions are what make the open source community such an amazing place to be learn, inspire, and create. Any contributions you make are **greatly appreciated**. 12 | 13 | 1. Fork the [js-libp2p Examples Project](https://github.com/libp2p/js-libp2p-examples) 14 | 2. Create your Feature Branch (`git checkout -b feature/amazing-example`) 15 | 3. Commit your Changes (`git commit -a -m 'feat: add some amazing example'`) 16 | 4. Push to the Branch (`git push origin feature/amazing-example`) 17 | 5. Open a Pull Request 18 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-discovery-mechanisms/.github/workflows/sync.yml: -------------------------------------------------------------------------------- 1 | name: pull 2 | 3 | on: 4 | workflow_dispatch 5 | 6 | jobs: 7 | sync: 8 | runs-on: ubuntu-latest 9 | steps: 10 | - uses: actions/checkout@v2 11 | - name: Pull from another repository 12 | uses: ipfs-examples/actions-pull-directory-from-repo@main 13 | with: 14 | source-repo: libp2p/js-libp2p-examples 15 | source-folder-path: examples/${{ github.event.repository.name }} 16 | source-branch: main 17 | target-branch: main 18 | git-username: github-actions 19 | git-email: github-actions@github.com 20 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-discovery-mechanisms/1-dht.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | 3 | import { noise } from '@chainsafe/libp2p-noise' 4 | import { yamux } from '@chainsafe/libp2p-yamux' 5 | import { bootstrap } from '@libp2p/bootstrap' 6 | import { identify } from '@libp2p/identify' 7 | import { kadDHT, removePublicAddressesMapper } from '@libp2p/kad-dht' 8 | import { ping } from '@libp2p/ping' 9 | import { tcp } from '@libp2p/tcp' 10 | import { createLibp2p } from 'libp2p' 11 | import bootstrappers from './bootstrappers.js' 12 | 13 | const node = await createLibp2p({ 14 | addresses: { 15 | listen: ['/ip4/0.0.0.0/tcp/0'] 16 | }, 17 | transports: [tcp()], 18 | streamMuxers: [yamux()], 19 | connectionEncrypters: [noise()], 20 | peerDiscovery: [ 21 | bootstrap({ 22 | list: bootstrappers 23 | }) 24 | ], 25 | services: { 26 | kadDHT: kadDHT({ 27 | protocol: '/ipfs/lan/kad/1.0.0', 28 | peerInfoMapper: removePublicAddressesMapper, 29 | clientMode: false 30 | }), 31 | identify: identify(), 32 | ping: ping() 33 | } 34 | }) 35 | 36 | node.addEventListener('peer:connect', (evt) => { 37 | const peerId = evt.detail 38 | console.log('Connection established to:', peerId.toString()) // Emitted when a peer has been found 39 | }) 40 | 41 | node.addEventListener('peer:discovery', (evt) => { 42 | const peerInfo = evt.detail 43 | 44 | console.log('Discovered:', peerInfo.id.toString()) 45 | }) 46 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-discovery-mechanisms/2-mdns.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | 3 | import { noise } from '@chainsafe/libp2p-noise' 4 | import { yamux } from '@chainsafe/libp2p-yamux' 5 | import { mdns } from '@libp2p/mdns' 6 | import { tcp } from '@libp2p/tcp' 7 | import { createLibp2p } from 'libp2p' 8 | 9 | const createNode = async () => { 10 | const node = await createLibp2p({ 11 | addresses: { 12 | listen: ['/ip4/0.0.0.0/tcp/0'] 13 | }, 14 | transports: [ 15 | tcp() 16 | ], 17 | streamMuxers: [ 18 | yamux() 19 | ], 20 | connectionEncrypters: [ 21 | noise() 22 | ], 23 | peerDiscovery: [ 24 | mdns({ 25 | interval: 20e3 26 | }) 27 | ] 28 | }) 29 | 30 | return node 31 | } 32 | 33 | ;(async () => { 34 | const [node1, node2] = await Promise.all([ 35 | createNode(), 36 | createNode() 37 | ]) 38 | 39 | node1.addEventListener('peer:discovery', (evt) => console.log('Discovered:', evt.detail.id.toString())) 40 | node2.addEventListener('peer:discovery', (evt) => console.log('Discovered:', evt.detail.id.toString())) 41 | })() 42 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-discovery-mechanisms/3-pubsub.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | 3 | import { gossipsub } from '@chainsafe/libp2p-gossipsub' 4 | import { noise } from '@chainsafe/libp2p-noise' 5 | import { yamux } from '@chainsafe/libp2p-yamux' 6 | import { bootstrap } from '@libp2p/bootstrap' 7 | import { identify } from '@libp2p/identify' 8 | import { pubsubPeerDiscovery } from '@libp2p/pubsub-peer-discovery' 9 | import { tcp } from '@libp2p/tcp' 10 | import { createLibp2p } from 'libp2p' 11 | 12 | const createNode = async (bootstrappers = []) => { 13 | const config = { 14 | addresses: { 15 | listen: ['/ip4/0.0.0.0/tcp/0'] 16 | }, 17 | transports: [tcp()], 18 | streamMuxers: [yamux()], 19 | connectionEncrypters: [noise()], 20 | peerDiscovery: [ 21 | pubsubPeerDiscovery({ 22 | interval: 1000 23 | }) 24 | ], 25 | services: { 26 | pubsub: gossipsub(), 27 | identify: identify() 28 | } 29 | } 30 | 31 | if (bootstrappers.length > 0) { 32 | config.peerDiscovery.push(bootstrap({ 33 | list: bootstrappers 34 | })) 35 | } 36 | 37 | return await createLibp2p(config) 38 | } 39 | 40 | const bootstrapper = await createNode([]) 41 | 42 | console.log(`libp2p bootstrapper started with id: ${bootstrapper.peerId.toString()}`) 43 | 44 | const bootstrapperMultiaddrs = bootstrapper.getMultiaddrs().map((m) => m.toString()) 45 | 46 | const [node1, node2] = await Promise.all([ 47 | createNode(bootstrapperMultiaddrs), 48 | createNode(bootstrapperMultiaddrs) 49 | ]) 50 | 51 | node1.addEventListener('peer:discovery', (evt) => { 52 | const peer = evt.detail 53 | console.log(`Peer ${node1.peerId.toString()} discovered: ${peer.id.toString()}`) 54 | }) 55 | node2.addEventListener('peer:discovery', (evt) => { 56 | const peer = evt.detail 57 | console.log(`Peer ${node2.peerId.toString()} discovered: ${peer.id.toString()}`) 58 | }) 59 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-discovery-mechanisms/LICENSE: -------------------------------------------------------------------------------- 1 | This project is dual licensed under MIT and Apache-2.0. 2 | 3 | MIT: https://www.opensource.org/licenses/mit 4 | Apache-2.0: https://www.apache.org/licenses/license-2.0 5 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-discovery-mechanisms/LICENSE-APACHE: -------------------------------------------------------------------------------- 1 | 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 2 | 3 | http://www.apache.org/licenses/LICENSE-2.0 4 | 5 | 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. 6 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-discovery-mechanisms/LICENSE-MIT: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-discovery-mechanisms/bootstrappers.js: -------------------------------------------------------------------------------- 1 | // Find this list at: https://github.com/ipfs/js-ipfs/blob/master/packages/ipfs-core-config/src/config.js 2 | export default [ 3 | '/ip4/104.131.131.82/tcp/4001/p2p/QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ', 4 | '/dnsaddr/bootstrap.libp2p.io/p2p/QmNnooDu7bfjPFoTZYxMNLWUQJyrVwtbZg5gBMjTezGAJN', 5 | '/dnsaddr/bootstrap.libp2p.io/p2p/QmbLHAnMoJPWSCR5Zhtx6BHJX9KiKNN6tpvbUcqanj75Nb', 6 | '/dnsaddr/bootstrap.libp2p.io/p2p/QmZa1sAxajnQjVM8WjWXoMbmPd7NsWhfKsPkErzpm9wGkp', 7 | '/dnsaddr/bootstrap.libp2p.io/p2p/QmQCU2EcMqAqQPR2i9bChDtGNJchTbq5TbXJJ16u19uLTa', 8 | '/dnsaddr/bootstrap.libp2p.io/p2p/QmcZf59bWwK5XFi76CZX8cbJ4BhTzzA3gU1ZjYZcYW3dwt' 9 | ] 10 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-discovery-mechanisms/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@libp2p/example-discovery-mechanisms", 3 | "version": "0.0.0", 4 | "description": "How to configure peer discovery mechanisms", 5 | "license": "Apache-2.0 OR MIT", 6 | "homepage": "https://github.com/libp2p/js-libp2p-examples/tree/main/examples/js-libp2p-example-discovery-mechanisms#readme", 7 | "repository": { 8 | "type": "git", 9 | "url": "git+https://github.com/libp2p/js-libp2p-examples.git" 10 | }, 11 | "bugs": { 12 | "url": "https://github.com/libp2p/js-libp2p-examples/issues" 13 | }, 14 | "type": "module", 15 | "scripts": { 16 | "test": "test-node-example test/*" 17 | }, 18 | "dependencies": { 19 | "@chainsafe/libp2p-gossipsub": "^14.1.0", 20 | "@chainsafe/libp2p-noise": "^16.0.0", 21 | "@chainsafe/libp2p-yamux": "^7.0.0", 22 | "@libp2p/bootstrap": "^11.0.0", 23 | "@libp2p/circuit-relay-v2": "^3.0.0", 24 | "@libp2p/identify": "^3.0.0", 25 | "@libp2p/kad-dht": "^15.0.0", 26 | "@libp2p/mdns": "^11.0.0", 27 | "@libp2p/ping": "^2.0.27", 28 | "@libp2p/pubsub-peer-discovery": "^11.0.0", 29 | "@libp2p/tcp": "^10.0.0", 30 | "libp2p": "^2.0.0" 31 | }, 32 | "devDependencies": { 33 | "execa": "^9.2.0", 34 | "p-wait-for": "^5.0.2", 35 | "test-ipfs-example": "^1.1.0", 36 | "uint8arrays": "^5.1.0" 37 | }, 38 | "private": true 39 | } 40 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-discovery-mechanisms/test/test-1-dht.spec.js: -------------------------------------------------------------------------------- 1 | import path from 'path' 2 | import { fileURLToPath } from 'url' 3 | import { waitForOutput } from 'test-ipfs-example/node' 4 | 5 | const __dirname = path.dirname(fileURLToPath(import.meta.url)) 6 | 7 | process.stdout.write('1.js\n') 8 | 9 | await waitForOutput('Connection established to:', 'node', [path.join(__dirname, '..', '1-dht.js')], { 10 | cwd: __dirname 11 | }) 12 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-discovery-mechanisms/test/test-2-mdns.spec.js: -------------------------------------------------------------------------------- 1 | import path from 'path' 2 | import { fileURLToPath } from 'url' 3 | import { execa } from 'execa' 4 | import pWaitFor from 'p-wait-for' 5 | import { toString as uint8ArrayToString } from 'uint8arrays/to-string' 6 | 7 | const __dirname = path.dirname(fileURLToPath(import.meta.url)) 8 | 9 | let discoveredNodes = 0 10 | 11 | process.stdout.write('2.js\n') 12 | 13 | const proc = execa('node', [path.join(__dirname, '..', '2-mdns.js')], { 14 | cwd: path.resolve(__dirname), 15 | all: true 16 | }) 17 | 18 | proc.all.on('data', async (data) => { 19 | process.stdout.write(data) 20 | const str = uint8ArrayToString(data) 21 | 22 | str.split('\n').forEach(line => { 23 | if (line.includes('Discovered:')) { 24 | discoveredNodes++ 25 | } 26 | }) 27 | }) 28 | 29 | await pWaitFor(() => discoveredNodes > 1, 600000) 30 | 31 | process.exit(0) 32 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-discovery-mechanisms/test/test-3-pubsub.spec.js: -------------------------------------------------------------------------------- 1 | import path from 'path' 2 | import { fileURLToPath } from 'url' 3 | import { execa } from 'execa' 4 | import pWaitFor from 'p-wait-for' 5 | import { toString as uint8ArrayToString } from 'uint8arrays/to-string' 6 | 7 | const __dirname = path.dirname(fileURLToPath(import.meta.url)) 8 | 9 | const discoveredPeers = [] 10 | 11 | process.stdout.write('3.js\n') 12 | 13 | const proc = execa('node', [path.join(__dirname, '..', '3-pubsub.js')], { 14 | cwd: path.resolve(__dirname), 15 | all: true 16 | }) 17 | 18 | proc.all.on('data', async (data) => { 19 | process.stdout.write(data) 20 | const str = uint8ArrayToString(data) 21 | const discoveredPeersRegex = /Peer\s+(?[^\s]+)\s+discovered:\s+(?[^\s]+)/ 22 | str.split('\n').forEach(line => { 23 | const peers = line.match(discoveredPeersRegex) 24 | if (peers != null) { 25 | // sort so we don't count reversed pair twice 26 | const match = [peers.groups.Peer1, peers.groups.Peer2].sort().join(',') 27 | if (!discoveredPeers.includes(match)) { 28 | discoveredPeers.push(match) 29 | } 30 | } 31 | }) 32 | }) 33 | 34 | await pWaitFor(() => discoveredPeers.length > 2, 600000) 35 | 36 | process.exit(0) 37 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-peer-and-content-routing/.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | # ⚠️ IMPORTANT ⚠️ 2 | 3 | # Please do not create a Pull Request for this repository 4 | 5 | The contents of this repository are automatically synced from the parent [js-libp2p Examples Project](https://github.com/libp2p/js-libp2p-examples) so any changes made to the standalone repository will be lost after the next sync. 6 | 7 | Please open a PR against [js-libp2p Examples](https://github.com/libp2p/js-libp2p-examples) instead. 8 | 9 | ## Contributing 10 | 11 | Contributions are what make the open source community such an amazing place to be learn, inspire, and create. Any contributions you make are **greatly appreciated**. 12 | 13 | 1. Fork the [js-libp2p Examples Project](https://github.com/libp2p/js-libp2p-examples) 14 | 2. Create your Feature Branch (`git checkout -b feature/amazing-example`) 15 | 3. Commit your Changes (`git commit -a -m 'feat: add some amazing example'`) 16 | 4. Push to the Branch (`git push origin feature/amazing-example`) 17 | 5. Open a Pull Request 18 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-peer-and-content-routing/.github/workflows/sync.yml: -------------------------------------------------------------------------------- 1 | name: pull 2 | 3 | on: 4 | workflow_dispatch 5 | 6 | jobs: 7 | sync: 8 | runs-on: ubuntu-latest 9 | steps: 10 | - uses: actions/checkout@v2 11 | - name: Pull from another repository 12 | uses: ipfs-examples/actions-pull-directory-from-repo@main 13 | with: 14 | source-repo: libp2p/js-libp2p-examples 15 | source-folder-path: examples/${{ github.event.repository.name }} 16 | source-branch: main 17 | target-branch: main 18 | git-username: github-actions 19 | git-email: github-actions@github.com 20 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-peer-and-content-routing/1.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | 3 | import { noise } from '@chainsafe/libp2p-noise' 4 | import { yamux } from '@chainsafe/libp2p-yamux' 5 | import { identify, identifyPush } from '@libp2p/identify' 6 | import { kadDHT, removePublicAddressesMapper } from '@libp2p/kad-dht' 7 | import { ping } from '@libp2p/ping' 8 | import { tcp } from '@libp2p/tcp' 9 | import { createLibp2p } from 'libp2p' 10 | 11 | const createNode = async () => { 12 | const node = await createLibp2p({ 13 | addresses: { 14 | listen: ['/ip4/0.0.0.0/tcp/0'] 15 | }, 16 | transports: [tcp()], 17 | streamMuxers: [yamux()], 18 | connectionEncrypters: [noise()], 19 | services: { 20 | // configure Kad-DHT to run on the local network 21 | dht: kadDHT({ 22 | protocol: '/ipfs/lan/kad/1.0.0', 23 | peerInfoMapper: removePublicAddressesMapper, 24 | clientMode: false 25 | }), 26 | identify: identify(), 27 | identifyPush: identifyPush(), 28 | ping: ping() 29 | } 30 | }) 31 | 32 | return node 33 | } 34 | 35 | const [node1, node2, node3] = await Promise.all([ 36 | createNode(), 37 | createNode(), 38 | createNode() 39 | ]) 40 | 41 | // Connect the nodes 1 -> 2 -> 3 42 | await Promise.all([ 43 | node1.dial(node2.getMultiaddrs()), 44 | node2.dial(node3.getMultiaddrs()) 45 | ]) 46 | 47 | // find peer 3 from peer 1 (there is no direct connection) 48 | const peer = await node1.peerRouting.findPeer(node3.peerId) 49 | 50 | console.log('Found it, multiaddrs are:') 51 | peer.multiaddrs.forEach((ma) => console.log(ma.toString())) 52 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-peer-and-content-routing/2.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | 3 | import { noise } from '@chainsafe/libp2p-noise' 4 | import { yamux } from '@chainsafe/libp2p-yamux' 5 | import { identify, identifyPush } from '@libp2p/identify' 6 | import { kadDHT, removePublicAddressesMapper } from '@libp2p/kad-dht' 7 | import { ping } from '@libp2p/ping' 8 | import { tcp } from '@libp2p/tcp' 9 | import all from 'it-all' 10 | import { createLibp2p } from 'libp2p' 11 | import { CID } from 'multiformats/cid' 12 | 13 | const createNode = async () => { 14 | const node = await createLibp2p({ 15 | addresses: { 16 | listen: ['/ip4/0.0.0.0/tcp/0'] 17 | }, 18 | transports: [tcp()], 19 | streamMuxers: [yamux()], 20 | connectionEncrypters: [noise()], 21 | services: { 22 | dht: kadDHT({ 23 | protocol: '/ipfs/lan/kad/1.0.0', 24 | peerInfoMapper: removePublicAddressesMapper, 25 | clientMode: false 26 | }), 27 | identify: identify(), 28 | identifyPush: identifyPush(), 29 | ping: ping() 30 | } 31 | }) 32 | 33 | return node 34 | } 35 | 36 | const [node1, node2, node3] = await Promise.all([ 37 | createNode(), 38 | createNode(), 39 | createNode() 40 | ]) 41 | 42 | await Promise.all([ 43 | node1.dial(node2.getMultiaddrs()), 44 | node2.dial(node3.getMultiaddrs()) 45 | ]) 46 | 47 | const cid = CID.parse('QmTp9VkYvnHyrqKQuFPiuZkiX9gPcqj6x5LJ1rmWuSySnL') 48 | await node1.contentRouting.provide(cid) 49 | 50 | console.log('Node %s is providing %s', node1.peerId.toString(), cid.toString()) 51 | 52 | const providers = await all(node3.contentRouting.findProviders(cid, { timeout: 3000 })) 53 | 54 | console.log('Found provider:', providers[0].id.toString()) 55 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-peer-and-content-routing/LICENSE: -------------------------------------------------------------------------------- 1 | This project is dual licensed under MIT and Apache-2.0. 2 | 3 | MIT: https://www.opensource.org/licenses/mit 4 | Apache-2.0: https://www.apache.org/licenses/license-2.0 5 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-peer-and-content-routing/LICENSE-APACHE: -------------------------------------------------------------------------------- 1 | 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 2 | 3 | http://www.apache.org/licenses/LICENSE-2.0 4 | 5 | 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. 6 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-peer-and-content-routing/LICENSE-MIT: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-peer-and-content-routing/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@libp2p/example-peer-and-content-routing", 3 | "version": "0.0.0", 4 | "description": "How to use peer and content routing", 5 | "license": "Apache-2.0 OR MIT", 6 | "homepage": "https://github.com/libp2p/js-libp2p-examples/tree/master/examples/js-libp2p-example-peer-and-content-routing#readme", 7 | "repository": { 8 | "type": "git", 9 | "url": "git+https://github.com/libp2p/js-libp2p-examples.git" 10 | }, 11 | "bugs": { 12 | "url": "https://github.com/libp2p/js-libp2p-examples/issues" 13 | }, 14 | "type": "module", 15 | "scripts": { 16 | "lint": "aegir lint", 17 | "test": "test-node-example test/*" 18 | }, 19 | "dependencies": { 20 | "@chainsafe/libp2p-noise": "^16.0.0", 21 | "@chainsafe/libp2p-yamux": "^7.0.0", 22 | "@libp2p/identify": "^3.0.1", 23 | "@libp2p/kad-dht": "^15.0.0", 24 | "@libp2p/ping": "^2.0.27", 25 | "@libp2p/tcp": "^10.0.0", 26 | "it-all": "^3.0.2", 27 | "libp2p": "^2.0.0", 28 | "multiformats": "^13.1.1" 29 | }, 30 | "devDependencies": { 31 | "test-ipfs-example": "^1.1.0" 32 | }, 33 | "private": true 34 | } 35 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-peer-and-content-routing/test/index.js: -------------------------------------------------------------------------------- 1 | import { test as test1 } from './test-1.js' 2 | import { test as test2 } from './test-2.js' 3 | 4 | await test1() 5 | await test2() 6 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-peer-and-content-routing/test/test-1.js: -------------------------------------------------------------------------------- 1 | import path from 'path' 2 | import { fileURLToPath } from 'url' 3 | import { waitForOutput } from 'test-ipfs-example/node' 4 | 5 | const __dirname = path.dirname(fileURLToPath(import.meta.url)) 6 | 7 | export async function test () { 8 | process.stdout.write('1.js\n') 9 | 10 | await waitForOutput('Found it, multiaddrs are:', 'node', [path.join(__dirname, '../1.js')], { 11 | cwd: __dirname 12 | }) 13 | } 14 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-peer-and-content-routing/test/test-2.js: -------------------------------------------------------------------------------- 1 | import path from 'path' 2 | import { fileURLToPath } from 'url' 3 | import { waitForOutput } from 'test-ipfs-example/node' 4 | 5 | const __dirname = path.dirname(fileURLToPath(import.meta.url)) 6 | 7 | export async function test () { 8 | process.stdout.write('2.js\n') 9 | 10 | await waitForOutput('Found provider:', 'node', [path.join(__dirname, '../2.js')], { 11 | cwd: __dirname 12 | }) 13 | } 14 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-pnet/.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | # ⚠️ IMPORTANT ⚠️ 2 | 3 | # Please do not create a Pull Request for this repository 4 | 5 | The contents of this repository are automatically synced from the parent [js-libp2p Examples Project](https://github.com/libp2p/js-libp2p-examples) so any changes made to the standalone repository will be lost after the next sync. 6 | 7 | Please open a PR against [js-libp2p Examples](https://github.com/libp2p/js-libp2p-examples) instead. 8 | 9 | ## Contributing 10 | 11 | Contributions are what make the open source community such an amazing place to be learn, inspire, and create. Any contributions you make are **greatly appreciated**. 12 | 13 | 1. Fork the [js-libp2p Examples Project](https://github.com/libp2p/js-libp2p-examples) 14 | 2. Create your Feature Branch (`git checkout -b feature/amazing-example`) 15 | 3. Commit your Changes (`git commit -a -m 'feat: add some amazing example'`) 16 | 4. Push to the Branch (`git push origin feature/amazing-example`) 17 | 5. Open a Pull Request 18 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-pnet/.github/workflows/sync.yml: -------------------------------------------------------------------------------- 1 | name: pull 2 | 3 | on: 4 | workflow_dispatch 5 | 6 | jobs: 7 | sync: 8 | runs-on: ubuntu-latest 9 | steps: 10 | - uses: actions/checkout@v2 11 | - name: Pull from another repository 12 | uses: ipfs-examples/actions-pull-directory-from-repo@main 13 | with: 14 | source-repo: libp2p/js-libp2p-examples 15 | source-folder-path: examples/${{ github.event.repository.name }} 16 | source-branch: main 17 | target-branch: main 18 | git-username: github-actions 19 | git-email: github-actions@github.com 20 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-pnet/LICENSE: -------------------------------------------------------------------------------- 1 | This project is dual licensed under MIT and Apache-2.0. 2 | 3 | MIT: https://www.opensource.org/licenses/mit 4 | Apache-2.0: https://www.apache.org/licenses/license-2.0 5 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-pnet/LICENSE-APACHE: -------------------------------------------------------------------------------- 1 | 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 2 | 3 | http://www.apache.org/licenses/LICENSE-2.0 4 | 5 | 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. 6 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-pnet/LICENSE-MIT: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-pnet/README.md: -------------------------------------------------------------------------------- 1 | # @libp2p/example-pnet 2 | 3 | [![libp2p.io](https://img.shields.io/badge/project-libp2p-yellow.svg?style=flat-square)](http://libp2p.io/) 4 | [![Discuss](https://img.shields.io/discourse/https/discuss.libp2p.io/posts.svg?style=flat-square)](https://discuss.libp2p.io) 5 | [![codecov](https://img.shields.io/codecov/c/github/libp2p/js-libp2p-examples.svg?style=flat-square)](https://codecov.io/gh/libp2p/js-libp2p-examples) 6 | [![CI](https://img.shields.io/github/actions/workflow/status/libp2p/js-libp2p-examples/ci.yml?branch=main\&style=flat-square)](https://github.com/libp2p/js-libp2p-examples/actions/workflows/ci.yml?query=branch%3Amain) 7 | 8 | > How to configure a libp2p private network 9 | 10 | libp2p networks allow any peer to connect to any other peer and to communicate 11 | with them via protocol streams. 12 | 13 | What if you only want to allow a certain subset of peers to connect to you? It's 14 | possible to use a pre-shared key to create a private network on top of the 15 | public libp2p network using the `@libp2p/pnet` module. 16 | 17 | ## Setup 18 | 19 | 1. Install the modules in the libp2p root directory, `npm install` and`npm run build`. 20 | 21 | ## Run 22 | 23 | Running the example will cause two nodes with the same swarm key to be started 24 | and exchange basic information. 25 | 26 | ``` 27 | node index.js 28 | ``` 29 | 30 | ### Using different keys 31 | 32 | This example includes `TASK` comments that can be used to try the example with 33 | different swarm keys. This will allow you to see how nodes will fail to connect 34 | if they are on different private networks and try to connect to one another. 35 | 36 | To change the swarm key of one of the nodes, look through `index.js` for 37 | comments starting with `TASK` to indicate where lines are that pertain to 38 | changing the swarm key of node 2. 39 | 40 | ### Exploring the repos 41 | 42 | Once you've run the example you can take a look at the repos in the `./tmp` 43 | directory to see how they differ, including the swarm keys. You should see a 44 | `swarm.key` file in each of the repos and when the nodes are on the same private 45 | network this contents of the `swarm.key` files should be the same. 46 | 47 | ## Need help? 48 | 49 | - Read the [js-libp2p documentation](https://github.com/libp2p/js-libp2p/tree/main/doc) 50 | - Check out the [js-libp2p API docs](https://libp2p.github.io/js-libp2p/) 51 | - Check out the [general libp2p documentation](https://docs.libp2p.io) for tips, how-tos and more 52 | - Read the [libp2p specs](https://github.com/libp2p/specs) 53 | - Ask a question on the [js-libp2p discussion board](https://github.com/libp2p/js-libp2p/discussions) 54 | 55 | ## License 56 | 57 | Licensed under either of 58 | 59 | - Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) 60 | - MIT ([LICENSE-MIT](LICENSE-MIT) / ) 61 | 62 | ## Contribution 63 | 64 | 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. 65 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-pnet/index.js: -------------------------------------------------------------------------------- 1 | /* eslint no-console: ["off"] */ 2 | 3 | import { generateKey } from '@libp2p/pnet' 4 | import { pipe } from 'it-pipe' 5 | import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string' 6 | import { toString as uint8ArrayToString } from 'uint8arrays/to-string' 7 | import { privateLibp2pNode } from './libp2p-node.js' 8 | 9 | // Create a Uint8Array and write the swarm key to it 10 | const swarmKey = new Uint8Array(95) 11 | generateKey(swarmKey) 12 | 13 | // This key is for testing a different key not working 14 | const otherSwarmKey = new Uint8Array(95) 15 | generateKey(otherSwarmKey) 16 | 17 | const node1 = await privateLibp2pNode(swarmKey) 18 | 19 | // TASK: switch the commented out line below so we're using a different key, to see the nodes fail to connect 20 | const node2 = await privateLibp2pNode(swarmKey) 21 | // const node2 = await privateLibp2pNode(otherSwarmKey) 22 | 23 | console.log('nodes started...') 24 | 25 | // connect node1 to node2 26 | await node1.dial(node2.getMultiaddrs()) 27 | 28 | node2.handle('/private', ({ stream }) => { 29 | pipe( 30 | stream, 31 | async function (source) { 32 | for await (const msg of source) { 33 | console.log(uint8ArrayToString(msg.subarray())) 34 | } 35 | } 36 | ) 37 | }) 38 | 39 | const stream = await node1.dialProtocol(node2.peerId, '/private') 40 | 41 | await pipe( 42 | [uint8ArrayFromString('This message is sent on a private network')], 43 | stream 44 | ) 45 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-pnet/libp2p-node.js: -------------------------------------------------------------------------------- 1 | import { noise } from '@chainsafe/libp2p-noise' 2 | import { yamux } from '@chainsafe/libp2p-yamux' 3 | import { preSharedKey } from '@libp2p/pnet' 4 | import { tcp } from '@libp2p/tcp' 5 | import { createLibp2p } from 'libp2p' 6 | 7 | /** 8 | * privateLibp2pNode returns a libp2p node function that will use the swarm 9 | * key with the given `swarmKey` to create the Protector 10 | * 11 | * @param {any} swarmKey 12 | */ 13 | export async function privateLibp2pNode (swarmKey) { 14 | const node = await createLibp2p({ 15 | addresses: { 16 | listen: ['/ip4/0.0.0.0/tcp/0'] 17 | }, 18 | transports: [tcp()], // We're only using the TCP transport for this example 19 | streamMuxers: [yamux()], // We're only using yamux muxing 20 | // Let's make sure to use identifying crypto in our pnet since the protector 21 | // doesn't care about node identity, and only the presence of private keys 22 | connectionEncrypters: [noise()], 23 | // Leave peer discovery empty, we don't want to find peers. We could omit 24 | // the property, but it's being left in for explicit readability. 25 | // We should explicitly dial pnet peers, or use a custom discovery service 26 | // for finding nodes in our pnet 27 | peerDiscovery: [], 28 | connectionProtector: preSharedKey({ 29 | psk: swarmKey 30 | }) 31 | }) 32 | 33 | return node 34 | } 35 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-pnet/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@libp2p/example-pnet", 3 | "version": "0.0.0", 4 | "description": "How to configure a libp2p private network", 5 | "license": "Apache-2.0 OR MIT", 6 | "homepage": "https://github.com/libp2p/js-libp2p-examples/tree/master/examples/js-libp2p-example-pnet#readme", 7 | "repository": { 8 | "type": "git", 9 | "url": "git+https://github.com/libp2p/js-libp2p-examples.git" 10 | }, 11 | "bugs": { 12 | "url": "https://github.com/libp2p/js-libp2p-examples/issues" 13 | }, 14 | "type": "module", 15 | "scripts": { 16 | "test": "test-node-example test/*" 17 | }, 18 | "dependencies": { 19 | "@chainsafe/libp2p-noise": "^16.0.0", 20 | "@chainsafe/libp2p-yamux": "^7.0.0", 21 | "@libp2p/pnet": "^2.0.1", 22 | "@libp2p/tcp": "^10.0.0", 23 | "it-pipe": "^3.0.1", 24 | "libp2p": "^2.0.0", 25 | "uint8arrays": "^5.1.0" 26 | }, 27 | "devDependencies": { 28 | "test-ipfs-example": "^1.1.0" 29 | }, 30 | "private": true 31 | } 32 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-pnet/test/index.js: -------------------------------------------------------------------------------- 1 | import path from 'path' 2 | import { fileURLToPath } from 'url' 3 | import { waitForOutput } from 'test-ipfs-example/node' 4 | 5 | const __dirname = path.dirname(fileURLToPath(import.meta.url)) 6 | 7 | await waitForOutput('This message is sent on a private network', 'node', [path.join(__dirname, '../index.js')], { 8 | cwd: __dirname 9 | }) 10 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-protocol-and-stream-muxing/.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | # ⚠️ IMPORTANT ⚠️ 2 | 3 | # Please do not create a Pull Request for this repository 4 | 5 | The contents of this repository are automatically synced from the parent [js-libp2p Examples Project](https://github.com/libp2p/js-libp2p-examples) so any changes made to the standalone repository will be lost after the next sync. 6 | 7 | Please open a PR against [js-libp2p Examples](https://github.com/libp2p/js-libp2p-examples) instead. 8 | 9 | ## Contributing 10 | 11 | Contributions are what make the open source community such an amazing place to be learn, inspire, and create. Any contributions you make are **greatly appreciated**. 12 | 13 | 1. Fork the [js-libp2p Examples Project](https://github.com/libp2p/js-libp2p-examples) 14 | 2. Create your Feature Branch (`git checkout -b feature/amazing-example`) 15 | 3. Commit your Changes (`git commit -a -m 'feat: add some amazing example'`) 16 | 4. Push to the Branch (`git push origin feature/amazing-example`) 17 | 5. Open a Pull Request 18 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-protocol-and-stream-muxing/.github/workflows/sync.yml: -------------------------------------------------------------------------------- 1 | name: pull 2 | 3 | on: 4 | workflow_dispatch 5 | 6 | jobs: 7 | sync: 8 | runs-on: ubuntu-latest 9 | steps: 10 | - uses: actions/checkout@v2 11 | - name: Pull from another repository 12 | uses: ipfs-examples/actions-pull-directory-from-repo@main 13 | with: 14 | source-repo: libp2p/js-libp2p-examples 15 | source-folder-path: examples/${{ github.event.repository.name }} 16 | source-branch: main 17 | target-branch: main 18 | git-username: github-actions 19 | git-email: github-actions@github.com 20 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-protocol-and-stream-muxing/1.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | 3 | import { noise } from '@chainsafe/libp2p-noise' 4 | import { yamux } from '@chainsafe/libp2p-yamux' 5 | import { tcp } from '@libp2p/tcp' 6 | import { pipe } from 'it-pipe' 7 | import { createLibp2p } from 'libp2p' 8 | import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string' 9 | import { toString as uint8ArrayToString } from 'uint8arrays/to-string' 10 | 11 | const createNode = async () => { 12 | const node = await createLibp2p({ 13 | addresses: { 14 | listen: ['/ip4/0.0.0.0/tcp/0'] 15 | }, 16 | transports: [tcp()], 17 | streamMuxers: [yamux()], 18 | connectionEncrypters: [noise()] 19 | }) 20 | 21 | return node 22 | } 23 | 24 | const [node1, node2] = await Promise.all([ 25 | createNode(), 26 | createNode() 27 | ]) 28 | 29 | // exact matching 30 | node2.handle('/your-protocol', ({ stream }) => { 31 | pipe( 32 | stream, 33 | async function (source) { 34 | for await (const msg of source) { 35 | console.log(uint8ArrayToString(msg.subarray())) 36 | } 37 | } 38 | ) 39 | }) 40 | 41 | // multiple protocols 42 | /* 43 | node2.handle(['/another-protocol/1.0.0', '/another-protocol/2.0.0'], ({ protocol, stream }) => { 44 | if (protocol === '/another-protocol/2.0.0') { 45 | // handle backwards compatibility 46 | } 47 | 48 | pipe( 49 | stream, 50 | async function (source) { 51 | for await (const msg of source) { 52 | console.log(uint8ArrayToString(msg)) 53 | } 54 | } 55 | ) 56 | }) 57 | */ 58 | 59 | const stream = await node1.dialProtocol(node2.getMultiaddrs(), ['/your-protocol']) 60 | await pipe( 61 | [uint8ArrayFromString('my own protocol, wow!')], 62 | stream 63 | ) 64 | 65 | /* 66 | const stream = node1.dialProtocol(node2.peerId, ['/another-protocol/1.0.0']) 67 | 68 | await pipe( 69 | ['my own protocol, wow!'], 70 | stream 71 | ) 72 | */ 73 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-protocol-and-stream-muxing/2.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | 3 | import { noise } from '@chainsafe/libp2p-noise' 4 | import { yamux } from '@chainsafe/libp2p-yamux' 5 | import { tcp } from '@libp2p/tcp' 6 | import { pipe } from 'it-pipe' 7 | import { createLibp2p } from 'libp2p' 8 | import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string' 9 | import { toString as uint8ArrayToString } from 'uint8arrays/to-string' 10 | 11 | const createNode = async () => { 12 | const node = await createLibp2p({ 13 | addresses: { 14 | listen: ['/ip4/0.0.0.0/tcp/0'] 15 | }, 16 | transports: [tcp()], 17 | streamMuxers: [yamux()], 18 | connectionEncrypters: [noise()] 19 | }) 20 | 21 | return node 22 | } 23 | 24 | const [node1, node2] = await Promise.all([ 25 | createNode(), 26 | createNode() 27 | ]) 28 | 29 | // Add node's 2 data to the PeerStore 30 | await node1.peerStore.patch(node2.peerId, { 31 | multiaddrs: node2.getMultiaddrs() 32 | }) 33 | 34 | node2.handle(['/a', '/b'], ({ protocol, stream }) => { 35 | pipe( 36 | stream, 37 | async function (source) { 38 | for await (const msg of source) { 39 | console.log(`from: ${protocol}, msg: ${uint8ArrayToString(msg.subarray())}`) 40 | } 41 | } 42 | ).finally(() => { 43 | // clean up resources 44 | stream.close() 45 | }) 46 | }) 47 | 48 | const stream1 = await node1.dialProtocol(node2.peerId, ['/a']) 49 | await pipe( 50 | [uint8ArrayFromString('protocol (a)')], 51 | stream1 52 | ) 53 | 54 | const stream2 = await node1.dialProtocol(node2.peerId, ['/b']) 55 | await pipe( 56 | [uint8ArrayFromString('protocol (b)')], 57 | stream2 58 | ) 59 | 60 | const stream3 = await node1.dialProtocol(node2.peerId, ['/b']) 61 | await pipe( 62 | [uint8ArrayFromString('another stream on protocol (b)')], 63 | stream3 64 | ) 65 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-protocol-and-stream-muxing/3.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | 3 | import { noise } from '@chainsafe/libp2p-noise' 4 | import { yamux } from '@chainsafe/libp2p-yamux' 5 | import { tcp } from '@libp2p/tcp' 6 | import { pipe } from 'it-pipe' 7 | import { createLibp2p } from 'libp2p' 8 | import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string' 9 | import { toString as uint8ArrayToString } from 'uint8arrays/to-string' 10 | 11 | const createNode = async () => { 12 | const node = await createLibp2p({ 13 | addresses: { 14 | listen: ['/ip4/0.0.0.0/tcp/0'] 15 | }, 16 | transports: [tcp()], 17 | streamMuxers: [yamux()], 18 | connectionEncrypters: [noise()] 19 | }) 20 | 21 | return node 22 | } 23 | 24 | const [node1, node2] = await Promise.all([ 25 | createNode(), 26 | createNode() 27 | ]) 28 | 29 | // Add node's 2 data to the PeerStore 30 | await node1.peerStore.patch(node2.peerId, { 31 | multiaddrs: node2.getMultiaddrs() 32 | }) 33 | 34 | node1.handle('/node-1', ({ stream }) => { 35 | pipe( 36 | stream, 37 | async function (source) { 38 | for await (const msg of source) { 39 | console.log(uint8ArrayToString(msg.subarray())) 40 | } 41 | } 42 | ) 43 | }) 44 | 45 | node2.handle('/node-2', ({ stream }) => { 46 | pipe( 47 | stream, 48 | async function (source) { 49 | for await (const msg of source) { 50 | console.log(uint8ArrayToString(msg.subarray())) 51 | } 52 | } 53 | ) 54 | }) 55 | 56 | const stream1 = await node1.dialProtocol(node2.peerId, ['/node-2']) 57 | await pipe( 58 | [uint8ArrayFromString('from 1 to 2')], 59 | stream1 60 | ) 61 | 62 | const stream2 = await node2.dialProtocol(node1.peerId, ['/node-1']) 63 | await pipe( 64 | [uint8ArrayFromString('from 2 to 1')], 65 | stream2 66 | ) 67 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-protocol-and-stream-muxing/LICENSE: -------------------------------------------------------------------------------- 1 | This project is dual licensed under MIT and Apache-2.0. 2 | 3 | MIT: https://www.opensource.org/licenses/mit 4 | Apache-2.0: https://www.apache.org/licenses/license-2.0 5 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-protocol-and-stream-muxing/LICENSE-APACHE: -------------------------------------------------------------------------------- 1 | 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 2 | 3 | http://www.apache.org/licenses/LICENSE-2.0 4 | 5 | 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. 6 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-protocol-and-stream-muxing/LICENSE-MIT: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-protocol-and-stream-muxing/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@libp2p/example-protocol-and-stream-muxing", 3 | "version": "0.0.0", 4 | "description": "How to use multiplexed protocol streams", 5 | "license": "Apache-2.0 OR MIT", 6 | "homepage": "https://github.com/libp2p/js-libp2p-examples/tree/master/examples/js-libp2p-example-protocol-and-stream-muxing#readme", 7 | "repository": { 8 | "type": "git", 9 | "url": "git+https://github.com/libp2p/js-libp2p-examples.git" 10 | }, 11 | "bugs": { 12 | "url": "https://github.com/libp2p/js-libp2p-examples/issues" 13 | }, 14 | "type": "module", 15 | "scripts": { 16 | "test": "test-node-example test/*" 17 | }, 18 | "dependencies": { 19 | "@chainsafe/libp2p-noise": "^16.0.0", 20 | "@chainsafe/libp2p-yamux": "^7.0.0", 21 | "@libp2p/tcp": "^10.0.0", 22 | "it-pipe": "^3.0.1", 23 | "libp2p": "^2.0.0", 24 | "uint8arrays": "^5.1.0" 25 | }, 26 | "devDependencies": { 27 | "test-ipfs-example": "^1.1.0" 28 | }, 29 | "private": true 30 | } 31 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-protocol-and-stream-muxing/test/test-1.js: -------------------------------------------------------------------------------- 1 | import path from 'path' 2 | import { fileURLToPath } from 'url' 3 | import { waitForOutput } from 'test-ipfs-example/node' 4 | 5 | const __dirname = path.dirname(fileURLToPath(import.meta.url)) 6 | 7 | export async function test () { 8 | process.stdout.write('1.js\n') 9 | 10 | await waitForOutput('my own protocol, wow!', 'node', [path.join(__dirname, '../1.js')], { 11 | cwd: __dirname 12 | }) 13 | } 14 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-protocol-and-stream-muxing/test/test-2.js: -------------------------------------------------------------------------------- 1 | import path from 'path' 2 | import { fileURLToPath } from 'url' 3 | import { waitForOutput } from 'test-ipfs-example/node' 4 | 5 | const __dirname = path.dirname(fileURLToPath(import.meta.url)) 6 | 7 | export async function test () { 8 | process.stdout.write('2.js\n') 9 | 10 | await waitForOutput('another stream on protocol (b)', 'node', [path.join(__dirname, '../2.js')], { 11 | cwd: __dirname 12 | }) 13 | } 14 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-protocol-and-stream-muxing/test/test-3.js: -------------------------------------------------------------------------------- 1 | import path from 'path' 2 | import { fileURLToPath } from 'url' 3 | import { waitForOutput } from 'test-ipfs-example/node' 4 | 5 | const __dirname = path.dirname(fileURLToPath(import.meta.url)) 6 | 7 | export async function test () { 8 | process.stdout.write('3.js\n') 9 | 10 | await waitForOutput('from 2 to 1', 'node', [path.join(__dirname, '../3.js')], { 11 | cwd: __dirname 12 | }) 13 | } 14 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-protocol-and-stream-muxing/test/test.js: -------------------------------------------------------------------------------- 1 | import { test as test1 } from './test-1.js' 2 | import { test as test2 } from './test-2.js' 3 | import { test as test3 } from './test-3.js' 4 | 5 | await test1() 6 | await test2() 7 | await test3() 8 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-pubsub/.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | # ⚠️ IMPORTANT ⚠️ 2 | 3 | # Please do not create a Pull Request for this repository 4 | 5 | The contents of this repository are automatically synced from the parent [js-libp2p Examples Project](https://github.com/libp2p/js-libp2p-examples) so any changes made to the standalone repository will be lost after the next sync. 6 | 7 | Please open a PR against [js-libp2p Examples](https://github.com/libp2p/js-libp2p-examples) instead. 8 | 9 | ## Contributing 10 | 11 | Contributions are what make the open source community such an amazing place to be learn, inspire, and create. Any contributions you make are **greatly appreciated**. 12 | 13 | 1. Fork the [js-libp2p Examples Project](https://github.com/libp2p/js-libp2p-examples) 14 | 2. Create your Feature Branch (`git checkout -b feature/amazing-example`) 15 | 3. Commit your Changes (`git commit -a -m 'feat: add some amazing example'`) 16 | 4. Push to the Branch (`git push origin feature/amazing-example`) 17 | 5. Open a Pull Request 18 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-pubsub/.github/workflows/sync.yml: -------------------------------------------------------------------------------- 1 | name: pull 2 | 3 | on: 4 | workflow_dispatch 5 | 6 | jobs: 7 | sync: 8 | runs-on: ubuntu-latest 9 | steps: 10 | - uses: actions/checkout@v2 11 | - name: Pull from another repository 12 | uses: ipfs-examples/actions-pull-directory-from-repo@main 13 | with: 14 | source-repo: libp2p/js-libp2p-examples 15 | source-folder-path: examples/${{ github.event.repository.name }} 16 | source-branch: main 17 | target-branch: main 18 | git-username: github-actions 19 | git-email: github-actions@github.com 20 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-pubsub/1.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | 3 | import { gossipsub } from '@chainsafe/libp2p-gossipsub' 4 | import { noise } from '@chainsafe/libp2p-noise' 5 | import { yamux } from '@chainsafe/libp2p-yamux' 6 | import { identify, identifyPush } from '@libp2p/identify' 7 | import { tcp } from '@libp2p/tcp' 8 | import { createLibp2p } from 'libp2p' 9 | import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string' 10 | import { toString as uint8ArrayToString } from 'uint8arrays/to-string' 11 | 12 | const createNode = async () => { 13 | const node = await createLibp2p({ 14 | addresses: { 15 | listen: ['/ip4/0.0.0.0/tcp/0'] 16 | }, 17 | transports: [tcp()], 18 | streamMuxers: [yamux()], 19 | connectionEncrypters: [noise()], 20 | services: { 21 | pubsub: gossipsub(), 22 | identify: identify(), 23 | identifyPush: identifyPush() 24 | } 25 | }) 26 | 27 | return node 28 | } 29 | 30 | const topic = 'news' 31 | 32 | const [node1, node2] = await Promise.all([ 33 | createNode(), 34 | createNode() 35 | ]) 36 | 37 | // Connect the two nodes 38 | await node1.dial(node2.getMultiaddrs()) 39 | 40 | node1.services.pubsub.subscribe(topic) 41 | node1.services.pubsub.addEventListener('message', (evt) => { 42 | console.log(`node1 received: ${uint8ArrayToString(evt.detail.data)} on topic ${evt.detail.topic}`) 43 | }) 44 | 45 | // Will not receive own published messages by default 46 | node2.services.pubsub.subscribe(topic) 47 | node2.services.pubsub.addEventListener('message', (evt) => { 48 | console.log(`node2 received: ${uint8ArrayToString(evt.detail.data)} on topic ${evt.detail.topic}`) 49 | }) 50 | 51 | // node2 publishes "news" every second 52 | setInterval(() => { 53 | node2.services.pubsub.publish(topic, uint8ArrayFromString('Bird bird bird, bird is the word!')).catch(err => { 54 | console.error(err) 55 | }) 56 | }, 1000) 57 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-pubsub/2.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | 3 | import { gossipsub } from '@chainsafe/libp2p-gossipsub' 4 | import { noise } from '@chainsafe/libp2p-noise' 5 | import { yamux } from '@chainsafe/libp2p-yamux' 6 | import { identify, identifyPush } from '@libp2p/identify' 7 | import { tcp } from '@libp2p/tcp' 8 | import { createLibp2p } from 'libp2p' 9 | import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string' 10 | import { toString as uint8ArrayToString } from 'uint8arrays/to-string' 11 | 12 | const createNode = async () => { 13 | const node = await createLibp2p({ 14 | addresses: { 15 | listen: ['/ip4/0.0.0.0/tcp/0'] 16 | }, 17 | transports: [tcp()], 18 | streamMuxers: [yamux()], 19 | connectionEncrypters: [noise()], 20 | services: { 21 | pubsub: gossipsub(), 22 | identify: identify(), 23 | identifyPush: identifyPush() 24 | } 25 | }) 26 | 27 | return node 28 | } 29 | 30 | const topic = 'fruit' 31 | 32 | const [node1, node2, node3] = await Promise.all([ 33 | createNode(), 34 | createNode(), 35 | createNode() 36 | ]) 37 | 38 | // connect node1 to node2 and node2 to node3 39 | await node1.dial(node2.getMultiaddrs()) 40 | await node2.dial(node3.getMultiaddrs()) 41 | 42 | // subscribe 43 | node1.services.pubsub.addEventListener('message', (evt) => { 44 | if (evt.detail.topic !== topic) { 45 | return 46 | } 47 | 48 | // Will not receive own published messages by default 49 | console.log(`node1 received: ${uint8ArrayToString(evt.detail.data)}`) 50 | }) 51 | node1.services.pubsub.subscribe(topic) 52 | 53 | node2.services.pubsub.addEventListener('message', (evt) => { 54 | if (evt.detail.topic !== topic) { 55 | return 56 | } 57 | 58 | console.log(`node2 received: ${uint8ArrayToString(evt.detail.data)}`) 59 | }) 60 | node2.services.pubsub.subscribe(topic) 61 | 62 | node3.services.pubsub.addEventListener('message', (evt) => { 63 | if (evt.detail.topic !== topic) { 64 | return 65 | } 66 | 67 | console.log(`node3 received: ${uint8ArrayToString(evt.detail.data)}`) 68 | }) 69 | node3.services.pubsub.subscribe(topic) 70 | 71 | // wait for subscriptions to propagate 72 | await hasSubscription(node1, node2, topic) 73 | await hasSubscription(node2, node3, topic) 74 | 75 | const validateFruit = (msgTopic, msg) => { 76 | const fruit = uint8ArrayToString(msg.data) 77 | const validFruit = ['banana', 'apple', 'orange'] 78 | 79 | return validFruit.includes(fruit) ? 'accept' : 'ignore' 80 | } 81 | 82 | // validate fruit 83 | node1.services.pubsub.topicValidators.set(topic, validateFruit) 84 | node2.services.pubsub.topicValidators.set(topic, validateFruit) 85 | node3.services.pubsub.topicValidators.set(topic, validateFruit) 86 | 87 | // node1 publishes "fruits" 88 | for (const fruit of ['banana', 'apple', 'car', 'orange']) { 89 | console.log('############## fruit ' + fruit + ' ##############') 90 | await node1.services.pubsub.publish(topic, uint8ArrayFromString(fruit)) 91 | } 92 | 93 | console.log('############## all messages sent ##############') 94 | 95 | async function delay (ms) { 96 | await new Promise((resolve) => { 97 | setTimeout(() => resolve(), ms) 98 | }) 99 | } 100 | 101 | // Wait for node1 to see that node2 has subscribed to the topic 102 | async function hasSubscription (node1, node2, topic) { 103 | while (true) { 104 | const subs = await node1.services.pubsub.getSubscribers(topic) 105 | 106 | if (subs.map(peer => peer.toString()).includes(node2.peerId.toString())) { 107 | return 108 | } 109 | 110 | // wait for subscriptions to propagate 111 | await delay(100) 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-pubsub/LICENSE: -------------------------------------------------------------------------------- 1 | This project is dual licensed under MIT and Apache-2.0. 2 | 3 | MIT: https://www.opensource.org/licenses/mit 4 | Apache-2.0: https://www.apache.org/licenses/license-2.0 5 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-pubsub/LICENSE-APACHE: -------------------------------------------------------------------------------- 1 | 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 2 | 3 | http://www.apache.org/licenses/LICENSE-2.0 4 | 5 | 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. 6 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-pubsub/LICENSE-MIT: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-pubsub/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@libp2p/example-pubsub", 3 | "version": "0.0.0", 4 | "description": "An example using libp2p pubsub", 5 | "license": "Apache-2.0 OR MIT", 6 | "homepage": "https://github.com/libp2p/js-libp2p-examples/tree/master/examples/js-libp2p-example-pubsub#readme", 7 | "repository": { 8 | "type": "git", 9 | "url": "git+https://github.com/libp2p/js-libp2p-examples.git" 10 | }, 11 | "bugs": { 12 | "url": "https://github.com/libp2p/js-libp2p-examples/issues" 13 | }, 14 | "type": "module", 15 | "files": [ 16 | "src", 17 | "dist", 18 | "!dist/test", 19 | "!**/*.tsbuildinfo" 20 | ], 21 | "exports": { 22 | ".": { 23 | "types": "./dist/src/index.d.ts", 24 | "import": "./src/index.js" 25 | } 26 | }, 27 | "scripts": { 28 | "test": "test-node-example test/*" 29 | }, 30 | "dependencies": { 31 | "@chainsafe/libp2p-gossipsub": "^14.1.0", 32 | "@chainsafe/libp2p-noise": "^16.0.0", 33 | "@chainsafe/libp2p-yamux": "^7.0.0", 34 | "@libp2p/identify": "^3.0.1", 35 | "@libp2p/tcp": "^10.0.0", 36 | "libp2p": "^2.0.0", 37 | "uint8arrays": "^5.1.0" 38 | }, 39 | "devDependencies": { 40 | "test-ipfs-example": "^1.1.0" 41 | }, 42 | "private": true 43 | } 44 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-pubsub/test/test-1.js: -------------------------------------------------------------------------------- 1 | import path from 'path' 2 | import { fileURLToPath } from 'url' 3 | import { waitForOutput } from 'test-ipfs-example/node' 4 | 5 | const __dirname = path.dirname(fileURLToPath(import.meta.url)) 6 | 7 | export async function test () { 8 | process.stdout.write('1.js\n') 9 | 10 | await waitForOutput('node1 received: Bird bird bird, bird is the word!', 'node', [path.join(__dirname, '../1.js')], { 11 | cwd: __dirname 12 | }) 13 | } 14 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-pubsub/test/test-2.js: -------------------------------------------------------------------------------- 1 | import path from 'path' 2 | import { fileURLToPath } from 'url' 3 | import { waitForOutput } from 'test-ipfs-example/node' 4 | 5 | const __dirname = path.dirname(fileURLToPath(import.meta.url)) 6 | 7 | export async function test () { 8 | process.stdout.write('2.js\n') 9 | 10 | try { 11 | await waitForOutput('node3 received: car', 'node', [path.join(__dirname, '../2.js')], { 12 | cwd: __dirname, 13 | timeout: 2000 14 | }) 15 | 16 | throw new Error('Matched content when should not have') 17 | } catch (err) { 18 | if (err.message !== 'Timed out' && !err.message.includes('Did not see')) { 19 | throw err 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-pubsub/test/test.js: -------------------------------------------------------------------------------- 1 | import { test as test1 } from './test-1.js' 2 | import { test as test2 } from './test-2.js' 3 | 4 | await test1() 5 | await test2() 6 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-transports/.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | # ⚠️ IMPORTANT ⚠️ 2 | 3 | # Please do not create a Pull Request for this repository 4 | 5 | The contents of this repository are automatically synced from the parent [js-libp2p Examples Project](https://github.com/libp2p/js-libp2p-examples) so any changes made to the standalone repository will be lost after the next sync. 6 | 7 | Please open a PR against [js-libp2p Examples](https://github.com/libp2p/js-libp2p-examples) instead. 8 | 9 | ## Contributing 10 | 11 | Contributions are what make the open source community such an amazing place to be learn, inspire, and create. Any contributions you make are **greatly appreciated**. 12 | 13 | 1. Fork the [js-libp2p Examples Project](https://github.com/libp2p/js-libp2p-examples) 14 | 2. Create your Feature Branch (`git checkout -b feature/amazing-example`) 15 | 3. Commit your Changes (`git commit -a -m 'feat: add some amazing example'`) 16 | 4. Push to the Branch (`git push origin feature/amazing-example`) 17 | 5. Open a Pull Request 18 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-transports/.github/workflows/sync.yml: -------------------------------------------------------------------------------- 1 | name: pull 2 | 3 | on: 4 | workflow_dispatch 5 | 6 | jobs: 7 | sync: 8 | runs-on: ubuntu-latest 9 | steps: 10 | - uses: actions/checkout@v2 11 | - name: Pull from another repository 12 | uses: ipfs-examples/actions-pull-directory-from-repo@main 13 | with: 14 | source-repo: libp2p/js-libp2p-examples 15 | source-folder-path: examples/${{ github.event.repository.name }} 16 | source-branch: main 17 | target-branch: main 18 | git-username: github-actions 19 | git-email: github-actions@github.com 20 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-transports/1.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | 3 | import { noise } from '@chainsafe/libp2p-noise' 4 | import { tcp } from '@libp2p/tcp' 5 | import { createLibp2p } from 'libp2p' 6 | 7 | const createNode = async () => { 8 | const node = await createLibp2p({ 9 | addresses: { 10 | // To signal the addresses we want to be available, we use 11 | // the multiaddr format, a self describable address 12 | listen: [ 13 | '/ip4/0.0.0.0/tcp/0' 14 | ] 15 | }, 16 | transports: [ 17 | tcp() 18 | ], 19 | connectionEncrypters: [ 20 | noise() 21 | ] 22 | }) 23 | 24 | return node 25 | } 26 | 27 | const node = await createNode() 28 | 29 | console.log('node has started') 30 | console.log('listening on:') 31 | node.getMultiaddrs().forEach((ma) => console.log(ma.toString())) 32 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-transports/2.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | 3 | import { noise } from '@chainsafe/libp2p-noise' 4 | import { yamux } from '@chainsafe/libp2p-yamux' 5 | import { tcp } from '@libp2p/tcp' 6 | import { pipe } from 'it-pipe' 7 | import toBuffer from 'it-to-buffer' 8 | import { createLibp2p } from 'libp2p' 9 | import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string' 10 | import { toString as uint8ArrayToString } from 'uint8arrays/to-string' 11 | 12 | const createNode = async () => { 13 | const node = await createLibp2p({ 14 | addresses: { 15 | // To signal the addresses we want to be available, we use 16 | // the multiaddr format, a self describable address 17 | listen: ['/ip4/0.0.0.0/tcp/0'] 18 | }, 19 | transports: [tcp()], 20 | connectionEncrypters: [noise()], 21 | streamMuxers: [yamux()] 22 | }) 23 | 24 | return node 25 | } 26 | 27 | function printAddrs (node, number) { 28 | console.log('node %s is listening on:', number) 29 | node.getMultiaddrs().forEach((ma) => console.log(ma.toString())) 30 | } 31 | 32 | const [node1, node2] = await Promise.all([ 33 | createNode(), 34 | createNode() 35 | ]) 36 | 37 | printAddrs(node1, '1') 38 | printAddrs(node2, '2') 39 | 40 | node2.handle('/print', async ({ stream }) => { 41 | const result = await pipe( 42 | stream, 43 | async function * (source) { 44 | for await (const list of source) { 45 | yield list.subarray() 46 | } 47 | }, 48 | toBuffer 49 | ) 50 | console.log(uint8ArrayToString(result)) 51 | }) 52 | 53 | await node1.peerStore.patch(node2.peerId, { 54 | multiaddrs: node2.getMultiaddrs() 55 | }) 56 | const stream = await node1.dialProtocol(node2.peerId, '/print') 57 | 58 | await pipe( 59 | ['Hello', ' ', 'p2p', ' ', 'world', '!'].map(str => uint8ArrayFromString(str)), 60 | stream 61 | ) 62 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-transports/3.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | 3 | import { noise } from '@chainsafe/libp2p-noise' 4 | import { yamux } from '@chainsafe/libp2p-yamux' 5 | import { tcp } from '@libp2p/tcp' 6 | import { webSockets } from '@libp2p/websockets' 7 | import { pipe } from 'it-pipe' 8 | import { createLibp2p } from 'libp2p' 9 | import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string' 10 | import { toString as uint8ArrayToString } from 'uint8arrays/to-string' 11 | 12 | const createNode = async (transports, addresses = []) => { 13 | if (!Array.isArray(addresses)) { 14 | addresses = [addresses] 15 | } 16 | 17 | const node = await createLibp2p({ 18 | addresses: { 19 | listen: addresses 20 | }, 21 | transports, 22 | connectionEncrypters: [noise()], 23 | streamMuxers: [yamux()] 24 | }) 25 | 26 | return node 27 | } 28 | 29 | function printAddrs (node, number) { 30 | console.log('node %s is listening on:', number) 31 | node.getMultiaddrs().forEach((ma) => console.log(ma.toString())) 32 | } 33 | 34 | function print ({ stream }) { 35 | pipe( 36 | stream, 37 | async function (source) { 38 | for await (const msg of source) { 39 | console.log(uint8ArrayToString(msg.subarray())) 40 | } 41 | } 42 | ) 43 | } 44 | 45 | const [node1, node2, node3] = await Promise.all([ 46 | createNode([tcp()], '/ip4/0.0.0.0/tcp/0'), 47 | createNode([tcp(), webSockets()], ['/ip4/0.0.0.0/tcp/0', '/ip4/127.0.0.1/tcp/10000/ws']), 48 | createNode([webSockets()], '/ip4/127.0.0.1/tcp/20000/ws') 49 | ]) 50 | 51 | printAddrs(node1, '1') 52 | printAddrs(node2, '2') 53 | printAddrs(node3, '3') 54 | 55 | node1.handle('/print', print) 56 | node2.handle('/print', print) 57 | node3.handle('/print', print) 58 | 59 | await node1.peerStore.patch(node2.peerId, { 60 | multiaddrs: node2.getMultiaddrs() 61 | }) 62 | await node2.peerStore.patch(node3.peerId, { 63 | multiaddrs: node3.getMultiaddrs() 64 | }) 65 | await node3.peerStore.patch(node1.peerId, { 66 | multiaddrs: node1.getMultiaddrs() 67 | }) 68 | 69 | // node 1 (TCP) dials to node 2 (TCP+WebSockets) 70 | const stream = await node1.dialProtocol(node2.peerId, '/print') 71 | await pipe( 72 | [uint8ArrayFromString('node 1 dialed to node 2 successfully')], 73 | stream 74 | ) 75 | 76 | // node 2 (TCP+WebSockets) dials to node 3 (WebSockets) 77 | const stream2 = await node2.dialProtocol(node3.peerId, '/print') 78 | await pipe( 79 | [uint8ArrayFromString('node 2 dialed to node 3 successfully')], 80 | stream2 81 | ) 82 | 83 | // node 3 (listening WebSockets) can dial node 1 (TCP) 84 | try { 85 | await node3.dialProtocol(node1.peerId, '/print') 86 | } catch (err) { 87 | console.log('node 3 failed to dial to node 1 with:', err.message) 88 | } 89 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-transports/4.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | 3 | import fs from 'fs' 4 | import { noise } from '@chainsafe/libp2p-noise' 5 | import { yamux } from '@chainsafe/libp2p-yamux' 6 | import { tcp } from '@libp2p/tcp' 7 | import { webSockets } from '@libp2p/websockets' 8 | import { pipe } from 'it-pipe' 9 | import { createLibp2p } from 'libp2p' 10 | import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string' 11 | import { toString as uint8ArrayToString } from 'uint8arrays/to-string' 12 | 13 | const createNode = async (addresses = []) => { 14 | if (!Array.isArray(addresses)) { 15 | addresses = [addresses] 16 | } 17 | 18 | const node = await createLibp2p({ 19 | addresses: { 20 | listen: addresses 21 | }, 22 | transports: [ 23 | tcp(), 24 | webSockets({ 25 | https: { 26 | cert: fs.readFileSync('./test_certs/cert.pem'), 27 | key: fs.readFileSync('./test_certs/key.pem') 28 | }, 29 | websocket: { 30 | rejectUnauthorized: false 31 | } 32 | }) 33 | ], 34 | connectionEncrypters: [noise()], 35 | streamMuxers: [yamux()] 36 | }) 37 | 38 | return node 39 | } 40 | 41 | function printAddrs (node, number) { 42 | console.log('node %s is listening on:', number) 43 | node.getMultiaddrs().forEach((ma) => console.log(ma.toString())) 44 | } 45 | 46 | function print ({ stream }) { 47 | pipe( 48 | stream, 49 | async function (source) { 50 | for await (const msg of source) { 51 | console.log(uint8ArrayToString(msg.subarray())) 52 | } 53 | } 54 | ) 55 | } 56 | 57 | const [node1, node2] = await Promise.all([ 58 | createNode('/ip4/127.0.0.1/tcp/10000/wss'), 59 | createNode([]) 60 | ]) 61 | 62 | printAddrs(node1, '1') 63 | printAddrs(node2, '2') 64 | 65 | node1.handle('/print', print) 66 | node2.handle('/print', print) 67 | 68 | const targetAddr = node1.getMultiaddrs()[0] 69 | 70 | // node 2 (Secure WebSockets) dials to node 1 (Secure Websockets) 71 | const stream = await node2.dialProtocol(targetAddr, '/print') 72 | await pipe( 73 | [uint8ArrayFromString('node 2 dialed to node 1 successfully')], 74 | stream 75 | ) 76 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-transports/LICENSE: -------------------------------------------------------------------------------- 1 | This project is dual licensed under MIT and Apache-2.0. 2 | 3 | MIT: https://www.opensource.org/licenses/mit 4 | Apache-2.0: https://www.apache.org/licenses/license-2.0 5 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-transports/LICENSE-APACHE: -------------------------------------------------------------------------------- 1 | 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 2 | 3 | http://www.apache.org/licenses/LICENSE-2.0 4 | 5 | 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. 6 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-transports/LICENSE-MIT: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-transports/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@libp2p/example-transports", 3 | "version": "0.0.0", 4 | "description": "An example using different types of libp2p transport", 5 | "license": "Apache-2.0 OR MIT", 6 | "homepage": "https://github.com/libp2p/js-libp2p-examples/tree/master/examples/js-libp2p-example-transports#readme", 7 | "repository": { 8 | "type": "git", 9 | "url": "git+https://github.com/libp2p/js-libp2p-examples.git" 10 | }, 11 | "bugs": { 12 | "url": "https://github.com/libp2p/js-libp2p-examples/issues" 13 | }, 14 | "type": "module", 15 | "scripts": { 16 | "test": "test-node-example test/*" 17 | }, 18 | "dependencies": { 19 | "@chainsafe/libp2p-noise": "^16.0.0", 20 | "@chainsafe/libp2p-yamux": "^7.0.0", 21 | "@libp2p/tcp": "^10.0.0", 22 | "@libp2p/websockets": "^9.1.0", 23 | "it-pipe": "^3.0.1", 24 | "it-to-buffer": "^4.0.2", 25 | "libp2p": "^2.0.0", 26 | "uint8arrays": "^5.1.0" 27 | }, 28 | "devDependencies": { 29 | "test-ipfs-example": "^1.1.0" 30 | }, 31 | "private": true 32 | } 33 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-transports/test/test-1.js: -------------------------------------------------------------------------------- 1 | import path from 'path' 2 | import { fileURLToPath } from 'url' 3 | import { waitForOutput } from 'test-ipfs-example/node' 4 | 5 | const __dirname = path.dirname(fileURLToPath(import.meta.url)) 6 | 7 | export async function test () { 8 | process.stdout.write('1.js\n') 9 | 10 | await waitForOutput('/p2p/', 'node', [path.join(__dirname, '../1.js')], { 11 | cwd: __dirname 12 | }) 13 | } 14 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-transports/test/test-2.js: -------------------------------------------------------------------------------- 1 | import path from 'path' 2 | import { fileURLToPath } from 'url' 3 | import { waitForOutput } from 'test-ipfs-example/node' 4 | 5 | const __dirname = path.dirname(fileURLToPath(import.meta.url)) 6 | 7 | export async function test () { 8 | process.stdout.write('2.js\n') 9 | 10 | await waitForOutput('Hello p2p world!', 'node', [path.join(__dirname, '../2.js')], { 11 | cwd: __dirname 12 | }) 13 | } 14 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-transports/test/test-3.js: -------------------------------------------------------------------------------- 1 | import path from 'path' 2 | import { fileURLToPath } from 'url' 3 | import { waitForOutput } from 'test-ipfs-example/node' 4 | 5 | const __dirname = path.dirname(fileURLToPath(import.meta.url)) 6 | 7 | export async function test () { 8 | process.stdout.write('3.js\n') 9 | 10 | await waitForOutput('node 3 failed to dial to node 1 with:', 'node', [path.join(__dirname, '../3.js')], { 11 | cwd: __dirname 12 | }) 13 | } 14 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-transports/test/test-4.js: -------------------------------------------------------------------------------- 1 | import path from 'path' 2 | import { fileURLToPath } from 'url' 3 | import { waitForOutput } from 'test-ipfs-example/node' 4 | 5 | const __dirname = path.dirname(fileURLToPath(import.meta.url)) 6 | 7 | export async function test () { 8 | process.stdout.write('4.js\n') 9 | 10 | await waitForOutput('node 2 dialed to node 1 successfully', 'node', [path.join(__dirname, '../4.js')], { 11 | cwd: path.join(__dirname, '../') 12 | }) 13 | } 14 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-transports/test/test.js: -------------------------------------------------------------------------------- 1 | import { test as test1 } from './test-1.js' 2 | import { test as test2 } from './test-2.js' 3 | import { test as test3 } from './test-3.js' 4 | import { test as test4 } from './test-4.js' 5 | 6 | await test1() 7 | await test2() 8 | await test3() 9 | await test4() 10 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-transports/test_certs/cert.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIFlzCCA3+gAwIBAgIUMYedwb9L/BtvZ7Lhu71iSKrXsa4wDQYJKoZIhvcNAQEL 3 | BQAwajELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAlZBMREwDwYDVQQHDAhTb21lQ2l0 4 | eTESMBAGA1UECgwJTXlDb21wYW55MRMwEQYDVQQLDApNeURpdmlzaW9uMRIwEAYD 5 | VQQDDAkxMjcuMC4wLjEwHhcNMjEwNDI4MDIzMjA5WhcNMjIwNDI4MDIzMjA5WjBq 6 | MQswCQYDVQQGEwJVUzELMAkGA1UECAwCVkExETAPBgNVBAcMCFNvbWVDaXR5MRIw 7 | EAYDVQQKDAlNeUNvbXBhbnkxEzARBgNVBAsMCk15RGl2aXNpb24xEjAQBgNVBAMM 8 | CTEyNy4wLjAuMTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANNhXBu0 9 | GH1Kzl9iaQxCxEnyyAShS5FYScdKxqpYsgJT4poLWLQBZQEFLEqbdillIlTZqMss 10 | jWqkFL2xmjqdcnOKFEZUarntVE2hxFYYQex2Fi8MYwFj+Pvt74d02xPyfzFNFgyX 11 | a1EakoGBwClaf3I7jW7raPudjcf4HnwQ7r/NwiO8FqHFZgLcTnwI8bk+cxDoDAqu 12 | mhqMB5nnerqvKEyR9Fb2PoL+8PwOPJOOKTDVwLMeMJu2WLR8AU2FzOj5SVI2qsu9 13 | Ps5azysD8KQAMcw4y9s6do36SaMQS85fbvXBV7XBqMD34HPBUbFiCoFoaCzK9Zfb 14 | pCXyVJMUNmw5hyq9nbjUt4Kvr/58bU2gjUKSdPf6KhBxFnDZwl+2qqPdVIb/qtwz 15 | HExtJWq3upklXNOg3HoR6vcr1O9ReJHrzLRMEb51WP1aN/qJ2/lRskcZ4A806qwr 16 | W67BvnOg6s3ZtxHN9v3bsyfsvC66w8PEfCnCVxugC7cUW0gtW54AU75T3ukg7X+m 17 | vECr/+qIzNEBIxxCPgefCG/JAdJhQ5SCvoARAVPStUIWDmigDeOt7go5nKbdVIJ4 18 | 7bbBFUhHT2mTHu30fHhRqSDcHzwE7Zz6YJIJmKq29UmzUazFnKlLU67MjLJwiDPm 19 | fC3GyOdAWkkZE5hjtkiy+3yWoEHhaJYRI1u3AgMBAAGjNTAzMAsGA1UdDwQEAwIE 20 | MDATBgNVHSUEDDAKBggrBgEFBQcDATAPBgNVHREECDAGhwR/AAABMA0GCSqGSIb3 21 | DQEBCwUAA4ICAQCx/ynu4iCQAK8VId/QQe7GqgOpFgx+6Mce9GQC6ZVEjAPgapsS 22 | Pl+l6+11cFjHKv0+Z/iN2JgkFmNXfwJcfYI0tHbMK+0U9hgKb1eFgiIwCqb4cPOz 23 | wMwusZ95BjIbtcEbL/+pMUpNhmjPz1fOILJZtDVq++lqJCv7t8+SoAmMVYtlcLNg 24 | muuV/UYR3uqvnAJmjgJVWs4otDGrxCYJE48M+9L2Gm05Htpi9WL1bZaQ+fJ85m85 25 | daedLc6R1/ZRTIH6i73sD4rYs0bx1fCJvkbcgXtKMHEkiHuG/MzR7Pa4cJAVKCx9 26 | lRTgrO7Gkllt2+jp4qg0YhdNq89e0DNA5cyB9H4udRgHQOcrlVRiX9OD/Kz+F5m/ 27 | fQwMdbnqdg3ar5DSa8Q5g3bdLbNSCcI9sjCLTkNxUC/XTWGdG03RCVIt1qvBvZHk 28 | JaG6xGpbRZ5CN0T9eindd38JBrkPAPfgl6qhwvcqh6uVFYua+7KmF9K+mKarlmMw 29 | 6RWaw2j4sMgUyRIS6fR9vDc20SrtoNvKQM1U6+0VYs1nizfkmsqqqRODmERKbKwc 30 | ahKJFubXfr8gz+PipAKFZbxr2EPAyoiNkx+0eM6Eedo55oP2BoGHEfXEoAonyMFM 31 | F/xTbpFtdRYE2hwsZCk86fpbcPTmdCY8txeZ7+4Bme2d9XXsTAxF64usqQ== 32 | -----END CERTIFICATE----- 33 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-transports/test_certs/key.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PRIVATE KEY----- 2 | MIIJRAIBADANBgkqhkiG9w0BAQEFAASCCS4wggkqAgEAAoICAQDTYVwbtBh9Ss5f 3 | YmkMQsRJ8sgEoUuRWEnHSsaqWLICU+KaC1i0AWUBBSxKm3YpZSJU2ajLLI1qpBS9 4 | sZo6nXJzihRGVGq57VRNocRWGEHsdhYvDGMBY/j77e+HdNsT8n8xTRYMl2tRGpKB 5 | gcApWn9yO41u62j7nY3H+B58EO6/zcIjvBahxWYC3E58CPG5PnMQ6AwKrpoajAeZ 6 | 53q6ryhMkfRW9j6C/vD8DjyTjikw1cCzHjCbtli0fAFNhczo+UlSNqrLvT7OWs8r 7 | A/CkADHMOMvbOnaN+kmjEEvOX271wVe1wajA9+BzwVGxYgqBaGgsyvWX26Ql8lST 8 | FDZsOYcqvZ241LeCr6/+fG1NoI1CknT3+ioQcRZw2cJftqqj3VSG/6rcMxxMbSVq 9 | t7qZJVzToNx6Eer3K9TvUXiR68y0TBG+dVj9Wjf6idv5UbJHGeAPNOqsK1uuwb5z 10 | oOrN2bcRzfb927Mn7LwuusPDxHwpwlcboAu3FFtILVueAFO+U97pIO1/prxAq//q 11 | iMzRASMcQj4HnwhvyQHSYUOUgr6AEQFT0rVCFg5ooA3jre4KOZym3VSCeO22wRVI 12 | R09pkx7t9Hx4Uakg3B88BO2c+mCSCZiqtvVJs1GsxZypS1OuzIyycIgz5nwtxsjn 13 | QFpJGROYY7ZIsvt8lqBB4WiWESNbtwIDAQABAoICAQCpGV3iG7Trpohp7gQzdsYo 14 | kjxI1+/oGkULVVqQs9vT2N+SdDlF50eyBT1lgfCJNQq97lIGF2IaSaD+D7Jd6c7B 15 | d1i42pd2ndGvORYj+cvjKqSchsA9QIjSoYnZRzZrQrdV7WESOZ/0hdlmGTJs4qTJ 16 | 8bI3ZcPaZjQiIO/iOHmGn0gL5lAEojH1X+C5gT4+/yJ2B+x6LyvAyPzbtj6MUctf 17 | VfOuDdf8W47VVV5IfJWfJ6C8qg4gw0M7P2ibZ8qBJcvuJSWFT6OK2UKaGtDLogw0 18 | X8tVWfO1qOB3vnWmZtoRZ9aO5JnnpWS9tY1w5gmZdLjB/Kt0DJXIdZALCURwV6U0 19 | q5XR0SETEgdRrNX92PA2lmxO9fAgXRSjP/OoeDjAVhnRfYyShDbEIb8GHk7nE+is 20 | 6ak5ufxKE53S8wB9L7MTPqTvxusBHi8saLevdnPBMQPvtEVkg2Iw/iPBsegUuUjD 21 | uzXlq4WUMCUBJEMVPuYEsaQizxpp2oM6AZj/ecuTKFX5CirFFWKOQ4cp+O8lrfI5 22 | ruwHrMkfjowDYcQaOLHq13anvt8+8LBlngVw+jiAGB/bGwrAwEZWUc8i1HbH/G8e 23 | sm0kMuCqV1GbRyMCUO3pWjzrsz8LEy74Jr0z7KZn52vLWrTkiD4NRXahxTBhHpXb 24 | AVclJ+a4BKk2rRJVRFRRQQKCAQEA7+uTl2ZHp1v7A8/I2zPIxoVz0fiwxwAjuv34 25 | cV+uxG0n5Tko4PKMxavddRFKNeGvrz0aO/GNX8NIW7pDqZ2CwHyskgUX/bFAqGKF 26 | Z/z2DmiZ2rdSUH89O3ysq+OF3RjX/FBNJ0SVdwtrpz3kCSWpa4PnmN7+IevL6zxY 27 | 8gLrs07Ge+ci94FZaDHBNrkGQ00krbOmwIvnc90hyRPCKfMS+u2/ejKZ5QDyRG+H 28 | jbQ008ZV2OqUdS6h1twfoJ1Q4QhHijB6PegRLGdZGuUXIQfFP8dIUsQluKSUFyOy 29 | bL9W2yBwtbn3EwYDHLJQnLICxfcTBWg/2vOIucsSjxG7KNY0yQKCAQEA4YwcVpi3 30 | D+8OcnbpRBRlHo84DRZorp0RO8vhxevvB1CcBnkLRIYXlS2JIfrnhZAI/5jBk1ei 31 | FmgRFyAjZ8gDdkDCiDMQMDUwUhLGSVurI9sk16B4TQKCM+iE0LDrXIy9ezJRJkj0 32 | rOt8sqo2/TOttm2KEXY8Cco59tU4bMZg5Tr9l7SMTTj4skTO6Jn6/6hX3XuFkJw7 33 | B0DsSzIqXyRHAzOidagIEoIr7k4cEGXsrSWoSiHg/eky1ihCyUw3vDDOmoViBR7s 34 | h5nLjQNNAzOtyoKLqST7B7uXkdUo5nV2IUHSGD5LNxlTaNp0XL9Ph3EBtcuwNuB6 35 | zyKXc+O5iNfMfwKCAQEA5/RJKCnRgsORxpif5xWEujIRzOHz/yFqagHarbnFHNEv 36 | rhT6Kak2YnIL1H/X0IoWsYSQlX2uofQKQ+ysOBM5c2HV8gKMtFAnY+SEeAn/1eRZ 37 | QzTTl1G84INj6Xc6V40KXD1CqoFLQ+G9vd4/Vnyb9H99bLXC2wa+ivo4QBqEyEGT 38 | 8fyAOOxMhUj9NSvjGzQ9DtbOk/9u0PztChtZL/d61TEAW2MKmHW2xGVTl7OvE0QA 39 | gYwh5b0k6La+uSj/JeE8USUXOjzgRZ7RbggouV1q3YOMr8BFe+NZ7Zksiqjej1Io 40 | xfk6H6FDZv4ao7QSrFR4hlTIz6V9/aqQkdOhsBSQyQKCAQEAzHwz4Qr5xVduGLbY 41 | S6HV/7vHDI6Jf+3lBvqUidWa013w5yls3sZXsSckkgshRoVMszayIbystnXJMNcx 42 | YlEDWn3iIItzHNHMKkzdOvsCETMIlvnkt6UTmK4xY+dSq4jp7Ty0N+qi8fdaCb2q 43 | tyrYTnHHYId6bUHMBY5QZsYAaTNvYNAO96A0UaNyl42q84iTiLkJYg9SsQPad15W 44 | 7gU84Jk6rEMYdndQDvEAHpnZ1y0yA2vtySZYsbK0wj34tgTl+0/8izn7JgF4ezNH 45 | 6iQ7Z0OuDT763IrmIxBH0ZEi9YnwSYyIsr6iUYjlQIUuPFRnQYQXEdm5Xfw1pZsL 46 | xhYoTwKCAQB9edDe4LX+0z9i4qr0iHV8H/WoyI5UD/Pc217PKkYM3+ewR9SL9D9z 47 | TS78Sl7HgRgEmIu+MR/u5B2ePf7jkvB/oxyPwqAzJeJ72mV3Mevm27G/Ndd8lt5W 48 | FBCGOx7ZeP4/Cv4mvPD979ix2IalDoWMSWJnpQPN+B1jGeCrUYAXQc1k/vU99gLa 49 | 8Tuu3WfBpVAsO7hAC9mu6tuLyfKVqiMOVs2aky9xLqiqW/6uIcGu+owrr+gkDDY/ 50 | JfBSUfxYKcjtJiHOEbFGrrRe93XsngmaTz/Hv9A/QLVCuJgWEHlt4WHSc+BtAtaV 51 | 9avp6VlyVNfe4KEKW7IekrI0cmfMdXkl 52 | -----END PRIVATE KEY----- 53 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-webrtc-private-to-private/.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | # ⚠️ IMPORTANT ⚠️ 2 | 3 | # Please do not create a Pull Request for this repository 4 | 5 | The contents of this repository are automatically synced from the parent [js-libp2p Examples Project](https://github.com/libp2p/js-libp2p-examples) so any changes made to the standalone repository will be lost after the next sync. 6 | 7 | Please open a PR against [js-libp2p Examples](https://github.com/libp2p/js-libp2p-examples) instead. 8 | 9 | ## Contributing 10 | 11 | Contributions are what make the open source community such an amazing place to be learn, inspire, and create. Any contributions you make are **greatly appreciated**. 12 | 13 | 1. Fork the [js-libp2p Examples Project](https://github.com/libp2p/js-libp2p-examples) 14 | 2. Create your Feature Branch (`git checkout -b feature/amazing-example`) 15 | 3. Commit your Changes (`git commit -a -m 'feat: add some amazing example'`) 16 | 4. Push to the Branch (`git push origin feature/amazing-example`) 17 | 5. Open a Pull Request 18 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-webrtc-private-to-private/.github/workflows/sync.yml: -------------------------------------------------------------------------------- 1 | name: pull 2 | 3 | on: 4 | workflow_dispatch 5 | 6 | jobs: 7 | sync: 8 | runs-on: ubuntu-latest 9 | steps: 10 | - uses: actions/checkout@v2 11 | - name: Pull from another repository 12 | uses: ipfs-examples/actions-pull-directory-from-repo@main 13 | with: 14 | source-repo: libp2p/js-libp2p-examples 15 | source-folder-path: examples/${{ github.event.repository.name }} 16 | source-branch: main 17 | target-branch: main 18 | git-username: github-actions 19 | git-email: github-actions@github.com 20 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-webrtc-private-to-private/LICENSE: -------------------------------------------------------------------------------- 1 | This project is dual licensed under MIT and Apache-2.0. 2 | 3 | MIT: https://www.opensource.org/licenses/mit 4 | Apache-2.0: https://www.apache.org/licenses/license-2.0 5 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-webrtc-private-to-private/LICENSE-APACHE: -------------------------------------------------------------------------------- 1 | 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 2 | 3 | http://www.apache.org/licenses/LICENSE-2.0 4 | 5 | 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. 6 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-webrtc-private-to-private/LICENSE-MIT: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-webrtc-private-to-private/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | js-libp2p WebRTC 7 | 24 | 25 | 26 |
27 |
28 | 29 | 30 | 31 |
32 |
33 | 34 | 35 | 36 |
37 |
38 |

Active Connections:

39 |
    40 |
    41 |
    42 |

    Listening addresses:

    43 |
      44 |
      45 |

      Output:

      46 |
      47 |
      48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-webrtc-private-to-private/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@libp2p/example-webrtc-private-to-private", 3 | "version": "1.0.0", 4 | "description": "Connect a browser to another browser", 5 | "type": "module", 6 | "scripts": { 7 | "start": "vite", 8 | "build": "vite build", 9 | "relay": "node relay.js", 10 | "test:firefox": "npm run build && playwright test --browser=firefox test", 11 | "test:chrome": "npm run build && playwright test test", 12 | "test": "npm run build && test-browser-example test" 13 | }, 14 | "dependencies": { 15 | "@chainsafe/libp2p-noise": "^16.0.0", 16 | "@chainsafe/libp2p-yamux": "^7.0.0", 17 | "@libp2p/circuit-relay-v2": "^3.0.0", 18 | "@libp2p/identify": "^3.0.1", 19 | "@libp2p/ping": "^2.0.1", 20 | "@libp2p/webrtc": "^5.0.0", 21 | "@libp2p/websockets": "^9.0.0", 22 | "@multiformats/multiaddr": "^12.0.0", 23 | "it-pushable": "^3.2.0", 24 | "libp2p": "^2.0.0", 25 | "vite": "^6.0.3" 26 | }, 27 | "devDependencies": { 28 | "test-ipfs-example": "^1.0.0" 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-webrtc-private-to-private/relay.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | 3 | import { noise } from '@chainsafe/libp2p-noise' 4 | import { yamux } from '@chainsafe/libp2p-yamux' 5 | import { circuitRelayServer } from '@libp2p/circuit-relay-v2' 6 | import { identify } from '@libp2p/identify' 7 | import { webSockets } from '@libp2p/websockets' 8 | import * as filters from '@libp2p/websockets/filters' 9 | import { createLibp2p } from 'libp2p' 10 | 11 | const server = await createLibp2p({ 12 | addresses: { 13 | listen: ['/ip4/127.0.0.1/tcp/0/ws'] 14 | }, 15 | transports: [ 16 | webSockets({ 17 | filter: filters.all 18 | }) 19 | ], 20 | connectionEncrypters: [noise()], 21 | streamMuxers: [yamux()], 22 | services: { 23 | identify: identify(), 24 | relay: circuitRelayServer({ 25 | // disable max reservations limit for demo purposes. in production you 26 | // should leave this set to the default of 15 to prevent abuse of your 27 | // node by network peers 28 | reservations: { 29 | maxReservations: Infinity 30 | } 31 | }) 32 | } 33 | }) 34 | 35 | console.info('The relay node is running and listening on the following multiaddrs:') 36 | console.info('') 37 | console.info(server.getMultiaddrs().map((ma) => ma.toString()).join('\n')) 38 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-webrtc-private-to-private/test/index.spec.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | import { noise } from '@chainsafe/libp2p-noise' 3 | import { yamux } from '@chainsafe/libp2p-yamux' 4 | import { circuitRelayServer } from '@libp2p/circuit-relay-v2' 5 | import { identify } from '@libp2p/identify' 6 | import { webSockets } from '@libp2p/websockets' 7 | import * as filters from '@libp2p/websockets/filters' 8 | import { createLibp2p } from 'libp2p' 9 | import { setup, expect } from 'test-ipfs-example/browser' 10 | 11 | // Setup 12 | const test = setup() 13 | 14 | // DOM 15 | const connectBtn = '#connect' 16 | const connectAddr = '#peer' 17 | const messageInput = '#message' 18 | const sendBtn = '#send' 19 | const output = '#output' 20 | const listeningAddresses = '#multiaddrs' 21 | 22 | let url 23 | 24 | // we spawn a js libp2p relay 25 | async function spawnRelay () { 26 | const relayNode = await createLibp2p({ 27 | addresses: { 28 | listen: ['/ip4/127.0.0.1/tcp/0/ws'] 29 | }, 30 | transports: [ 31 | webSockets({ 32 | filter: filters.all 33 | }) 34 | ], 35 | connectionEncrypters: [noise()], 36 | streamMuxers: [yamux()], 37 | services: { 38 | identify: identify(), 39 | relay: circuitRelayServer() 40 | } 41 | }) 42 | 43 | const relayNodeAddr = relayNode.getMultiaddrs()[0].toString() 44 | 45 | return { relayNode, relayNodeAddr } 46 | } 47 | 48 | test.describe('browser to browser example:', () => { 49 | let relayNode 50 | let relayNodeAddr 51 | 52 | // eslint-disable-next-line no-empty-pattern 53 | test.beforeAll(async ({ servers }, testInfo) => { 54 | testInfo.setTimeout(5 * 60_000) 55 | const r = await spawnRelay() 56 | relayNode = r.relayNode 57 | relayNodeAddr = r.relayNodeAddr 58 | url = servers[0].url 59 | }, {}) 60 | 61 | test.afterAll(() => { 62 | relayNode.stop() 63 | }) 64 | 65 | test.beforeEach(async ({ page }) => { 66 | await page.goto(url) 67 | }) 68 | 69 | test('should connect to another browser peer and send a message', async ({ page: pageA, context }) => { 70 | // load second page 71 | const pageB = await context.newPage() 72 | await pageB.goto(url) 73 | 74 | // connect the first page to the relay 75 | const relayedAddressA = await dialRelay(pageA, relayNodeAddr) 76 | 77 | // dial first page from second page over relay 78 | await dialPeerOverRelay(pageB, relayedAddressA) 79 | 80 | // stop the relay 81 | await relayNode.stop() 82 | 83 | // send a message from a to b 84 | await sendMessage(pageA, pageB, 'hello B from A') 85 | 86 | // send a message from b to a 87 | await sendMessage(pageB, pageA, 'hello A from B') 88 | }) 89 | }) 90 | 91 | async function sendMessage (senderPage, recipientPage, message) { 92 | // send the message to the peer over webRTC 93 | await senderPage.fill(messageInput, message) 94 | await senderPage.click(sendBtn) 95 | 96 | // check the message was sent 97 | await expect(senderPage.locator(output)).toContainText(`Sending message '${message}'`) 98 | // check the message was received 99 | await expect(recipientPage.locator(output)).toContainText(`Received message '${message}'`) 100 | } 101 | 102 | async function dialRelay (page, address) { 103 | // add the go libp2p multiaddress to the input field and submit 104 | await page.fill(connectAddr, address) 105 | await page.click(connectBtn) 106 | 107 | const outputLocator = page.locator(output) 108 | await expect(outputLocator).toContainText(`Dialing '${address}'`) 109 | await expect(outputLocator).toContainText('Connected to relay') 110 | 111 | const multiaddrsLocator = page.locator(listeningAddresses) 112 | await expect(multiaddrsLocator).toHaveText(/webrtc/) 113 | 114 | const multiaddrs = await page.textContent(listeningAddresses) 115 | const addr = multiaddrs.split(address).filter(str => str.includes('webrtc')).pop() 116 | 117 | return address + addr 118 | } 119 | 120 | async function dialPeerOverRelay (page, address) { 121 | // add the go libp2p multiaddr to the input field and submit 122 | await page.fill(connectAddr, address) 123 | await page.click(connectBtn) 124 | 125 | const outputLocator = page.locator(output) 126 | await expect(outputLocator).toContainText(`Dialing '${address}'`) 127 | await expect(outputLocator).toContainText(`Connected to '${address}'`) 128 | } 129 | -------------------------------------------------------------------------------- /examples/js-libp2p-example-webrtc-private-to-private/vite.config.js: -------------------------------------------------------------------------------- 1 | export default { 2 | build: { 3 | target: 'es2022' 4 | }, 5 | optimizeDeps: { 6 | esbuildOptions: { target: 'es2022', supported: { bigint: true } } 7 | }, 8 | server: { 9 | open: true 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "js-libp2p-examples", 3 | "version": "1.0.0", 4 | "description": "Examples of how to use js-libp2p", 5 | "type": "module", 6 | "scripts": { 7 | "reset": "aegir run clean && aegir clean **/node_modules **/package-lock.json", 8 | "test": "aegir run --concurrency 1 test", 9 | "clean": "aegir run clean", 10 | "build": "aegir run build", 11 | "lint": "aegir exec aegir -- lint --files '**/*.{js,ts,jsx}' '!**/node_modules/**' '!**/dist/**'", 12 | "lint:fix": "aegir exec aegir -- lint --files '**/*.{js,ts,jsx}' '!**/node_modules/**' '!**/dist/**' --fix", 13 | "dep-check": "aegir run dep-check" 14 | }, 15 | "repository": { 16 | "type": "git", 17 | "url": "git+https://github.com/libp2p/js-libp2p-examples.git" 18 | }, 19 | "author": "", 20 | "license": "ISC", 21 | "bugs": { 22 | "url": "https://github.com/libp2p/js-libp2p-examples/issues" 23 | }, 24 | "homepage": "https://github.com/libp2p/js-libp2p-examples#readme", 25 | "eslintConfig": { 26 | "extends": "ipfs", 27 | "parserOptions": { 28 | "project": true, 29 | "sourceType": "module" 30 | } 31 | }, 32 | "devDependencies": { 33 | "aegir": "^45.0.8" 34 | }, 35 | "workspaces": [ 36 | "examples/*" 37 | ], 38 | "private": true 39 | } 40 | --------------------------------------------------------------------------------