├── .aegir.js ├── .github ├── dependabot.yml ├── pull_request_template.md └── workflows │ ├── generated-pr.yml │ ├── js-test-and-release.yml │ ├── semantic-pull-request.yml │ └── stale.yml ├── .gitignore ├── CHANGELOG.md ├── CODEOWNERS ├── LICENSE ├── LICENSE-APACHE ├── LICENSE-MIT ├── README.md ├── package.json ├── src └── index.ts ├── test └── index.spec.ts ├── tsconfig.json └── typedoc.json /.aegir.js: -------------------------------------------------------------------------------- 1 | import { createServer } from 'ipfsd-ctl' 2 | import * as ipfsHttpModule from 'kubo-rpc-client' 3 | import goIpfsModule from 'kubo' 4 | 5 | let server 6 | 7 | export default { 8 | test: { 9 | before: async () => { 10 | server = createServer({ 11 | host: '127.0.0.1', 12 | port: 57583 13 | }, { 14 | type: 'go', 15 | ipfsHttpModule, 16 | ipfsBin: goIpfsModule.path(), 17 | test: true 18 | }) 19 | 20 | await server.start() 21 | }, 22 | after: () => server.stop() 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: npm 4 | directory: "/" 5 | schedule: 6 | interval: daily 7 | time: "10:00" 8 | open-pull-requests-limit: 10 9 | commit-message: 10 | prefix: "deps" 11 | prefix-development: "deps(dev)" 12 | -------------------------------------------------------------------------------- /.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/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/js-test-and-release.yml: -------------------------------------------------------------------------------- 1 | name: test & maybe release 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | pull_request: 8 | workflow_dispatch: 9 | 10 | permissions: 11 | contents: write 12 | id-token: write 13 | packages: write 14 | pull-requests: write 15 | 16 | concurrency: 17 | group: ${{ github.workflow }}-${{ github.event_name }}-${{ github.event_name == 'push' && github.sha || github.ref }} 18 | cancel-in-progress: true 19 | 20 | jobs: 21 | js-test-and-release: 22 | uses: ipdxco/unified-github-workflows/.github/workflows/js-test-and-release.yml@v1.0 23 | secrets: 24 | DOCKER_TOKEN: ${{ secrets.DOCKER_TOKEN }} 25 | DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }} 26 | NPM_TOKEN: ${{ secrets.NPM_TOKEN }} 27 | UCI_GITHUB_TOKEN: ${{ secrets.UCI_GITHUB_TOKEN }} 28 | CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} 29 | -------------------------------------------------------------------------------- /.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 | .vscode 10 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## [4.0.14](https://github.com/libp2p/js-libp2p-delegated-peer-routing/compare/v4.0.13...v4.0.14) (2023-10-09) 2 | 3 | 4 | ### Dependencies 5 | 6 | * swap go-ipfs for kubo ([#154](https://github.com/libp2p/js-libp2p-delegated-peer-routing/issues/154)) ([0e3ca6c](https://github.com/libp2p/js-libp2p-delegated-peer-routing/commit/0e3ca6cc057caf87911d4be4467fc31e9698559c)) 7 | 8 | ## [4.0.13](https://github.com/libp2p/js-libp2p-delegated-peer-routing/compare/v4.0.12...v4.0.13) (2023-10-06) 9 | 10 | 11 | ### Trivial Changes 12 | 13 | * add missing dep ([ba7f237](https://github.com/libp2p/js-libp2p-delegated-peer-routing/commit/ba7f23742998980231f6be4bb885979f9bab1059)) 14 | * Update .github/pull_request_template.md [skip ci] ([7ec087a](https://github.com/libp2p/js-libp2p-delegated-peer-routing/commit/7ec087a24013a4406393efee09c8385c976ff6c6)) 15 | * update config ([4095e1d](https://github.com/libp2p/js-libp2p-delegated-peer-routing/commit/4095e1d0efb563f27d1fae1df6ef9bfe3011fcdc)) 16 | 17 | 18 | ### Dependencies 19 | 20 | * **dev:** bump aegir from 39.0.13 to 40.0.8 ([#149](https://github.com/libp2p/js-libp2p-delegated-peer-routing/issues/149)) ([2b97412](https://github.com/libp2p/js-libp2p-delegated-peer-routing/commit/2b97412c2eeb080732434008d61cf38d6163ec37)) 21 | 22 | ## [4.0.12](https://github.com/libp2p/js-libp2p-delegated-peer-routing/compare/v4.0.11...v4.0.12) (2023-08-30) 23 | 24 | 25 | ### Dependencies 26 | 27 | * upgrade all deps ([#153](https://github.com/libp2p/js-libp2p-delegated-peer-routing/issues/153)) ([6835c29](https://github.com/libp2p/js-libp2p-delegated-peer-routing/commit/6835c292721de83cc43ad9c0279550ce7b8063e1)) 28 | 29 | ## [4.0.11](https://github.com/libp2p/js-libp2p-delegated-peer-routing/compare/v4.0.10...v4.0.11) (2023-08-24) 30 | 31 | 32 | ### Trivial Changes 33 | 34 | * add or force update .github/workflows/js-test-and-release.yml ([#152](https://github.com/libp2p/js-libp2p-delegated-peer-routing/issues/152)) ([fbd004f](https://github.com/libp2p/js-libp2p-delegated-peer-routing/commit/fbd004f7bd8f51d0db1ca408fdfcec65096a603c)) 35 | * delete templates [skip ci] ([#151](https://github.com/libp2p/js-libp2p-delegated-peer-routing/issues/151)) ([4f1dd24](https://github.com/libp2p/js-libp2p-delegated-peer-routing/commit/4f1dd24d66ee781b826ee7ad5be0262b88f8ba4a)) 36 | * Update CODEOWNERS [skip ci] ([61f7181](https://github.com/libp2p/js-libp2p-delegated-peer-routing/commit/61f7181c499943a0bd8eb429f462982fcc19e6e7)) 37 | 38 | 39 | ### Dependencies 40 | 41 | * bump multiformats from 11.0.2 to 12.0.1 ([#141](https://github.com/libp2p/js-libp2p-delegated-peer-routing/issues/141)) ([09e2564](https://github.com/libp2p/js-libp2p-delegated-peer-routing/commit/09e2564c97c4599526383928309b0968e07255d8)) 42 | 43 | ## [4.0.10](https://github.com/libp2p/js-libp2p-delegated-peer-routing/compare/v4.0.9...v4.0.10) (2023-08-01) 44 | 45 | 46 | ### Dependencies 47 | 48 | * bump @libp2p/logger from 2.1.1 to 3.0.0 ([#146](https://github.com/libp2p/js-libp2p-delegated-peer-routing/issues/146)) ([92d5157](https://github.com/libp2p/js-libp2p-delegated-peer-routing/commit/92d51573fd6e9adfa30b03c49b1cf03b40987426)) 49 | * bump @libp2p/peer-id from 2.0.4 to 3.0.0 ([#147](https://github.com/libp2p/js-libp2p-delegated-peer-routing/issues/147)) ([a973107](https://github.com/libp2p/js-libp2p-delegated-peer-routing/commit/a973107981bf3bb255b9937e4b773bd8f066d437)) 50 | * **dev:** bump @libp2p/peer-id-factory from 2.0.4 to 3.0.0 ([#148](https://github.com/libp2p/js-libp2p-delegated-peer-routing/issues/148)) ([9cc56e0](https://github.com/libp2p/js-libp2p-delegated-peer-routing/commit/9cc56e0b5374336e3702f41ef9e513e54a4dbae8)) 51 | 52 | ## [4.0.9](https://github.com/libp2p/js-libp2p-delegated-peer-routing/compare/v4.0.8...v4.0.9) (2023-07-03) 53 | 54 | 55 | ### Trivial Changes 56 | 57 | * Update .github/workflows/semantic-pull-request.yml [skip ci] ([c8a44d6](https://github.com/libp2p/js-libp2p-delegated-peer-routing/commit/c8a44d67250fa8a7a4dfa70e5010bfb4c7dcb077)) 58 | * Update .github/workflows/stale.yml [skip ci] ([dca049c](https://github.com/libp2p/js-libp2p-delegated-peer-routing/commit/dca049c2b20f6dfbef273d42f2c525a0f8ba6ddf)) 59 | * Update .github/workflows/stale.yml [skip ci] ([b97c54f](https://github.com/libp2p/js-libp2p-delegated-peer-routing/commit/b97c54f2dd9b9543812e409c4f14f3882273e99f)) 60 | 61 | 62 | ### Dependencies 63 | 64 | * **dev:** bump go-ipfs from 0.20.0 to 0.21.0 ([#142](https://github.com/libp2p/js-libp2p-delegated-peer-routing/issues/142)) ([6d6e445](https://github.com/libp2p/js-libp2p-delegated-peer-routing/commit/6d6e445bd43a0ea6db0b0d6eccba8be6d11a2176)) 65 | 66 | ## [4.0.8](https://github.com/libp2p/js-libp2p-delegated-peer-routing/compare/v4.0.7...v4.0.8) (2023-05-31) 67 | 68 | 69 | ### Dependencies 70 | 71 | * swap ipfs-http-client for kubo-rpc-client ([#140](https://github.com/libp2p/js-libp2p-delegated-peer-routing/issues/140)) ([0f3e0a3](https://github.com/libp2p/js-libp2p-delegated-peer-routing/commit/0f3e0a380b0dfec0395283ad49030a03399ae645)) 72 | 73 | ## [4.0.7](https://github.com/libp2p/js-libp2p-delegated-peer-routing/compare/v4.0.6...v4.0.7) (2023-05-31) 74 | 75 | 76 | ### Dependencies 77 | 78 | * **dev:** bump aegir from 38.1.8 to 39.0.9 ([#139](https://github.com/libp2p/js-libp2p-delegated-peer-routing/issues/139)) ([797c287](https://github.com/libp2p/js-libp2p-delegated-peer-routing/commit/797c287d54cea3226debcdbd196a7d5e17641b1f)) 79 | * **dev:** bump it-drain from 2.0.1 to 3.0.2 ([#135](https://github.com/libp2p/js-libp2p-delegated-peer-routing/issues/135)) ([9933748](https://github.com/libp2p/js-libp2p-delegated-peer-routing/commit/993374867a6a9b189bfb23abc4ba5851528b59b7)) 80 | 81 | ## [4.0.6](https://github.com/libp2p/js-libp2p-delegated-peer-routing/compare/v4.0.5...v4.0.6) (2023-05-05) 82 | 83 | 84 | ### Bug Fixes 85 | 86 | * remove use of timeout-abort-controller ([#129](https://github.com/libp2p/js-libp2p-delegated-peer-routing/issues/129)) ([2fbde9a](https://github.com/libp2p/js-libp2p-delegated-peer-routing/commit/2fbde9a1d297948fee320eeda4f4b0c53d3e75f0)) 87 | 88 | ## [4.0.5](https://github.com/libp2p/js-libp2p-delegated-peer-routing/compare/v4.0.4...v4.0.5) (2023-03-31) 89 | 90 | 91 | ### Dependencies 92 | 93 | * **dev:** bump it-all from 2.0.1 to 3.0.1 ([#124](https://github.com/libp2p/js-libp2p-delegated-peer-routing/issues/124)) ([8d41444](https://github.com/libp2p/js-libp2p-delegated-peer-routing/commit/8d4144478f566f85ab64f9054ca0f378025a23c9)) 94 | 95 | ## [4.0.4](https://github.com/libp2p/js-libp2p-delegated-peer-routing/compare/v4.0.3...v4.0.4) (2023-03-22) 96 | 97 | 98 | ### Bug Fixes 99 | 100 | * replace err-code with CodeError ([#122](https://github.com/libp2p/js-libp2p-delegated-peer-routing/issues/122)) ([a02a0ce](https://github.com/libp2p/js-libp2p-delegated-peer-routing/commit/a02a0cea483acbfccf6fbb2399d5dff03dfb5a8e)) 101 | 102 | ## [4.0.3](https://github.com/libp2p/js-libp2p-delegated-peer-routing/compare/v4.0.2...v4.0.3) (2023-03-21) 103 | 104 | 105 | ### Bug Fixes 106 | 107 | * **debug-logs:** use 'libp2p:' namespace ([#121](https://github.com/libp2p/js-libp2p-delegated-peer-routing/issues/121)) ([a3e085e](https://github.com/libp2p/js-libp2p-delegated-peer-routing/commit/a3e085e113ddcf032ae7a4a61f6fdd7fb95cebd2)) 108 | 109 | ## [4.0.2](https://github.com/libp2p/js-libp2p-delegated-peer-routing/compare/v4.0.1...v4.0.2) (2023-03-20) 110 | 111 | 112 | ### Dependencies 113 | 114 | * **dev:** bump ipfsd-ctl from 12.2.2 to 13.0.0 ([#104](https://github.com/libp2p/js-libp2p-delegated-peer-routing/issues/104)) ([9221778](https://github.com/libp2p/js-libp2p-delegated-peer-routing/commit/9221778669ed0b926d85a745e3a3adaf9e64ed24)) 115 | 116 | ## [4.0.1](https://github.com/libp2p/js-libp2p-delegated-peer-routing/compare/v4.0.0...v4.0.1) (2023-03-16) 117 | 118 | 119 | ### Trivial Changes 120 | 121 | * Update .github/workflows/semantic-pull-request.yml [skip ci] ([b0f81bf](https://github.com/libp2p/js-libp2p-delegated-peer-routing/commit/b0f81bf27e440b3420d8516c41156c527d8d8c78)) 122 | * Update .github/workflows/semantic-pull-request.yml [skip ci] ([c89a5e1](https://github.com/libp2p/js-libp2p-delegated-peer-routing/commit/c89a5e14ac5d7fb433d68aa6df36c84fc6f4a4be)) 123 | * Update .github/workflows/semantic-pull-request.yml [skip ci] ([dc5e6d9](https://github.com/libp2p/js-libp2p-delegated-peer-routing/commit/dc5e6d9b06a1ffba4d787bd8f0c96a6b0a755e62)) 124 | * upgrade aegir to `38.1.2` ([#109](https://github.com/libp2p/js-libp2p-delegated-peer-routing/issues/109)) ([17e7928](https://github.com/libp2p/js-libp2p-delegated-peer-routing/commit/17e79283b9a50bdee6d6f15405299a7e2cd1bac1)) 125 | 126 | 127 | ### Documentation 128 | 129 | * Update README.md ([#117](https://github.com/libp2p/js-libp2p-delegated-peer-routing/issues/117)) ([2662c50](https://github.com/libp2p/js-libp2p-delegated-peer-routing/commit/2662c50eee8f58fedbae281b6494b9352a14498a)) 130 | 131 | ## [4.0.0](https://github.com/libp2p/js-libp2p-delegated-peer-routing/compare/v3.0.1...v4.0.0) (2023-01-06) 132 | 133 | 134 | ### ⚠ BREAKING CHANGES 135 | 136 | * update multiformats to v11 (#101) 137 | 138 | ### Bug Fixes 139 | 140 | * update multiformats to v11 ([#101](https://github.com/libp2p/js-libp2p-delegated-peer-routing/issues/101)) ([c924389](https://github.com/libp2p/js-libp2p-delegated-peer-routing/commit/c924389f7a0156978497e6b293c9c2dc39885be0)) 141 | 142 | ## [3.0.1](https://github.com/libp2p/js-libp2p-delegated-peer-routing/compare/v3.0.0...v3.0.1) (2022-12-19) 143 | 144 | 145 | ### Documentation 146 | 147 | * publish api docs ([#99](https://github.com/libp2p/js-libp2p-delegated-peer-routing/issues/99)) ([5bd7679](https://github.com/libp2p/js-libp2p-delegated-peer-routing/commit/5bd7679865a0dd14412ad50a5180798a27dc41c3)) 148 | 149 | ## [3.0.0](https://github.com/libp2p/js-libp2p-delegated-peer-routing/compare/v2.0.2...v3.0.0) (2022-10-13) 150 | 151 | 152 | ### ⚠ BREAKING CHANGES 153 | 154 | * modules no longer implement `Initializable` instead switching to constructor injection 155 | 156 | ### Bug Fixes 157 | 158 | * remove @libp2p/components ([#90](https://github.com/libp2p/js-libp2p-delegated-peer-routing/issues/90)) ([a3816b1](https://github.com/libp2p/js-libp2p-delegated-peer-routing/commit/a3816b1da57ffcee5e378271d70778f62aa90402)) 159 | 160 | 161 | ### Trivial Changes 162 | 163 | * Update .github/workflows/stale.yml [skip ci] ([4f472d3](https://github.com/libp2p/js-libp2p-delegated-peer-routing/commit/4f472d30506ea297500859481e75db993bce2a82)) 164 | 165 | ## [2.0.2](https://github.com/libp2p/js-libp2p-delegated-peer-routing/compare/v2.0.1...v2.0.2) (2022-09-07) 166 | 167 | 168 | ### Dependencies 169 | 170 | * update all ipfs related deps ([#87](https://github.com/libp2p/js-libp2p-delegated-peer-routing/issues/87)) ([0f4b87f](https://github.com/libp2p/js-libp2p-delegated-peer-routing/commit/0f4b87fe00471d62988d94f8026555d2b0377dc0)) 171 | 172 | ## [2.0.1](https://github.com/libp2p/js-libp2p-delegated-peer-routing/compare/v2.0.0...v2.0.1) (2022-06-15) 173 | 174 | 175 | ### Trivial Changes 176 | 177 | * update deps ([#77](https://github.com/libp2p/js-libp2p-delegated-peer-routing/issues/77)) ([d982ab9](https://github.com/libp2p/js-libp2p-delegated-peer-routing/commit/d982ab96db013e5b752ff04dedcb8201fb00c5fc)) 178 | 179 | ## [2.0.0](https://github.com/libp2p/js-libp2p-delegated-peer-routing/compare/v1.0.5...v2.0.0) (2022-06-15) 180 | 181 | 182 | ### ⚠ BREAKING CHANGES 183 | 184 | * uses new single-issue libp2p interface modules 185 | 186 | ### Features 187 | 188 | * update to latest libp2p interfaces ([#76](https://github.com/libp2p/js-libp2p-delegated-peer-routing/issues/76)) ([413ebe9](https://github.com/libp2p/js-libp2p-delegated-peer-routing/commit/413ebe96ce6c64e2fc0daac6de4cf5c08ab844ad)) 189 | 190 | ### [1.0.5](https://github.com/libp2p/js-libp2p-delegated-peer-routing/compare/v1.0.4...v1.0.5) (2022-06-06) 191 | 192 | 193 | ### Bug Fixes 194 | 195 | * update ipfs-http-client ([#72](https://github.com/libp2p/js-libp2p-delegated-peer-routing/issues/72)) ([5998f1c](https://github.com/libp2p/js-libp2p-delegated-peer-routing/commit/5998f1cb5bfe810fb7fed6fb7362f5e8b551ce45)) 196 | 197 | ### [1.0.4](https://github.com/libp2p/js-libp2p-delegated-peer-routing/compare/v1.0.3...v1.0.4) (2022-05-23) 198 | 199 | 200 | ### Trivial Changes 201 | 202 | * **deps:** bump @libp2p/interfaces from 1.3.32 to 2.0.1 ([#70](https://github.com/libp2p/js-libp2p-delegated-peer-routing/issues/70)) ([ebd8b76](https://github.com/libp2p/js-libp2p-delegated-peer-routing/commit/ebd8b76c9177c0d14e8756f7cedb7c425ec349fb)) 203 | 204 | ### [1.0.3](https://github.com/libp2p/js-libp2p-delegated-peer-routing/compare/v1.0.2...v1.0.3) (2022-05-11) 205 | 206 | 207 | ### Bug Fixes 208 | 209 | * abort in flight requests when shutting down ([#68](https://github.com/libp2p/js-libp2p-delegated-peer-routing/issues/68)) ([31c5db6](https://github.com/libp2p/js-libp2p-delegated-peer-routing/commit/31c5db667e70dd17751fb26f39bd58f4ca3db89c)) 210 | 211 | ### [1.0.2](https://github.com/libp2p/js-libp2p-delegated-peer-routing/compare/v1.0.1...v1.0.2) (2022-03-24) 212 | 213 | 214 | ### Bug Fixes 215 | 216 | * update interfaces ([#60](https://github.com/libp2p/js-libp2p-delegated-peer-routing/issues/60)) ([f494708](https://github.com/libp2p/js-libp2p-delegated-peer-routing/commit/f494708df5d75c0af6e85591e2481c4a1ab4794b)) 217 | 218 | ### [1.0.1](https://github.com/libp2p/js-libp2p-delegated-peer-routing/compare/v1.0.0...v1.0.1) (2022-03-16) 219 | 220 | 221 | ### Bug Fixes 222 | 223 | * update interfaces ([#59](https://github.com/libp2p/js-libp2p-delegated-peer-routing/issues/59)) ([67e8ae3](https://github.com/libp2p/js-libp2p-delegated-peer-routing/commit/67e8ae3c1adae5b4833b514f38e16f54439dab75)) 224 | 225 | ## [1.0.0](https://github.com/libp2p/js-libp2p-delegated-peer-routing/compare/v0.11.1...v1.0.0) (2022-03-04) 226 | 227 | 228 | ### ⚠ BREAKING CHANGES 229 | 230 | * switch to named exports, ESM only 231 | 232 | ### Features 233 | 234 | * convert to typescript ([#58](https://github.com/libp2p/js-libp2p-delegated-peer-routing/issues/58)) ([3013bf8](https://github.com/libp2p/js-libp2p-delegated-peer-routing/commit/3013bf8c733f23ce08c98c4faad94d8b8bcd63cd)) 235 | 236 | ## [0.11.1](https://github.com/libp2p/js-libp2p-delegated-peer-routing/compare/v0.11.0...v0.11.1) (2021-12-07) 237 | 238 | 239 | ### Bug Fixes 240 | 241 | * yield closer peers as they arrive ([#51](https://github.com/libp2p/js-libp2p-delegated-peer-routing/issues/51)) ([1892785](https://github.com/libp2p/js-libp2p-delegated-peer-routing/commit/1892785d70a5d709aac66f2494f79e7768a2b7c4)) 242 | 243 | 244 | 245 | # [0.11.0](https://github.com/libp2p/js-libp2p-delegated-peer-routing/compare/v0.10.0...v0.11.0) (2021-12-02) 246 | 247 | 248 | ### chore 249 | 250 | * update peer-id dep ([#47](https://github.com/libp2p/js-libp2p-delegated-peer-routing/issues/47)) ([1664f69](https://github.com/libp2p/js-libp2p-delegated-peer-routing/commit/1664f69b7234e8bc41dc6641ebd70fb8fa1b0129)) 251 | 252 | 253 | ### BREAKING CHANGES 254 | 255 | * requires node 15 256 | 257 | 258 | 259 | # [0.10.0](https://github.com/libp2p/js-libp2p-delegated-peer-routing/compare/v0.9.0...v0.10.0) (2021-07-07) 260 | 261 | 262 | ### chore 263 | 264 | * update to new multiformats ([#46](https://github.com/libp2p/js-libp2p-delegated-peer-routing/issues/46)) ([44cd293](https://github.com/libp2p/js-libp2p-delegated-peer-routing/commit/44cd2933b705285cc5081e7469ddc3c137a539dc)) 265 | 266 | 267 | ### BREAKING CHANGES 268 | 269 | * uses the CID class from the new multiformats module 270 | 271 | 272 | 273 | # [0.9.0](https://github.com/libp2p/js-libp2p-delegated-peer-routing/compare/v0.8.1...v0.9.0) (2021-04-09) 274 | 275 | 276 | 277 | ## [0.8.2](https://github.com/libp2p/js-libp2p-delegated-peer-routing/compare/v0.8.1...v0.8.2) (2020-11-30) 278 | 279 | 280 | 281 | ## [0.8.1](https://github.com/libp2p/js-libp2p-delegated-peer-routing/compare/v0.4.0...v0.8.1) (2020-11-27) 282 | 283 | 284 | ### Bug Fixes 285 | 286 | * accept http client instance ([#39](https://github.com/libp2p/js-libp2p-delegated-peer-routing/issues/39)) ([bd9ecc3](https://github.com/libp2p/js-libp2p-delegated-peer-routing/commit/bd9ecc311e87604d489cae5e832691bd1dec7429)) 287 | 288 | 289 | ### chore 290 | 291 | * make ipfs-http-client a peer dependency ([#32](https://github.com/libp2p/js-libp2p-delegated-peer-routing/issues/32)) ([a1b1b5e](https://github.com/libp2p/js-libp2p-delegated-peer-routing/commit/a1b1b5ec59af97f5ab708c757808940dbcb070d9)) 292 | * remove-peer-info-from-api ([#25](https://github.com/libp2p/js-libp2p-delegated-peer-routing/issues/25)) ([f49ddc0](https://github.com/libp2p/js-libp2p-delegated-peer-routing/commit/f49ddc0740963587fc0976c2a627f241bd045abf)) 293 | 294 | 295 | ### Features 296 | 297 | * add support for api dht/query endpoint ([#37](https://github.com/libp2p/js-libp2p-delegated-peer-routing/issues/37)) ([6fa569c](https://github.com/libp2p/js-libp2p-delegated-peer-routing/commit/6fa569cdaaeca3ca200af8b3c10b2a098faff5c1)) 298 | 299 | 300 | ### BREAKING CHANGES 301 | 302 | * The ipfs-http-client must now be installed 303 | as a peer dependency. It is no longer included as a dependency 304 | of this module. 305 | 306 | The reason the http-client should be a peerDependency and 307 | not a dependency is that its API requires knowledge of the 308 | http-client (we pass in the api endpoint details). 309 | * findPeer returns id and addrs properties instead of peer-info instance 310 | 311 | * chore: address review 312 | 313 | 314 | 315 | # [0.8.0](https://github.com/libp2p/js-libp2p-delegated-peer-routing/compare/v0.7.0...v0.8.0) (2020-10-21) 316 | 317 | 318 | 319 | 320 | # [0.7.0](https://github.com/libp2p/js-libp2p-delegated-peer-routing/compare/v0.6.1...v0.7.0) (2020-08-26) 321 | 322 | 323 | ### Bug Fixes 324 | 325 | * accept http client instance ([#39](https://github.com/libp2p/js-libp2p-delegated-peer-routing/issues/39)) ([bd9ecc3](https://github.com/libp2p/js-libp2p-delegated-peer-routing/commit/bd9ecc3)) 326 | 327 | 328 | 329 | 330 | ## [0.6.1](https://github.com/libp2p/js-libp2p-delegated-peer-routing/compare/v0.6.0...v0.6.1) (2020-08-14) 331 | 332 | 333 | ### Features 334 | 335 | * add support for api dht/query endpoint ([#37](https://github.com/libp2p/js-libp2p-delegated-peer-routing/issues/37)) ([6fa569c](https://github.com/libp2p/js-libp2p-delegated-peer-routing/commit/6fa569c)) 336 | 337 | 338 | 339 | 340 | # [0.6.0](https://github.com/libp2p/js-libp2p-delegated-peer-routing/compare/v0.5.0...v0.6.0) (2020-08-12) 341 | 342 | 343 | 344 | 345 | # [0.5.0](https://github.com/libp2p/js-libp2p-delegated-peer-routing/compare/v0.4.3...v0.5.0) (2020-04-23) 346 | 347 | 348 | ### Chores 349 | 350 | * make ipfs-http-client a peer dependency ([#32](https://github.com/libp2p/js-libp2p-delegated-peer-routing/issues/32)) ([a1b1b5e](https://github.com/libp2p/js-libp2p-delegated-peer-routing/commit/a1b1b5e)) 351 | * remove-peer-info-from-api ([#25](https://github.com/libp2p/js-libp2p-delegated-peer-routing/issues/25)) ([f49ddc0](https://github.com/libp2p/js-libp2p-delegated-peer-routing/commit/f49ddc0)) 352 | 353 | 354 | ### BREAKING CHANGES 355 | 356 | * The ipfs-http-client must now be installed 357 | as a peer dependency. It is no longer included as a dependency 358 | of this module. 359 | 360 | The reason the http-client should be a peerDependency and 361 | not a dependency is that its API requires knowledge of the 362 | http-client (we pass in the api endpoint details). 363 | * findPeer returns id and addrs properties instead of peer-info instance 364 | 365 | * chore: address review 366 | 367 | 368 | 369 | 370 | ## [0.4.3](https://github.com/libp2p/js-libp2p-delegated-peer-routing/compare/v0.4.2...v0.4.3) (2020-04-16) 371 | 372 | 373 | 374 | 375 | ## [0.4.2](https://github.com/libp2p/js-libp2p-delegated-peer-routing/compare/v0.4.1...v0.4.2) (2020-04-09) 376 | 377 | 378 | 379 | 380 | ## [0.4.1](https://github.com/libp2p/js-libp2p-delegated-peer-routing/compare/v0.4.0...v0.4.1) (2020-02-04) 381 | 382 | 383 | 384 | 385 | # [0.4.0](https://github.com/libp2p/js-libp2p-delegated-peer-routing/compare/v0.3.1...v0.4.0) (2019-11-29) 386 | 387 | 388 | ### Chores 389 | 390 | * rename timeout option ([#14](https://github.com/libp2p/js-libp2p-delegated-peer-routing/issues/14)) ([36d852f](https://github.com/libp2p/js-libp2p-delegated-peer-routing/commit/36d852f)) 391 | 392 | 393 | ### BREAKING CHANGES 394 | 395 | * maxTimeout option renamed to timeout 396 | 397 | 398 | 399 | 400 | ## [0.3.1](https://github.com/libp2p/js-libp2p-delegated-peer-routing/compare/v0.3.0...v0.3.1) (2019-07-24) 401 | 402 | 403 | ### Bug Fixes 404 | 405 | * limit concurrent HTTP requests ([#12](https://github.com/libp2p/js-libp2p-delegated-peer-routing/issues/12)) ([e844d30](https://github.com/libp2p/js-libp2p-delegated-peer-routing/commit/e844d30)) 406 | 407 | 408 | 409 | 410 | # [0.3.0](https://github.com/libp2p/js-libp2p-delegated-peer-routing/compare/v0.2.3...v0.3.0) (2019-07-12) 411 | 412 | 413 | ### Features 414 | 415 | * refactor to use async/await ([#8](https://github.com/libp2p/js-libp2p-delegated-peer-routing/issues/8)) ([1827328](https://github.com/libp2p/js-libp2p-delegated-peer-routing/commit/1827328)) 416 | 417 | 418 | ### BREAKING CHANGES 419 | 420 | * API refactored to use async/await 421 | 422 | Also upgrades all the deps, moves from `ipfs-api` to `ipfs-http-client` 423 | and removes a lot of results massaging that is now done in the 424 | http client. 425 | 426 | 427 | 428 | 429 | ## [0.2.3](https://github.com/libp2p/js-libp2p-delegated-peer-routing/compare/v0.2.2...v0.2.3) (2019-07-10) 430 | 431 | 432 | 433 | 434 | ## [0.2.2](https://github.com/libp2p/js-libp2p-delegated-peer-routing/compare/v0.2.1...v0.2.2) (2018-09-27) 435 | 436 | 437 | ### Features 438 | 439 | * add timeout defaults ([#6](https://github.com/libp2p/js-libp2p-delegated-peer-routing/issues/6)) ([2909585](https://github.com/libp2p/js-libp2p-delegated-peer-routing/commit/2909585)) 440 | 441 | 442 | 443 | 444 | ## [0.2.1](https://github.com/libp2p/js-libp2p-delegated-peer-routing/compare/v0.2.0...v0.2.1) (2018-08-30) 445 | 446 | 447 | ### Bug Fixes 448 | 449 | * better support for peer ids ([#5](https://github.com/libp2p/js-libp2p-delegated-peer-routing/issues/5)) ([60655a9](https://github.com/libp2p/js-libp2p-delegated-peer-routing/commit/60655a9)) 450 | 451 | 452 | 453 | 454 | # 0.2.0 (2018-08-23) 455 | 456 | 457 | ### Bug Fixes 458 | 459 | * Syntax highlighting on README ([67fb497](https://github.com/libp2p/js-libp2p-delegated-peer-routing/commit/67fb497)) 460 | 461 | 462 | ### Features 463 | 464 | * initial implementation ([#1](https://github.com/libp2p/js-libp2p-delegated-peer-routing/issues/1)) ([7fd93ae](https://github.com/libp2p/js-libp2p-delegated-peer-routing/commit/7fd93ae)) 465 | -------------------------------------------------------------------------------- /CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @libp2p/js-libp2p-dev 2 | -------------------------------------------------------------------------------- /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 | # @libp2p/delegated-peer-routing 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-delegated-peer-routing.svg?style=flat-square)](https://codecov.io/gh/libp2p/js-libp2p-delegated-peer-routing) 6 | [![CI](https://img.shields.io/github/actions/workflow/status/libp2p/js-libp2p-delegated-peer-routing/js-test-and-release.yml?branch=master\&style=flat-square)](https://github.com/libp2p/js-libp2p-delegated-peer-routing/actions/workflows/js-test-and-release.yml?query=branch%3Amaster) 7 | 8 | > Leverage other peers in the libp2p network to perform Peer Routing calls. 9 | 10 | ## Table of contents 11 | 12 | - [Install](#install) 13 | - [Browser ` 32 | ``` 33 | 34 | Leverage other peers in the network to perform Peer Routing calls. 35 | 36 | Requires access to `/api/v0/dht/findpeer` and `/api/v0/dht/query` HTTP API endpoints of the delegate node. 37 | 38 | ## Requirements 39 | 40 | `libp2p-delegated-peer-routing` leverages the `kubo-rpc-client` library and requires an instance of it as a constructor argument. 41 | 42 | ```sh 43 | npm install kubo-rpc-client libp2p-delegated-peer-routing 44 | ``` 45 | 46 | ## Example 47 | 48 | ```js 49 | import { createLibp2p } from 'libp2p' 50 | import { delegatedPeerRouting } from '@libp2p/delegated-peer-routing' 51 | import { create as kuboClient } from 'kubo-rpc-client' 52 | 53 | // default is to use ipfs.io 54 | const client = kuboClient({ 55 | // use default api settings 56 | protocol: 'https', 57 | port: 443, 58 | host: 'node0.delegate.ipfs.io' 59 | }) 60 | 61 | const node = await createLibp2p({ 62 | peerRouters: [ 63 | delegatedPeerRouting(client) 64 | ] 65 | //.. other config 66 | }) 67 | await node.start() 68 | 69 | const peerInfo = await node.peerRouting.findPeer('peerid') 70 | console.log('peerInfo', peerInfo) 71 | ``` 72 | 73 | ## API Docs 74 | 75 | - 76 | 77 | ## License 78 | 79 | Licensed under either of 80 | 81 | - Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) 82 | - MIT ([LICENSE-MIT](LICENSE-MIT) / ) 83 | 84 | ## Contribution 85 | 86 | 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. 87 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@libp2p/delegated-peer-routing", 3 | "version": "4.0.14", 4 | "description": "Leverage other peers in the libp2p network to perform Peer Routing calls.", 5 | "license": "Apache-2.0 OR MIT", 6 | "homepage": "https://github.com/libp2p/js-libp2p-delegated-peer-routing#readme", 7 | "repository": { 8 | "type": "git", 9 | "url": "git+https://github.com/libp2p/js-libp2p-delegated-peer-routing.git" 10 | }, 11 | "bugs": { 12 | "url": "https://github.com/libp2p/js-libp2p-delegated-peer-routing/issues" 13 | }, 14 | "type": "module", 15 | "types": "./dist/src/index.d.ts", 16 | "files": [ 17 | "src", 18 | "dist", 19 | "!dist/test", 20 | "!**/*.tsbuildinfo" 21 | ], 22 | "exports": { 23 | ".": { 24 | "types": "./src/index.d.ts", 25 | "import": "./dist/src/index.js" 26 | } 27 | }, 28 | "eslintConfig": { 29 | "extends": "ipfs", 30 | "parserOptions": { 31 | "project": true, 32 | "sourceType": "module" 33 | } 34 | }, 35 | "release": { 36 | "branches": [ 37 | "master" 38 | ], 39 | "plugins": [ 40 | [ 41 | "@semantic-release/commit-analyzer", 42 | { 43 | "preset": "conventionalcommits", 44 | "releaseRules": [ 45 | { 46 | "breaking": true, 47 | "release": "major" 48 | }, 49 | { 50 | "revert": true, 51 | "release": "patch" 52 | }, 53 | { 54 | "type": "feat", 55 | "release": "minor" 56 | }, 57 | { 58 | "type": "fix", 59 | "release": "patch" 60 | }, 61 | { 62 | "type": "docs", 63 | "release": "patch" 64 | }, 65 | { 66 | "type": "test", 67 | "release": "patch" 68 | }, 69 | { 70 | "type": "deps", 71 | "release": "patch" 72 | }, 73 | { 74 | "scope": "no-release", 75 | "release": false 76 | } 77 | ] 78 | } 79 | ], 80 | [ 81 | "@semantic-release/release-notes-generator", 82 | { 83 | "preset": "conventionalcommits", 84 | "presetConfig": { 85 | "types": [ 86 | { 87 | "type": "feat", 88 | "section": "Features" 89 | }, 90 | { 91 | "type": "fix", 92 | "section": "Bug Fixes" 93 | }, 94 | { 95 | "type": "chore", 96 | "section": "Trivial Changes" 97 | }, 98 | { 99 | "type": "docs", 100 | "section": "Documentation" 101 | }, 102 | { 103 | "type": "deps", 104 | "section": "Dependencies" 105 | }, 106 | { 107 | "type": "test", 108 | "section": "Tests" 109 | } 110 | ] 111 | } 112 | } 113 | ], 114 | "@semantic-release/changelog", 115 | "@semantic-release/npm", 116 | "@semantic-release/github", 117 | "@semantic-release/git" 118 | ] 119 | }, 120 | "scripts": { 121 | "clean": "aegir clean", 122 | "lint": "aegir lint", 123 | "dep-check": "aegir dep-check", 124 | "build": "aegir build", 125 | "test": "aegir test", 126 | "test:chrome": "aegir test -t browser --cov", 127 | "test:chrome-webworker": "aegir test -t webworker", 128 | "test:firefox": "aegir test -t browser -- --browser firefox", 129 | "test:firefox-webworker": "aegir test -t webworker -- --browser firefox", 130 | "test:node": "aegir test -t node --cov", 131 | "test:electron-main": "aegir test -t electron-main", 132 | "release": "aegir release", 133 | "docs": "aegir docs" 134 | }, 135 | "dependencies": { 136 | "@libp2p/interface-peer-id": "^2.0.2", 137 | "@libp2p/interface-peer-info": "^1.0.10", 138 | "@libp2p/interface-peer-routing": "^1.1.1", 139 | "@libp2p/interfaces": "^3.3.2", 140 | "@libp2p/logger": "^3.0.2", 141 | "@libp2p/peer-id": "^3.0.2", 142 | "any-signal": "^4.1.1", 143 | "ipfs-core-types": "^0.14.1", 144 | "multiformats": "^12.1.2", 145 | "p-defer": "^4.0.0", 146 | "p-queue": "^7.3.4" 147 | }, 148 | "devDependencies": { 149 | "@libp2p/peer-id-factory": "^3.0.3", 150 | "aegir": "^41.0.3", 151 | "ipfsd-ctl": "^13.0.0", 152 | "it-all": "^3.0.3", 153 | "it-drain": "^3.0.3", 154 | "kubo": "^0.23.0", 155 | "kubo-rpc-client": "^3.0.1", 156 | "uint8arrays": "^4.0.6", 157 | "wherearewe": "^2.0.1" 158 | }, 159 | "browser": { 160 | "kubo": false 161 | } 162 | } 163 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | import { CodeError } from '@libp2p/interfaces/errors' 2 | import { logger } from '@libp2p/logger' 3 | import { peerIdFromBytes } from '@libp2p/peer-id' 4 | import { anySignal } from 'any-signal' 5 | import { CID } from 'multiformats/cid' 6 | import defer from 'p-defer' 7 | import PQueue from 'p-queue' 8 | import type { PeerId } from '@libp2p/interface-peer-id' 9 | import type { PeerInfo } from '@libp2p/interface-peer-info' 10 | import type { PeerRouting } from '@libp2p/interface-peer-routing' 11 | import type { Startable } from '@libp2p/interfaces/startable' 12 | import type { AbortOptions } from 'ipfs-core-types/src/utils' 13 | 14 | const log = logger('libp2p:delegated-peer-routing') 15 | 16 | const DEFAULT_TIMEOUT = 30e3 // 30 second default 17 | const CONCURRENT_HTTP_REQUESTS = 4 18 | 19 | export interface HTTPClientExtraOptions { 20 | headers?: Record 21 | searchParams?: URLSearchParams 22 | } 23 | 24 | export enum EventTypes { 25 | SENDING_QUERY = 0, 26 | PEER_RESPONSE, 27 | FINAL_PEER, 28 | QUERY_ERROR, 29 | PROVIDER, 30 | VALUE, 31 | ADDING_PEER, 32 | DIALING_PEER 33 | } 34 | 35 | /** 36 | * The types of messages set/received during DHT queries 37 | */ 38 | export enum MessageType { 39 | PUT_VALUE = 0, 40 | GET_VALUE, 41 | ADD_PROVIDER, 42 | GET_PROVIDERS, 43 | FIND_NODE, 44 | PING 45 | } 46 | 47 | export type MessageName = keyof typeof MessageType 48 | 49 | export interface DHTRecord { 50 | key: Uint8Array 51 | value: Uint8Array 52 | timeReceived?: Date 53 | } 54 | 55 | export interface SendingQueryEvent { 56 | type: EventTypes.SENDING_QUERY 57 | name: 'SENDING_QUERY' 58 | } 59 | 60 | export interface PeerResponseEvent { 61 | from: PeerId 62 | type: EventTypes.PEER_RESPONSE 63 | name: 'PEER_RESPONSE' 64 | messageType: MessageType 65 | messageName: MessageName 66 | providers: PeerInfo[] 67 | closer: PeerInfo[] 68 | record?: DHTRecord 69 | } 70 | 71 | export interface FinalPeerEvent { 72 | peer: PeerInfo 73 | type: EventTypes.FINAL_PEER 74 | name: 'FINAL_PEER' 75 | } 76 | 77 | export interface QueryErrorEvent { 78 | type: EventTypes.QUERY_ERROR 79 | name: 'QUERY_ERROR' 80 | error: Error 81 | } 82 | 83 | export interface ProviderEvent { 84 | type: EventTypes.PROVIDER 85 | name: 'PROVIDER' 86 | providers: PeerInfo[] 87 | } 88 | 89 | export interface ValueEvent { 90 | type: EventTypes.VALUE 91 | name: 'VALUE' 92 | value: Uint8Array 93 | } 94 | 95 | export interface AddingPeerEvent { 96 | type: EventTypes.ADDING_PEER 97 | name: 'ADDING_PEER' 98 | peer: PeerId 99 | } 100 | 101 | export interface DialingPeerEvent { 102 | peer: PeerId 103 | type: EventTypes.DIALING_PEER 104 | name: 'DIALING_PEER' 105 | } 106 | 107 | export type QueryEvent = SendingQueryEvent | PeerResponseEvent | FinalPeerEvent | QueryErrorEvent | ProviderEvent | ValueEvent | AddingPeerEvent | DialingPeerEvent 108 | 109 | export interface Delegate { 110 | getEndpointConfig(): { protocol: string, host: string, port: string } 111 | 112 | dht: { 113 | findPeer(peerId: PeerId, options?: AbortOptions): AsyncIterable 114 | query(peerId: PeerId | CID, options?: AbortOptions): AsyncIterable 115 | } 116 | } 117 | 118 | class DelegatedPeerRouting implements PeerRouting, Startable { 119 | private readonly client: Delegate 120 | private readonly httpQueue: PQueue 121 | private started: boolean 122 | private abortController: AbortController 123 | 124 | /** 125 | * Create a new DelegatedPeerRouting instance 126 | */ 127 | constructor (client: Delegate) { 128 | if (client == null) { 129 | throw new Error('missing ipfs http client') 130 | } 131 | 132 | this.client = client 133 | this.started = false 134 | this.abortController = new AbortController() 135 | 136 | // limit concurrency to avoid request flood in web browser 137 | // https://github.com/libp2p/js-libp2p-delegated-content-routing/issues/12 138 | this.httpQueue = new PQueue({ 139 | concurrency: CONCURRENT_HTTP_REQUESTS 140 | }) 141 | 142 | const { 143 | protocol, 144 | host, 145 | port 146 | } = client.getEndpointConfig() 147 | 148 | log(`enabled DelegatedPeerRouting via ${protocol}://${host}:${port}`) 149 | } 150 | 151 | isStarted (): boolean { 152 | return this.started 153 | } 154 | 155 | start (): void { 156 | this.started = true 157 | } 158 | 159 | stop (): void { 160 | this.httpQueue.clear() 161 | this.abortController.abort() 162 | this.abortController = new AbortController() 163 | this.started = false 164 | } 165 | 166 | /** 167 | * Attempts to find the given peer 168 | */ 169 | async findPeer (id: PeerId, options: HTTPClientExtraOptions & AbortOptions = {}): Promise { 170 | log('findPeer starts: %p', id) 171 | options.timeout = options.timeout ?? DEFAULT_TIMEOUT 172 | 173 | const signal = anySignal([this.abortController.signal, options.signal]) 174 | const onStart = defer() 175 | const onFinish = defer() 176 | 177 | void this.httpQueue.add(async () => { 178 | onStart.resolve() 179 | return onFinish.promise 180 | }) 181 | 182 | try { 183 | await onStart.promise 184 | 185 | for await (const event of this.client.dht.findPeer(id, { 186 | ...options, 187 | signal 188 | })) { 189 | if (event.name === 'FINAL_PEER' && event.peer.multiaddrs.length > 0) { 190 | const peerInfo: PeerInfo = { 191 | id: event.peer.id, 192 | multiaddrs: event.peer.multiaddrs, 193 | protocols: [] 194 | } 195 | 196 | return peerInfo 197 | } 198 | } 199 | 200 | throw new CodeError('Not found', 'ERR_NOT_FOUND') 201 | } catch (err: any) { 202 | log.error('findPeer errored: %o', err) 203 | 204 | throw err 205 | } finally { 206 | signal.clear() 207 | onFinish.resolve() 208 | log('findPeer finished: %p', id) 209 | } 210 | } 211 | 212 | /** 213 | * Attempt to find the closest peers on the network to the given key 214 | */ 215 | async * getClosestPeers (key: Uint8Array, options: HTTPClientExtraOptions & AbortOptions = {}): AsyncGenerator { 216 | let cidOrPeerId: CID | PeerId 217 | const cid = CID.asCID(key) 218 | 219 | if (cid != null) { 220 | cidOrPeerId = cid 221 | } else { 222 | cidOrPeerId = peerIdFromBytes(key) 223 | } 224 | 225 | log('getClosestPeers starts: %s', cidOrPeerId) 226 | options.timeout = options.timeout ?? DEFAULT_TIMEOUT 227 | 228 | const signal = anySignal([this.abortController.signal, options.signal]) 229 | const onStart = defer() 230 | const onFinish = defer() 231 | 232 | void this.httpQueue.add(async () => { 233 | onStart.resolve() 234 | return onFinish.promise 235 | }) 236 | 237 | try { 238 | await onStart.promise 239 | 240 | for await (const event of this.client.dht.query(cidOrPeerId, { 241 | ...options, 242 | signal 243 | })) { 244 | if (event.name === 'PEER_RESPONSE') { 245 | yield * event.closer.map(closer => ({ 246 | id: closer.id, 247 | multiaddrs: closer.multiaddrs, 248 | protocols: [] 249 | })) 250 | } 251 | } 252 | } catch (err) { 253 | log.error('getClosestPeers errored:', err) 254 | throw err 255 | } finally { 256 | signal.clear() 257 | onFinish.resolve() 258 | log('getClosestPeers finished: %b', key) 259 | } 260 | } 261 | } 262 | 263 | export function delegatedPeerRouting (client: Delegate): (components?: any) => PeerRouting { 264 | return () => new DelegatedPeerRouting(client) 265 | } 266 | -------------------------------------------------------------------------------- /test/index.spec.ts: -------------------------------------------------------------------------------- 1 | /* eslint-env mocha */ 2 | 3 | import { stop } from '@libp2p/interfaces/startable' 4 | import { peerIdFromString } from '@libp2p/peer-id' 5 | import { createEd25519PeerId } from '@libp2p/peer-id-factory' 6 | import { expect } from 'aegir/chai' 7 | import { type Controller, createFactory } from 'ipfsd-ctl' 8 | import all from 'it-all' 9 | import drain from 'it-drain' 10 | import goIpfs from 'kubo' 11 | import { create, type Options, CID as IPFSCID } from 'kubo-rpc-client' 12 | import { CID } from 'multiformats/cid' 13 | import pDefer from 'p-defer' 14 | import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string' 15 | import { isElectronMain, isNode } from 'wherearewe' 16 | import { delegatedPeerRouting } from '../src/index.js' 17 | import type { PeerId } from '@libp2p/interface-peer-id' 18 | import type { AbortOptions } from '@libp2p/interfaces' 19 | import type { IDResult } from 'ipfs-core-types/src/root' 20 | 21 | const factory = createFactory({ 22 | type: 'go', 23 | ipfsHttpModule: { create }, 24 | ipfsBin: isNode || isElectronMain ? goIpfs.path() : undefined, 25 | test: true, 26 | disposable: true, 27 | endpoint: 'http://localhost:57583' 28 | }) 29 | 30 | async function spawnNode (bootstrap: any[] = []): Promise<{ node: Controller, id: IDResult }> { 31 | const node = await factory.spawn({ 32 | // Lock down the nodes so testing can be deterministic 33 | ipfsOptions: { 34 | config: { 35 | Bootstrap: bootstrap 36 | } 37 | } 38 | }) 39 | const id = await node.api.id() 40 | 41 | return { 42 | node, 43 | id 44 | } 45 | } 46 | 47 | function createIpfsClient (opts: Options): any { 48 | const client = create(opts) 49 | 50 | return { 51 | getEndpointConfig: () => client.getEndpointConfig(), 52 | block: { 53 | async stat (cid: CID, options?: AbortOptions) { 54 | const result = await client.block.stat(IPFSCID.parse(cid.toString()), options) 55 | 56 | return { 57 | cid: CID.parse(result.cid.toString()), 58 | size: result.size 59 | } 60 | } 61 | }, 62 | dht: { 63 | async * findPeer (peerId: PeerId, options?: AbortOptions) { 64 | yield * client.dht.findPeer(peerId, options) 65 | }, 66 | async * query (peerId: PeerId | CID, options?: AbortOptions) { 67 | yield * client.dht.query(peerId, options) 68 | } 69 | } 70 | } 71 | } 72 | 73 | describe('DelegatedPeerRouting', function () { 74 | this.timeout(20 * 1000) // we're spawning daemons, give ci some time 75 | 76 | let nodeToFind: Controller 77 | let peerIdToFind: IDResult 78 | let delegatedNode: Controller 79 | let bootstrapNode: Controller 80 | let bootstrapId: IDResult 81 | 82 | before(async () => { 83 | // Spawn a "Boostrap" node that doesnt connect to anything 84 | const bootstrap = await spawnNode() 85 | bootstrapNode = bootstrap.node 86 | bootstrapId = bootstrap.id 87 | 88 | // Spawn our local node and bootstrap the bootstrapper node 89 | const local = await spawnNode(bootstrapId.addresses) 90 | nodeToFind = local.node 91 | peerIdToFind = local.id 92 | 93 | // Spawn the delegate node and bootstrap the bootstrapper node 94 | const delegate = await spawnNode(bootstrapId.addresses) 95 | delegatedNode = delegate.node 96 | }) 97 | 98 | after(async () => { 99 | return Promise.all([ 100 | nodeToFind.stop(), 101 | delegatedNode.stop(), 102 | bootstrapNode.stop() 103 | ]) 104 | }) 105 | 106 | describe('create', () => { 107 | it('should require an http api client instance at construction time', () => { 108 | // @ts-expect-error invalid parameters 109 | expect(() => delegatedPeerRouting()()).to.throw() 110 | }) 111 | 112 | it('should accept an http api client instance at construction time', () => { 113 | const client = createIpfsClient({ 114 | protocol: 'http', 115 | port: 8000, 116 | host: 'localhost' 117 | }) 118 | 119 | const router = delegatedPeerRouting(client)() 120 | 121 | expect(router).to.have.property('client') 122 | .that.has.property('getEndpointConfig') 123 | .that.is.a('function') 124 | 125 | expect(client.getEndpointConfig()).to.deep.include({ 126 | protocol: 'http:', 127 | port: '8000', 128 | host: 'localhost' 129 | }) 130 | }) 131 | }) 132 | 133 | describe('findPeers', () => { 134 | it('should be able to find peers via the delegate with a peer id string', async () => { 135 | const opts = delegatedNode.apiAddr.toOptions() 136 | 137 | const router = delegatedPeerRouting(createIpfsClient({ 138 | protocol: 'http', 139 | port: opts.port, 140 | host: opts.host 141 | }))() 142 | 143 | const peer = await router.findPeer(peerIdToFind.id) 144 | 145 | const { id, multiaddrs } = peer 146 | expect(id).to.exist() 147 | expect(multiaddrs).to.exist() 148 | 149 | expect(id.equals(peerIdToFind.id)).to.be.true() 150 | }) 151 | 152 | it('should be able to find peers via the delegate with a peerid', async () => { 153 | const opts = delegatedNode.apiAddr.toOptions() 154 | 155 | const router = delegatedPeerRouting(createIpfsClient({ 156 | protocol: 'http', 157 | port: opts.port, 158 | host: opts.host 159 | }))() 160 | 161 | const peer = await router.findPeer(peerIdToFind.id) 162 | 163 | const { id, multiaddrs } = peer 164 | expect(id).to.exist() 165 | expect(multiaddrs).to.exist() 166 | 167 | expect(id.toString()).to.eql(peerIdToFind.id.toString()) 168 | }) 169 | 170 | it('should be able to specify a timeout', async () => { 171 | const opts = delegatedNode.apiAddr.toOptions() 172 | 173 | const router = delegatedPeerRouting(createIpfsClient({ 174 | protocol: 'http', 175 | port: opts.port, 176 | host: opts.host 177 | }))() 178 | const signal = AbortSignal.timeout(5e3) 179 | 180 | const peer = await router.findPeer(peerIdToFind.id, { signal }) 181 | 182 | const { id, multiaddrs } = peer 183 | expect(id).to.exist() 184 | expect(multiaddrs).to.exist() 185 | 186 | expect(id.toString()).to.eql(peerIdToFind.id.toString()) 187 | }) 188 | 189 | it('should not be able to find peers not on the network', async () => { 190 | const opts = delegatedNode.apiAddr.toOptions() 191 | 192 | const router = delegatedPeerRouting(createIpfsClient({ 193 | protocol: 'http', 194 | port: opts.port, 195 | host: opts.host 196 | }))() 197 | 198 | // This is one of the default Bootstrap nodes, but we're not connected to it 199 | // so we'll test with it. 200 | await expect(router.findPeer(peerIdFromString('QmSoLV4Bbm51jM9C4gDYZQ9Cy3U6aXMJDAbzgu2fzaDs64'))) 201 | .to.eventually.be.rejected.with.property('code', 'ERR_NOT_FOUND') 202 | }) 203 | }) 204 | 205 | describe('query', () => { 206 | it('should be able to query for the closest peers', async () => { 207 | const opts = delegatedNode.apiAddr.toOptions() 208 | 209 | const router = delegatedPeerRouting(createIpfsClient({ 210 | protocol: 'http', 211 | port: opts.port, 212 | host: opts.host 213 | }))() 214 | 215 | const nodeId = await delegatedNode.api.id() 216 | const delegatePeerId = nodeId.id 217 | 218 | const key = peerIdToFind.id.toBytes() 219 | 220 | const closerPeers = await all(router.getClosestPeers(key)) 221 | 222 | // we should be closest to the 2 other peers 223 | expect(closerPeers.length).to.equal(2) 224 | closerPeers.forEach(result => { 225 | // shouldn't be the delegate 226 | 227 | expect(delegatePeerId.equals(result.id)).to.equal(false) 228 | expect(result.multiaddrs).to.be.an('array') 229 | }) 230 | }) 231 | 232 | it('should find closest peers even if the peer does not exist', async () => { 233 | const opts = delegatedNode.apiAddr.toOptions() 234 | 235 | const router = delegatedPeerRouting(createIpfsClient({ 236 | protocol: 'http', 237 | port: opts.port, 238 | host: opts.host 239 | }))() 240 | 241 | const nodeId = await delegatedNode.api.id() 242 | const delegatePeerId = nodeId.id 243 | 244 | const peerId = await createEd25519PeerId() 245 | const closerPeers = await all(router.getClosestPeers(peerId.toBytes())) 246 | 247 | // we should be closest to the 2 other peers 248 | expect(closerPeers.length).to.equal(2) 249 | closerPeers.forEach(result => { 250 | // shouldnt be the delegate 251 | 252 | expect(delegatePeerId.equals(result.id)).to.equal(false) 253 | expect(result.multiaddrs).to.be.an('array') 254 | }) 255 | }) 256 | }) 257 | 258 | describe('stop', () => { 259 | it('should cancel in-flight requests when stopping', async () => { 260 | const opts = delegatedNode.apiAddr.toOptions() 261 | 262 | const router = delegatedPeerRouting(createIpfsClient({ 263 | protocol: 'http', 264 | port: opts.port, 265 | host: opts.host 266 | }))() 267 | 268 | const deferred = pDefer() 269 | const peer = uint8ArrayFromString('QmVv4Wz46JaZJeH5PMV4LGbRiiMKEmszPYY3g6fjGnVXBs', 'base58btc') 270 | 271 | void drain(router.getClosestPeers(peer)) 272 | .then(() => { 273 | deferred.reject(new Error('Did not abort')) 274 | }) 275 | .catch(err => { 276 | deferred.resolve(err) 277 | }) 278 | 279 | await stop(router) 280 | await expect(deferred.promise).to.eventually.have.property('message').that.matches(/aborted/) 281 | }) 282 | }) 283 | }) 284 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "aegir/src/config/tsconfig.aegir.json", 3 | "compilerOptions": { 4 | "outDir": "dist", 5 | "emitDeclarationOnly": false, 6 | "module": "ES2020" 7 | }, 8 | "include": [ 9 | "src", 10 | "test" 11 | ] 12 | } 13 | -------------------------------------------------------------------------------- /typedoc.json: -------------------------------------------------------------------------------- 1 | { 2 | "entryPoints": [ 3 | "./src/index.ts" 4 | ] 5 | } 6 | --------------------------------------------------------------------------------