From 3b652646b1283f9854fc425d5faceb7b206c443f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 24 Oct 2023 18:12:25 +0100 Subject: [PATCH 01/24] chore(deps): bump golang.org/x/net from 0.8.0 to 0.17.0 (#2155) Bumps [golang.org/x/net](https://github.com/golang/net) from 0.8.0 to 0.17.0. - [Commits](https://github.com/golang/net/compare/v0.8.0...v0.17.0) --- updated-dependencies: - dependency-name: golang.org/x/net dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .../go-libp2p-webtransport-server/go.mod | 8 ++++---- .../go-libp2p-webtransport-server/go.sum | 16 ++++++++-------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/packages/transport-webtransport/go-libp2p-webtransport-server/go.mod b/packages/transport-webtransport/go-libp2p-webtransport-server/go.mod index 311a59911f..a78490047f 100644 --- a/packages/transport-webtransport/go-libp2p-webtransport-server/go.mod +++ b/packages/transport-webtransport/go-libp2p-webtransport-server/go.mod @@ -81,13 +81,13 @@ require ( go.uber.org/fx v1.19.2 // indirect go.uber.org/multierr v1.11.0 // indirect go.uber.org/zap v1.24.0 // indirect - golang.org/x/crypto v0.7.0 // indirect + golang.org/x/crypto v0.14.0 // indirect golang.org/x/exp v0.0.0-20230321023759-10a507213a29 // indirect golang.org/x/mod v0.10.0 // indirect - golang.org/x/net v0.8.0 // indirect + golang.org/x/net v0.17.0 // indirect golang.org/x/sync v0.1.0 // indirect - golang.org/x/sys v0.7.0 // indirect - golang.org/x/text v0.8.0 // indirect + golang.org/x/sys v0.13.0 // indirect + golang.org/x/text v0.13.0 // indirect golang.org/x/tools v0.7.0 // indirect google.golang.org/protobuf v1.30.0 // indirect lukechampine.com/blake3 v1.1.7 // indirect diff --git a/packages/transport-webtransport/go-libp2p-webtransport-server/go.sum b/packages/transport-webtransport/go-libp2p-webtransport-server/go.sum index 2ad1bc14c9..fae4ef6754 100644 --- a/packages/transport-webtransport/go-libp2p-webtransport-server/go.sum +++ b/packages/transport-webtransport/go-libp2p-webtransport-server/go.sum @@ -355,8 +355,8 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20200602180216-279210d13fed/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= -golang.org/x/crypto v0.7.0 h1:AvwMYaRytfdeVt3u6mLaxYtErKYjxA2OXjJ1HHq6t3A= -golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= +golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc= +golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20230321023759-10a507213a29 h1:ooxPy7fPvB4kwsA2h+iBNHkAbp/4JxTSwCmvdjEYmug= golang.org/x/exp v0.0.0-20230321023759-10a507213a29/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= @@ -388,8 +388,8 @@ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwY golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= -golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ= -golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= +golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= +golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -426,15 +426,15 @@ golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU= -golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= +golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68= -golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= +golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= From 7534ae7b9a1773df3e93e7a2ec95e6407c767f81 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 24 Oct 2023 18:12:45 +0100 Subject: [PATCH 02/24] chore(deps): bump golang.org/x/net from 0.8.0 to 0.17.0 (#2156) Bumps [golang.org/x/net](https://github.com/golang/net) from 0.8.0 to 0.17.0. - [Commits](https://github.com/golang/net/compare/v0.8.0...v0.17.0) --- updated-dependencies: - dependency-name: golang.org/x/net dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .../webrtc/go-libp2p-server/go.mod | 8 ++++---- .../webrtc/go-libp2p-server/go.sum | 16 ++++++++-------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/examples/libp2p-in-the-browser/webrtc/go-libp2p-server/go.mod b/examples/libp2p-in-the-browser/webrtc/go-libp2p-server/go.mod index 1a1a228601..4df488ec10 100644 --- a/examples/libp2p-in-the-browser/webrtc/go-libp2p-server/go.mod +++ b/examples/libp2p-in-the-browser/webrtc/go-libp2p-server/go.mod @@ -103,13 +103,13 @@ require ( go.uber.org/fx v1.19.2 // indirect go.uber.org/multierr v1.10.0 // indirect go.uber.org/zap v1.24.0 // indirect - golang.org/x/crypto v0.7.0 // indirect + golang.org/x/crypto v0.14.0 // indirect golang.org/x/exp v0.0.0-20230321023759-10a507213a29 // indirect golang.org/x/mod v0.9.0 // indirect - golang.org/x/net v0.8.0 // indirect + golang.org/x/net v0.17.0 // indirect golang.org/x/sync v0.1.0 // indirect - golang.org/x/sys v0.7.0 // indirect - golang.org/x/text v0.8.0 // indirect + golang.org/x/sys v0.13.0 // indirect + golang.org/x/text v0.13.0 // indirect golang.org/x/tools v0.7.0 // indirect google.golang.org/protobuf v1.30.0 // indirect lukechampine.com/blake3 v1.1.7 // indirect diff --git a/examples/libp2p-in-the-browser/webrtc/go-libp2p-server/go.sum b/examples/libp2p-in-the-browser/webrtc/go-libp2p-server/go.sum index 9a3080ca00..e19e647d1d 100644 --- a/examples/libp2p-in-the-browser/webrtc/go-libp2p-server/go.sum +++ b/examples/libp2p-in-the-browser/webrtc/go-libp2p-server/go.sum @@ -437,8 +437,8 @@ golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5y golang.org/x/crypto v0.0.0-20220427172511-eb4f295cb31f/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20221010152910-d6f0a8c073c2/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.5.0/go.mod h1:NK/OQwhpMQP3MwtdjgLlYHnH9ebylxKWv3e0fK+mkQU= -golang.org/x/crypto v0.7.0 h1:AvwMYaRytfdeVt3u6mLaxYtErKYjxA2OXjJ1HHq6t3A= -golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= +golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc= +golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20230321023759-10a507213a29 h1:ooxPy7fPvB4kwsA2h+iBNHkAbp/4JxTSwCmvdjEYmug= golang.org/x/exp v0.0.0-20230321023759-10a507213a29/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= @@ -483,8 +483,8 @@ golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= golang.org/x/net v0.4.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE= golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws= -golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ= -golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= +golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= +golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -537,8 +537,8 @@ golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU= -golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= +golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= @@ -554,8 +554,8 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68= -golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= +golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= From 2f6a2397f7e8ec7cf2edda7c9996be263a423661 Mon Sep 17 00:00:00 2001 From: Alex Potsides Date: Wed, 25 Oct 2023 06:23:42 +0100 Subject: [PATCH 03/24] fix: export DHT record class (#2168) This needs to be exported for reuse by things that create DHT records such as IPNS. Exported as `Record` because it's a KAD-DHT specific record and `KAD-DHT` in a class name is redundant within the scope of the KAD-DHT module. --- packages/kad-dht/src/index.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/kad-dht/src/index.ts b/packages/kad-dht/src/index.ts index 742f7cf456..edb1e4f679 100644 --- a/packages/kad-dht/src/index.ts +++ b/packages/kad-dht/src/index.ts @@ -13,6 +13,8 @@ import type { Datastore } from 'interface-datastore' import type { CID } from 'multiformats/cid' import type { ProgressOptions, ProgressEvent } from 'progress-events' +export { Libp2pRecord as Record } from './record/index.js' + /** * The types of events emitted during DHT queries */ From 68504939a6af12eced6334fb41f033c3b1e2450d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 25 Oct 2023 06:34:43 +0100 Subject: [PATCH 04/24] deps: bump sinon from 16.1.3 to 17.0.0 (#2167) Bumps [sinon](https://github.com/sinonjs/sinon) from 16.1.3 to 17.0.0. - [Release notes](https://github.com/sinonjs/sinon/releases) - [Changelog](https://github.com/sinonjs/sinon/blob/main/docs/changelog.md) - [Commits](https://github.com/sinonjs/sinon/compare/v16.1.3...v17.0.0) --- updated-dependencies: - dependency-name: sinon dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Alex Potsides --- packages/interface-compliance-tests/package.json | 2 +- packages/interface/package.json | 2 +- packages/kad-dht/package.json | 2 +- packages/libp2p/package.json | 2 +- packages/logger/package.json | 2 +- packages/peer-store/package.json | 2 +- packages/pubsub-floodsub/package.json | 2 +- packages/pubsub/package.json | 2 +- packages/transport-tcp/package.json | 2 +- packages/transport-webrtc/package.json | 2 +- 10 files changed, 10 insertions(+), 10 deletions(-) diff --git a/packages/interface-compliance-tests/package.json b/packages/interface-compliance-tests/package.json index f467311297..3f7c9ae1c4 100644 --- a/packages/interface-compliance-tests/package.json +++ b/packages/interface-compliance-tests/package.json @@ -131,7 +131,7 @@ "p-limit": "^4.0.0", "p-wait-for": "^5.0.2", "protons-runtime": "^5.0.0", - "sinon": "^16.0.0", + "sinon": "^17.0.0", "uint8arraylist": "^2.4.3", "uint8arrays": "^4.0.6" }, diff --git a/packages/interface/package.json b/packages/interface/package.json index 25e4b96c14..239ccc0be1 100644 --- a/packages/interface/package.json +++ b/packages/interface/package.json @@ -173,7 +173,7 @@ "delay": "^6.0.0", "it-all": "^3.0.3", "it-drain": "^3.0.3", - "sinon": "^16.0.0", + "sinon": "^17.0.0", "sinon-ts": "^1.0.0" } } diff --git a/packages/kad-dht/package.json b/packages/kad-dht/package.json index 4a215a7bfc..be55a32b43 100644 --- a/packages/kad-dht/package.json +++ b/packages/kad-dht/package.json @@ -106,7 +106,7 @@ "p-retry": "^6.0.0", "p-wait-for": "^5.0.2", "protons": "^7.0.2", - "sinon": "^16.0.0", + "sinon": "^17.0.0", "ts-sinon": "^2.0.2", "which": "^4.0.0" }, diff --git a/packages/libp2p/package.json b/packages/libp2p/package.json index 14ec1b4da7..bec42a043f 100644 --- a/packages/libp2p/package.json +++ b/packages/libp2p/package.json @@ -193,7 +193,7 @@ "p-times": "^4.0.0", "p-wait-for": "^5.0.2", "protons": "^7.0.2", - "sinon": "^16.0.0", + "sinon": "^17.0.0", "sinon-ts": "^1.0.0" }, "browser": { diff --git a/packages/logger/package.json b/packages/logger/package.json index 38babeb080..7933263171 100644 --- a/packages/logger/package.json +++ b/packages/logger/package.json @@ -59,7 +59,7 @@ "@libp2p/peer-id": "^3.0.3", "@types/debug": "^4.1.7", "aegir": "^41.0.2", - "sinon": "^16.0.0", + "sinon": "^17.0.0", "uint8arrays": "^4.0.4" } } diff --git a/packages/peer-store/package.json b/packages/peer-store/package.json index 74350542c4..81f61193d0 100644 --- a/packages/peer-store/package.json +++ b/packages/peer-store/package.json @@ -77,6 +77,6 @@ "p-defer": "^4.0.0", "p-event": "^6.0.0", "protons": "^7.0.2", - "sinon": "^16.0.0" + "sinon": "^17.0.0" } } diff --git a/packages/pubsub-floodsub/package.json b/packages/pubsub-floodsub/package.json index 0099535d9b..2b49e8ce8f 100644 --- a/packages/pubsub-floodsub/package.json +++ b/packages/pubsub-floodsub/package.json @@ -72,6 +72,6 @@ "multiformats": "^12.0.1", "p-wait-for": "^5.0.2", "protons": "^7.0.2", - "sinon": "^16.0.0" + "sinon": "^17.0.0" } } diff --git a/packages/pubsub/package.json b/packages/pubsub/package.json index baf14e94f9..faf89c3d97 100644 --- a/packages/pubsub/package.json +++ b/packages/pubsub/package.json @@ -104,6 +104,6 @@ "p-wait-for": "^5.0.2", "protons": "^7.0.2", "protons-runtime": "^5.0.0", - "sinon": "^16.0.0" + "sinon": "^17.0.0" } } diff --git a/packages/transport-tcp/package.json b/packages/transport-tcp/package.json index 7633c493bb..117123a15c 100644 --- a/packages/transport-tcp/package.json +++ b/packages/transport-tcp/package.json @@ -65,7 +65,7 @@ "it-all": "^3.0.1", "it-pipe": "^3.0.1", "p-defer": "^4.0.0", - "sinon": "^16.0.0", + "sinon": "^17.0.0", "uint8arrays": "^4.0.4" } } diff --git a/packages/transport-webrtc/package.json b/packages/transport-webrtc/package.json index 21254dbdea..7ffebe70d4 100644 --- a/packages/transport-webrtc/package.json +++ b/packages/transport-webrtc/package.json @@ -88,7 +88,7 @@ "libp2p": "^0.46.14", "p-retry": "^6.1.0", "protons": "^7.0.2", - "sinon": "^16.0.0", + "sinon": "^17.0.0", "sinon-ts": "^1.0.0" }, "browser": { From ce0e38d28240303f7afc7f37de441b067e3e855e Mon Sep 17 00:00:00 2001 From: Alex Potsides Date: Wed, 25 Oct 2023 08:35:12 +0100 Subject: [PATCH 05/24] fix: allow DHT self-query to time out (#2169) When we run our first self-query we first check the routing table to see if it has peers. If not we wait for some peers to be discovered before continuing. The change here is to use the general query AbortSignal to abort waiting for peers to be discovered. If they are not discovered allow other queries to continue and fail with eaiser to understand error messages. Also fixes some logging typos and makes error messages more understandable. --- packages/kad-dht/src/dual-kad-dht.ts | 12 +--------- packages/kad-dht/src/query-self.ts | 24 +++++++++++-------- packages/kad-dht/src/record/selectors.ts | 2 +- packages/kad-dht/src/record/validators.ts | 2 +- .../kad-dht/test/record/selection.spec.ts | 12 +++------- .../kad-dht/test/record/validator.spec.ts | 4 +--- 6 files changed, 21 insertions(+), 35 deletions(-) diff --git a/packages/kad-dht/src/dual-kad-dht.ts b/packages/kad-dht/src/dual-kad-dht.ts index efc93ab936..6d704725fb 100644 --- a/packages/kad-dht/src/dual-kad-dht.ts +++ b/packages/kad-dht/src/dual-kad-dht.ts @@ -103,8 +103,6 @@ function multiaddrIsPublic (multiaddr: Multiaddr): boolean { // dns4 or dns6 or dnsaddr if (tuples[0][0] === DNS4_CODE || tuples[0][0] === DNS6_CODE || tuples[0][0] === DNSADDR_CODE) { - log('%m is public %s', multiaddr, true) - return true } @@ -113,8 +111,6 @@ function multiaddrIsPublic (multiaddr: Multiaddr): boolean { const result = isPrivate(`${tuples[0][1]}`) const isPublic = result == null || !result - log('%m is public %s', multiaddr, isPublic) - return isPublic } @@ -170,13 +166,7 @@ export class DefaultDualKadDHT extends EventEmitter impleme components.events.addEventListener('self:peer:update', (evt) => { log('received update of self-peer info') const hasPublicAddress = evt.detail.peer.addresses - .some(({ multiaddr }) => { - const isPublic = multiaddrIsPublic(multiaddr) - - log('%m is public %s', multiaddr, isPublic) - - return isPublic - }) + .some(({ multiaddr }) => multiaddrIsPublic(multiaddr)) this.getMode() .then(async mode => { diff --git a/packages/kad-dht/src/query-self.ts b/packages/kad-dht/src/query-self.ts index 49f3826dbd..06c74d98e3 100644 --- a/packages/kad-dht/src/query-self.ts +++ b/packages/kad-dht/src/query-self.ts @@ -105,11 +105,6 @@ export class QuerySelf implements Startable { this.querySelfPromise = pDefer() - if (this.routingTable.size === 0) { - // wait to discover at least one DHT peer - await pEvent(this.routingTable, 'peer:add') - } - if (this.started) { this.controller = new AbortController() const signal = anySignal([this.controller.signal, AbortSignal.timeout(this.queryTimeout)]) @@ -122,7 +117,16 @@ export class QuerySelf implements Startable { } catch {} // fails on node < 15.4 try { + if (this.routingTable.size === 0) { + this.log('routing table was empty, waiting for some peers before running query') + // wait to discover at least one DHT peer + await pEvent(this.routingTable, 'peer:add', { + signal + }) + } + this.log('run self-query, look for %d peers timing out after %dms', this.count, this.queryTimeout) + const start = Date.now() const found = await pipe( this.peerRouting.getClosestPeers(this.components.peerId.toBytes(), { @@ -133,16 +137,16 @@ export class QuerySelf implements Startable { async (source) => length(source) ) - this.log('self-query ran successfully - found %d peers', found) + this.log('self-query found %d peers in %dms', found, Date.now() - start) + } catch (err: any) { + this.log.error('self-query error', err) + } finally { + signal.clear() if (this.initialQuerySelfHasRun != null) { this.initialQuerySelfHasRun.resolve() this.initialQuerySelfHasRun = undefined } - } catch (err: any) { - this.log.error('self-query error', err) - } finally { - signal.clear() } } diff --git a/packages/kad-dht/src/record/selectors.ts b/packages/kad-dht/src/record/selectors.ts index 7753bf3b03..825af34154 100644 --- a/packages/kad-dht/src/record/selectors.ts +++ b/packages/kad-dht/src/record/selectors.ts @@ -24,7 +24,7 @@ export function bestRecord (selectors: Selectors, k: Uint8Array, records: Uint8A const selector = selectors[parts[1].toString()] if (selector == null) { - const errMsg = `Unrecognized key prefix: ${parts[1]}` + const errMsg = `No selector function configured for key type "${parts[1]}"` throw new CodeError(errMsg, 'ERR_UNRECOGNIZED_KEY_PREFIX') } diff --git a/packages/kad-dht/src/record/validators.ts b/packages/kad-dht/src/record/validators.ts index 7302a083f5..a31e09b550 100644 --- a/packages/kad-dht/src/record/validators.ts +++ b/packages/kad-dht/src/record/validators.ts @@ -23,7 +23,7 @@ export async function verifyRecord (validators: Validators, record: Libp2pRecord const validator = validators[parts[1].toString()] if (validator == null) { - const errMsg = 'Invalid record keytype' + const errMsg = `No validator available for key type "${parts[1]}"` throw new CodeError(errMsg, 'ERR_INVALID_RECORD_KEY_TYPE') } diff --git a/packages/kad-dht/test/record/selection.spec.ts b/packages/kad-dht/test/record/selection.spec.ts index cf4b441943..49556941dd 100644 --- a/packages/kad-dht/test/record/selection.spec.ts +++ b/packages/kad-dht/test/record/selection.spec.ts @@ -13,26 +13,20 @@ describe('selection', () => { it('throws no records given when no records received', () => { expect( () => selection.bestRecord({}, uint8ArrayFromString('/'), []) - ).to.throw( - /No records given/ - ) + ).to.throw().with.property('code', 'ERR_NO_RECORDS_RECEIVED') }) it('throws on missing selector in the record key', () => { expect( () => selection.bestRecord({}, uint8ArrayFromString('/'), records) - ).to.throw( - /Record key does not have a selector function/ - ) + ).to.throw().with.property('code', 'ERR_NO_SELECTOR_FUNCTION_FOR_RECORD_KEY') }) it('throws on unknown key prefix', () => { expect( // @ts-expect-error invalid input () => selection.bestRecord({ world () {} }, uint8ArrayFromString('/hello/'), records) - ).to.throw( - /Unrecognized key prefix: hello/ - ) + ).to.throw().with.property('code', 'ERR_UNRECOGNIZED_KEY_PREFIX') }) it('returns the index from the matching selector', () => { diff --git a/packages/kad-dht/test/record/validator.spec.ts b/packages/kad-dht/test/record/validator.spec.ts index 0fd7c2320b..86fbb1b21b 100644 --- a/packages/kad-dht/test/record/validator.spec.ts +++ b/packages/kad-dht/test/record/validator.spec.ts @@ -86,9 +86,7 @@ describe('validator', () => { } } await expect(validator.verifyRecord(validators, rec)) - .to.eventually.rejectedWith( - /Invalid record keytype/ - ) + .to.eventually.rejected.with.property('code', 'ERR_INVALID_RECORD_KEY_TYPE') }) }) From ab2c1f6731ccfe21a39482bdab217a8abd3f027b Mon Sep 17 00:00:00 2001 From: Chad Nehemiah Date: Wed, 25 Oct 2023 02:58:52 -0500 Subject: [PATCH 06/24] fix: remove relay:removed event listener after relay is removed (#1998) When a relay is removed, also remove the event listener Closes #1944 Closes https://github.com/libp2p/js-libp2p/issues/2106 --------- Co-authored-by: Alex Potsides --- .../src/circuit-relay/transport/listener.ts | 10 ++++-- .../libp2p/test/circuit-relay/relay.node.ts | 33 +++++++++++++++++-- packages/libp2p/test/circuit-relay/utils.ts | 17 ++++++++++ 3 files changed, 55 insertions(+), 5 deletions(-) diff --git a/packages/libp2p/src/circuit-relay/transport/listener.ts b/packages/libp2p/src/circuit-relay/transport/listener.ts index dea961b5fd..bb67007db9 100644 --- a/packages/libp2p/src/circuit-relay/transport/listener.ts +++ b/packages/libp2p/src/circuit-relay/transport/listener.ts @@ -31,9 +31,11 @@ class CircuitRelayTransportListener extends EventEmitter impleme this.listeningAddrs = new PeerMap() // remove listening addrs when a relay is removed - this.relayStore.addEventListener('relay:removed', (evt) => { - this.#removeRelayPeer(evt.detail) - }) + this.relayStore.addEventListener('relay:removed', this._onRemoveRelayPeer) + } + + _onRemoveRelayPeer = (evt: CustomEvent): void => { + this.#removeRelayPeer(evt.detail) } async listen (addr: Multiaddr): Promise { @@ -100,6 +102,8 @@ class CircuitRelayTransportListener extends EventEmitter impleme this.listeningAddrs.delete(peerId) if (had) { + log.trace('removing relay event listener for peer %p', peerId) + this.relayStore.removeEventListener('relay:removed', this._onRemoveRelayPeer) // Announce listen addresses change this.safeDispatchEvent('close', {}) } diff --git a/packages/libp2p/test/circuit-relay/relay.node.ts b/packages/libp2p/test/circuit-relay/relay.node.ts index 936dfbb869..bcf608a10d 100644 --- a/packages/libp2p/test/circuit-relay/relay.node.ts +++ b/packages/libp2p/test/circuit-relay/relay.node.ts @@ -21,7 +21,7 @@ import { HopMessage, Status } from '../../src/circuit-relay/pb/index.js' import { identifyService } from '../../src/identify/index.js' import { createLibp2p, type Libp2pOptions } from '../../src/index.js' import { plaintext } from '../../src/insecure/index.js' -import { discoveredRelayConfig, doesNotHaveRelay, getRelayAddress, hasRelay, usingAsRelay } from './utils.js' +import { discoveredRelayConfig, doesNotHaveRelay, getRelayAddress, hasRelay, notUsingAsRelay, usingAsRelay, usingAsRelayCount } from './utils.js' import type { Components } from '../../src/components.js' import type { Libp2p } from '@libp2p/interface' import type { Connection } from '@libp2p/interface/connection' @@ -354,7 +354,7 @@ describe('circuit-relay', () => { transports: [ tcp(), circuitRelayTransport({ - discoverRelays: 1 + discoverRelays: 3 }) ] }), @@ -603,6 +603,35 @@ describe('circuit-relay', () => { expect(events[1].detail.remotePeer.toString()).to.equal(relay1.peerId.toString()) }) + it('should remove the relay event listener when the relay stops', async () => { + // discover relay and make reservation + await local.dial(relay1.getMultiaddrs()[0]) + await local.dial(relay2.getMultiaddrs()[0]) + + await usingAsRelayCount(local, [relay1, relay2], 2) + + // expect 2 listeners + // @ts-expect-error these are private fields + const listeners = local.components.transportManager.getListeners() + + // @ts-expect-error as a result these will have any types + const circuitListener = listeners.filter(listener => { + // @ts-expect-error as a result these will have any types + const circuitMultiaddrs = listener.getAddrs().filter(ma => Circuit.matches(ma)) + return circuitMultiaddrs.length > 0 + }) + + expect(circuitListener[0].relayStore.listenerCount('relay:removed')).to.equal(2) + + // remove one listener + await local.hangUp(relay1.peerId) + + await notUsingAsRelay(local, relay1) + + // expect 1 listener + expect(circuitListener[0].relayStore.listenerCount('relay:removed')).to.equal(1) + }) + it('should mark a relayed connection as transient', async () => { // discover relay and make reservation const connectionToRelay = await remote.dial(relay1.getMultiaddrs()[0]) diff --git a/packages/libp2p/test/circuit-relay/utils.ts b/packages/libp2p/test/circuit-relay/utils.ts index e11bd708f6..aa3cde6e15 100644 --- a/packages/libp2p/test/circuit-relay/utils.ts +++ b/packages/libp2p/test/circuit-relay/utils.ts @@ -30,6 +30,23 @@ export async function usingAsRelay (node: Libp2p, relay: Libp2p, opts?: PWaitFor }, opts) } +export async function usingAsRelayCount (node: Libp2p, relays: Libp2p[], count: number): Promise { + // Wait for peer to be used as a relay + await pWaitFor(async () => { + let relayCount = 0 + + for (const relay of relays) { + for (const addr of node.getMultiaddrs()) { + const search = `${relay.peerId.toString()}/p2p-circuit` + if (addr.toString().includes(search)) { + relayCount++ + } + } + } + return relayCount === count + }) +} + export async function notUsingAsRelay (node: Libp2p, relay: Libp2p, opts?: PWaitForOptions): Promise { // Wait for peer to be used as a relay await pWaitFor(() => { From f9d1c07274df5cb281acaf26797be3b913b90052 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 25 Oct 2023 09:37:08 +0100 Subject: [PATCH 07/24] deps: bump prom-client from 14.2.0 to 15.0.0 (#2142) Bumps [prom-client](https://github.com/siimon/prom-client) from 14.2.0 to 15.0.0. - [Release notes](https://github.com/siimon/prom-client/releases) - [Changelog](https://github.com/siimon/prom-client/blob/master/CHANGELOG.md) - [Commits](https://github.com/siimon/prom-client/compare/v14.2.0...v15.0.0) --- updated-dependencies: - dependency-name: prom-client dependency-type: direct:production update-type: version-update:semver-major ... --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: achingbrain --- doc/package.json | 2 +- packages/metrics-prometheus/package.json | 2 +- packages/metrics-prometheus/src/index.ts | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/doc/package.json b/doc/package.json index a1b9c91f2d..c73eb0317b 100644 --- a/doc/package.json +++ b/doc/package.json @@ -30,7 +30,7 @@ "@libp2p/tcp": "^8.0.0", "aegir": "^41.0.2", "libp2p": "^0.46.0", - "prom-client": "^14.2.0" + "prom-client": "^15.0.0" }, "private": true } diff --git a/packages/metrics-prometheus/package.json b/packages/metrics-prometheus/package.json index 87fd6acc4a..f15dc7b1b2 100644 --- a/packages/metrics-prometheus/package.json +++ b/packages/metrics-prometheus/package.json @@ -47,7 +47,7 @@ "@libp2p/logger": "^3.0.3", "it-foreach": "^2.0.3", "it-stream-types": "^2.0.1", - "prom-client": "^14.2.0" + "prom-client": "^15.0.0" }, "devDependencies": { "@libp2p/interface-compliance-tests": "^4.1.1", diff --git a/packages/metrics-prometheus/src/index.ts b/packages/metrics-prometheus/src/index.ts index 3e6accc57c..46675605d8 100644 --- a/packages/metrics-prometheus/src/index.ts +++ b/packages/metrics-prometheus/src/index.ts @@ -96,7 +96,7 @@ import { logger } from '@libp2p/logger' import each from 'it-foreach' -import { collectDefaultMetrics, type DefaultMetricsCollectorConfiguration, register, type Registry } from 'prom-client' +import { collectDefaultMetrics, type DefaultMetricsCollectorConfiguration, register, type Registry, type RegistryContentType } from 'prom-client' import { PrometheusCounterGroup } from './counter-group.js' import { PrometheusCounter } from './counter.js' import { PrometheusMetricGroup } from './metric-group.js' @@ -126,7 +126,7 @@ export interface PrometheusMetricsInit { /** * prom-client options to pass to the `collectDefaultMetrics` function */ - defaultMetrics?: DefaultMetricsCollectorConfiguration + defaultMetrics?: DefaultMetricsCollectorConfiguration /** * All metrics in prometheus are global so to prevent clashes in naming From b5a808af700207fe5e086133bb505367177a086e Mon Sep 17 00:00:00 2001 From: Alex Potsides Date: Wed, 25 Oct 2023 12:51:13 +0100 Subject: [PATCH 08/24] refactor: rename event emitter class (#2159) We add types to a EventEmitter class which extends the plain js EventTarget. The name is chosen to give familiarity to node developers but it's not generally a good idea. This refactor: 1. Exports a new TypedEventTarget interface which adds types to EventTarget 2. Renames EventEmitter to TypedEventEmitter to draw a distinction between them In the future all consuming code should rely on the TypedEventTarget interface while implemmenting code uses TypedEventEmitter as an implementation of a TypedEventEmitter. By depending on the interface and not the implementation consuming code is isolated from problems that arise when two versions of `@libp2p/interface` is in the dependency tree and the event subsystems would otherwise be compatible due to type overlap. This maifests as an error message about incompatible implementations of the private `#listeners` field in EventEmitter. --- .../src/mocks/connection-manager.ts | 6 +++--- .../src/mocks/peer-discovery.ts | 4 ++-- .../src/mocks/upgrader.ts | 6 +++--- .../src/pubsub/utils.ts | 4 ++-- .../src/transport/dial-test.ts | 4 ++-- .../src/transport/listen-test.ts | 4 ++-- packages/interface/src/events.ts | 21 ++++++++++++++++++- packages/interface/src/index.ts | 4 ++-- .../interface/src/peer-discovery/index.ts | 4 ++-- packages/interface/src/pubsub/index.ts | 6 +++--- packages/interface/src/transport/index.ts | 4 ++-- packages/kad-dht/src/dual-kad-dht.ts | 4 ++-- packages/kad-dht/src/index.ts | 4 ++-- packages/kad-dht/src/kad-dht.ts | 4 ++-- packages/kad-dht/src/network.ts | 4 ++-- packages/kad-dht/src/query/manager.ts | 4 ++-- packages/kad-dht/src/query/query-path.ts | 6 +++--- packages/kad-dht/src/routing-table/index.ts | 4 ++-- .../kad-dht/src/routing-table/k-bucket.ts | 6 ++---- packages/kad-dht/src/topology-listener.ts | 4 ++-- packages/kad-dht/test/routing-table.spec.ts | 4 ++-- .../test/rpc/handlers/get-providers.spec.ts | 4 ++-- .../test/rpc/handlers/get-value.spec.ts | 4 ++-- packages/kad-dht/test/rpc/index.node.ts | 4 ++-- packages/kad-dht/test/utils/test-dht.ts | 4 ++-- packages/libp2p/src/address-manager/index.ts | 4 ++-- packages/libp2p/src/circuit-relay/index.ts | 4 ++-- .../circuit-relay/server/advert-service.ts | 4 ++-- .../libp2p/src/circuit-relay/server/index.ts | 4 ++-- .../src/circuit-relay/transport/discovery.ts | 4 ++-- .../src/circuit-relay/transport/index.ts | 4 ++-- .../src/circuit-relay/transport/listener.ts | 4 ++-- .../transport/reservation-store.ts | 8 +++---- packages/libp2p/src/components.ts | 6 +++--- .../src/connection-manager/auto-dial.ts | 4 ++-- .../connection-manager/connection-pruner.ts | 6 +++--- .../libp2p/src/connection-manager/index.ts | 6 +++--- packages/libp2p/src/identify/identify.ts | 4 ++-- packages/libp2p/src/identify/index.ts | 4 ++-- packages/libp2p/src/libp2p.ts | 6 +++--- packages/libp2p/src/registrar.ts | 4 ++-- packages/libp2p/src/transport-manager.ts | 4 ++-- packages/libp2p/src/upgrader.ts | 6 +++--- .../test/addresses/address-manager.spec.ts | 6 +++--- .../libp2p/test/circuit-relay/hop.spec.ts | 6 +++--- .../libp2p/test/circuit-relay/stop.spec.ts | 4 ++-- .../test/connection-manager/auto-dial.spec.ts | 6 +++--- .../test/connection-manager/direct.node.ts | 6 +++--- .../test/connection-manager/direct.spec.ts | 4 ++-- .../test/connection-manager/index.node.ts | 6 +++--- .../test/connection-manager/index.spec.ts | 12 +++++------ packages/libp2p/test/fetch/index.spec.ts | 4 ++-- packages/libp2p/test/identify/index.spec.ts | 4 ++-- packages/libp2p/test/identify/push.spec.ts | 4 ++-- .../libp2p/test/peer-discovery/index.node.ts | 4 ++-- packages/libp2p/test/ping/index.spec.ts | 4 ++-- .../libp2p/test/registrar/registrar.spec.ts | 8 +++---- .../test/transports/transport-manager.node.ts | 4 ++-- .../test/transports/transport-manager.spec.ts | 4 ++-- .../libp2p/test/upgrading/upgrader.spec.ts | 6 +++--- .../libp2p/test/upnp-nat/upnp-nat.node.ts | 4 ++-- .../peer-discovery-bootstrap/src/index.ts | 4 ++-- packages/peer-discovery-mdns/src/index.ts | 4 ++-- packages/peer-store/src/index.ts | 6 +++--- packages/peer-store/test/index.spec.ts | 6 +++--- packages/peer-store/test/merge.spec.ts | 6 +++--- packages/peer-store/test/patch.spec.ts | 6 +++--- packages/peer-store/test/save.spec.ts | 6 +++--- packages/protocol-perf/test/index.spec.ts | 4 ++-- packages/pubsub/src/index.ts | 4 ++-- packages/pubsub/src/peer-streams.ts | 4 ++-- packages/transport-tcp/src/listener.ts | 4 ++-- .../test/connection-limits.spec.ts | 10 ++++----- .../transport-tcp/test/connection.spec.ts | 4 ++-- .../transport-tcp/test/listen-dial.spec.ts | 6 +++--- .../test/max-connections.spec.ts | 4 ++-- .../src/private-to-private/listener.ts | 4 ++-- packages/transport-websockets/.aegir.js | 4 ++-- packages/transport-websockets/src/listener.ts | 4 ++-- packages/transport-websockets/test/browser.ts | 4 ++-- packages/transport-websockets/test/node.ts | 4 ++-- 81 files changed, 212 insertions(+), 195 deletions(-) diff --git a/packages/interface-compliance-tests/src/mocks/connection-manager.ts b/packages/interface-compliance-tests/src/mocks/connection-manager.ts index 4f5cecbac0..81904d407f 100644 --- a/packages/interface-compliance-tests/src/mocks/connection-manager.ts +++ b/packages/interface-compliance-tests/src/mocks/connection-manager.ts @@ -6,7 +6,7 @@ import { isMultiaddr, type Multiaddr } from '@multiformats/multiaddr' import { connectionPair } from './connection.js' import type { Libp2pEvents, PendingDial } from '@libp2p/interface' import type { Connection } from '@libp2p/interface/connection' -import type { EventEmitter } from '@libp2p/interface/events' +import type { TypedEventTarget } from '@libp2p/interface/events' import type { PubSub } from '@libp2p/interface/pubsub' import type { Startable } from '@libp2p/interface/startable' import type { ConnectionManager } from '@libp2p/interface-internal/connection-manager' @@ -16,7 +16,7 @@ export interface MockNetworkComponents { peerId: PeerId registrar: Registrar connectionManager: ConnectionManager - events: EventEmitter + events: TypedEventTarget pubsub?: PubSub } @@ -51,7 +51,7 @@ export const mockNetwork = new MockNetwork() export interface MockConnectionManagerComponents { peerId: PeerId registrar: Registrar - events: EventEmitter + events: TypedEventTarget } class MockConnectionManager implements ConnectionManager, Startable { diff --git a/packages/interface-compliance-tests/src/mocks/peer-discovery.ts b/packages/interface-compliance-tests/src/mocks/peer-discovery.ts index eab17bea6d..69bd2afc29 100644 --- a/packages/interface-compliance-tests/src/mocks/peer-discovery.ts +++ b/packages/interface-compliance-tests/src/mocks/peer-discovery.ts @@ -1,4 +1,4 @@ -import { EventEmitter } from '@libp2p/interface/events' +import { TypedEventEmitter } from '@libp2p/interface/events' import { peerDiscovery } from '@libp2p/interface/peer-discovery' import * as PeerIdFactory from '@libp2p/peer-id-factory' import { multiaddr } from '@multiformats/multiaddr' @@ -12,7 +12,7 @@ interface MockDiscoveryInit { /** * Emits 'peer' events on discovery. */ -export class MockDiscovery extends EventEmitter implements PeerDiscovery { +export class MockDiscovery extends TypedEventEmitter implements PeerDiscovery { public readonly options: MockDiscoveryInit private _isRunning: boolean private _timer: any diff --git a/packages/interface-compliance-tests/src/mocks/upgrader.ts b/packages/interface-compliance-tests/src/mocks/upgrader.ts index b4ef88002d..4f69268071 100644 --- a/packages/interface-compliance-tests/src/mocks/upgrader.ts +++ b/packages/interface-compliance-tests/src/mocks/upgrader.ts @@ -1,18 +1,18 @@ import { mockConnection } from './connection.js' import type { Libp2pEvents } from '@libp2p/interface' import type { Connection, MultiaddrConnection } from '@libp2p/interface/connection' -import type { EventEmitter } from '@libp2p/interface/events' +import type { TypedEventTarget } from '@libp2p/interface/events' import type { Upgrader, UpgraderOptions } from '@libp2p/interface/transport' import type { Registrar } from '@libp2p/interface-internal/registrar' export interface MockUpgraderInit { registrar?: Registrar - events?: EventEmitter + events?: TypedEventTarget } class MockUpgrader implements Upgrader { private readonly registrar?: Registrar - private readonly events?: EventEmitter + private readonly events?: TypedEventTarget constructor (init: MockUpgraderInit) { this.registrar = init.registrar diff --git a/packages/interface-compliance-tests/src/pubsub/utils.ts b/packages/interface-compliance-tests/src/pubsub/utils.ts index 79bf894479..fdd7c2552c 100644 --- a/packages/interface-compliance-tests/src/pubsub/utils.ts +++ b/packages/interface-compliance-tests/src/pubsub/utils.ts @@ -1,4 +1,4 @@ -import { EventEmitter } from '@libp2p/interface/events' +import { TypedEventEmitter } from '@libp2p/interface/events' import { createEd25519PeerId } from '@libp2p/peer-id-factory' import { pEvent } from 'p-event' import pWaitFor from 'p-wait-for' @@ -19,7 +19,7 @@ export async function createComponents (): Promise { const components: any = { peerId: await createEd25519PeerId(), registrar: mockRegistrar(), - events: new EventEmitter() + events: new TypedEventEmitter() } components.connectionManager = mockConnectionManager(components) diff --git a/packages/interface-compliance-tests/src/transport/dial-test.ts b/packages/interface-compliance-tests/src/transport/dial-test.ts index 2139a755d0..98035d9aa5 100644 --- a/packages/interface-compliance-tests/src/transport/dial-test.ts +++ b/packages/interface-compliance-tests/src/transport/dial-test.ts @@ -1,5 +1,5 @@ import { AbortError } from '@libp2p/interface/errors' -import { EventEmitter } from '@libp2p/interface/events' +import { TypedEventEmitter } from '@libp2p/interface/events' import { expect } from 'aegir/chai' import all from 'it-all' import drain from 'it-drain' @@ -27,7 +27,7 @@ export default (common: TestSetup): void => { registrar = mockRegistrar() upgrader = mockUpgrader({ registrar, - events: new EventEmitter() + events: new TypedEventEmitter() }); ({ addrs, transport, connector } = await common.setup()) diff --git a/packages/interface-compliance-tests/src/transport/listen-test.ts b/packages/interface-compliance-tests/src/transport/listen-test.ts index d518511dc7..d9f3a17c22 100644 --- a/packages/interface-compliance-tests/src/transport/listen-test.ts +++ b/packages/interface-compliance-tests/src/transport/listen-test.ts @@ -1,5 +1,5 @@ /* eslint max-nested-callbacks: ["error", 8] */ -import { CustomEvent, EventEmitter } from '@libp2p/interface/events' +import { CustomEvent, TypedEventEmitter } from '@libp2p/interface/events' import { expect } from 'aegir/chai' import drain from 'it-drain' import { pipe } from 'it-pipe' @@ -27,7 +27,7 @@ export default (common: TestSetup): void => { registrar = mockRegistrar() upgrader = mockUpgrader({ registrar, - events: new EventEmitter() + events: new TypedEventEmitter() }); ({ transport, addrs } = await common.setup()) diff --git a/packages/interface/src/events.ts b/packages/interface/src/events.ts index 4fff7e8f91..2f4e863b0e 100644 --- a/packages/interface/src/events.ts +++ b/packages/interface/src/events.ts @@ -15,7 +15,23 @@ interface Listener { * https://github.com/microsoft/TypeScript/issues/299 * etc */ -export class EventEmitter> extends EventTarget { +export interface TypedEventTarget > extends EventTarget { + addEventListener(type: K, listener: EventHandler | null, options?: boolean | AddEventListenerOptions): void + + listenerCount (type: string): number + + removeEventListener(type: K, listener?: EventHandler | null, options?: boolean | EventListenerOptions): void + + removeEventListener (type: string, listener?: EventHandler, options?: boolean | EventListenerOptions): void + + safeDispatchEvent(type: keyof EventMap, detail: CustomEventInit): boolean +} + +/** + * An implementation of a typed event target + * etc + */ +export class TypedEventEmitter> extends EventTarget implements TypedEventTarget { #listeners = new Map() listenerCount (type: string): number { @@ -98,3 +114,6 @@ class CustomEventPolyfill extends Event { } export const CustomEvent = globalThis.CustomEvent ?? CustomEventPolyfill + +// TODO: remove this in v1 +export { TypedEventEmitter as EventEmitter } diff --git a/packages/interface/src/index.ts b/packages/interface/src/index.ts index 0dd02078f8..d50e335d69 100644 --- a/packages/interface/src/index.ts +++ b/packages/interface/src/index.ts @@ -16,7 +16,7 @@ import type { Connection, NewStreamOptions, Stream } from './connection/index.js' import type { ContentRouting } from './content-routing/index.js' -import type { EventEmitter } from './events.js' +import type { TypedEventTarget } from './events.js' import type { KeyChain } from './keychain/index.js' import type { Metrics } from './metrics/index.js' import type { PeerId } from './peer-id/index.js' @@ -303,7 +303,7 @@ export interface PendingDial { /** * Libp2p nodes implement this interface. */ -export interface Libp2p extends Startable, EventEmitter> { +export interface Libp2p extends Startable, TypedEventTarget> { /** * The PeerId is a unique identifier for a node on the network. * diff --git a/packages/interface/src/peer-discovery/index.ts b/packages/interface/src/peer-discovery/index.ts index 4b8aa9c258..55b1227eb1 100644 --- a/packages/interface/src/peer-discovery/index.ts +++ b/packages/interface/src/peer-discovery/index.ts @@ -1,4 +1,4 @@ -import type { EventEmitter } from '../events.js' +import type { TypedEventTarget } from '../events.js' import type { PeerInfo } from '../peer-info/index.js' /** @@ -26,4 +26,4 @@ export interface PeerDiscoveryEvents { 'peer': CustomEvent } -export interface PeerDiscovery extends EventEmitter {} +export interface PeerDiscovery extends TypedEventTarget {} diff --git a/packages/interface/src/pubsub/index.ts b/packages/interface/src/pubsub/index.ts index 6fd94382a1..1ce9464b6b 100644 --- a/packages/interface/src/pubsub/index.ts +++ b/packages/interface/src/pubsub/index.ts @@ -1,5 +1,5 @@ import type { Stream } from '../connection/index.js' -import type { EventEmitter } from '../events.js' +import type { TypedEventTarget } from '../events.js' import type { PeerId } from '../peer-id/index.js' import type { Pushable } from 'it-pushable' import type { Uint8ArrayList } from 'uint8arraylist' @@ -65,7 +65,7 @@ export interface PubSubRPC { messages: PubSubRPCMessage[] } -export interface PeerStreams extends EventEmitter { +export interface PeerStreams extends TypedEventTarget { id: PeerId protocol: string outboundStream?: Pushable @@ -152,7 +152,7 @@ export interface TopicValidatorFn { (peer: PeerId, message: Message): TopicValidatorResult | Promise } -export interface PubSub = PubSubEvents> extends EventEmitter { +export interface PubSub = PubSubEvents> extends TypedEventTarget { /** * The global signature policy controls whether or not we sill send and receive * signed or unsigned messages. diff --git a/packages/interface/src/transport/index.ts b/packages/interface/src/transport/index.ts index 5acbfcc50e..22ab1a803b 100644 --- a/packages/interface/src/transport/index.ts +++ b/packages/interface/src/transport/index.ts @@ -1,5 +1,5 @@ import type { Connection, MultiaddrConnection } from '../connection/index.js' -import type { EventEmitter } from '../events.js' +import type { TypedEventTarget } from '../events.js' import type { AbortOptions } from '../index.js' import type { StreamMuxerFactory } from '../stream-muxer/index.js' import type { Multiaddr } from '@multiformats/multiaddr' @@ -11,7 +11,7 @@ export interface ListenerEvents { 'close': CustomEvent } -export interface Listener extends EventEmitter { +export interface Listener extends TypedEventTarget { /** * Start a listener */ diff --git a/packages/kad-dht/src/dual-kad-dht.ts b/packages/kad-dht/src/dual-kad-dht.ts index 6d704725fb..ef06f739ea 100644 --- a/packages/kad-dht/src/dual-kad-dht.ts +++ b/packages/kad-dht/src/dual-kad-dht.ts @@ -1,6 +1,6 @@ import { type ContentRouting, contentRouting } from '@libp2p/interface/content-routing' import { CodeError } from '@libp2p/interface/errors' -import { EventEmitter, CustomEvent } from '@libp2p/interface/events' +import { TypedEventEmitter, CustomEvent } from '@libp2p/interface/events' import { type PeerDiscovery, peerDiscovery, type PeerDiscoveryEvents } from '@libp2p/interface/peer-discovery' import { type PeerRouting, peerRouting } from '@libp2p/interface/peer-routing' import { logger } from '@libp2p/logger' @@ -121,7 +121,7 @@ function multiaddrIsPublic (multiaddr: Multiaddr): boolean { * A DHT implementation modelled after Kademlia with S/Kademlia modifications. * Original implementation in go: https://github.com/libp2p/go-libp2p-kad-dht. */ -export class DefaultDualKadDHT extends EventEmitter implements DualKadDHT, PeerDiscovery { +export class DefaultDualKadDHT extends TypedEventEmitter implements DualKadDHT, PeerDiscovery { public readonly wan: DefaultKadDHT public readonly lan: DefaultKadDHT public readonly components: KadDHTComponents diff --git a/packages/kad-dht/src/index.ts b/packages/kad-dht/src/index.ts index edb1e4f679..679a7ba62f 100644 --- a/packages/kad-dht/src/index.ts +++ b/packages/kad-dht/src/index.ts @@ -1,7 +1,7 @@ import { DefaultDualKadDHT } from './dual-kad-dht.js' import type { ProvidersInit } from './providers.js' import type { Libp2pEvents, AbortOptions } from '@libp2p/interface' -import type { EventEmitter } from '@libp2p/interface/events' +import type { TypedEventTarget } from '@libp2p/interface/events' import type { Metrics } from '@libp2p/interface/metrics' import type { PeerId } from '@libp2p/interface/peer-id' import type { PeerInfo } from '@libp2p/interface/peer-info' @@ -314,7 +314,7 @@ export interface KadDHTComponents { metrics?: Metrics connectionManager: ConnectionManager datastore: Datastore - events: EventEmitter + events: TypedEventTarget } export function kadDHT (init?: KadDHTInit): (components: KadDHTComponents) => DualKadDHT { diff --git a/packages/kad-dht/src/kad-dht.ts b/packages/kad-dht/src/kad-dht.ts index f9f260452c..fb5be07aa9 100644 --- a/packages/kad-dht/src/kad-dht.ts +++ b/packages/kad-dht/src/kad-dht.ts @@ -1,4 +1,4 @@ -import { CustomEvent, EventEmitter } from '@libp2p/interface/events' +import { CustomEvent, TypedEventEmitter } from '@libp2p/interface/events' import { type Logger, logger } from '@libp2p/logger' import pDefer from 'p-defer' import { PROTOCOL_DHT, PROTOCOL_PREFIX, LAN_PREFIX } from './constants.js' @@ -39,7 +39,7 @@ export interface SingleKadDHTInit extends KadDHTInit { * A DHT implementation modelled after Kademlia with S/Kademlia modifications. * Original implementation in go: https://github.com/libp2p/go-libp2p-kad-dht. */ -export class DefaultKadDHT extends EventEmitter implements KadDHT { +export class DefaultKadDHT extends TypedEventEmitter implements KadDHT { public protocol: string public routingTable: RoutingTable public providers: Providers diff --git a/packages/kad-dht/src/network.ts b/packages/kad-dht/src/network.ts index b10ad6e592..c968b10f9b 100644 --- a/packages/kad-dht/src/network.ts +++ b/packages/kad-dht/src/network.ts @@ -1,5 +1,5 @@ import { CodeError } from '@libp2p/interface/errors' -import { EventEmitter, CustomEvent } from '@libp2p/interface/events' +import { TypedEventEmitter, CustomEvent } from '@libp2p/interface/events' import { logger } from '@libp2p/logger' import { abortableDuplex } from 'abortable-iterator' import drain from 'it-drain' @@ -35,7 +35,7 @@ interface NetworkEvents { /** * Handle network operations for the dht */ -export class Network extends EventEmitter implements Startable { +export class Network extends TypedEventEmitter implements Startable { private readonly log: Logger private readonly protocol: string private running: boolean diff --git a/packages/kad-dht/src/query/manager.ts b/packages/kad-dht/src/query/manager.ts index df830faf2d..675c9a9f81 100644 --- a/packages/kad-dht/src/query/manager.ts +++ b/packages/kad-dht/src/query/manager.ts @@ -1,6 +1,6 @@ import { setMaxListeners } from 'events' import { AbortError } from '@libp2p/interface/errors' -import { EventEmitter, CustomEvent } from '@libp2p/interface/events' +import { TypedEventEmitter, CustomEvent } from '@libp2p/interface/events' import { logger } from '@libp2p/logger' import { PeerSet } from '@libp2p/peer-collections' import { anySignal } from 'any-signal' @@ -143,7 +143,7 @@ export class QueryManager implements Startable { // query a subset of peers up to `kBucketSize / 2` in length const startTime = Date.now() - const cleanUp = new EventEmitter() + const cleanUp = new TypedEventEmitter() try { if (options.isSelfQuery !== true && this.initialQuerySelfHasRun != null) { diff --git a/packages/kad-dht/src/query/query-path.ts b/packages/kad-dht/src/query/query-path.ts index 991f1abd42..382585ae26 100644 --- a/packages/kad-dht/src/query/query-path.ts +++ b/packages/kad-dht/src/query/query-path.ts @@ -9,7 +9,7 @@ import { queryErrorEvent } from './events.js' import type { CleanUpEvents } from './manager.js' import type { QueryEvent, QueryOptions } from '../index.js' import type { QueryFunc } from '../query/types.js' -import type { EventEmitter } from '@libp2p/interface/events' +import type { TypedEventTarget } from '@libp2p/interface/events' import type { PeerId } from '@libp2p/interface/peer-id' import type { Logger } from '@libp2p/logger' import type { PeerSet } from '@libp2p/peer-collections' @@ -60,7 +60,7 @@ export interface QueryPathOptions extends QueryOptions { /** * will emit a 'cleanup' event if the caller exits the for..await of early */ - cleanUp: EventEmitter + cleanUp: TypedEventTarget /** * A timeout for queryFunc in ms @@ -185,7 +185,7 @@ export async function * queryPath (options: QueryPathOptions): AsyncGenerator, log: Logger): AsyncGenerator { +async function * toGenerator (queue: Queue, signal: AbortSignal, cleanUp: TypedEventTarget, log: Logger): AsyncGenerator { let deferred = defer() let running = true const results: QueryEvent[] = [] diff --git a/packages/kad-dht/src/routing-table/index.ts b/packages/kad-dht/src/routing-table/index.ts index b0bfbb90ff..ee7b24bcf8 100644 --- a/packages/kad-dht/src/routing-table/index.ts +++ b/packages/kad-dht/src/routing-table/index.ts @@ -1,4 +1,4 @@ -import { EventEmitter } from '@libp2p/interface/events' +import { TypedEventEmitter } from '@libp2p/interface/events' import { logger } from '@libp2p/logger' import { PeerSet } from '@libp2p/peer-collections' import Queue from 'p-queue' @@ -43,7 +43,7 @@ export interface RoutingTableEvents { * A wrapper around `k-bucket`, to provide easy store and * retrieval for peers. */ -export class RoutingTable extends EventEmitter implements Startable { +export class RoutingTable extends TypedEventEmitter implements Startable { public kBucketSize: number public kb?: KBucket public pingQueue: Queue diff --git a/packages/kad-dht/src/routing-table/k-bucket.ts b/packages/kad-dht/src/routing-table/k-bucket.ts index b8e510d0a2..57585926e9 100644 --- a/packages/kad-dht/src/routing-table/k-bucket.ts +++ b/packages/kad-dht/src/routing-table/k-bucket.ts @@ -27,7 +27,7 @@ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -import { EventEmitter } from '@libp2p/interface/events' +import { TypedEventEmitter } from '@libp2p/interface/events' import type { PeerId } from '@libp2p/interface/peer-id' function arrayEquals (array1: Uint8Array, array2: Uint8Array): boolean { @@ -122,10 +122,8 @@ export interface Bucket { /** * Implementation of a Kademlia DHT k-bucket used for storing * contact (peer node) information. - * - * @extends EventEmitter */ -export class KBucket extends EventEmitter { +export class KBucket extends TypedEventEmitter { public localNodeId: Uint8Array public root: Bucket private readonly numberOfNodesPerKBucket: number diff --git a/packages/kad-dht/src/topology-listener.ts b/packages/kad-dht/src/topology-listener.ts index 462b633a3c..8af9a210a4 100644 --- a/packages/kad-dht/src/topology-listener.ts +++ b/packages/kad-dht/src/topology-listener.ts @@ -1,4 +1,4 @@ -import { CustomEvent, EventEmitter } from '@libp2p/interface/events' +import { CustomEvent, TypedEventEmitter } from '@libp2p/interface/events' import { logger } from '@libp2p/logger' import type { KadDHTComponents } from '.' import type { PeerId } from '@libp2p/interface/peer-id' @@ -17,7 +17,7 @@ export interface TopologyListenerEvents { /** * Receives notifications of new peers joining the network that support the DHT protocol */ -export class TopologyListener extends EventEmitter implements Startable { +export class TopologyListener extends TypedEventEmitter implements Startable { private readonly log: Logger private readonly components: KadDHTComponents private readonly protocol: string diff --git a/packages/kad-dht/test/routing-table.spec.ts b/packages/kad-dht/test/routing-table.spec.ts index 669115c349..35381a044f 100644 --- a/packages/kad-dht/test/routing-table.spec.ts +++ b/packages/kad-dht/test/routing-table.spec.ts @@ -1,6 +1,6 @@ /* eslint-env mocha */ -import { EventEmitter, CustomEvent } from '@libp2p/interface/events' +import { TypedEventEmitter, CustomEvent } from '@libp2p/interface/events' import { mockConnectionManager } from '@libp2p/interface-compliance-tests/mocks' import { PeerSet } from '@libp2p/peer-collections' import { peerIdFromString } from '@libp2p/peer-id' @@ -33,7 +33,7 @@ describe('Routing Table', () => { beforeEach(async function () { this.timeout(20 * 1000) - const events = new EventEmitter() + const events = new TypedEventEmitter() components = { peerId: await createPeerId(), diff --git a/packages/kad-dht/test/rpc/handlers/get-providers.spec.ts b/packages/kad-dht/test/rpc/handlers/get-providers.spec.ts index 20cab3c7e7..18a3706f64 100644 --- a/packages/kad-dht/test/rpc/handlers/get-providers.spec.ts +++ b/packages/kad-dht/test/rpc/handlers/get-providers.spec.ts @@ -1,6 +1,6 @@ /* eslint-env mocha */ -import { EventEmitter } from '@libp2p/interface/events' +import { TypedEventEmitter } from '@libp2p/interface/events' import { PersistentPeerStore } from '@libp2p/peer-store' import { multiaddr } from '@multiformats/multiaddr' import { expect } from 'aegir/chai' @@ -43,7 +43,7 @@ describe('rpc - handlers - GetProviders', () => { peerStore = new PersistentPeerStore({ peerId, datastore: new MemoryDatastore(), - events: new EventEmitter() + events: new TypedEventEmitter() }) const components: GetProvidersHandlerComponents = { diff --git a/packages/kad-dht/test/rpc/handlers/get-value.spec.ts b/packages/kad-dht/test/rpc/handlers/get-value.spec.ts index 32cf1c9bba..ad79dda7c6 100644 --- a/packages/kad-dht/test/rpc/handlers/get-value.spec.ts +++ b/packages/kad-dht/test/rpc/handlers/get-value.spec.ts @@ -1,6 +1,6 @@ /* eslint-env mocha */ -import { EventEmitter } from '@libp2p/interface/events' +import { TypedEventEmitter } from '@libp2p/interface/events' import { PersistentPeerStore } from '@libp2p/peer-store' import { expect } from 'aegir/chai' import { MemoryDatastore } from 'datastore-core' @@ -40,7 +40,7 @@ describe('rpc - handlers - GetValue', () => { peerStore = new PersistentPeerStore({ peerId, datastore, - events: new EventEmitter() + events: new TypedEventEmitter() }) const components: GetValueHandlerComponents = { diff --git a/packages/kad-dht/test/rpc/index.node.ts b/packages/kad-dht/test/rpc/index.node.ts index da58989b23..25ced21d11 100644 --- a/packages/kad-dht/test/rpc/index.node.ts +++ b/packages/kad-dht/test/rpc/index.node.ts @@ -1,6 +1,6 @@ /* eslint-env mocha */ -import { EventEmitter } from '@libp2p/interface/events' +import { TypedEventEmitter } from '@libp2p/interface/events' import { start } from '@libp2p/interface/startable' import { mockStream } from '@libp2p/interface-compliance-tests/mocks' import { PersistentPeerStore } from '@libp2p/peer-store' @@ -51,7 +51,7 @@ describe('rpc', () => { } components.peerStore = new PersistentPeerStore({ ...components, - events: new EventEmitter() + events: new TypedEventEmitter() }) await start(...Object.values(components)) diff --git a/packages/kad-dht/test/utils/test-dht.ts b/packages/kad-dht/test/utils/test-dht.ts index 04be4041be..bfddebdaad 100644 --- a/packages/kad-dht/test/utils/test-dht.ts +++ b/packages/kad-dht/test/utils/test-dht.ts @@ -1,4 +1,4 @@ -import { EventEmitter } from '@libp2p/interface/events' +import { TypedEventEmitter } from '@libp2p/interface/events' import { start, stop } from '@libp2p/interface/startable' import { mockRegistrar, mockConnectionManager, mockNetwork } from '@libp2p/interface-compliance-tests/mocks' import { logger } from '@libp2p/logger' @@ -29,7 +29,7 @@ export class TestDHT { } async spawn (options: Partial = {}, autoStart = true): Promise { - const events = new EventEmitter() + const events = new TypedEventEmitter() const components: KadDHTComponents = { peerId: await createPeerId(), datastore: new MemoryDatastore(), diff --git a/packages/libp2p/src/address-manager/index.ts b/packages/libp2p/src/address-manager/index.ts index 44a8504f51..f6bafad41f 100644 --- a/packages/libp2p/src/address-manager/index.ts +++ b/packages/libp2p/src/address-manager/index.ts @@ -3,7 +3,7 @@ import { peerIdFromString } from '@libp2p/peer-id' import { multiaddr } from '@multiformats/multiaddr' import { debounce } from './utils.js' import type { Libp2pEvents } from '@libp2p/interface' -import type { EventEmitter } from '@libp2p/interface/events' +import type { TypedEventTarget } from '@libp2p/interface/events' import type { PeerId } from '@libp2p/interface/peer-id' import type { PeerStore } from '@libp2p/interface/peer-store' import type { TransportManager } from '@libp2p/interface-internal/transport-manager' @@ -38,7 +38,7 @@ export interface DefaultAddressManagerComponents { peerId: PeerId transportManager: TransportManager peerStore: PeerStore - events: EventEmitter + events: TypedEventTarget } /** diff --git a/packages/libp2p/src/circuit-relay/index.ts b/packages/libp2p/src/circuit-relay/index.ts index 91ab9007e4..5e8757fb10 100644 --- a/packages/libp2p/src/circuit-relay/index.ts +++ b/packages/libp2p/src/circuit-relay/index.ts @@ -35,7 +35,7 @@ */ import type { Limit } from './pb/index.js' -import type { EventEmitter } from '@libp2p/interface/events' +import type { TypedEventEmitter } from '@libp2p/interface/events' import type { PeerMap } from '@libp2p/peer-collections' import type { Multiaddr } from '@multiformats/multiaddr' @@ -51,7 +51,7 @@ export interface CircuitRelayServiceEvents { 'relay:advert:error': CustomEvent } -export interface CircuitRelayService extends EventEmitter { +export interface CircuitRelayService extends TypedEventEmitter { reservations: PeerMap } diff --git a/packages/libp2p/src/circuit-relay/server/advert-service.ts b/packages/libp2p/src/circuit-relay/server/advert-service.ts index 5d2c61990f..4e84f41c2c 100644 --- a/packages/libp2p/src/circuit-relay/server/advert-service.ts +++ b/packages/libp2p/src/circuit-relay/server/advert-service.ts @@ -1,4 +1,4 @@ -import { EventEmitter } from '@libp2p/interface/events' +import { TypedEventEmitter } from '@libp2p/interface/events' import { logger } from '@libp2p/logger' import pRetry from 'p-retry' import { codes } from '../../errors.js' @@ -31,7 +31,7 @@ export interface AdvertServiceEvents { 'advert:error': CustomEvent } -export class AdvertService extends EventEmitter implements Startable { +export class AdvertService extends TypedEventEmitter implements Startable { private readonly contentRouting: ContentRouting private timeout?: any private started: boolean diff --git a/packages/libp2p/src/circuit-relay/server/index.ts b/packages/libp2p/src/circuit-relay/server/index.ts index aed3d5be8b..8fce918570 100644 --- a/packages/libp2p/src/circuit-relay/server/index.ts +++ b/packages/libp2p/src/circuit-relay/server/index.ts @@ -1,5 +1,5 @@ import { setMaxListeners } from 'events' -import { EventEmitter } from '@libp2p/interface/events' +import { TypedEventEmitter } from '@libp2p/interface/events' import { logger } from '@libp2p/logger' import { peerIdFromBytes } from '@libp2p/peer-id' import { RecordEnvelope } from '@libp2p/peer-record' @@ -99,7 +99,7 @@ const defaults = { maxOutboundStopStreams: MAX_CONNECTIONS } -class CircuitRelayServer extends EventEmitter implements Startable, CircuitRelayService { +class CircuitRelayServer extends TypedEventEmitter implements Startable, CircuitRelayService { private readonly registrar: Registrar private readonly peerStore: PeerStore private readonly addressManager: AddressManager diff --git a/packages/libp2p/src/circuit-relay/transport/discovery.ts b/packages/libp2p/src/circuit-relay/transport/discovery.ts index 58ddc80cd9..77a4af1208 100644 --- a/packages/libp2p/src/circuit-relay/transport/discovery.ts +++ b/packages/libp2p/src/circuit-relay/transport/discovery.ts @@ -1,4 +1,4 @@ -import { EventEmitter } from '@libp2p/interface/events' +import { TypedEventEmitter } from '@libp2p/interface/events' import { logger } from '@libp2p/logger' import { RELAY_RENDEZVOUS_NS, @@ -32,7 +32,7 @@ export interface RelayDiscoveryComponents { * ReservationManager automatically makes a circuit v2 reservation on any connected * peers that support the circuit v2 HOP protocol. */ -export class RelayDiscovery extends EventEmitter implements Startable { +export class RelayDiscovery extends TypedEventEmitter implements Startable { private readonly peerId: PeerId private readonly peerStore: PeerStore private readonly contentRouting: ContentRouting diff --git a/packages/libp2p/src/circuit-relay/transport/index.ts b/packages/libp2p/src/circuit-relay/transport/index.ts index 483f9a0366..022b44c57e 100644 --- a/packages/libp2p/src/circuit-relay/transport/index.ts +++ b/packages/libp2p/src/circuit-relay/transport/index.ts @@ -17,7 +17,7 @@ import type { Libp2pEvents, AbortOptions } from '@libp2p/interface' import type { Connection, Stream } from '@libp2p/interface/connection' import type { ConnectionGater } from '@libp2p/interface/connection-gater' import type { ContentRouting } from '@libp2p/interface/content-routing' -import type { EventEmitter } from '@libp2p/interface/events' +import type { TypedEventTarget } from '@libp2p/interface/events' import type { PeerId } from '@libp2p/interface/peer-id' import type { PeerStore } from '@libp2p/interface/peer-store' import type { AddressManager } from '@libp2p/interface-internal/address-manager' @@ -50,7 +50,7 @@ export interface CircuitRelayTransportComponents extends RelayDiscoveryComponent addressManager: AddressManager contentRouting: ContentRouting connectionGater: ConnectionGater - events: EventEmitter + events: TypedEventTarget } interface ConnectOptions { diff --git a/packages/libp2p/src/circuit-relay/transport/listener.ts b/packages/libp2p/src/circuit-relay/transport/listener.ts index bb67007db9..29b6c6e608 100644 --- a/packages/libp2p/src/circuit-relay/transport/listener.ts +++ b/packages/libp2p/src/circuit-relay/transport/listener.ts @@ -1,5 +1,5 @@ import { CodeError } from '@libp2p/interface/errors' -import { EventEmitter } from '@libp2p/interface/events' +import { TypedEventEmitter } from '@libp2p/interface/events' import { logger } from '@libp2p/logger' import { PeerMap } from '@libp2p/peer-collections' import { peerIdFromString } from '@libp2p/peer-id' @@ -18,7 +18,7 @@ export interface CircuitRelayTransportListenerComponents { relayStore: ReservationStore } -class CircuitRelayTransportListener extends EventEmitter implements Listener { +class CircuitRelayTransportListener extends TypedEventEmitter implements Listener { private readonly connectionManager: ConnectionManager private readonly relayStore: ReservationStore private readonly listeningAddrs: PeerMap diff --git a/packages/libp2p/src/circuit-relay/transport/reservation-store.ts b/packages/libp2p/src/circuit-relay/transport/reservation-store.ts index 2edcd4f998..9300357240 100644 --- a/packages/libp2p/src/circuit-relay/transport/reservation-store.ts +++ b/packages/libp2p/src/circuit-relay/transport/reservation-store.ts @@ -1,4 +1,4 @@ -import { EventEmitter } from '@libp2p/interface/events' +import { TypedEventEmitter, type TypedEventTarget } from '@libp2p/interface/events' import { logger } from '@libp2p/logger' import { PeerMap } from '@libp2p/peer-collections' import { multiaddr } from '@multiformats/multiaddr' @@ -32,7 +32,7 @@ export interface RelayStoreComponents { connectionManager: ConnectionManager transportManager: TransportManager peerStore: PeerStore - events: EventEmitter + events: TypedEventTarget } export interface RelayStoreInit { @@ -76,12 +76,12 @@ export interface ReservationStoreEvents { 'relay:removed': CustomEvent } -export class ReservationStore extends EventEmitter implements Startable { +export class ReservationStore extends TypedEventEmitter implements Startable { private readonly peerId: PeerId private readonly connectionManager: ConnectionManager private readonly transportManager: TransportManager private readonly peerStore: PeerStore - private readonly events: EventEmitter + private readonly events: TypedEventTarget private readonly reserveQueue: PeerJobQueue private readonly reservations: PeerMap private readonly maxDiscoveredRelays: number diff --git a/packages/libp2p/src/components.ts b/packages/libp2p/src/components.ts index f11fb2cfb6..2d65d956dc 100644 --- a/packages/libp2p/src/components.ts +++ b/packages/libp2p/src/components.ts @@ -4,7 +4,7 @@ import type { Libp2pEvents } from '@libp2p/interface' import type { ConnectionProtector } from '@libp2p/interface/connection' import type { ConnectionGater } from '@libp2p/interface/connection-gater' import type { ContentRouting } from '@libp2p/interface/content-routing' -import type { EventEmitter } from '@libp2p/interface/events' +import type { TypedEventTarget } from '@libp2p/interface/events' import type { Metrics } from '@libp2p/interface/metrics' import type { PeerId } from '@libp2p/interface/peer-id' import type { PeerRouting } from '@libp2p/interface/peer-routing' @@ -18,7 +18,7 @@ import type { Datastore } from 'interface-datastore' export interface Components extends Record, Startable { peerId: PeerId - events: EventEmitter + events: TypedEventTarget addressManager: AddressManager peerStore: PeerStore upgrader: Upgrader @@ -35,7 +35,7 @@ export interface Components extends Record, Startable { export interface ComponentsInit { peerId?: PeerId - events?: EventEmitter + events?: TypedEventTarget addressManager?: AddressManager peerStore?: PeerStore upgrader?: Upgrader diff --git a/packages/libp2p/src/connection-manager/auto-dial.ts b/packages/libp2p/src/connection-manager/auto-dial.ts index 6d27e6f42b..a110adfd46 100644 --- a/packages/libp2p/src/connection-manager/auto-dial.ts +++ b/packages/libp2p/src/connection-manager/auto-dial.ts @@ -4,7 +4,7 @@ import { toString as uint8ArrayToString } from 'uint8arrays/to-string' import { PeerJobQueue } from '../utils/peer-job-queue.js' import { AUTO_DIAL_CONCURRENCY, AUTO_DIAL_DISCOVERED_PEERS_DEBOUNCE, AUTO_DIAL_INTERVAL, AUTO_DIAL_MAX_QUEUE_LENGTH, AUTO_DIAL_PEER_RETRY_THRESHOLD, AUTO_DIAL_PRIORITY, LAST_DIAL_FAILURE_KEY, MIN_CONNECTIONS } from './constants.js' import type { Libp2pEvents } from '@libp2p/interface' -import type { EventEmitter } from '@libp2p/interface/events' +import type { TypedEventTarget } from '@libp2p/interface/events' import type { PeerStore } from '@libp2p/interface/peer-store' import type { Startable } from '@libp2p/interface/startable' import type { ConnectionManager } from '@libp2p/interface-internal/connection-manager' @@ -24,7 +24,7 @@ interface AutoDialInit { interface AutoDialComponents { connectionManager: ConnectionManager peerStore: PeerStore - events: EventEmitter + events: TypedEventTarget } const defaultOptions = { diff --git a/packages/libp2p/src/connection-manager/connection-pruner.ts b/packages/libp2p/src/connection-manager/connection-pruner.ts index 04fb85d7fb..adbed0a56c 100644 --- a/packages/libp2p/src/connection-manager/connection-pruner.ts +++ b/packages/libp2p/src/connection-manager/connection-pruner.ts @@ -2,7 +2,7 @@ import { logger } from '@libp2p/logger' import { PeerMap } from '@libp2p/peer-collections' import { MAX_CONNECTIONS } from './constants.js' import type { Libp2pEvents } from '@libp2p/interface' -import type { EventEmitter } from '@libp2p/interface/events' +import type { TypedEventTarget } from '@libp2p/interface/events' import type { PeerStore } from '@libp2p/interface/peer-store' import type { ConnectionManager } from '@libp2p/interface-internal/connection-manager' import type { Multiaddr } from '@multiformats/multiaddr' @@ -17,7 +17,7 @@ interface ConnectionPrunerInit { interface ConnectionPrunerComponents { connectionManager: ConnectionManager peerStore: PeerStore - events: EventEmitter + events: TypedEventTarget } const defaultOptions = { @@ -33,7 +33,7 @@ export class ConnectionPruner { private readonly connectionManager: ConnectionManager private readonly peerStore: PeerStore private readonly allow: Multiaddr[] - private readonly events: EventEmitter + private readonly events: TypedEventTarget constructor (components: ConnectionPrunerComponents, init: ConnectionPrunerInit = {}) { this.maxConnections = init.maxConnections ?? defaultOptions.maxConnections diff --git a/packages/libp2p/src/connection-manager/index.ts b/packages/libp2p/src/connection-manager/index.ts index d94612fd9f..c13e49a53a 100644 --- a/packages/libp2p/src/connection-manager/index.ts +++ b/packages/libp2p/src/connection-manager/index.ts @@ -15,7 +15,7 @@ import { DialQueue } from './dial-queue.js' import type { PendingDial, AddressSorter, Libp2pEvents, AbortOptions } from '@libp2p/interface' import type { Connection, MultiaddrConnection } from '@libp2p/interface/connection' import type { ConnectionGater } from '@libp2p/interface/connection-gater' -import type { EventEmitter } from '@libp2p/interface/events' +import type { TypedEventTarget } from '@libp2p/interface/events' import type { Metrics } from '@libp2p/interface/metrics' import type { PeerId } from '@libp2p/interface/peer-id' import type { Peer, PeerStore } from '@libp2p/interface/peer-store' @@ -165,7 +165,7 @@ export interface DefaultConnectionManagerComponents { peerStore: PeerStore transportManager: TransportManager connectionGater: ConnectionGater - events: EventEmitter + events: TypedEventTarget } /** @@ -187,7 +187,7 @@ export class DefaultConnectionManager implements ConnectionManager, Startable { private readonly peerStore: PeerStore private readonly metrics?: Metrics - private readonly events: EventEmitter + private readonly events: TypedEventTarget constructor (components: DefaultConnectionManagerComponents, init: ConnectionManagerInit = {}) { this.maxConnections = init.maxConnections ?? defaultOptions.maxConnections diff --git a/packages/libp2p/src/identify/identify.ts b/packages/libp2p/src/identify/identify.ts index caa5248b45..940533ef50 100644 --- a/packages/libp2p/src/identify/identify.ts +++ b/packages/libp2p/src/identify/identify.ts @@ -21,7 +21,7 @@ import { Identify } from './pb/message.js' import type { IdentifyService, IdentifyServiceComponents, IdentifyServiceInit } from './index.js' import type { Libp2pEvents, IdentifyResult, SignedPeerRecord, AbortOptions } from '@libp2p/interface' import type { Connection, Stream } from '@libp2p/interface/connection' -import type { EventEmitter } from '@libp2p/interface/events' +import type { TypedEventTarget } from '@libp2p/interface/events' import type { PeerId } from '@libp2p/interface/peer-id' import type { Peer, PeerStore } from '@libp2p/interface/peer-store' import type { Startable } from '@libp2p/interface/startable' @@ -70,7 +70,7 @@ export class DefaultIdentifyService implements Startable, IdentifyService { private readonly maxPushOutgoingStreams: number private readonly maxIdentifyMessageSize: number private readonly maxObservedAddresses: number - private readonly events: EventEmitter + private readonly events: TypedEventTarget private readonly runOnTransientConnection: boolean constructor (components: IdentifyServiceComponents, init: IdentifyServiceInit) { diff --git a/packages/libp2p/src/identify/index.ts b/packages/libp2p/src/identify/index.ts index c74238e832..61dc2e3523 100644 --- a/packages/libp2p/src/identify/index.ts +++ b/packages/libp2p/src/identify/index.ts @@ -5,7 +5,7 @@ import { import { DefaultIdentifyService } from './identify.js' import { Identify } from './pb/message.js' import type { AbortOptions, IdentifyResult, Libp2pEvents } from '@libp2p/interface' -import type { EventEmitter } from '@libp2p/interface/events' +import type { TypedEventTarget } from '@libp2p/interface/events' import type { PeerId } from '@libp2p/interface/peer-id' import type { PeerStore } from '@libp2p/interface/peer-store' import type { Connection } from '@libp2p/interface/src/connection/index.js' @@ -58,7 +58,7 @@ export interface IdentifyServiceComponents { connectionManager: ConnectionManager registrar: Registrar addressManager: AddressManager - events: EventEmitter + events: TypedEventTarget } /** diff --git a/packages/libp2p/src/libp2p.ts b/packages/libp2p/src/libp2p.ts index 29c80f0cc7..cdc0c5caa8 100644 --- a/packages/libp2p/src/libp2p.ts +++ b/packages/libp2p/src/libp2p.ts @@ -2,7 +2,7 @@ import { setMaxListeners } from 'events' import { unmarshalPublicKey } from '@libp2p/crypto/keys' import { type ContentRouting, contentRouting } from '@libp2p/interface/content-routing' import { CodeError } from '@libp2p/interface/errors' -import { EventEmitter, CustomEvent } from '@libp2p/interface/events' +import { TypedEventEmitter, CustomEvent } from '@libp2p/interface/events' import { peerDiscovery } from '@libp2p/interface/peer-discovery' import { type PeerRouting, peerRouting } from '@libp2p/interface/peer-routing' import { DefaultKeyChain } from '@libp2p/keychain' @@ -42,7 +42,7 @@ import type { Datastore } from 'interface-datastore' const log = logger('libp2p') -export class Libp2pNode> extends EventEmitter implements Libp2p { +export class Libp2pNode> extends TypedEventEmitter implements Libp2p { public peerId: PeerId public peerStore: PeerStore public contentRouting: ContentRouting @@ -59,7 +59,7 @@ export class Libp2pNode> extends // event bus - components can listen to this emitter to be notified of system events // and also cause them to be emitted - const events = new EventEmitter() + const events = new TypedEventEmitter() const originalDispatch = events.dispatchEvent.bind(events) events.dispatchEvent = (evt: any) => { const internalResult = originalDispatch(evt) diff --git a/packages/libp2p/src/registrar.ts b/packages/libp2p/src/registrar.ts index c679888f4f..268a35c364 100644 --- a/packages/libp2p/src/registrar.ts +++ b/packages/libp2p/src/registrar.ts @@ -3,7 +3,7 @@ import { logger } from '@libp2p/logger' import merge from 'merge-options' import { codes } from './errors.js' import type { Libp2pEvents, PeerUpdate } from '@libp2p/interface' -import type { EventEmitter } from '@libp2p/interface/events' +import type { TypedEventTarget } from '@libp2p/interface/events' import type { PeerId } from '@libp2p/interface/peer-id' import type { PeerStore } from '@libp2p/interface/peer-store' import type { Topology } from '@libp2p/interface/topology' @@ -19,7 +19,7 @@ export interface RegistrarComponents { peerId: PeerId connectionManager: ConnectionManager peerStore: PeerStore - events: EventEmitter + events: TypedEventTarget } /** diff --git a/packages/libp2p/src/transport-manager.ts b/packages/libp2p/src/transport-manager.ts index 38f5359616..f18ecdcecc 100644 --- a/packages/libp2p/src/transport-manager.ts +++ b/packages/libp2p/src/transport-manager.ts @@ -5,7 +5,7 @@ import { logger } from '@libp2p/logger' import { codes } from './errors.js' import type { Libp2pEvents, AbortOptions } from '@libp2p/interface' import type { Connection } from '@libp2p/interface/connection' -import type { EventEmitter } from '@libp2p/interface/events' +import type { TypedEventTarget } from '@libp2p/interface/events' import type { Metrics } from '@libp2p/interface/metrics' import type { Startable } from '@libp2p/interface/startable' import type { Listener, Transport, Upgrader } from '@libp2p/interface/transport' @@ -23,7 +23,7 @@ export interface DefaultTransportManagerComponents { metrics?: Metrics addressManager: AddressManager upgrader: Upgrader - events: EventEmitter + events: TypedEventTarget } export class DefaultTransportManager implements TransportManager, Startable { diff --git a/packages/libp2p/src/upgrader.ts b/packages/libp2p/src/upgrader.ts index 18934e3ad0..ad27ba02db 100644 --- a/packages/libp2p/src/upgrader.ts +++ b/packages/libp2p/src/upgrader.ts @@ -11,7 +11,7 @@ import type { Libp2pEvents, AbortOptions } from '@libp2p/interface' import type { MultiaddrConnection, Connection, Stream, ConnectionProtector, NewStreamOptions } from '@libp2p/interface/connection' import type { ConnectionEncrypter, SecuredConnection } from '@libp2p/interface/connection-encrypter' import type { ConnectionGater } from '@libp2p/interface/connection-gater' -import type { EventEmitter } from '@libp2p/interface/events' +import type { TypedEventTarget } from '@libp2p/interface/events' import type { Metrics } from '@libp2p/interface/metrics' import type { PeerId } from '@libp2p/interface/peer-id' import type { PeerStore } from '@libp2p/interface/peer-store' @@ -104,7 +104,7 @@ export interface DefaultUpgraderComponents { connectionProtector?: ConnectionProtector registrar: Registrar peerStore: PeerStore - events: EventEmitter + events: TypedEventTarget } type EncryptedConn = Duplex, Source, Promise> @@ -116,7 +116,7 @@ export class DefaultUpgrader implements Upgrader { private readonly connectionEncryption: Map private readonly muxers: Map private readonly inboundUpgradeTimeout: number - private readonly events: EventEmitter + private readonly events: TypedEventTarget constructor (components: DefaultUpgraderComponents, init: UpgraderInit) { this.components = components diff --git a/packages/libp2p/test/addresses/address-manager.spec.ts b/packages/libp2p/test/addresses/address-manager.spec.ts index 7f67fa9b07..5bee38bb70 100644 --- a/packages/libp2p/test/addresses/address-manager.spec.ts +++ b/packages/libp2p/test/addresses/address-manager.spec.ts @@ -1,6 +1,6 @@ /* eslint-env mocha */ -import { EventEmitter } from '@libp2p/interface/events' +import { TypedEventEmitter, type TypedEventTarget } from '@libp2p/interface/events' import { createEd25519PeerId } from '@libp2p/peer-id-factory' import { multiaddr } from '@multiformats/multiaddr' import { expect } from 'aegir/chai' @@ -18,7 +18,7 @@ const announceAddreses = ['/dns4/peer.io'] describe('Address Manager', () => { let peerId: PeerId let peerStore: StubbedInstance - let events: EventEmitter + let events: TypedEventTarget beforeEach(async () => { peerId = await createEd25519PeerId() @@ -26,7 +26,7 @@ describe('Address Manager', () => { // @ts-expect-error incorrect return type patch: Promise.resolve({}) }) - events = new EventEmitter() + events = new TypedEventEmitter() }) it('should not need any addresses', () => { diff --git a/packages/libp2p/test/circuit-relay/hop.spec.ts b/packages/libp2p/test/circuit-relay/hop.spec.ts index 7c3405197c..b1beb7abb9 100644 --- a/packages/libp2p/test/circuit-relay/hop.spec.ts +++ b/packages/libp2p/test/circuit-relay/hop.spec.ts @@ -1,7 +1,7 @@ /* eslint-env mocha */ /* eslint max-nested-callbacks: ['error', 5] */ -import { EventEmitter } from '@libp2p/interface/events' +import { TypedEventEmitter, type TypedEventTarget } from '@libp2p/interface/events' import { isStartable } from '@libp2p/interface/startable' import { mockRegistrar, mockUpgrader, mockNetwork, mockConnectionManager, mockConnectionGater } from '@libp2p/interface-compliance-tests/mocks' import { PeerMap } from '@libp2p/peer-collections' @@ -38,7 +38,7 @@ interface Node { connectionManager: ConnectionManager circuitRelayTransport: Transport connectionGater: ConnectionGater - events: EventEmitter + events: TypedEventTarget } let peerIndex = 0 @@ -66,7 +66,7 @@ describe('circuit-relay hop protocol', function () { ]) const peerStore = stubInterface() - const events = new EventEmitter() + const events = new TypedEventEmitter() events.addEventListener('connection:open', (evt) => { const conn = evt.detail connections.set(conn.remotePeer, conn) diff --git a/packages/libp2p/test/circuit-relay/stop.spec.ts b/packages/libp2p/test/circuit-relay/stop.spec.ts index 872f01d104..f17642b951 100644 --- a/packages/libp2p/test/circuit-relay/stop.spec.ts +++ b/packages/libp2p/test/circuit-relay/stop.spec.ts @@ -1,6 +1,6 @@ /* eslint-env mocha */ -import { EventEmitter } from '@libp2p/interface/events' +import { TypedEventEmitter } from '@libp2p/interface/events' import { isStartable } from '@libp2p/interface/startable' import { mockStream } from '@libp2p/interface-compliance-tests/mocks' import { createEd25519PeerId } from '@libp2p/peer-id-factory' @@ -43,7 +43,7 @@ describe('circuit-relay stop protocol', function () { transportManager: stubInterface(), upgrader: stubInterface(), connectionGater: stubInterface(), - events: new EventEmitter() + events: new TypedEventEmitter() } transport = circuitRelayTransport({ diff --git a/packages/libp2p/test/connection-manager/auto-dial.spec.ts b/packages/libp2p/test/connection-manager/auto-dial.spec.ts index 3c5968bdf1..13634b49e1 100644 --- a/packages/libp2p/test/connection-manager/auto-dial.spec.ts +++ b/packages/libp2p/test/connection-manager/auto-dial.spec.ts @@ -1,6 +1,6 @@ /* eslint-env mocha */ -import { EventEmitter } from '@libp2p/interface/events' +import { TypedEventEmitter, type TypedEventTarget } from '@libp2p/interface/events' import { PeerMap } from '@libp2p/peer-collections' import { createEd25519PeerId } from '@libp2p/peer-id-factory' import { PersistentPeerStore } from '@libp2p/peer-store' @@ -23,13 +23,13 @@ import type { ConnectionManager } from '@libp2p/interface-internal/connection-ma describe('auto-dial', () => { let autoDialler: AutoDial - let events: EventEmitter + let events: TypedEventTarget let peerStore: PeerStore let peerId: PeerId beforeEach(async () => { peerId = await createEd25519PeerId() - events = new EventEmitter() + events = new TypedEventEmitter() peerStore = new PersistentPeerStore({ datastore: new MemoryDatastore(), events, diff --git a/packages/libp2p/test/connection-manager/direct.node.ts b/packages/libp2p/test/connection-manager/direct.node.ts index 6da375ad6b..ae5ff3aed3 100644 --- a/packages/libp2p/test/connection-manager/direct.node.ts +++ b/packages/libp2p/test/connection-manager/direct.node.ts @@ -6,7 +6,7 @@ import path from 'node:path' import { yamux } from '@chainsafe/libp2p-yamux' import { type Connection, type ConnectionProtector, isConnection } from '@libp2p/interface/connection' import { AbortError } from '@libp2p/interface/errors' -import { EventEmitter } from '@libp2p/interface/events' +import { TypedEventEmitter } from '@libp2p/interface/events' import { start, stop } from '@libp2p/interface/startable' import { mockConnection, mockConnectionGater, mockDuplex, mockMultiaddrConnection, mockUpgrader } from '@libp2p/interface-compliance-tests/mocks' import { mplex } from '@libp2p/mplex' @@ -58,7 +58,7 @@ describe('dialing (direct, TCP)', () => { createEd25519PeerId() ]) - const remoteEvents = new EventEmitter() + const remoteEvents = new TypedEventEmitter() remoteComponents = defaultComponents({ peerId: remotePeerId, events: remoteEvents, @@ -78,7 +78,7 @@ describe('dialing (direct, TCP)', () => { remoteTM = remoteComponents.transportManager = new DefaultTransportManager(remoteComponents) remoteTM.add(tcp()()) - const localEvents = new EventEmitter() + const localEvents = new TypedEventEmitter() localComponents = defaultComponents({ peerId: localPeerId, events: localEvents, diff --git a/packages/libp2p/test/connection-manager/direct.spec.ts b/packages/libp2p/test/connection-manager/direct.spec.ts index 780c45f605..305ae4e524 100644 --- a/packages/libp2p/test/connection-manager/direct.spec.ts +++ b/packages/libp2p/test/connection-manager/direct.spec.ts @@ -2,7 +2,7 @@ import { yamux } from '@chainsafe/libp2p-yamux' import { AbortError } from '@libp2p/interface/errors' -import { EventEmitter } from '@libp2p/interface/events' +import { TypedEventEmitter } from '@libp2p/interface/events' import { mockConnectionGater, mockDuplex, mockMultiaddrConnection, mockUpgrader, mockConnection } from '@libp2p/interface-compliance-tests/mocks' import { mplex } from '@libp2p/mplex' import { peerIdFromString } from '@libp2p/peer-id' @@ -45,7 +45,7 @@ describe('dialing (direct, WebSockets)', () => { let connectionManager: DefaultConnectionManager beforeEach(async () => { - const localEvents = new EventEmitter() + const localEvents = new TypedEventEmitter() localComponents = defaultComponents({ peerId: await createEd25519PeerId(), datastore: new MemoryDatastore(), diff --git a/packages/libp2p/test/connection-manager/index.node.ts b/packages/libp2p/test/connection-manager/index.node.ts index add7158a47..cac8b990d3 100644 --- a/packages/libp2p/test/connection-manager/index.node.ts +++ b/packages/libp2p/test/connection-manager/index.node.ts @@ -1,6 +1,6 @@ /* eslint-env mocha */ -import { EventEmitter } from '@libp2p/interface/events' +import { TypedEventEmitter } from '@libp2p/interface/events' import { start } from '@libp2p/interface/startable' import { mockConnection, mockDuplex, mockMultiaddrConnection } from '@libp2p/interface-compliance-tests/mocks' import { expect } from 'aegir/chai' @@ -53,7 +53,7 @@ describe('Connection Manager', () => { peerStore, transportManager: stubInterface(), connectionGater: stubInterface(), - events: new EventEmitter() + events: new TypedEventEmitter() }) const connectionManager = new DefaultConnectionManager(components, { maxConnections: 1000, @@ -91,7 +91,7 @@ describe('Connection Manager', () => { peerStore, transportManager: stubInterface(), connectionGater: stubInterface(), - events: new EventEmitter() + events: new TypedEventEmitter() }) const connectionManager = new DefaultConnectionManager(components, { maxConnections: 1000, diff --git a/packages/libp2p/test/connection-manager/index.spec.ts b/packages/libp2p/test/connection-manager/index.spec.ts index 699339da03..ee31843332 100644 --- a/packages/libp2p/test/connection-manager/index.spec.ts +++ b/packages/libp2p/test/connection-manager/index.spec.ts @@ -1,6 +1,6 @@ /* eslint-env mocha */ -import { EventEmitter } from '@libp2p/interface/events' +import { TypedEventEmitter } from '@libp2p/interface/events' import { KEEP_ALIVE } from '@libp2p/interface/peer-store/tags' import { mockConnection, mockDuplex, mockMultiaddrConnection, mockMetrics } from '@libp2p/interface-compliance-tests/mocks' import { createEd25519PeerId } from '@libp2p/peer-id-factory' @@ -365,7 +365,7 @@ describe('Connection Manager', () => { peerStore: stubInterface(), transportManager: stubInterface(), connectionGater: stubInterface(), - events: new EventEmitter() + events: new TypedEventEmitter() }, { ...defaultOptions, deny: [ @@ -393,7 +393,7 @@ describe('Connection Manager', () => { peerStore: stubInterface(), transportManager: stubInterface(), connectionGater: stubInterface(), - events: new EventEmitter() + events: new TypedEventEmitter() }, { ...defaultOptions, maxConnections: 1 @@ -425,7 +425,7 @@ describe('Connection Manager', () => { peerStore: stubInterface(), transportManager: stubInterface(), connectionGater: stubInterface(), - events: new EventEmitter() + events: new TypedEventEmitter() }, { ...defaultOptions, inboundConnectionThreshold: 1 @@ -461,7 +461,7 @@ describe('Connection Manager', () => { peerStore: stubInterface(), transportManager: stubInterface(), connectionGater: stubInterface(), - events: new EventEmitter() + events: new TypedEventEmitter() }, { ...defaultOptions, maxConnections: 1, @@ -497,7 +497,7 @@ describe('Connection Manager', () => { peerStore: stubInterface(), transportManager: stubInterface(), connectionGater: stubInterface(), - events: new EventEmitter() + events: new TypedEventEmitter() }, { ...defaultOptions, maxIncomingPendingConnections: 1 diff --git a/packages/libp2p/test/fetch/index.spec.ts b/packages/libp2p/test/fetch/index.spec.ts index 9ef87c88e5..7b90a0f7db 100644 --- a/packages/libp2p/test/fetch/index.spec.ts +++ b/packages/libp2p/test/fetch/index.spec.ts @@ -1,6 +1,6 @@ /* eslint-env mocha */ -import { EventEmitter } from '@libp2p/interface/events' +import { TypedEventEmitter } from '@libp2p/interface/events' import { start, stop } from '@libp2p/interface/startable' import { mockRegistrar, mockUpgrader, connectionPair } from '@libp2p/interface-compliance-tests/mocks' import { createEd25519PeerId } from '@libp2p/peer-id-factory' @@ -27,7 +27,7 @@ const defaultInit: FetchServiceInit = { async function createComponents (index: number): Promise { const peerId = await createEd25519PeerId() - const events = new EventEmitter() + const events = new TypedEventEmitter() const components = defaultComponents({ peerId, registrar: mockRegistrar(), diff --git a/packages/libp2p/test/identify/index.spec.ts b/packages/libp2p/test/identify/index.spec.ts index ed7d54ff09..63134a7d0c 100644 --- a/packages/libp2p/test/identify/index.spec.ts +++ b/packages/libp2p/test/identify/index.spec.ts @@ -1,7 +1,7 @@ /* eslint-env mocha */ /* eslint max-nested-callbacks: ["error", 6] */ -import { EventEmitter } from '@libp2p/interface/events' +import { TypedEventEmitter } from '@libp2p/interface/events' import { start, stop } from '@libp2p/interface/startable' import { mockConnectionGater, mockRegistrar, mockUpgrader, connectionPair } from '@libp2p/interface-compliance-tests/mocks' import { createEd25519PeerId } from '@libp2p/peer-id-factory' @@ -51,7 +51,7 @@ const protocols = [MULTICODEC_IDENTIFY, MULTICODEC_IDENTIFY_PUSH] async function createComponents (index: number): Promise { const peerId = await createEd25519PeerId() - const events = new EventEmitter() + const events = new TypedEventEmitter() const components = defaultComponents({ peerId, datastore: new MemoryDatastore(), diff --git a/packages/libp2p/test/identify/push.spec.ts b/packages/libp2p/test/identify/push.spec.ts index 2916a8e1c4..a73bdc3655 100644 --- a/packages/libp2p/test/identify/push.spec.ts +++ b/packages/libp2p/test/identify/push.spec.ts @@ -1,6 +1,6 @@ /* eslint-env mocha */ -import { EventEmitter } from '@libp2p/interface/events' +import { TypedEventEmitter } from '@libp2p/interface/events' import { start, stop } from '@libp2p/interface/startable' import { mockConnectionGater, mockRegistrar, mockUpgrader, connectionPair } from '@libp2p/interface-compliance-tests/mocks' import { createEd25519PeerId } from '@libp2p/peer-id-factory' @@ -42,7 +42,7 @@ const protocols = [MULTICODEC_IDENTIFY, MULTICODEC_IDENTIFY_PUSH] async function createComponents (index: number): Promise { const peerId = await createEd25519PeerId() - const events = new EventEmitter() + const events = new TypedEventEmitter() const components = defaultComponents({ peerId, datastore: new MemoryDatastore(), diff --git a/packages/libp2p/test/peer-discovery/index.node.ts b/packages/libp2p/test/peer-discovery/index.node.ts index 7adfb0c867..d3d6bd0939 100644 --- a/packages/libp2p/test/peer-discovery/index.node.ts +++ b/packages/libp2p/test/peer-discovery/index.node.ts @@ -2,7 +2,7 @@ import { bootstrap } from '@libp2p/bootstrap' import { randomBytes } from '@libp2p/crypto' -import { EventEmitter } from '@libp2p/interface/events' +import { TypedEventEmitter } from '@libp2p/interface/events' import { peerDiscovery } from '@libp2p/interface/peer-discovery' import { kadDHT } from '@libp2p/kad-dht' import { mdns } from '@libp2p/mdns' @@ -22,7 +22,7 @@ import type { KadDHT } from '@libp2p/kad-dht' const listenAddr = multiaddr('/ip4/127.0.0.1/tcp/0') -class TestPeerDiscovery extends EventEmitter implements PeerDiscovery { +class TestPeerDiscovery extends TypedEventEmitter implements PeerDiscovery { get [peerDiscovery] (): PeerDiscovery { return this } diff --git a/packages/libp2p/test/ping/index.spec.ts b/packages/libp2p/test/ping/index.spec.ts index c37d5d0ebe..9b6aef1385 100644 --- a/packages/libp2p/test/ping/index.spec.ts +++ b/packages/libp2p/test/ping/index.spec.ts @@ -1,6 +1,6 @@ /* eslint-env mocha */ -import { EventEmitter } from '@libp2p/interface/events' +import { TypedEventEmitter } from '@libp2p/interface/events' import { start, stop } from '@libp2p/interface/startable' import { mockRegistrar, mockUpgrader, connectionPair } from '@libp2p/interface-compliance-tests/mocks' import { createEd25519PeerId } from '@libp2p/peer-id-factory' @@ -28,7 +28,7 @@ const defaultInit: PingServiceInit = { async function createComponents (index: number): Promise { const peerId = await createEd25519PeerId() - const events = new EventEmitter() + const events = new TypedEventEmitter() const components = defaultComponents({ peerId, registrar: mockRegistrar(), diff --git a/packages/libp2p/test/registrar/registrar.spec.ts b/packages/libp2p/test/registrar/registrar.spec.ts index 0e5b585acf..138b45b30e 100644 --- a/packages/libp2p/test/registrar/registrar.spec.ts +++ b/packages/libp2p/test/registrar/registrar.spec.ts @@ -2,7 +2,7 @@ import { yamux } from '@chainsafe/libp2p-yamux' import { CodeError } from '@libp2p/interface/errors' -import { EventEmitter } from '@libp2p/interface/events' +import { TypedEventEmitter, type TypedEventTarget } from '@libp2p/interface/events' import { mockDuplex, mockMultiaddrConnection, mockUpgrader, mockConnection } from '@libp2p/interface-compliance-tests/mocks' import { mplex } from '@libp2p/mplex' import { createEd25519PeerId } from '@libp2p/peer-id-factory' @@ -43,7 +43,7 @@ describe('registrar', () => { describe('errors', () => { beforeEach(() => { - const events = new EventEmitter() + const events = new TypedEventEmitter() components = defaultComponents({ peerId, events, @@ -81,13 +81,13 @@ describe('registrar', () => { let peerId: PeerId let connectionManager: StubbedInstance let peerStore: StubbedInstance - let events: EventEmitter + let events: TypedEventTarget beforeEach(async () => { peerId = await createEd25519PeerId() connectionManager = stubInterface() peerStore = stubInterface() - events = new EventEmitter() + events = new TypedEventEmitter() registrar = new DefaultRegistrar({ peerId, diff --git a/packages/libp2p/test/transports/transport-manager.node.ts b/packages/libp2p/test/transports/transport-manager.node.ts index 7404e88bbe..290414e618 100644 --- a/packages/libp2p/test/transports/transport-manager.node.ts +++ b/packages/libp2p/test/transports/transport-manager.node.ts @@ -1,6 +1,6 @@ /* eslint-env mocha */ -import { EventEmitter } from '@libp2p/interface/events' +import { TypedEventEmitter } from '@libp2p/interface/events' import { start, stop } from '@libp2p/interface/startable' import { FaultTolerance } from '@libp2p/interface/transport' import { mockUpgrader } from '@libp2p/interface-compliance-tests/mocks' @@ -33,7 +33,7 @@ describe('Transport Manager (TCP)', () => { }) beforeEach(async () => { - const events = new EventEmitter() + const events = new TypedEventEmitter() components = defaultComponents({ peerId: localPeer, events, diff --git a/packages/libp2p/test/transports/transport-manager.spec.ts b/packages/libp2p/test/transports/transport-manager.spec.ts index 89024dd8bc..c71a124a92 100644 --- a/packages/libp2p/test/transports/transport-manager.spec.ts +++ b/packages/libp2p/test/transports/transport-manager.spec.ts @@ -1,6 +1,6 @@ /* eslint-env mocha */ -import { EventEmitter } from '@libp2p/interface/events' +import { TypedEventEmitter } from '@libp2p/interface/events' import { start, stop } from '@libp2p/interface/startable' import { FaultTolerance } from '@libp2p/interface/transport' import { mockUpgrader } from '@libp2p/interface-compliance-tests/mocks' @@ -26,7 +26,7 @@ describe('Transport Manager (WebSockets)', () => { let components: Components beforeEach(async () => { - const events = new EventEmitter() + const events = new TypedEventEmitter() components = { peerId: await createEd25519PeerId(), events, diff --git a/packages/libp2p/test/upgrading/upgrader.spec.ts b/packages/libp2p/test/upgrading/upgrader.spec.ts index f1343f128e..6f83c08ecd 100644 --- a/packages/libp2p/test/upgrading/upgrader.spec.ts +++ b/packages/libp2p/test/upgrading/upgrader.spec.ts @@ -1,7 +1,7 @@ /* eslint-env mocha */ import { yamux } from '@chainsafe/libp2p-yamux' -import { EventEmitter } from '@libp2p/interface/events' +import { TypedEventEmitter } from '@libp2p/interface/events' import { mockConnectionGater, mockConnectionManager, mockMultiaddrConnPair, mockRegistrar, mockStream, mockMuxer } from '@libp2p/interface-compliance-tests/mocks' import { mplex } from '@libp2p/mplex' import { createEd25519PeerId } from '@libp2p/peer-id-factory' @@ -76,7 +76,7 @@ describe('Upgrader', () => { registrar: mockRegistrar(), datastore: new MemoryDatastore(), connectionProtector: localConnectionProtector, - events: new EventEmitter() + events: new TypedEventEmitter() }) localComponents.peerStore = new PersistentPeerStore(localComponents) localComponents.connectionManager = mockConnectionManager(localComponents) @@ -103,7 +103,7 @@ describe('Upgrader', () => { registrar: mockRegistrar(), datastore: new MemoryDatastore(), connectionProtector: remoteConnectionProtector, - events: new EventEmitter() + events: new TypedEventEmitter() }) remoteComponents.peerStore = new PersistentPeerStore(remoteComponents) remoteComponents.connectionManager = mockConnectionManager(remoteComponents) diff --git a/packages/libp2p/test/upnp-nat/upnp-nat.node.ts b/packages/libp2p/test/upnp-nat/upnp-nat.node.ts index 42d6cc6407..8e39909147 100644 --- a/packages/libp2p/test/upnp-nat/upnp-nat.node.ts +++ b/packages/libp2p/test/upnp-nat/upnp-nat.node.ts @@ -1,6 +1,6 @@ /* eslint-env mocha */ -import { EventEmitter } from '@libp2p/interface/events' +import { TypedEventEmitter } from '@libp2p/interface/events' import { start, stop } from '@libp2p/interface/startable' import { FaultTolerance } from '@libp2p/interface/transport' import { mockUpgrader } from '@libp2p/interface-compliance-tests/mocks' @@ -31,7 +31,7 @@ describe('UPnP NAT (TCP)', () => { let client: StubbedInstance async function createNatManager (addrs = DEFAULT_ADDRESSES, natManagerOptions = {}): Promise<{ natManager: any, components: Components }> { - const events = new EventEmitter() + const events = new TypedEventEmitter() const components: any = defaultComponents({ peerId: await createEd25519PeerId(), upgrader: mockUpgrader({ events }), diff --git a/packages/peer-discovery-bootstrap/src/index.ts b/packages/peer-discovery-bootstrap/src/index.ts index 1debb10fc6..7400d494f4 100644 --- a/packages/peer-discovery-bootstrap/src/index.ts +++ b/packages/peer-discovery-bootstrap/src/index.ts @@ -1,4 +1,4 @@ -import { EventEmitter } from '@libp2p/interface/events' +import { TypedEventEmitter } from '@libp2p/interface/events' import { peerDiscovery } from '@libp2p/interface/peer-discovery' import { logger } from '@libp2p/logger' import { peerIdFromString } from '@libp2p/peer-id' @@ -50,7 +50,7 @@ export interface BootstrapComponents { /** * Emits 'peer' events on a regular interval for each peer in the provided list. */ -class Bootstrap extends EventEmitter implements PeerDiscovery, Startable { +class Bootstrap extends TypedEventEmitter implements PeerDiscovery, Startable { static tag = 'bootstrap' private timer?: ReturnType diff --git a/packages/peer-discovery-mdns/src/index.ts b/packages/peer-discovery-mdns/src/index.ts index 7424131c06..98d568640e 100644 --- a/packages/peer-discovery-mdns/src/index.ts +++ b/packages/peer-discovery-mdns/src/index.ts @@ -1,4 +1,4 @@ -import { CustomEvent, EventEmitter } from '@libp2p/interface/events' +import { CustomEvent, TypedEventEmitter } from '@libp2p/interface/events' import { peerDiscovery } from '@libp2p/interface/peer-discovery' import { logger } from '@libp2p/logger' import multicastDNS from 'multicast-dns' @@ -24,7 +24,7 @@ export interface MulticastDNSComponents { addressManager: AddressManager } -class MulticastDNS extends EventEmitter implements PeerDiscovery, Startable { +class MulticastDNS extends TypedEventEmitter implements PeerDiscovery, Startable { public mdns?: multicastDNS.MulticastDNS private readonly broadcast: boolean diff --git a/packages/peer-store/src/index.ts b/packages/peer-store/src/index.ts index d130a8a7c3..ec9b4632bf 100644 --- a/packages/peer-store/src/index.ts +++ b/packages/peer-store/src/index.ts @@ -3,7 +3,7 @@ import { RecordEnvelope, PeerRecord } from '@libp2p/peer-record' import all from 'it-all' import { PersistentStore, type PeerUpdate } from './store.js' import type { Libp2pEvents } from '@libp2p/interface' -import type { EventEmitter } from '@libp2p/interface/events' +import type { TypedEventTarget } from '@libp2p/interface/events' import type { PeerId } from '@libp2p/interface/peer-id' import type { PeerStore, Peer, PeerData, PeerQuery } from '@libp2p/interface/peer-store' import type { Multiaddr } from '@multiformats/multiaddr' @@ -14,7 +14,7 @@ const log = logger('libp2p:peer-store') export interface PersistentPeerStoreComponents { peerId: PeerId datastore: Datastore - events: EventEmitter + events: TypedEventTarget } /** @@ -33,7 +33,7 @@ export interface PersistentPeerStoreInit { */ export class PersistentPeerStore implements PeerStore { private readonly store: PersistentStore - private readonly events: EventEmitter + private readonly events: TypedEventTarget private readonly peerId: PeerId constructor (components: PersistentPeerStoreComponents, init: PersistentPeerStoreInit = {}) { diff --git a/packages/peer-store/test/index.spec.ts b/packages/peer-store/test/index.spec.ts index 868d811c72..e5fd106beb 100644 --- a/packages/peer-store/test/index.spec.ts +++ b/packages/peer-store/test/index.spec.ts @@ -1,7 +1,7 @@ /* eslint-env mocha */ /* eslint max-nested-callbacks: ["error", 6] */ -import { EventEmitter } from '@libp2p/interface/events' +import { TypedEventEmitter, type TypedEventTarget } from '@libp2p/interface/events' import { createEd25519PeerId } from '@libp2p/peer-id-factory' import { RecordEnvelope, PeerRecord } from '@libp2p/peer-record' import { multiaddr } from '@multiformats/multiaddr' @@ -18,12 +18,12 @@ describe('PersistentPeerStore', () => { let peerId: PeerId let otherPeerId: PeerId let peerStore: PersistentPeerStore - let events: EventEmitter + let events: TypedEventTarget beforeEach(async () => { peerId = await createEd25519PeerId() otherPeerId = await createEd25519PeerId() - events = new EventEmitter() + events = new TypedEventEmitter() peerStore = new PersistentPeerStore({ peerId, events, datastore: new MemoryDatastore() }) }) diff --git a/packages/peer-store/test/merge.spec.ts b/packages/peer-store/test/merge.spec.ts index 304512781f..eefeec19c7 100644 --- a/packages/peer-store/test/merge.spec.ts +++ b/packages/peer-store/test/merge.spec.ts @@ -1,7 +1,7 @@ /* eslint-env mocha */ /* eslint max-nested-callbacks: ["error", 6] */ -import { EventEmitter } from '@libp2p/interface/events' +import { TypedEventEmitter, type TypedEventTarget } from '@libp2p/interface/events' import { createEd25519PeerId } from '@libp2p/peer-id-factory' import { multiaddr } from '@multiformats/multiaddr' import { expect } from 'aegir/chai' @@ -20,12 +20,12 @@ describe('merge', () => { let peerId: PeerId let otherPeerId: PeerId let peerStore: PersistentPeerStore - let events: EventEmitter + let events: TypedEventTarget beforeEach(async () => { peerId = await createEd25519PeerId() otherPeerId = await createEd25519PeerId() - events = new EventEmitter() + events = new TypedEventEmitter() peerStore = new PersistentPeerStore({ peerId, events, datastore: new MemoryDatastore() }) }) diff --git a/packages/peer-store/test/patch.spec.ts b/packages/peer-store/test/patch.spec.ts index a30e22e872..929425dcb9 100644 --- a/packages/peer-store/test/patch.spec.ts +++ b/packages/peer-store/test/patch.spec.ts @@ -1,7 +1,7 @@ /* eslint-env mocha */ /* eslint max-nested-callbacks: ["error", 6] */ -import { EventEmitter } from '@libp2p/interface/events' +import { TypedEventEmitter, type TypedEventTarget } from '@libp2p/interface/events' import { createEd25519PeerId } from '@libp2p/peer-id-factory' import { multiaddr } from '@multiformats/multiaddr' import { expect } from 'aegir/chai' @@ -20,12 +20,12 @@ describe('patch', () => { let peerId: PeerId let otherPeerId: PeerId let peerStore: PersistentPeerStore - let events: EventEmitter + let events: TypedEventTarget beforeEach(async () => { peerId = await createEd25519PeerId() otherPeerId = await createEd25519PeerId() - events = new EventEmitter() + events = new TypedEventEmitter() peerStore = new PersistentPeerStore({ peerId, events, datastore: new MemoryDatastore() }) }) diff --git a/packages/peer-store/test/save.spec.ts b/packages/peer-store/test/save.spec.ts index 43552cb883..23a7e29905 100644 --- a/packages/peer-store/test/save.spec.ts +++ b/packages/peer-store/test/save.spec.ts @@ -1,7 +1,7 @@ /* eslint-env mocha */ /* eslint max-nested-callbacks: ["error", 6] */ -import { EventEmitter } from '@libp2p/interface/events' +import { TypedEventEmitter, type TypedEventTarget } from '@libp2p/interface/events' import { createEd25519PeerId, createRSAPeerId, createSecp256k1PeerId } from '@libp2p/peer-id-factory' import { multiaddr } from '@multiformats/multiaddr' import { expect } from 'aegir/chai' @@ -23,12 +23,12 @@ describe('save', () => { let peerId: PeerId let otherPeerId: PeerId let peerStore: PersistentPeerStore - let events: EventEmitter + let events: TypedEventTarget beforeEach(async () => { peerId = await createEd25519PeerId() otherPeerId = await createEd25519PeerId() - events = new EventEmitter() + events = new TypedEventEmitter() peerStore = new PersistentPeerStore({ peerId, events, datastore: new MemoryDatastore() }) }) diff --git a/packages/protocol-perf/test/index.spec.ts b/packages/protocol-perf/test/index.spec.ts index 83fd6c310f..fc8299ed10 100644 --- a/packages/protocol-perf/test/index.spec.ts +++ b/packages/protocol-perf/test/index.spec.ts @@ -1,6 +1,6 @@ /* eslint-env mocha */ -import { EventEmitter } from '@libp2p/interface/events' +import { TypedEventEmitter } from '@libp2p/interface/events' import { start, stop } from '@libp2p/interface/startable' import { connectionPair, mockRegistrar, type MockNetworkComponents, mockConnectionManager } from '@libp2p/interface-compliance-tests/mocks' import { createEd25519PeerId } from '@libp2p/peer-id-factory' @@ -11,7 +11,7 @@ export async function createComponents (): Promise { const components: any = { peerId: await createEd25519PeerId(), registrar: mockRegistrar(), - events: new EventEmitter() + events: new TypedEventEmitter() } components.connectionManager = mockConnectionManager(components) diff --git a/packages/pubsub/src/index.ts b/packages/pubsub/src/index.ts index b8760e3a4f..2de4fa3fce 100644 --- a/packages/pubsub/src/index.ts +++ b/packages/pubsub/src/index.ts @@ -1,5 +1,5 @@ import { CodeError } from '@libp2p/interface/errors' -import { EventEmitter, CustomEvent } from '@libp2p/interface/events' +import { TypedEventEmitter, CustomEvent } from '@libp2p/interface/events' import { type PubSub, type Message, type StrictNoSign, type StrictSign, type PubSubInit, type PubSubEvents, type PeerStreams, type PubSubRPCMessage, type PubSubRPC, type PubSubRPCSubscription, type SubscriptionChangeData, type PublishResult, type TopicValidatorFn, TopicValidatorResult } from '@libp2p/interface/pubsub' import { logger } from '@libp2p/logger' import { PeerMap, PeerSet } from '@libp2p/peer-collections' @@ -28,7 +28,7 @@ export interface PubSubComponents { * PubSubBaseProtocol handles the peers and connections logic for pubsub routers * and specifies the API that pubsub routers should have. */ -export abstract class PubSubBaseProtocol = PubSubEvents> extends EventEmitter implements PubSub { +export abstract class PubSubBaseProtocol = PubSubEvents> extends TypedEventEmitter implements PubSub { public started: boolean /** * Map of topics to which peers are subscribed to diff --git a/packages/pubsub/src/peer-streams.ts b/packages/pubsub/src/peer-streams.ts index c4a13387a5..8e1646907a 100644 --- a/packages/pubsub/src/peer-streams.ts +++ b/packages/pubsub/src/peer-streams.ts @@ -1,4 +1,4 @@ -import { EventEmitter, CustomEvent } from '@libp2p/interface/events' +import { TypedEventEmitter, CustomEvent } from '@libp2p/interface/events' import { logger } from '@libp2p/logger' import { abortableSource } from 'abortable-iterator' import * as lp from 'it-length-prefixed' @@ -20,7 +20,7 @@ export interface PeerStreamsInit { /** * Thin wrapper around a peer's inbound / outbound pubsub streams */ -export class PeerStreams extends EventEmitter { +export class PeerStreams extends TypedEventEmitter { public readonly id: PeerId public readonly protocol: string /** diff --git a/packages/transport-tcp/src/listener.ts b/packages/transport-tcp/src/listener.ts index 95792ed137..ee2d1a20f9 100644 --- a/packages/transport-tcp/src/listener.ts +++ b/packages/transport-tcp/src/listener.ts @@ -1,6 +1,6 @@ import net from 'net' import { CodeError } from '@libp2p/interface/errors' -import { EventEmitter, CustomEvent } from '@libp2p/interface/events' +import { TypedEventEmitter, CustomEvent } from '@libp2p/interface/events' import { logger } from '@libp2p/logger' import { CODE_P2P } from './constants.js' import { toMultiaddrConnection } from './socket-to-conn.js' @@ -71,7 +71,7 @@ type Status = { code: TCPListenerStatusCode.INACTIVE } | { netConfig: NetConfig } -export class TCPListener extends EventEmitter implements Listener { +export class TCPListener extends TypedEventEmitter implements Listener { private readonly server: net.Server /** Keep track of open connections to destroy in case of timeout */ private readonly connections = new Set() diff --git a/packages/transport-tcp/test/connection-limits.spec.ts b/packages/transport-tcp/test/connection-limits.spec.ts index 30aea96ac7..67a47c23e7 100644 --- a/packages/transport-tcp/test/connection-limits.spec.ts +++ b/packages/transport-tcp/test/connection-limits.spec.ts @@ -1,6 +1,6 @@ import net from 'node:net' import { promisify } from 'util' -import { EventEmitter } from '@libp2p/interface/events' +import { TypedEventEmitter } from '@libp2p/interface/events' import { mockUpgrader } from '@libp2p/interface-compliance-tests/mocks' import { multiaddr } from '@multiformats/multiaddr' import { expect } from 'aegir/chai' @@ -88,7 +88,7 @@ describe('closeAbove/listenBelow', () => { const trasnport = tcp({ closeServerOnMaxConnections: { listenBelow, closeAbove } })() const upgrader = mockUpgrader({ - events: new EventEmitter() + events: new TypedEventEmitter() }) const listener = trasnport.createListener({ upgrader }) as TCPListener // eslint-disable-next-line @typescript-eslint/promise-function-async @@ -115,7 +115,7 @@ describe('closeAbove/listenBelow', () => { const trasnport = tcp({ closeServerOnMaxConnections: { listenBelow, closeAbove } })() const upgrader = mockUpgrader({ - events: new EventEmitter() + events: new TypedEventEmitter() }) const listener = trasnport.createListener({ upgrader }) as TCPListener // eslint-disable-next-line @typescript-eslint/promise-function-async @@ -150,7 +150,7 @@ describe('closeAbove/listenBelow', () => { const trasnport = tcp({ closeServerOnMaxConnections: { listenBelow, closeAbove } })() const upgrader = mockUpgrader({ - events: new EventEmitter() + events: new TypedEventEmitter() }) const listener = trasnport.createListener({ upgrader }) as TCPListener // eslint-disable-next-line @typescript-eslint/promise-function-async @@ -181,7 +181,7 @@ describe('closeAbove/listenBelow', () => { const trasnport = tcp({ closeServerOnMaxConnections: { listenBelow, closeAbove } })() const upgrader = mockUpgrader({ - events: new EventEmitter() + events: new TypedEventEmitter() }) const listener = trasnport.createListener({ upgrader }) as TCPListener // eslint-disable-next-line @typescript-eslint/promise-function-async diff --git a/packages/transport-tcp/test/connection.spec.ts b/packages/transport-tcp/test/connection.spec.ts index 0308d61708..a8cb893edb 100644 --- a/packages/transport-tcp/test/connection.spec.ts +++ b/packages/transport-tcp/test/connection.spec.ts @@ -1,4 +1,4 @@ -import { EventEmitter } from '@libp2p/interface/events' +import { TypedEventEmitter } from '@libp2p/interface/events' import { mockUpgrader } from '@libp2p/interface-compliance-tests/mocks' import { multiaddr } from '@multiformats/multiaddr' import { expect } from 'aegir/chai' @@ -13,7 +13,7 @@ describe('valid localAddr and remoteAddr', () => { beforeEach(() => { transport = tcp()() upgrader = mockUpgrader({ - events: new EventEmitter() + events: new TypedEventEmitter() }) }) diff --git a/packages/transport-tcp/test/listen-dial.spec.ts b/packages/transport-tcp/test/listen-dial.spec.ts index a2988bce77..4c7f608350 100644 --- a/packages/transport-tcp/test/listen-dial.spec.ts +++ b/packages/transport-tcp/test/listen-dial.spec.ts @@ -1,6 +1,6 @@ import os from 'os' import path from 'path' -import { EventEmitter } from '@libp2p/interface/events' +import { TypedEventEmitter } from '@libp2p/interface/events' import { mockRegistrar, mockUpgrader } from '@libp2p/interface-compliance-tests/mocks' import { multiaddr } from '@multiformats/multiaddr' import { expect } from 'aegir/chai' @@ -22,7 +22,7 @@ describe('listen', () => { beforeEach(() => { transport = tcp()() upgrader = mockUpgrader({ - events: new EventEmitter() + events: new TypedEventEmitter() }) }) @@ -175,7 +175,7 @@ describe('dial', () => { }) upgrader = mockUpgrader({ registrar, - events: new EventEmitter() + events: new TypedEventEmitter() }) transport = tcp()() diff --git a/packages/transport-tcp/test/max-connections.spec.ts b/packages/transport-tcp/test/max-connections.spec.ts index 13d18d0c14..495a23e991 100644 --- a/packages/transport-tcp/test/max-connections.spec.ts +++ b/packages/transport-tcp/test/max-connections.spec.ts @@ -1,6 +1,6 @@ import net from 'node:net' import { promisify } from 'node:util' -import { EventEmitter } from '@libp2p/interface/events' +import { TypedEventEmitter } from '@libp2p/interface/events' import { mockUpgrader } from '@libp2p/interface-compliance-tests/mocks' import { multiaddr } from '@multiformats/multiaddr' import { expect } from 'aegir/chai' @@ -22,7 +22,7 @@ describe('maxConnections', () => { const transport = tcp({ maxConnections })() const upgrader = mockUpgrader({ - events: new EventEmitter() + events: new TypedEventEmitter() }) const listener = transport.createListener({ upgrader }) // eslint-disable-next-line @typescript-eslint/promise-function-async diff --git a/packages/transport-webrtc/src/private-to-private/listener.ts b/packages/transport-webrtc/src/private-to-private/listener.ts index 53a3d299c6..6a73e9e14a 100644 --- a/packages/transport-webrtc/src/private-to-private/listener.ts +++ b/packages/transport-webrtc/src/private-to-private/listener.ts @@ -1,4 +1,4 @@ -import { EventEmitter } from '@libp2p/interface/events' +import { TypedEventEmitter } from '@libp2p/interface/events' import { Circuit } from '@multiformats/mafmt' import type { PeerId } from '@libp2p/interface/peer-id' import type { ListenerEvents, Listener } from '@libp2p/interface/transport' @@ -14,7 +14,7 @@ export interface WebRTCPeerListenerInit { shutdownController: AbortController } -export class WebRTCPeerListener extends EventEmitter implements Listener { +export class WebRTCPeerListener extends TypedEventEmitter implements Listener { private readonly peerId: PeerId private readonly transportManager: TransportManager private readonly shutdownController: AbortController diff --git a/packages/transport-websockets/.aegir.js b/packages/transport-websockets/.aegir.js index 1a81ef61be..d7e24c7d10 100644 --- a/packages/transport-websockets/.aegir.js +++ b/packages/transport-websockets/.aegir.js @@ -6,7 +6,7 @@ export default { async before () { const { multiaddr } = await import('@multiformats/multiaddr') const { mockRegistrar, mockUpgrader } = await import('@libp2p/interface-compliance-tests/mocks') - const { EventEmitter } = await import('@libp2p/interface/events') + const { TypedEventEmitter } = await import('@libp2p/interface/events') const { webSockets } = await import('./dist/src/index.js') const protocol = '/echo/1.0.0' @@ -19,7 +19,7 @@ export default { }) const upgrader = mockUpgrader({ registrar, - events: new EventEmitter() + events: new TypedEventEmitter() }) const ws = webSockets()() diff --git a/packages/transport-websockets/src/listener.ts b/packages/transport-websockets/src/listener.ts index 9adb5957ae..6f307c0ecb 100644 --- a/packages/transport-websockets/src/listener.ts +++ b/packages/transport-websockets/src/listener.ts @@ -1,5 +1,5 @@ import os from 'os' -import { EventEmitter, CustomEvent } from '@libp2p/interface/events' +import { TypedEventEmitter, CustomEvent } from '@libp2p/interface/events' import { logger } from '@libp2p/logger' import { ipPortToMultiaddr as toMultiaddr } from '@libp2p/utils/ip-port-to-multiaddr' import { multiaddr, protocols } from '@multiformats/multiaddr' @@ -14,7 +14,7 @@ import type { WebSocketServer } from 'it-ws/server' const log = logger('libp2p:websockets:listener') -class WebSocketListener extends EventEmitter implements Listener { +class WebSocketListener extends TypedEventEmitter implements Listener { private readonly connections: Set private listeningMultiaddr?: Multiaddr private readonly server: WebSocketServer diff --git a/packages/transport-websockets/test/browser.ts b/packages/transport-websockets/test/browser.ts index 616f09e37e..88e311c67c 100644 --- a/packages/transport-websockets/test/browser.ts +++ b/packages/transport-websockets/test/browser.ts @@ -1,6 +1,6 @@ /* eslint-env mocha */ -import { EventEmitter } from '@libp2p/interface/events' +import { TypedEventEmitter } from '@libp2p/interface/events' import { mockUpgrader } from '@libp2p/interface-compliance-tests/mocks' import { multiaddr } from '@multiformats/multiaddr' import { expect } from 'aegir/chai' @@ -23,7 +23,7 @@ describe('libp2p-websockets', () => { ws = webSockets()() conn = await ws.dial(ma, { upgrader: mockUpgrader({ - events: new EventEmitter() + events: new TypedEventEmitter() }) }) }) diff --git a/packages/transport-websockets/test/node.ts b/packages/transport-websockets/test/node.ts index 32aa1b02ae..8c296900ce 100644 --- a/packages/transport-websockets/test/node.ts +++ b/packages/transport-websockets/test/node.ts @@ -4,7 +4,7 @@ import fs from 'fs' import http from 'http' import https from 'https' -import { EventEmitter } from '@libp2p/interface/events' +import { TypedEventEmitter } from '@libp2p/interface/events' import { mockRegistrar, mockUpgrader } from '@libp2p/interface-compliance-tests/mocks' import { multiaddr } from '@multiformats/multiaddr' import { expect } from 'aegir/chai' @@ -41,7 +41,7 @@ void registrar.handle(protocol, (evt) => { }) const upgrader = mockUpgrader({ registrar, - events: new EventEmitter() + events: new TypedEventEmitter() }) describe('instantiate the transport', () => { From de4f4c3e0336ba2f8b3330c797d00e40c0b45b35 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 25 Oct 2023 14:08:12 +0100 Subject: [PATCH 09/24] chore: release master (#2170) Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- .release-please-manifest.json | 2 +- interop/CHANGELOG.md | 11 +++++++++++ interop/package.json | 8 ++++---- packages/kad-dht/CHANGELOG.md | 8 ++++++++ packages/kad-dht/package.json | 2 +- packages/libp2p/CHANGELOG.md | 16 +++++++++++++++- packages/libp2p/package.json | 4 ++-- packages/protocol-perf/CHANGELOG.md | 9 +++++++++ packages/protocol-perf/package.json | 4 ++-- packages/transport-webrtc/CHANGELOG.md | 9 +++++++++ packages/transport-webrtc/package.json | 4 ++-- packages/transport-webtransport/CHANGELOG.md | 9 +++++++++ packages/transport-webtransport/package.json | 4 ++-- 13 files changed, 75 insertions(+), 15 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 71b4d4c4f6..2d1529db7b 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1 +1 @@ -{"interop":"1.0.6","packages/crypto":"2.0.5","packages/interface":"0.1.3","packages/interface-compliance-tests":"4.1.1","packages/interface-internal":"0.1.6","packages/kad-dht":"10.0.9","packages/keychain":"3.0.5","packages/libp2p":"0.46.14","packages/logger":"3.0.3","packages/metrics-prometheus":"2.0.8","packages/multistream-select":"4.0.3","packages/peer-collections":"4.0.5","packages/peer-discovery-bootstrap":"9.0.8","packages/peer-discovery-mdns":"9.0.10","packages/peer-id":"3.0.3","packages/peer-id-factory":"3.0.5","packages/peer-record":"6.0.6","packages/peer-store":"9.0.6","packages/protocol-perf":"1.1.11","packages/pubsub":"8.0.7","packages/pubsub-floodsub":"8.0.9","packages/stream-multiplexer-mplex":"9.0.8","packages/transport-tcp":"8.0.9","packages/transport-webrtc":"3.2.3","packages/transport-websockets":"7.0.9","packages/transport-webtransport":"3.1.3","packages/utils":"4.0.4"} \ No newline at end of file +{"interop":"1.0.7","packages/crypto":"2.0.5","packages/interface":"0.1.3","packages/interface-compliance-tests":"4.1.1","packages/interface-internal":"0.1.6","packages/kad-dht":"10.0.10","packages/keychain":"3.0.5","packages/libp2p":"0.46.15","packages/logger":"3.0.3","packages/metrics-prometheus":"2.0.8","packages/multistream-select":"4.0.3","packages/peer-collections":"4.0.5","packages/peer-discovery-bootstrap":"9.0.8","packages/peer-discovery-mdns":"9.0.10","packages/peer-id":"3.0.3","packages/peer-id-factory":"3.0.5","packages/peer-record":"6.0.6","packages/peer-store":"9.0.6","packages/protocol-perf":"1.1.12","packages/pubsub":"8.0.7","packages/pubsub-floodsub":"8.0.9","packages/stream-multiplexer-mplex":"9.0.8","packages/transport-tcp":"8.0.9","packages/transport-webrtc":"3.2.4","packages/transport-websockets":"7.0.9","packages/transport-webtransport":"3.1.4","packages/utils":"4.0.4"} \ No newline at end of file diff --git a/interop/CHANGELOG.md b/interop/CHANGELOG.md index fb517accc5..92beaecf30 100644 --- a/interop/CHANGELOG.md +++ b/interop/CHANGELOG.md @@ -1,5 +1,16 @@ # Changelog +### [1.0.7](https://www.github.com/libp2p/js-libp2p/compare/multidim-interop-v1.0.6...multidim-interop-v1.0.7) (2023-10-25) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * @libp2p/webrtc bumped from ^3.2.3 to ^3.2.4 + * @libp2p/webtransport bumped from ^3.1.3 to ^3.1.4 + * libp2p bumped from ^0.46.14 to ^0.46.15 + ### [1.0.6](https://www.github.com/libp2p/js-libp2p/compare/multidim-interop-v1.0.5...multidim-interop-v1.0.6) (2023-10-10) diff --git a/interop/package.json b/interop/package.json index 3ab015c03a..6e0672d979 100644 --- a/interop/package.json +++ b/interop/package.json @@ -1,6 +1,6 @@ { "name": "@libp2p/multidim-interop", - "version": "1.0.6", + "version": "1.0.7", "description": "Multidimensional interop tests", "author": "Glen De Cauwsemaecker / @marcopolo", "license": "Apache-2.0 OR MIT", @@ -54,13 +54,13 @@ "@chainsafe/libp2p-yamux": "^5.0.0", "@libp2p/mplex": "^9.0.8", "@libp2p/tcp": "^8.0.9", - "@libp2p/webrtc": "^3.2.3", + "@libp2p/webrtc": "^3.2.4", "@libp2p/websockets": "^7.0.9", - "@libp2p/webtransport": "^3.1.3", + "@libp2p/webtransport": "^3.1.4", "@multiformats/mafmt": "^12.1.2", "@multiformats/multiaddr": "^12.1.5", "aegir": "^41.0.2", - "libp2p": "^0.46.14", + "libp2p": "^0.46.15", "redis": "^4.5.1" }, "browser": { diff --git a/packages/kad-dht/CHANGELOG.md b/packages/kad-dht/CHANGELOG.md index 9cbeb5a94c..9682a64034 100644 --- a/packages/kad-dht/CHANGELOG.md +++ b/packages/kad-dht/CHANGELOG.md @@ -5,6 +5,14 @@ * skip self-query if not running ([#479](https://github.com/libp2p/js-libp2p-kad-dht/issues/479)) ([7095290](https://github.com/libp2p/js-libp2p-kad-dht/commit/70952907a27fd8778773172059879656b4f08855)) +### [10.0.10](https://www.github.com/libp2p/js-libp2p/compare/kad-dht-v10.0.9...kad-dht-v10.0.10) (2023-10-25) + + +### Bug Fixes + +* allow DHT self-query to time out ([#2169](https://www.github.com/libp2p/js-libp2p/issues/2169)) ([ce0e38d](https://www.github.com/libp2p/js-libp2p/commit/ce0e38d28240303f7afc7f37de441b067e3e855e)) +* export DHT record class ([#2168](https://www.github.com/libp2p/js-libp2p/issues/2168)) ([2f6a239](https://www.github.com/libp2p/js-libp2p/commit/2f6a2397f7e8ec7cf2edda7c9996be263a423661)) + ### [10.0.9](https://www.github.com/libp2p/js-libp2p/compare/kad-dht-v10.0.8...kad-dht-v10.0.9) (2023-10-06) diff --git a/packages/kad-dht/package.json b/packages/kad-dht/package.json index be55a32b43..8fbe9803a0 100644 --- a/packages/kad-dht/package.json +++ b/packages/kad-dht/package.json @@ -1,6 +1,6 @@ { "name": "@libp2p/kad-dht", - "version": "10.0.9", + "version": "10.0.10", "description": "JavaScript implementation of the Kad-DHT for libp2p", "license": "Apache-2.0 OR MIT", "homepage": "https://github.com/libp2p/js-libp2p/tree/master/packages/kad-dht#readme", diff --git a/packages/libp2p/CHANGELOG.md b/packages/libp2p/CHANGELOG.md index 36d4003014..d3ae00b22e 100644 --- a/packages/libp2p/CHANGELOG.md +++ b/packages/libp2p/CHANGELOG.md @@ -20,6 +20,20 @@ * @libp2p/tcp bumped from ^8.0.5 to ^8.0.6 * @libp2p/websockets bumped from ^7.0.5 to ^7.0.6 +### [0.46.15](https://www.github.com/libp2p/js-libp2p/compare/libp2p-v0.46.14...libp2p-v0.46.15) (2023-10-25) + + +### Bug Fixes + +* remove relay:removed event listener after relay is removed ([#1998](https://www.github.com/libp2p/js-libp2p/issues/1998)) ([ab2c1f6](https://www.github.com/libp2p/js-libp2p/commit/ab2c1f6731ccfe21a39482bdab217a8abd3f027b)) + + +### Dependencies + +* The following workspace dependencies were updated + * devDependencies + * @libp2p/kad-dht bumped from ^10.0.9 to ^10.0.10 + ### [0.46.14](https://www.github.com/libp2p/js-libp2p/compare/libp2p-v0.46.13...libp2p-v0.46.14) (2023-10-10) @@ -2546,4 +2560,4 @@ for subscribe to see how it should be used. -## [0.5.5](https://github.com/libp2p/js-libp2p/compare/v0.5.4...v0.5.5) (2017-03-21) +## [0.5.5](https://github.com/libp2p/js-libp2p/compare/v0.5.4...v0.5.5) (2017-03-21) \ No newline at end of file diff --git a/packages/libp2p/package.json b/packages/libp2p/package.json index bec42a043f..55345125fb 100644 --- a/packages/libp2p/package.json +++ b/packages/libp2p/package.json @@ -1,6 +1,6 @@ { "name": "libp2p", - "version": "0.46.14", + "version": "0.46.15", "description": "JavaScript implementation of libp2p, a modular peer to peer network stack", "license": "Apache-2.0 OR MIT", "homepage": "https://github.com/libp2p/js-libp2p/tree/master/packages/libp2p#readme", @@ -177,7 +177,7 @@ "@libp2p/floodsub": "^8.0.9", "@libp2p/interface-compliance-tests": "^4.1.1", "@libp2p/interop": "^9.0.0", - "@libp2p/kad-dht": "^10.0.9", + "@libp2p/kad-dht": "^10.0.10", "@libp2p/mdns": "^9.0.10", "@libp2p/mplex": "^9.0.8", "@libp2p/tcp": "^8.0.9", diff --git a/packages/protocol-perf/CHANGELOG.md b/packages/protocol-perf/CHANGELOG.md index edfb9ed294..6887569649 100644 --- a/packages/protocol-perf/CHANGELOG.md +++ b/packages/protocol-perf/CHANGELOG.md @@ -1,5 +1,14 @@ # Changelog +### [1.1.12](https://www.github.com/libp2p/js-libp2p/compare/perf-v1.1.11...perf-v1.1.12) (2023-10-25) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * libp2p bumped from ^0.46.14 to ^0.46.15 + ### [1.1.11](https://www.github.com/libp2p/js-libp2p/compare/perf-v1.1.10...perf-v1.1.11) (2023-10-10) diff --git a/packages/protocol-perf/package.json b/packages/protocol-perf/package.json index 6902f8d8f0..b4bfb57b06 100644 --- a/packages/protocol-perf/package.json +++ b/packages/protocol-perf/package.json @@ -1,6 +1,6 @@ { "name": "@libp2p/perf", - "version": "1.1.11", + "version": "1.1.12", "description": "Implementation of Perf Protocol", "author": "@maschad / @marcopolo", "license": "Apache-2.0 OR MIT", @@ -59,7 +59,7 @@ "@libp2p/peer-id-factory": "^3.0.5", "@libp2p/tcp": "^8.0.9", "@multiformats/multiaddr": "^12.1.5", - "libp2p": "^0.46.14", + "libp2p": "^0.46.15", "uint8arrays": "^4.0.6", "yargs": "^17.7.2" }, diff --git a/packages/transport-webrtc/CHANGELOG.md b/packages/transport-webrtc/CHANGELOG.md index ca190b424c..ebb6dfbdd8 100644 --- a/packages/transport-webrtc/CHANGELOG.md +++ b/packages/transport-webrtc/CHANGELOG.md @@ -5,6 +5,15 @@ * add browser-to-browser test for bi-directional communication ([#172](https://github.com/libp2p/js-libp2p-webrtc/issues/172)) ([1ec3d8a](https://github.com/libp2p/js-libp2p-webrtc/commit/1ec3d8a8b611d5227f430037e2547fd86d115eaa)) +### [3.2.4](https://www.github.com/libp2p/js-libp2p/compare/webrtc-v3.2.3...webrtc-v3.2.4) (2023-10-25) + + +### Dependencies + +* The following workspace dependencies were updated + * devDependencies + * libp2p bumped from ^0.46.14 to ^0.46.15 + ### [3.2.3](https://www.github.com/libp2p/js-libp2p/compare/webrtc-v3.2.2...webrtc-v3.2.3) (2023-10-10) diff --git a/packages/transport-webrtc/package.json b/packages/transport-webrtc/package.json index 7ffebe70d4..919d5c5032 100644 --- a/packages/transport-webrtc/package.json +++ b/packages/transport-webrtc/package.json @@ -1,6 +1,6 @@ { "name": "@libp2p/webrtc", - "version": "3.2.3", + "version": "3.2.4", "description": "A libp2p transport using WebRTC connections", "license": "Apache-2.0 OR MIT", "homepage": "https://github.com/libp2p/js-libp2p/tree/master/packages/transport-webrtc#readme", @@ -85,7 +85,7 @@ "it-length": "^3.0.2", "it-map": "^3.0.3", "it-pair": "^2.0.6", - "libp2p": "^0.46.14", + "libp2p": "^0.46.15", "p-retry": "^6.1.0", "protons": "^7.0.2", "sinon": "^17.0.0", diff --git a/packages/transport-webtransport/CHANGELOG.md b/packages/transport-webtransport/CHANGELOG.md index 84afa61866..d00fa59b6a 100644 --- a/packages/transport-webtransport/CHANGELOG.md +++ b/packages/transport-webtransport/CHANGELOG.md @@ -11,6 +11,15 @@ * bump @chainsafe/libp2p-noise from 11.0.4 to 12.0.1 ([#80](https://github.com/libp2p/js-libp2p-webtransport/issues/80)) ([599dab1](https://github.com/libp2p/js-libp2p-webtransport/commit/599dab1b4f6ae816b0c0feefc926c1b38d24b676)) +### [3.1.4](https://www.github.com/libp2p/js-libp2p/compare/webtransport-v3.1.3...webtransport-v3.1.4) (2023-10-25) + + +### Dependencies + +* The following workspace dependencies were updated + * devDependencies + * libp2p bumped from ^0.46.14 to ^0.46.15 + ### [3.1.3](https://www.github.com/libp2p/js-libp2p/compare/webtransport-v3.1.2...webtransport-v3.1.3) (2023-10-10) diff --git a/packages/transport-webtransport/package.json b/packages/transport-webtransport/package.json index e0442f0712..2e5df8d2c5 100644 --- a/packages/transport-webtransport/package.json +++ b/packages/transport-webtransport/package.json @@ -1,6 +1,6 @@ { "name": "@libp2p/webtransport", - "version": "3.1.3", + "version": "3.1.4", "description": "JavaScript implementation of the WebTransport module that libp2p uses and that implements the interface-transport spec", "license": "Apache-2.0 OR MIT", "homepage": "https://github.com/libp2p/js-libp2p/tree/master/packages/transport-webtransport#readme", @@ -75,7 +75,7 @@ "devDependencies": { "@libp2p/peer-id-factory": "^3.0.5", "aegir": "^41.0.2", - "libp2p": "^0.46.14", + "libp2p": "^0.46.15", "p-defer": "^4.0.0" }, "browser": { From 0ef5f7f62d9c6d822e0a4b99cc203a1516b11f2f Mon Sep 17 00:00:00 2001 From: Alex Potsides Date: Wed, 25 Oct 2023 15:38:16 +0100 Subject: [PATCH 10/24] fix: revert "refactor: rename event emitter class" (#2172) This reverts commit b5a808af700207fe5e086133bb505367177a086e. --- .../src/mocks/connection-manager.ts | 6 +++--- .../src/mocks/peer-discovery.ts | 4 ++-- .../src/mocks/upgrader.ts | 6 +++--- .../src/pubsub/utils.ts | 4 ++-- .../src/transport/dial-test.ts | 4 ++-- .../src/transport/listen-test.ts | 4 ++-- packages/interface/src/events.ts | 21 +------------------ packages/interface/src/index.ts | 4 ++-- .../interface/src/peer-discovery/index.ts | 4 ++-- packages/interface/src/pubsub/index.ts | 6 +++--- packages/interface/src/transport/index.ts | 4 ++-- packages/kad-dht/src/dual-kad-dht.ts | 4 ++-- packages/kad-dht/src/index.ts | 4 ++-- packages/kad-dht/src/kad-dht.ts | 4 ++-- packages/kad-dht/src/network.ts | 4 ++-- packages/kad-dht/src/query/manager.ts | 4 ++-- packages/kad-dht/src/query/query-path.ts | 6 +++--- packages/kad-dht/src/routing-table/index.ts | 4 ++-- .../kad-dht/src/routing-table/k-bucket.ts | 6 ++++-- packages/kad-dht/src/topology-listener.ts | 4 ++-- packages/kad-dht/test/routing-table.spec.ts | 4 ++-- .../test/rpc/handlers/get-providers.spec.ts | 4 ++-- .../test/rpc/handlers/get-value.spec.ts | 4 ++-- packages/kad-dht/test/rpc/index.node.ts | 4 ++-- packages/kad-dht/test/utils/test-dht.ts | 4 ++-- packages/libp2p/src/address-manager/index.ts | 4 ++-- packages/libp2p/src/circuit-relay/index.ts | 4 ++-- .../circuit-relay/server/advert-service.ts | 4 ++-- .../libp2p/src/circuit-relay/server/index.ts | 4 ++-- .../src/circuit-relay/transport/discovery.ts | 4 ++-- .../src/circuit-relay/transport/index.ts | 4 ++-- .../src/circuit-relay/transport/listener.ts | 4 ++-- .../transport/reservation-store.ts | 8 +++---- packages/libp2p/src/components.ts | 6 +++--- .../src/connection-manager/auto-dial.ts | 4 ++-- .../connection-manager/connection-pruner.ts | 6 +++--- .../libp2p/src/connection-manager/index.ts | 6 +++--- packages/libp2p/src/identify/identify.ts | 4 ++-- packages/libp2p/src/identify/index.ts | 4 ++-- packages/libp2p/src/libp2p.ts | 6 +++--- packages/libp2p/src/registrar.ts | 4 ++-- packages/libp2p/src/transport-manager.ts | 4 ++-- packages/libp2p/src/upgrader.ts | 6 +++--- .../test/addresses/address-manager.spec.ts | 6 +++--- .../libp2p/test/circuit-relay/hop.spec.ts | 6 +++--- .../libp2p/test/circuit-relay/stop.spec.ts | 4 ++-- .../test/connection-manager/auto-dial.spec.ts | 6 +++--- .../test/connection-manager/direct.node.ts | 6 +++--- .../test/connection-manager/direct.spec.ts | 4 ++-- .../test/connection-manager/index.node.ts | 6 +++--- .../test/connection-manager/index.spec.ts | 12 +++++------ packages/libp2p/test/fetch/index.spec.ts | 4 ++-- packages/libp2p/test/identify/index.spec.ts | 4 ++-- packages/libp2p/test/identify/push.spec.ts | 4 ++-- .../libp2p/test/peer-discovery/index.node.ts | 4 ++-- packages/libp2p/test/ping/index.spec.ts | 4 ++-- .../libp2p/test/registrar/registrar.spec.ts | 8 +++---- .../test/transports/transport-manager.node.ts | 4 ++-- .../test/transports/transport-manager.spec.ts | 4 ++-- .../libp2p/test/upgrading/upgrader.spec.ts | 6 +++--- .../libp2p/test/upnp-nat/upnp-nat.node.ts | 4 ++-- .../peer-discovery-bootstrap/src/index.ts | 4 ++-- packages/peer-discovery-mdns/src/index.ts | 4 ++-- packages/peer-store/src/index.ts | 6 +++--- packages/peer-store/test/index.spec.ts | 6 +++--- packages/peer-store/test/merge.spec.ts | 6 +++--- packages/peer-store/test/patch.spec.ts | 6 +++--- packages/peer-store/test/save.spec.ts | 6 +++--- packages/protocol-perf/test/index.spec.ts | 4 ++-- packages/pubsub/src/index.ts | 4 ++-- packages/pubsub/src/peer-streams.ts | 4 ++-- packages/transport-tcp/src/listener.ts | 4 ++-- .../test/connection-limits.spec.ts | 10 ++++----- .../transport-tcp/test/connection.spec.ts | 4 ++-- .../transport-tcp/test/listen-dial.spec.ts | 6 +++--- .../test/max-connections.spec.ts | 4 ++-- .../src/private-to-private/listener.ts | 4 ++-- packages/transport-websockets/.aegir.js | 4 ++-- packages/transport-websockets/src/listener.ts | 4 ++-- packages/transport-websockets/test/browser.ts | 4 ++-- packages/transport-websockets/test/node.ts | 4 ++-- 81 files changed, 195 insertions(+), 212 deletions(-) diff --git a/packages/interface-compliance-tests/src/mocks/connection-manager.ts b/packages/interface-compliance-tests/src/mocks/connection-manager.ts index 81904d407f..4f5cecbac0 100644 --- a/packages/interface-compliance-tests/src/mocks/connection-manager.ts +++ b/packages/interface-compliance-tests/src/mocks/connection-manager.ts @@ -6,7 +6,7 @@ import { isMultiaddr, type Multiaddr } from '@multiformats/multiaddr' import { connectionPair } from './connection.js' import type { Libp2pEvents, PendingDial } from '@libp2p/interface' import type { Connection } from '@libp2p/interface/connection' -import type { TypedEventTarget } from '@libp2p/interface/events' +import type { EventEmitter } from '@libp2p/interface/events' import type { PubSub } from '@libp2p/interface/pubsub' import type { Startable } from '@libp2p/interface/startable' import type { ConnectionManager } from '@libp2p/interface-internal/connection-manager' @@ -16,7 +16,7 @@ export interface MockNetworkComponents { peerId: PeerId registrar: Registrar connectionManager: ConnectionManager - events: TypedEventTarget + events: EventEmitter pubsub?: PubSub } @@ -51,7 +51,7 @@ export const mockNetwork = new MockNetwork() export interface MockConnectionManagerComponents { peerId: PeerId registrar: Registrar - events: TypedEventTarget + events: EventEmitter } class MockConnectionManager implements ConnectionManager, Startable { diff --git a/packages/interface-compliance-tests/src/mocks/peer-discovery.ts b/packages/interface-compliance-tests/src/mocks/peer-discovery.ts index 69bd2afc29..eab17bea6d 100644 --- a/packages/interface-compliance-tests/src/mocks/peer-discovery.ts +++ b/packages/interface-compliance-tests/src/mocks/peer-discovery.ts @@ -1,4 +1,4 @@ -import { TypedEventEmitter } from '@libp2p/interface/events' +import { EventEmitter } from '@libp2p/interface/events' import { peerDiscovery } from '@libp2p/interface/peer-discovery' import * as PeerIdFactory from '@libp2p/peer-id-factory' import { multiaddr } from '@multiformats/multiaddr' @@ -12,7 +12,7 @@ interface MockDiscoveryInit { /** * Emits 'peer' events on discovery. */ -export class MockDiscovery extends TypedEventEmitter implements PeerDiscovery { +export class MockDiscovery extends EventEmitter implements PeerDiscovery { public readonly options: MockDiscoveryInit private _isRunning: boolean private _timer: any diff --git a/packages/interface-compliance-tests/src/mocks/upgrader.ts b/packages/interface-compliance-tests/src/mocks/upgrader.ts index 4f69268071..b4ef88002d 100644 --- a/packages/interface-compliance-tests/src/mocks/upgrader.ts +++ b/packages/interface-compliance-tests/src/mocks/upgrader.ts @@ -1,18 +1,18 @@ import { mockConnection } from './connection.js' import type { Libp2pEvents } from '@libp2p/interface' import type { Connection, MultiaddrConnection } from '@libp2p/interface/connection' -import type { TypedEventTarget } from '@libp2p/interface/events' +import type { EventEmitter } from '@libp2p/interface/events' import type { Upgrader, UpgraderOptions } from '@libp2p/interface/transport' import type { Registrar } from '@libp2p/interface-internal/registrar' export interface MockUpgraderInit { registrar?: Registrar - events?: TypedEventTarget + events?: EventEmitter } class MockUpgrader implements Upgrader { private readonly registrar?: Registrar - private readonly events?: TypedEventTarget + private readonly events?: EventEmitter constructor (init: MockUpgraderInit) { this.registrar = init.registrar diff --git a/packages/interface-compliance-tests/src/pubsub/utils.ts b/packages/interface-compliance-tests/src/pubsub/utils.ts index fdd7c2552c..79bf894479 100644 --- a/packages/interface-compliance-tests/src/pubsub/utils.ts +++ b/packages/interface-compliance-tests/src/pubsub/utils.ts @@ -1,4 +1,4 @@ -import { TypedEventEmitter } from '@libp2p/interface/events' +import { EventEmitter } from '@libp2p/interface/events' import { createEd25519PeerId } from '@libp2p/peer-id-factory' import { pEvent } from 'p-event' import pWaitFor from 'p-wait-for' @@ -19,7 +19,7 @@ export async function createComponents (): Promise { const components: any = { peerId: await createEd25519PeerId(), registrar: mockRegistrar(), - events: new TypedEventEmitter() + events: new EventEmitter() } components.connectionManager = mockConnectionManager(components) diff --git a/packages/interface-compliance-tests/src/transport/dial-test.ts b/packages/interface-compliance-tests/src/transport/dial-test.ts index 98035d9aa5..2139a755d0 100644 --- a/packages/interface-compliance-tests/src/transport/dial-test.ts +++ b/packages/interface-compliance-tests/src/transport/dial-test.ts @@ -1,5 +1,5 @@ import { AbortError } from '@libp2p/interface/errors' -import { TypedEventEmitter } from '@libp2p/interface/events' +import { EventEmitter } from '@libp2p/interface/events' import { expect } from 'aegir/chai' import all from 'it-all' import drain from 'it-drain' @@ -27,7 +27,7 @@ export default (common: TestSetup): void => { registrar = mockRegistrar() upgrader = mockUpgrader({ registrar, - events: new TypedEventEmitter() + events: new EventEmitter() }); ({ addrs, transport, connector } = await common.setup()) diff --git a/packages/interface-compliance-tests/src/transport/listen-test.ts b/packages/interface-compliance-tests/src/transport/listen-test.ts index d9f3a17c22..d518511dc7 100644 --- a/packages/interface-compliance-tests/src/transport/listen-test.ts +++ b/packages/interface-compliance-tests/src/transport/listen-test.ts @@ -1,5 +1,5 @@ /* eslint max-nested-callbacks: ["error", 8] */ -import { CustomEvent, TypedEventEmitter } from '@libp2p/interface/events' +import { CustomEvent, EventEmitter } from '@libp2p/interface/events' import { expect } from 'aegir/chai' import drain from 'it-drain' import { pipe } from 'it-pipe' @@ -27,7 +27,7 @@ export default (common: TestSetup): void => { registrar = mockRegistrar() upgrader = mockUpgrader({ registrar, - events: new TypedEventEmitter() + events: new EventEmitter() }); ({ transport, addrs } = await common.setup()) diff --git a/packages/interface/src/events.ts b/packages/interface/src/events.ts index 2f4e863b0e..4fff7e8f91 100644 --- a/packages/interface/src/events.ts +++ b/packages/interface/src/events.ts @@ -15,23 +15,7 @@ interface Listener { * https://github.com/microsoft/TypeScript/issues/299 * etc */ -export interface TypedEventTarget > extends EventTarget { - addEventListener(type: K, listener: EventHandler | null, options?: boolean | AddEventListenerOptions): void - - listenerCount (type: string): number - - removeEventListener(type: K, listener?: EventHandler | null, options?: boolean | EventListenerOptions): void - - removeEventListener (type: string, listener?: EventHandler, options?: boolean | EventListenerOptions): void - - safeDispatchEvent(type: keyof EventMap, detail: CustomEventInit): boolean -} - -/** - * An implementation of a typed event target - * etc - */ -export class TypedEventEmitter> extends EventTarget implements TypedEventTarget { +export class EventEmitter> extends EventTarget { #listeners = new Map() listenerCount (type: string): number { @@ -114,6 +98,3 @@ class CustomEventPolyfill extends Event { } export const CustomEvent = globalThis.CustomEvent ?? CustomEventPolyfill - -// TODO: remove this in v1 -export { TypedEventEmitter as EventEmitter } diff --git a/packages/interface/src/index.ts b/packages/interface/src/index.ts index d50e335d69..0dd02078f8 100644 --- a/packages/interface/src/index.ts +++ b/packages/interface/src/index.ts @@ -16,7 +16,7 @@ import type { Connection, NewStreamOptions, Stream } from './connection/index.js' import type { ContentRouting } from './content-routing/index.js' -import type { TypedEventTarget } from './events.js' +import type { EventEmitter } from './events.js' import type { KeyChain } from './keychain/index.js' import type { Metrics } from './metrics/index.js' import type { PeerId } from './peer-id/index.js' @@ -303,7 +303,7 @@ export interface PendingDial { /** * Libp2p nodes implement this interface. */ -export interface Libp2p extends Startable, TypedEventTarget> { +export interface Libp2p extends Startable, EventEmitter> { /** * The PeerId is a unique identifier for a node on the network. * diff --git a/packages/interface/src/peer-discovery/index.ts b/packages/interface/src/peer-discovery/index.ts index 55b1227eb1..4b8aa9c258 100644 --- a/packages/interface/src/peer-discovery/index.ts +++ b/packages/interface/src/peer-discovery/index.ts @@ -1,4 +1,4 @@ -import type { TypedEventTarget } from '../events.js' +import type { EventEmitter } from '../events.js' import type { PeerInfo } from '../peer-info/index.js' /** @@ -26,4 +26,4 @@ export interface PeerDiscoveryEvents { 'peer': CustomEvent } -export interface PeerDiscovery extends TypedEventTarget {} +export interface PeerDiscovery extends EventEmitter {} diff --git a/packages/interface/src/pubsub/index.ts b/packages/interface/src/pubsub/index.ts index 1ce9464b6b..6fd94382a1 100644 --- a/packages/interface/src/pubsub/index.ts +++ b/packages/interface/src/pubsub/index.ts @@ -1,5 +1,5 @@ import type { Stream } from '../connection/index.js' -import type { TypedEventTarget } from '../events.js' +import type { EventEmitter } from '../events.js' import type { PeerId } from '../peer-id/index.js' import type { Pushable } from 'it-pushable' import type { Uint8ArrayList } from 'uint8arraylist' @@ -65,7 +65,7 @@ export interface PubSubRPC { messages: PubSubRPCMessage[] } -export interface PeerStreams extends TypedEventTarget { +export interface PeerStreams extends EventEmitter { id: PeerId protocol: string outboundStream?: Pushable @@ -152,7 +152,7 @@ export interface TopicValidatorFn { (peer: PeerId, message: Message): TopicValidatorResult | Promise } -export interface PubSub = PubSubEvents> extends TypedEventTarget { +export interface PubSub = PubSubEvents> extends EventEmitter { /** * The global signature policy controls whether or not we sill send and receive * signed or unsigned messages. diff --git a/packages/interface/src/transport/index.ts b/packages/interface/src/transport/index.ts index 22ab1a803b..5acbfcc50e 100644 --- a/packages/interface/src/transport/index.ts +++ b/packages/interface/src/transport/index.ts @@ -1,5 +1,5 @@ import type { Connection, MultiaddrConnection } from '../connection/index.js' -import type { TypedEventTarget } from '../events.js' +import type { EventEmitter } from '../events.js' import type { AbortOptions } from '../index.js' import type { StreamMuxerFactory } from '../stream-muxer/index.js' import type { Multiaddr } from '@multiformats/multiaddr' @@ -11,7 +11,7 @@ export interface ListenerEvents { 'close': CustomEvent } -export interface Listener extends TypedEventTarget { +export interface Listener extends EventEmitter { /** * Start a listener */ diff --git a/packages/kad-dht/src/dual-kad-dht.ts b/packages/kad-dht/src/dual-kad-dht.ts index ef06f739ea..6d704725fb 100644 --- a/packages/kad-dht/src/dual-kad-dht.ts +++ b/packages/kad-dht/src/dual-kad-dht.ts @@ -1,6 +1,6 @@ import { type ContentRouting, contentRouting } from '@libp2p/interface/content-routing' import { CodeError } from '@libp2p/interface/errors' -import { TypedEventEmitter, CustomEvent } from '@libp2p/interface/events' +import { EventEmitter, CustomEvent } from '@libp2p/interface/events' import { type PeerDiscovery, peerDiscovery, type PeerDiscoveryEvents } from '@libp2p/interface/peer-discovery' import { type PeerRouting, peerRouting } from '@libp2p/interface/peer-routing' import { logger } from '@libp2p/logger' @@ -121,7 +121,7 @@ function multiaddrIsPublic (multiaddr: Multiaddr): boolean { * A DHT implementation modelled after Kademlia with S/Kademlia modifications. * Original implementation in go: https://github.com/libp2p/go-libp2p-kad-dht. */ -export class DefaultDualKadDHT extends TypedEventEmitter implements DualKadDHT, PeerDiscovery { +export class DefaultDualKadDHT extends EventEmitter implements DualKadDHT, PeerDiscovery { public readonly wan: DefaultKadDHT public readonly lan: DefaultKadDHT public readonly components: KadDHTComponents diff --git a/packages/kad-dht/src/index.ts b/packages/kad-dht/src/index.ts index 679a7ba62f..edb1e4f679 100644 --- a/packages/kad-dht/src/index.ts +++ b/packages/kad-dht/src/index.ts @@ -1,7 +1,7 @@ import { DefaultDualKadDHT } from './dual-kad-dht.js' import type { ProvidersInit } from './providers.js' import type { Libp2pEvents, AbortOptions } from '@libp2p/interface' -import type { TypedEventTarget } from '@libp2p/interface/events' +import type { EventEmitter } from '@libp2p/interface/events' import type { Metrics } from '@libp2p/interface/metrics' import type { PeerId } from '@libp2p/interface/peer-id' import type { PeerInfo } from '@libp2p/interface/peer-info' @@ -314,7 +314,7 @@ export interface KadDHTComponents { metrics?: Metrics connectionManager: ConnectionManager datastore: Datastore - events: TypedEventTarget + events: EventEmitter } export function kadDHT (init?: KadDHTInit): (components: KadDHTComponents) => DualKadDHT { diff --git a/packages/kad-dht/src/kad-dht.ts b/packages/kad-dht/src/kad-dht.ts index fb5be07aa9..f9f260452c 100644 --- a/packages/kad-dht/src/kad-dht.ts +++ b/packages/kad-dht/src/kad-dht.ts @@ -1,4 +1,4 @@ -import { CustomEvent, TypedEventEmitter } from '@libp2p/interface/events' +import { CustomEvent, EventEmitter } from '@libp2p/interface/events' import { type Logger, logger } from '@libp2p/logger' import pDefer from 'p-defer' import { PROTOCOL_DHT, PROTOCOL_PREFIX, LAN_PREFIX } from './constants.js' @@ -39,7 +39,7 @@ export interface SingleKadDHTInit extends KadDHTInit { * A DHT implementation modelled after Kademlia with S/Kademlia modifications. * Original implementation in go: https://github.com/libp2p/go-libp2p-kad-dht. */ -export class DefaultKadDHT extends TypedEventEmitter implements KadDHT { +export class DefaultKadDHT extends EventEmitter implements KadDHT { public protocol: string public routingTable: RoutingTable public providers: Providers diff --git a/packages/kad-dht/src/network.ts b/packages/kad-dht/src/network.ts index c968b10f9b..b10ad6e592 100644 --- a/packages/kad-dht/src/network.ts +++ b/packages/kad-dht/src/network.ts @@ -1,5 +1,5 @@ import { CodeError } from '@libp2p/interface/errors' -import { TypedEventEmitter, CustomEvent } from '@libp2p/interface/events' +import { EventEmitter, CustomEvent } from '@libp2p/interface/events' import { logger } from '@libp2p/logger' import { abortableDuplex } from 'abortable-iterator' import drain from 'it-drain' @@ -35,7 +35,7 @@ interface NetworkEvents { /** * Handle network operations for the dht */ -export class Network extends TypedEventEmitter implements Startable { +export class Network extends EventEmitter implements Startable { private readonly log: Logger private readonly protocol: string private running: boolean diff --git a/packages/kad-dht/src/query/manager.ts b/packages/kad-dht/src/query/manager.ts index 675c9a9f81..df830faf2d 100644 --- a/packages/kad-dht/src/query/manager.ts +++ b/packages/kad-dht/src/query/manager.ts @@ -1,6 +1,6 @@ import { setMaxListeners } from 'events' import { AbortError } from '@libp2p/interface/errors' -import { TypedEventEmitter, CustomEvent } from '@libp2p/interface/events' +import { EventEmitter, CustomEvent } from '@libp2p/interface/events' import { logger } from '@libp2p/logger' import { PeerSet } from '@libp2p/peer-collections' import { anySignal } from 'any-signal' @@ -143,7 +143,7 @@ export class QueryManager implements Startable { // query a subset of peers up to `kBucketSize / 2` in length const startTime = Date.now() - const cleanUp = new TypedEventEmitter() + const cleanUp = new EventEmitter() try { if (options.isSelfQuery !== true && this.initialQuerySelfHasRun != null) { diff --git a/packages/kad-dht/src/query/query-path.ts b/packages/kad-dht/src/query/query-path.ts index 382585ae26..991f1abd42 100644 --- a/packages/kad-dht/src/query/query-path.ts +++ b/packages/kad-dht/src/query/query-path.ts @@ -9,7 +9,7 @@ import { queryErrorEvent } from './events.js' import type { CleanUpEvents } from './manager.js' import type { QueryEvent, QueryOptions } from '../index.js' import type { QueryFunc } from '../query/types.js' -import type { TypedEventTarget } from '@libp2p/interface/events' +import type { EventEmitter } from '@libp2p/interface/events' import type { PeerId } from '@libp2p/interface/peer-id' import type { Logger } from '@libp2p/logger' import type { PeerSet } from '@libp2p/peer-collections' @@ -60,7 +60,7 @@ export interface QueryPathOptions extends QueryOptions { /** * will emit a 'cleanup' event if the caller exits the for..await of early */ - cleanUp: TypedEventTarget + cleanUp: EventEmitter /** * A timeout for queryFunc in ms @@ -185,7 +185,7 @@ export async function * queryPath (options: QueryPathOptions): AsyncGenerator, log: Logger): AsyncGenerator { +async function * toGenerator (queue: Queue, signal: AbortSignal, cleanUp: EventEmitter, log: Logger): AsyncGenerator { let deferred = defer() let running = true const results: QueryEvent[] = [] diff --git a/packages/kad-dht/src/routing-table/index.ts b/packages/kad-dht/src/routing-table/index.ts index ee7b24bcf8..b0bfbb90ff 100644 --- a/packages/kad-dht/src/routing-table/index.ts +++ b/packages/kad-dht/src/routing-table/index.ts @@ -1,4 +1,4 @@ -import { TypedEventEmitter } from '@libp2p/interface/events' +import { EventEmitter } from '@libp2p/interface/events' import { logger } from '@libp2p/logger' import { PeerSet } from '@libp2p/peer-collections' import Queue from 'p-queue' @@ -43,7 +43,7 @@ export interface RoutingTableEvents { * A wrapper around `k-bucket`, to provide easy store and * retrieval for peers. */ -export class RoutingTable extends TypedEventEmitter implements Startable { +export class RoutingTable extends EventEmitter implements Startable { public kBucketSize: number public kb?: KBucket public pingQueue: Queue diff --git a/packages/kad-dht/src/routing-table/k-bucket.ts b/packages/kad-dht/src/routing-table/k-bucket.ts index 57585926e9..b8e510d0a2 100644 --- a/packages/kad-dht/src/routing-table/k-bucket.ts +++ b/packages/kad-dht/src/routing-table/k-bucket.ts @@ -27,7 +27,7 @@ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -import { TypedEventEmitter } from '@libp2p/interface/events' +import { EventEmitter } from '@libp2p/interface/events' import type { PeerId } from '@libp2p/interface/peer-id' function arrayEquals (array1: Uint8Array, array2: Uint8Array): boolean { @@ -122,8 +122,10 @@ export interface Bucket { /** * Implementation of a Kademlia DHT k-bucket used for storing * contact (peer node) information. + * + * @extends EventEmitter */ -export class KBucket extends TypedEventEmitter { +export class KBucket extends EventEmitter { public localNodeId: Uint8Array public root: Bucket private readonly numberOfNodesPerKBucket: number diff --git a/packages/kad-dht/src/topology-listener.ts b/packages/kad-dht/src/topology-listener.ts index 8af9a210a4..462b633a3c 100644 --- a/packages/kad-dht/src/topology-listener.ts +++ b/packages/kad-dht/src/topology-listener.ts @@ -1,4 +1,4 @@ -import { CustomEvent, TypedEventEmitter } from '@libp2p/interface/events' +import { CustomEvent, EventEmitter } from '@libp2p/interface/events' import { logger } from '@libp2p/logger' import type { KadDHTComponents } from '.' import type { PeerId } from '@libp2p/interface/peer-id' @@ -17,7 +17,7 @@ export interface TopologyListenerEvents { /** * Receives notifications of new peers joining the network that support the DHT protocol */ -export class TopologyListener extends TypedEventEmitter implements Startable { +export class TopologyListener extends EventEmitter implements Startable { private readonly log: Logger private readonly components: KadDHTComponents private readonly protocol: string diff --git a/packages/kad-dht/test/routing-table.spec.ts b/packages/kad-dht/test/routing-table.spec.ts index 35381a044f..669115c349 100644 --- a/packages/kad-dht/test/routing-table.spec.ts +++ b/packages/kad-dht/test/routing-table.spec.ts @@ -1,6 +1,6 @@ /* eslint-env mocha */ -import { TypedEventEmitter, CustomEvent } from '@libp2p/interface/events' +import { EventEmitter, CustomEvent } from '@libp2p/interface/events' import { mockConnectionManager } from '@libp2p/interface-compliance-tests/mocks' import { PeerSet } from '@libp2p/peer-collections' import { peerIdFromString } from '@libp2p/peer-id' @@ -33,7 +33,7 @@ describe('Routing Table', () => { beforeEach(async function () { this.timeout(20 * 1000) - const events = new TypedEventEmitter() + const events = new EventEmitter() components = { peerId: await createPeerId(), diff --git a/packages/kad-dht/test/rpc/handlers/get-providers.spec.ts b/packages/kad-dht/test/rpc/handlers/get-providers.spec.ts index 18a3706f64..20cab3c7e7 100644 --- a/packages/kad-dht/test/rpc/handlers/get-providers.spec.ts +++ b/packages/kad-dht/test/rpc/handlers/get-providers.spec.ts @@ -1,6 +1,6 @@ /* eslint-env mocha */ -import { TypedEventEmitter } from '@libp2p/interface/events' +import { EventEmitter } from '@libp2p/interface/events' import { PersistentPeerStore } from '@libp2p/peer-store' import { multiaddr } from '@multiformats/multiaddr' import { expect } from 'aegir/chai' @@ -43,7 +43,7 @@ describe('rpc - handlers - GetProviders', () => { peerStore = new PersistentPeerStore({ peerId, datastore: new MemoryDatastore(), - events: new TypedEventEmitter() + events: new EventEmitter() }) const components: GetProvidersHandlerComponents = { diff --git a/packages/kad-dht/test/rpc/handlers/get-value.spec.ts b/packages/kad-dht/test/rpc/handlers/get-value.spec.ts index ad79dda7c6..32cf1c9bba 100644 --- a/packages/kad-dht/test/rpc/handlers/get-value.spec.ts +++ b/packages/kad-dht/test/rpc/handlers/get-value.spec.ts @@ -1,6 +1,6 @@ /* eslint-env mocha */ -import { TypedEventEmitter } from '@libp2p/interface/events' +import { EventEmitter } from '@libp2p/interface/events' import { PersistentPeerStore } from '@libp2p/peer-store' import { expect } from 'aegir/chai' import { MemoryDatastore } from 'datastore-core' @@ -40,7 +40,7 @@ describe('rpc - handlers - GetValue', () => { peerStore = new PersistentPeerStore({ peerId, datastore, - events: new TypedEventEmitter() + events: new EventEmitter() }) const components: GetValueHandlerComponents = { diff --git a/packages/kad-dht/test/rpc/index.node.ts b/packages/kad-dht/test/rpc/index.node.ts index 25ced21d11..da58989b23 100644 --- a/packages/kad-dht/test/rpc/index.node.ts +++ b/packages/kad-dht/test/rpc/index.node.ts @@ -1,6 +1,6 @@ /* eslint-env mocha */ -import { TypedEventEmitter } from '@libp2p/interface/events' +import { EventEmitter } from '@libp2p/interface/events' import { start } from '@libp2p/interface/startable' import { mockStream } from '@libp2p/interface-compliance-tests/mocks' import { PersistentPeerStore } from '@libp2p/peer-store' @@ -51,7 +51,7 @@ describe('rpc', () => { } components.peerStore = new PersistentPeerStore({ ...components, - events: new TypedEventEmitter() + events: new EventEmitter() }) await start(...Object.values(components)) diff --git a/packages/kad-dht/test/utils/test-dht.ts b/packages/kad-dht/test/utils/test-dht.ts index bfddebdaad..04be4041be 100644 --- a/packages/kad-dht/test/utils/test-dht.ts +++ b/packages/kad-dht/test/utils/test-dht.ts @@ -1,4 +1,4 @@ -import { TypedEventEmitter } from '@libp2p/interface/events' +import { EventEmitter } from '@libp2p/interface/events' import { start, stop } from '@libp2p/interface/startable' import { mockRegistrar, mockConnectionManager, mockNetwork } from '@libp2p/interface-compliance-tests/mocks' import { logger } from '@libp2p/logger' @@ -29,7 +29,7 @@ export class TestDHT { } async spawn (options: Partial = {}, autoStart = true): Promise { - const events = new TypedEventEmitter() + const events = new EventEmitter() const components: KadDHTComponents = { peerId: await createPeerId(), datastore: new MemoryDatastore(), diff --git a/packages/libp2p/src/address-manager/index.ts b/packages/libp2p/src/address-manager/index.ts index f6bafad41f..44a8504f51 100644 --- a/packages/libp2p/src/address-manager/index.ts +++ b/packages/libp2p/src/address-manager/index.ts @@ -3,7 +3,7 @@ import { peerIdFromString } from '@libp2p/peer-id' import { multiaddr } from '@multiformats/multiaddr' import { debounce } from './utils.js' import type { Libp2pEvents } from '@libp2p/interface' -import type { TypedEventTarget } from '@libp2p/interface/events' +import type { EventEmitter } from '@libp2p/interface/events' import type { PeerId } from '@libp2p/interface/peer-id' import type { PeerStore } from '@libp2p/interface/peer-store' import type { TransportManager } from '@libp2p/interface-internal/transport-manager' @@ -38,7 +38,7 @@ export interface DefaultAddressManagerComponents { peerId: PeerId transportManager: TransportManager peerStore: PeerStore - events: TypedEventTarget + events: EventEmitter } /** diff --git a/packages/libp2p/src/circuit-relay/index.ts b/packages/libp2p/src/circuit-relay/index.ts index 5e8757fb10..91ab9007e4 100644 --- a/packages/libp2p/src/circuit-relay/index.ts +++ b/packages/libp2p/src/circuit-relay/index.ts @@ -35,7 +35,7 @@ */ import type { Limit } from './pb/index.js' -import type { TypedEventEmitter } from '@libp2p/interface/events' +import type { EventEmitter } from '@libp2p/interface/events' import type { PeerMap } from '@libp2p/peer-collections' import type { Multiaddr } from '@multiformats/multiaddr' @@ -51,7 +51,7 @@ export interface CircuitRelayServiceEvents { 'relay:advert:error': CustomEvent } -export interface CircuitRelayService extends TypedEventEmitter { +export interface CircuitRelayService extends EventEmitter { reservations: PeerMap } diff --git a/packages/libp2p/src/circuit-relay/server/advert-service.ts b/packages/libp2p/src/circuit-relay/server/advert-service.ts index 4e84f41c2c..5d2c61990f 100644 --- a/packages/libp2p/src/circuit-relay/server/advert-service.ts +++ b/packages/libp2p/src/circuit-relay/server/advert-service.ts @@ -1,4 +1,4 @@ -import { TypedEventEmitter } from '@libp2p/interface/events' +import { EventEmitter } from '@libp2p/interface/events' import { logger } from '@libp2p/logger' import pRetry from 'p-retry' import { codes } from '../../errors.js' @@ -31,7 +31,7 @@ export interface AdvertServiceEvents { 'advert:error': CustomEvent } -export class AdvertService extends TypedEventEmitter implements Startable { +export class AdvertService extends EventEmitter implements Startable { private readonly contentRouting: ContentRouting private timeout?: any private started: boolean diff --git a/packages/libp2p/src/circuit-relay/server/index.ts b/packages/libp2p/src/circuit-relay/server/index.ts index 8fce918570..aed3d5be8b 100644 --- a/packages/libp2p/src/circuit-relay/server/index.ts +++ b/packages/libp2p/src/circuit-relay/server/index.ts @@ -1,5 +1,5 @@ import { setMaxListeners } from 'events' -import { TypedEventEmitter } from '@libp2p/interface/events' +import { EventEmitter } from '@libp2p/interface/events' import { logger } from '@libp2p/logger' import { peerIdFromBytes } from '@libp2p/peer-id' import { RecordEnvelope } from '@libp2p/peer-record' @@ -99,7 +99,7 @@ const defaults = { maxOutboundStopStreams: MAX_CONNECTIONS } -class CircuitRelayServer extends TypedEventEmitter implements Startable, CircuitRelayService { +class CircuitRelayServer extends EventEmitter implements Startable, CircuitRelayService { private readonly registrar: Registrar private readonly peerStore: PeerStore private readonly addressManager: AddressManager diff --git a/packages/libp2p/src/circuit-relay/transport/discovery.ts b/packages/libp2p/src/circuit-relay/transport/discovery.ts index 77a4af1208..58ddc80cd9 100644 --- a/packages/libp2p/src/circuit-relay/transport/discovery.ts +++ b/packages/libp2p/src/circuit-relay/transport/discovery.ts @@ -1,4 +1,4 @@ -import { TypedEventEmitter } from '@libp2p/interface/events' +import { EventEmitter } from '@libp2p/interface/events' import { logger } from '@libp2p/logger' import { RELAY_RENDEZVOUS_NS, @@ -32,7 +32,7 @@ export interface RelayDiscoveryComponents { * ReservationManager automatically makes a circuit v2 reservation on any connected * peers that support the circuit v2 HOP protocol. */ -export class RelayDiscovery extends TypedEventEmitter implements Startable { +export class RelayDiscovery extends EventEmitter implements Startable { private readonly peerId: PeerId private readonly peerStore: PeerStore private readonly contentRouting: ContentRouting diff --git a/packages/libp2p/src/circuit-relay/transport/index.ts b/packages/libp2p/src/circuit-relay/transport/index.ts index 022b44c57e..483f9a0366 100644 --- a/packages/libp2p/src/circuit-relay/transport/index.ts +++ b/packages/libp2p/src/circuit-relay/transport/index.ts @@ -17,7 +17,7 @@ import type { Libp2pEvents, AbortOptions } from '@libp2p/interface' import type { Connection, Stream } from '@libp2p/interface/connection' import type { ConnectionGater } from '@libp2p/interface/connection-gater' import type { ContentRouting } from '@libp2p/interface/content-routing' -import type { TypedEventTarget } from '@libp2p/interface/events' +import type { EventEmitter } from '@libp2p/interface/events' import type { PeerId } from '@libp2p/interface/peer-id' import type { PeerStore } from '@libp2p/interface/peer-store' import type { AddressManager } from '@libp2p/interface-internal/address-manager' @@ -50,7 +50,7 @@ export interface CircuitRelayTransportComponents extends RelayDiscoveryComponent addressManager: AddressManager contentRouting: ContentRouting connectionGater: ConnectionGater - events: TypedEventTarget + events: EventEmitter } interface ConnectOptions { diff --git a/packages/libp2p/src/circuit-relay/transport/listener.ts b/packages/libp2p/src/circuit-relay/transport/listener.ts index 29b6c6e608..bb67007db9 100644 --- a/packages/libp2p/src/circuit-relay/transport/listener.ts +++ b/packages/libp2p/src/circuit-relay/transport/listener.ts @@ -1,5 +1,5 @@ import { CodeError } from '@libp2p/interface/errors' -import { TypedEventEmitter } from '@libp2p/interface/events' +import { EventEmitter } from '@libp2p/interface/events' import { logger } from '@libp2p/logger' import { PeerMap } from '@libp2p/peer-collections' import { peerIdFromString } from '@libp2p/peer-id' @@ -18,7 +18,7 @@ export interface CircuitRelayTransportListenerComponents { relayStore: ReservationStore } -class CircuitRelayTransportListener extends TypedEventEmitter implements Listener { +class CircuitRelayTransportListener extends EventEmitter implements Listener { private readonly connectionManager: ConnectionManager private readonly relayStore: ReservationStore private readonly listeningAddrs: PeerMap diff --git a/packages/libp2p/src/circuit-relay/transport/reservation-store.ts b/packages/libp2p/src/circuit-relay/transport/reservation-store.ts index 9300357240..2edcd4f998 100644 --- a/packages/libp2p/src/circuit-relay/transport/reservation-store.ts +++ b/packages/libp2p/src/circuit-relay/transport/reservation-store.ts @@ -1,4 +1,4 @@ -import { TypedEventEmitter, type TypedEventTarget } from '@libp2p/interface/events' +import { EventEmitter } from '@libp2p/interface/events' import { logger } from '@libp2p/logger' import { PeerMap } from '@libp2p/peer-collections' import { multiaddr } from '@multiformats/multiaddr' @@ -32,7 +32,7 @@ export interface RelayStoreComponents { connectionManager: ConnectionManager transportManager: TransportManager peerStore: PeerStore - events: TypedEventTarget + events: EventEmitter } export interface RelayStoreInit { @@ -76,12 +76,12 @@ export interface ReservationStoreEvents { 'relay:removed': CustomEvent } -export class ReservationStore extends TypedEventEmitter implements Startable { +export class ReservationStore extends EventEmitter implements Startable { private readonly peerId: PeerId private readonly connectionManager: ConnectionManager private readonly transportManager: TransportManager private readonly peerStore: PeerStore - private readonly events: TypedEventTarget + private readonly events: EventEmitter private readonly reserveQueue: PeerJobQueue private readonly reservations: PeerMap private readonly maxDiscoveredRelays: number diff --git a/packages/libp2p/src/components.ts b/packages/libp2p/src/components.ts index 2d65d956dc..f11fb2cfb6 100644 --- a/packages/libp2p/src/components.ts +++ b/packages/libp2p/src/components.ts @@ -4,7 +4,7 @@ import type { Libp2pEvents } from '@libp2p/interface' import type { ConnectionProtector } from '@libp2p/interface/connection' import type { ConnectionGater } from '@libp2p/interface/connection-gater' import type { ContentRouting } from '@libp2p/interface/content-routing' -import type { TypedEventTarget } from '@libp2p/interface/events' +import type { EventEmitter } from '@libp2p/interface/events' import type { Metrics } from '@libp2p/interface/metrics' import type { PeerId } from '@libp2p/interface/peer-id' import type { PeerRouting } from '@libp2p/interface/peer-routing' @@ -18,7 +18,7 @@ import type { Datastore } from 'interface-datastore' export interface Components extends Record, Startable { peerId: PeerId - events: TypedEventTarget + events: EventEmitter addressManager: AddressManager peerStore: PeerStore upgrader: Upgrader @@ -35,7 +35,7 @@ export interface Components extends Record, Startable { export interface ComponentsInit { peerId?: PeerId - events?: TypedEventTarget + events?: EventEmitter addressManager?: AddressManager peerStore?: PeerStore upgrader?: Upgrader diff --git a/packages/libp2p/src/connection-manager/auto-dial.ts b/packages/libp2p/src/connection-manager/auto-dial.ts index a110adfd46..6d27e6f42b 100644 --- a/packages/libp2p/src/connection-manager/auto-dial.ts +++ b/packages/libp2p/src/connection-manager/auto-dial.ts @@ -4,7 +4,7 @@ import { toString as uint8ArrayToString } from 'uint8arrays/to-string' import { PeerJobQueue } from '../utils/peer-job-queue.js' import { AUTO_DIAL_CONCURRENCY, AUTO_DIAL_DISCOVERED_PEERS_DEBOUNCE, AUTO_DIAL_INTERVAL, AUTO_DIAL_MAX_QUEUE_LENGTH, AUTO_DIAL_PEER_RETRY_THRESHOLD, AUTO_DIAL_PRIORITY, LAST_DIAL_FAILURE_KEY, MIN_CONNECTIONS } from './constants.js' import type { Libp2pEvents } from '@libp2p/interface' -import type { TypedEventTarget } from '@libp2p/interface/events' +import type { EventEmitter } from '@libp2p/interface/events' import type { PeerStore } from '@libp2p/interface/peer-store' import type { Startable } from '@libp2p/interface/startable' import type { ConnectionManager } from '@libp2p/interface-internal/connection-manager' @@ -24,7 +24,7 @@ interface AutoDialInit { interface AutoDialComponents { connectionManager: ConnectionManager peerStore: PeerStore - events: TypedEventTarget + events: EventEmitter } const defaultOptions = { diff --git a/packages/libp2p/src/connection-manager/connection-pruner.ts b/packages/libp2p/src/connection-manager/connection-pruner.ts index adbed0a56c..04fb85d7fb 100644 --- a/packages/libp2p/src/connection-manager/connection-pruner.ts +++ b/packages/libp2p/src/connection-manager/connection-pruner.ts @@ -2,7 +2,7 @@ import { logger } from '@libp2p/logger' import { PeerMap } from '@libp2p/peer-collections' import { MAX_CONNECTIONS } from './constants.js' import type { Libp2pEvents } from '@libp2p/interface' -import type { TypedEventTarget } from '@libp2p/interface/events' +import type { EventEmitter } from '@libp2p/interface/events' import type { PeerStore } from '@libp2p/interface/peer-store' import type { ConnectionManager } from '@libp2p/interface-internal/connection-manager' import type { Multiaddr } from '@multiformats/multiaddr' @@ -17,7 +17,7 @@ interface ConnectionPrunerInit { interface ConnectionPrunerComponents { connectionManager: ConnectionManager peerStore: PeerStore - events: TypedEventTarget + events: EventEmitter } const defaultOptions = { @@ -33,7 +33,7 @@ export class ConnectionPruner { private readonly connectionManager: ConnectionManager private readonly peerStore: PeerStore private readonly allow: Multiaddr[] - private readonly events: TypedEventTarget + private readonly events: EventEmitter constructor (components: ConnectionPrunerComponents, init: ConnectionPrunerInit = {}) { this.maxConnections = init.maxConnections ?? defaultOptions.maxConnections diff --git a/packages/libp2p/src/connection-manager/index.ts b/packages/libp2p/src/connection-manager/index.ts index c13e49a53a..d94612fd9f 100644 --- a/packages/libp2p/src/connection-manager/index.ts +++ b/packages/libp2p/src/connection-manager/index.ts @@ -15,7 +15,7 @@ import { DialQueue } from './dial-queue.js' import type { PendingDial, AddressSorter, Libp2pEvents, AbortOptions } from '@libp2p/interface' import type { Connection, MultiaddrConnection } from '@libp2p/interface/connection' import type { ConnectionGater } from '@libp2p/interface/connection-gater' -import type { TypedEventTarget } from '@libp2p/interface/events' +import type { EventEmitter } from '@libp2p/interface/events' import type { Metrics } from '@libp2p/interface/metrics' import type { PeerId } from '@libp2p/interface/peer-id' import type { Peer, PeerStore } from '@libp2p/interface/peer-store' @@ -165,7 +165,7 @@ export interface DefaultConnectionManagerComponents { peerStore: PeerStore transportManager: TransportManager connectionGater: ConnectionGater - events: TypedEventTarget + events: EventEmitter } /** @@ -187,7 +187,7 @@ export class DefaultConnectionManager implements ConnectionManager, Startable { private readonly peerStore: PeerStore private readonly metrics?: Metrics - private readonly events: TypedEventTarget + private readonly events: EventEmitter constructor (components: DefaultConnectionManagerComponents, init: ConnectionManagerInit = {}) { this.maxConnections = init.maxConnections ?? defaultOptions.maxConnections diff --git a/packages/libp2p/src/identify/identify.ts b/packages/libp2p/src/identify/identify.ts index 940533ef50..caa5248b45 100644 --- a/packages/libp2p/src/identify/identify.ts +++ b/packages/libp2p/src/identify/identify.ts @@ -21,7 +21,7 @@ import { Identify } from './pb/message.js' import type { IdentifyService, IdentifyServiceComponents, IdentifyServiceInit } from './index.js' import type { Libp2pEvents, IdentifyResult, SignedPeerRecord, AbortOptions } from '@libp2p/interface' import type { Connection, Stream } from '@libp2p/interface/connection' -import type { TypedEventTarget } from '@libp2p/interface/events' +import type { EventEmitter } from '@libp2p/interface/events' import type { PeerId } from '@libp2p/interface/peer-id' import type { Peer, PeerStore } from '@libp2p/interface/peer-store' import type { Startable } from '@libp2p/interface/startable' @@ -70,7 +70,7 @@ export class DefaultIdentifyService implements Startable, IdentifyService { private readonly maxPushOutgoingStreams: number private readonly maxIdentifyMessageSize: number private readonly maxObservedAddresses: number - private readonly events: TypedEventTarget + private readonly events: EventEmitter private readonly runOnTransientConnection: boolean constructor (components: IdentifyServiceComponents, init: IdentifyServiceInit) { diff --git a/packages/libp2p/src/identify/index.ts b/packages/libp2p/src/identify/index.ts index 61dc2e3523..c74238e832 100644 --- a/packages/libp2p/src/identify/index.ts +++ b/packages/libp2p/src/identify/index.ts @@ -5,7 +5,7 @@ import { import { DefaultIdentifyService } from './identify.js' import { Identify } from './pb/message.js' import type { AbortOptions, IdentifyResult, Libp2pEvents } from '@libp2p/interface' -import type { TypedEventTarget } from '@libp2p/interface/events' +import type { EventEmitter } from '@libp2p/interface/events' import type { PeerId } from '@libp2p/interface/peer-id' import type { PeerStore } from '@libp2p/interface/peer-store' import type { Connection } from '@libp2p/interface/src/connection/index.js' @@ -58,7 +58,7 @@ export interface IdentifyServiceComponents { connectionManager: ConnectionManager registrar: Registrar addressManager: AddressManager - events: TypedEventTarget + events: EventEmitter } /** diff --git a/packages/libp2p/src/libp2p.ts b/packages/libp2p/src/libp2p.ts index cdc0c5caa8..29c80f0cc7 100644 --- a/packages/libp2p/src/libp2p.ts +++ b/packages/libp2p/src/libp2p.ts @@ -2,7 +2,7 @@ import { setMaxListeners } from 'events' import { unmarshalPublicKey } from '@libp2p/crypto/keys' import { type ContentRouting, contentRouting } from '@libp2p/interface/content-routing' import { CodeError } from '@libp2p/interface/errors' -import { TypedEventEmitter, CustomEvent } from '@libp2p/interface/events' +import { EventEmitter, CustomEvent } from '@libp2p/interface/events' import { peerDiscovery } from '@libp2p/interface/peer-discovery' import { type PeerRouting, peerRouting } from '@libp2p/interface/peer-routing' import { DefaultKeyChain } from '@libp2p/keychain' @@ -42,7 +42,7 @@ import type { Datastore } from 'interface-datastore' const log = logger('libp2p') -export class Libp2pNode> extends TypedEventEmitter implements Libp2p { +export class Libp2pNode> extends EventEmitter implements Libp2p { public peerId: PeerId public peerStore: PeerStore public contentRouting: ContentRouting @@ -59,7 +59,7 @@ export class Libp2pNode> extends // event bus - components can listen to this emitter to be notified of system events // and also cause them to be emitted - const events = new TypedEventEmitter() + const events = new EventEmitter() const originalDispatch = events.dispatchEvent.bind(events) events.dispatchEvent = (evt: any) => { const internalResult = originalDispatch(evt) diff --git a/packages/libp2p/src/registrar.ts b/packages/libp2p/src/registrar.ts index 268a35c364..c679888f4f 100644 --- a/packages/libp2p/src/registrar.ts +++ b/packages/libp2p/src/registrar.ts @@ -3,7 +3,7 @@ import { logger } from '@libp2p/logger' import merge from 'merge-options' import { codes } from './errors.js' import type { Libp2pEvents, PeerUpdate } from '@libp2p/interface' -import type { TypedEventTarget } from '@libp2p/interface/events' +import type { EventEmitter } from '@libp2p/interface/events' import type { PeerId } from '@libp2p/interface/peer-id' import type { PeerStore } from '@libp2p/interface/peer-store' import type { Topology } from '@libp2p/interface/topology' @@ -19,7 +19,7 @@ export interface RegistrarComponents { peerId: PeerId connectionManager: ConnectionManager peerStore: PeerStore - events: TypedEventTarget + events: EventEmitter } /** diff --git a/packages/libp2p/src/transport-manager.ts b/packages/libp2p/src/transport-manager.ts index f18ecdcecc..38f5359616 100644 --- a/packages/libp2p/src/transport-manager.ts +++ b/packages/libp2p/src/transport-manager.ts @@ -5,7 +5,7 @@ import { logger } from '@libp2p/logger' import { codes } from './errors.js' import type { Libp2pEvents, AbortOptions } from '@libp2p/interface' import type { Connection } from '@libp2p/interface/connection' -import type { TypedEventTarget } from '@libp2p/interface/events' +import type { EventEmitter } from '@libp2p/interface/events' import type { Metrics } from '@libp2p/interface/metrics' import type { Startable } from '@libp2p/interface/startable' import type { Listener, Transport, Upgrader } from '@libp2p/interface/transport' @@ -23,7 +23,7 @@ export interface DefaultTransportManagerComponents { metrics?: Metrics addressManager: AddressManager upgrader: Upgrader - events: TypedEventTarget + events: EventEmitter } export class DefaultTransportManager implements TransportManager, Startable { diff --git a/packages/libp2p/src/upgrader.ts b/packages/libp2p/src/upgrader.ts index ad27ba02db..18934e3ad0 100644 --- a/packages/libp2p/src/upgrader.ts +++ b/packages/libp2p/src/upgrader.ts @@ -11,7 +11,7 @@ import type { Libp2pEvents, AbortOptions } from '@libp2p/interface' import type { MultiaddrConnection, Connection, Stream, ConnectionProtector, NewStreamOptions } from '@libp2p/interface/connection' import type { ConnectionEncrypter, SecuredConnection } from '@libp2p/interface/connection-encrypter' import type { ConnectionGater } from '@libp2p/interface/connection-gater' -import type { TypedEventTarget } from '@libp2p/interface/events' +import type { EventEmitter } from '@libp2p/interface/events' import type { Metrics } from '@libp2p/interface/metrics' import type { PeerId } from '@libp2p/interface/peer-id' import type { PeerStore } from '@libp2p/interface/peer-store' @@ -104,7 +104,7 @@ export interface DefaultUpgraderComponents { connectionProtector?: ConnectionProtector registrar: Registrar peerStore: PeerStore - events: TypedEventTarget + events: EventEmitter } type EncryptedConn = Duplex, Source, Promise> @@ -116,7 +116,7 @@ export class DefaultUpgrader implements Upgrader { private readonly connectionEncryption: Map private readonly muxers: Map private readonly inboundUpgradeTimeout: number - private readonly events: TypedEventTarget + private readonly events: EventEmitter constructor (components: DefaultUpgraderComponents, init: UpgraderInit) { this.components = components diff --git a/packages/libp2p/test/addresses/address-manager.spec.ts b/packages/libp2p/test/addresses/address-manager.spec.ts index 5bee38bb70..7f67fa9b07 100644 --- a/packages/libp2p/test/addresses/address-manager.spec.ts +++ b/packages/libp2p/test/addresses/address-manager.spec.ts @@ -1,6 +1,6 @@ /* eslint-env mocha */ -import { TypedEventEmitter, type TypedEventTarget } from '@libp2p/interface/events' +import { EventEmitter } from '@libp2p/interface/events' import { createEd25519PeerId } from '@libp2p/peer-id-factory' import { multiaddr } from '@multiformats/multiaddr' import { expect } from 'aegir/chai' @@ -18,7 +18,7 @@ const announceAddreses = ['/dns4/peer.io'] describe('Address Manager', () => { let peerId: PeerId let peerStore: StubbedInstance - let events: TypedEventTarget + let events: EventEmitter beforeEach(async () => { peerId = await createEd25519PeerId() @@ -26,7 +26,7 @@ describe('Address Manager', () => { // @ts-expect-error incorrect return type patch: Promise.resolve({}) }) - events = new TypedEventEmitter() + events = new EventEmitter() }) it('should not need any addresses', () => { diff --git a/packages/libp2p/test/circuit-relay/hop.spec.ts b/packages/libp2p/test/circuit-relay/hop.spec.ts index b1beb7abb9..7c3405197c 100644 --- a/packages/libp2p/test/circuit-relay/hop.spec.ts +++ b/packages/libp2p/test/circuit-relay/hop.spec.ts @@ -1,7 +1,7 @@ /* eslint-env mocha */ /* eslint max-nested-callbacks: ['error', 5] */ -import { TypedEventEmitter, type TypedEventTarget } from '@libp2p/interface/events' +import { EventEmitter } from '@libp2p/interface/events' import { isStartable } from '@libp2p/interface/startable' import { mockRegistrar, mockUpgrader, mockNetwork, mockConnectionManager, mockConnectionGater } from '@libp2p/interface-compliance-tests/mocks' import { PeerMap } from '@libp2p/peer-collections' @@ -38,7 +38,7 @@ interface Node { connectionManager: ConnectionManager circuitRelayTransport: Transport connectionGater: ConnectionGater - events: TypedEventTarget + events: EventEmitter } let peerIndex = 0 @@ -66,7 +66,7 @@ describe('circuit-relay hop protocol', function () { ]) const peerStore = stubInterface() - const events = new TypedEventEmitter() + const events = new EventEmitter() events.addEventListener('connection:open', (evt) => { const conn = evt.detail connections.set(conn.remotePeer, conn) diff --git a/packages/libp2p/test/circuit-relay/stop.spec.ts b/packages/libp2p/test/circuit-relay/stop.spec.ts index f17642b951..872f01d104 100644 --- a/packages/libp2p/test/circuit-relay/stop.spec.ts +++ b/packages/libp2p/test/circuit-relay/stop.spec.ts @@ -1,6 +1,6 @@ /* eslint-env mocha */ -import { TypedEventEmitter } from '@libp2p/interface/events' +import { EventEmitter } from '@libp2p/interface/events' import { isStartable } from '@libp2p/interface/startable' import { mockStream } from '@libp2p/interface-compliance-tests/mocks' import { createEd25519PeerId } from '@libp2p/peer-id-factory' @@ -43,7 +43,7 @@ describe('circuit-relay stop protocol', function () { transportManager: stubInterface(), upgrader: stubInterface(), connectionGater: stubInterface(), - events: new TypedEventEmitter() + events: new EventEmitter() } transport = circuitRelayTransport({ diff --git a/packages/libp2p/test/connection-manager/auto-dial.spec.ts b/packages/libp2p/test/connection-manager/auto-dial.spec.ts index 13634b49e1..3c5968bdf1 100644 --- a/packages/libp2p/test/connection-manager/auto-dial.spec.ts +++ b/packages/libp2p/test/connection-manager/auto-dial.spec.ts @@ -1,6 +1,6 @@ /* eslint-env mocha */ -import { TypedEventEmitter, type TypedEventTarget } from '@libp2p/interface/events' +import { EventEmitter } from '@libp2p/interface/events' import { PeerMap } from '@libp2p/peer-collections' import { createEd25519PeerId } from '@libp2p/peer-id-factory' import { PersistentPeerStore } from '@libp2p/peer-store' @@ -23,13 +23,13 @@ import type { ConnectionManager } from '@libp2p/interface-internal/connection-ma describe('auto-dial', () => { let autoDialler: AutoDial - let events: TypedEventTarget + let events: EventEmitter let peerStore: PeerStore let peerId: PeerId beforeEach(async () => { peerId = await createEd25519PeerId() - events = new TypedEventEmitter() + events = new EventEmitter() peerStore = new PersistentPeerStore({ datastore: new MemoryDatastore(), events, diff --git a/packages/libp2p/test/connection-manager/direct.node.ts b/packages/libp2p/test/connection-manager/direct.node.ts index ae5ff3aed3..6da375ad6b 100644 --- a/packages/libp2p/test/connection-manager/direct.node.ts +++ b/packages/libp2p/test/connection-manager/direct.node.ts @@ -6,7 +6,7 @@ import path from 'node:path' import { yamux } from '@chainsafe/libp2p-yamux' import { type Connection, type ConnectionProtector, isConnection } from '@libp2p/interface/connection' import { AbortError } from '@libp2p/interface/errors' -import { TypedEventEmitter } from '@libp2p/interface/events' +import { EventEmitter } from '@libp2p/interface/events' import { start, stop } from '@libp2p/interface/startable' import { mockConnection, mockConnectionGater, mockDuplex, mockMultiaddrConnection, mockUpgrader } from '@libp2p/interface-compliance-tests/mocks' import { mplex } from '@libp2p/mplex' @@ -58,7 +58,7 @@ describe('dialing (direct, TCP)', () => { createEd25519PeerId() ]) - const remoteEvents = new TypedEventEmitter() + const remoteEvents = new EventEmitter() remoteComponents = defaultComponents({ peerId: remotePeerId, events: remoteEvents, @@ -78,7 +78,7 @@ describe('dialing (direct, TCP)', () => { remoteTM = remoteComponents.transportManager = new DefaultTransportManager(remoteComponents) remoteTM.add(tcp()()) - const localEvents = new TypedEventEmitter() + const localEvents = new EventEmitter() localComponents = defaultComponents({ peerId: localPeerId, events: localEvents, diff --git a/packages/libp2p/test/connection-manager/direct.spec.ts b/packages/libp2p/test/connection-manager/direct.spec.ts index 305ae4e524..780c45f605 100644 --- a/packages/libp2p/test/connection-manager/direct.spec.ts +++ b/packages/libp2p/test/connection-manager/direct.spec.ts @@ -2,7 +2,7 @@ import { yamux } from '@chainsafe/libp2p-yamux' import { AbortError } from '@libp2p/interface/errors' -import { TypedEventEmitter } from '@libp2p/interface/events' +import { EventEmitter } from '@libp2p/interface/events' import { mockConnectionGater, mockDuplex, mockMultiaddrConnection, mockUpgrader, mockConnection } from '@libp2p/interface-compliance-tests/mocks' import { mplex } from '@libp2p/mplex' import { peerIdFromString } from '@libp2p/peer-id' @@ -45,7 +45,7 @@ describe('dialing (direct, WebSockets)', () => { let connectionManager: DefaultConnectionManager beforeEach(async () => { - const localEvents = new TypedEventEmitter() + const localEvents = new EventEmitter() localComponents = defaultComponents({ peerId: await createEd25519PeerId(), datastore: new MemoryDatastore(), diff --git a/packages/libp2p/test/connection-manager/index.node.ts b/packages/libp2p/test/connection-manager/index.node.ts index cac8b990d3..add7158a47 100644 --- a/packages/libp2p/test/connection-manager/index.node.ts +++ b/packages/libp2p/test/connection-manager/index.node.ts @@ -1,6 +1,6 @@ /* eslint-env mocha */ -import { TypedEventEmitter } from '@libp2p/interface/events' +import { EventEmitter } from '@libp2p/interface/events' import { start } from '@libp2p/interface/startable' import { mockConnection, mockDuplex, mockMultiaddrConnection } from '@libp2p/interface-compliance-tests/mocks' import { expect } from 'aegir/chai' @@ -53,7 +53,7 @@ describe('Connection Manager', () => { peerStore, transportManager: stubInterface(), connectionGater: stubInterface(), - events: new TypedEventEmitter() + events: new EventEmitter() }) const connectionManager = new DefaultConnectionManager(components, { maxConnections: 1000, @@ -91,7 +91,7 @@ describe('Connection Manager', () => { peerStore, transportManager: stubInterface(), connectionGater: stubInterface(), - events: new TypedEventEmitter() + events: new EventEmitter() }) const connectionManager = new DefaultConnectionManager(components, { maxConnections: 1000, diff --git a/packages/libp2p/test/connection-manager/index.spec.ts b/packages/libp2p/test/connection-manager/index.spec.ts index ee31843332..699339da03 100644 --- a/packages/libp2p/test/connection-manager/index.spec.ts +++ b/packages/libp2p/test/connection-manager/index.spec.ts @@ -1,6 +1,6 @@ /* eslint-env mocha */ -import { TypedEventEmitter } from '@libp2p/interface/events' +import { EventEmitter } from '@libp2p/interface/events' import { KEEP_ALIVE } from '@libp2p/interface/peer-store/tags' import { mockConnection, mockDuplex, mockMultiaddrConnection, mockMetrics } from '@libp2p/interface-compliance-tests/mocks' import { createEd25519PeerId } from '@libp2p/peer-id-factory' @@ -365,7 +365,7 @@ describe('Connection Manager', () => { peerStore: stubInterface(), transportManager: stubInterface(), connectionGater: stubInterface(), - events: new TypedEventEmitter() + events: new EventEmitter() }, { ...defaultOptions, deny: [ @@ -393,7 +393,7 @@ describe('Connection Manager', () => { peerStore: stubInterface(), transportManager: stubInterface(), connectionGater: stubInterface(), - events: new TypedEventEmitter() + events: new EventEmitter() }, { ...defaultOptions, maxConnections: 1 @@ -425,7 +425,7 @@ describe('Connection Manager', () => { peerStore: stubInterface(), transportManager: stubInterface(), connectionGater: stubInterface(), - events: new TypedEventEmitter() + events: new EventEmitter() }, { ...defaultOptions, inboundConnectionThreshold: 1 @@ -461,7 +461,7 @@ describe('Connection Manager', () => { peerStore: stubInterface(), transportManager: stubInterface(), connectionGater: stubInterface(), - events: new TypedEventEmitter() + events: new EventEmitter() }, { ...defaultOptions, maxConnections: 1, @@ -497,7 +497,7 @@ describe('Connection Manager', () => { peerStore: stubInterface(), transportManager: stubInterface(), connectionGater: stubInterface(), - events: new TypedEventEmitter() + events: new EventEmitter() }, { ...defaultOptions, maxIncomingPendingConnections: 1 diff --git a/packages/libp2p/test/fetch/index.spec.ts b/packages/libp2p/test/fetch/index.spec.ts index 7b90a0f7db..9ef87c88e5 100644 --- a/packages/libp2p/test/fetch/index.spec.ts +++ b/packages/libp2p/test/fetch/index.spec.ts @@ -1,6 +1,6 @@ /* eslint-env mocha */ -import { TypedEventEmitter } from '@libp2p/interface/events' +import { EventEmitter } from '@libp2p/interface/events' import { start, stop } from '@libp2p/interface/startable' import { mockRegistrar, mockUpgrader, connectionPair } from '@libp2p/interface-compliance-tests/mocks' import { createEd25519PeerId } from '@libp2p/peer-id-factory' @@ -27,7 +27,7 @@ const defaultInit: FetchServiceInit = { async function createComponents (index: number): Promise { const peerId = await createEd25519PeerId() - const events = new TypedEventEmitter() + const events = new EventEmitter() const components = defaultComponents({ peerId, registrar: mockRegistrar(), diff --git a/packages/libp2p/test/identify/index.spec.ts b/packages/libp2p/test/identify/index.spec.ts index 63134a7d0c..ed7d54ff09 100644 --- a/packages/libp2p/test/identify/index.spec.ts +++ b/packages/libp2p/test/identify/index.spec.ts @@ -1,7 +1,7 @@ /* eslint-env mocha */ /* eslint max-nested-callbacks: ["error", 6] */ -import { TypedEventEmitter } from '@libp2p/interface/events' +import { EventEmitter } from '@libp2p/interface/events' import { start, stop } from '@libp2p/interface/startable' import { mockConnectionGater, mockRegistrar, mockUpgrader, connectionPair } from '@libp2p/interface-compliance-tests/mocks' import { createEd25519PeerId } from '@libp2p/peer-id-factory' @@ -51,7 +51,7 @@ const protocols = [MULTICODEC_IDENTIFY, MULTICODEC_IDENTIFY_PUSH] async function createComponents (index: number): Promise { const peerId = await createEd25519PeerId() - const events = new TypedEventEmitter() + const events = new EventEmitter() const components = defaultComponents({ peerId, datastore: new MemoryDatastore(), diff --git a/packages/libp2p/test/identify/push.spec.ts b/packages/libp2p/test/identify/push.spec.ts index a73bdc3655..2916a8e1c4 100644 --- a/packages/libp2p/test/identify/push.spec.ts +++ b/packages/libp2p/test/identify/push.spec.ts @@ -1,6 +1,6 @@ /* eslint-env mocha */ -import { TypedEventEmitter } from '@libp2p/interface/events' +import { EventEmitter } from '@libp2p/interface/events' import { start, stop } from '@libp2p/interface/startable' import { mockConnectionGater, mockRegistrar, mockUpgrader, connectionPair } from '@libp2p/interface-compliance-tests/mocks' import { createEd25519PeerId } from '@libp2p/peer-id-factory' @@ -42,7 +42,7 @@ const protocols = [MULTICODEC_IDENTIFY, MULTICODEC_IDENTIFY_PUSH] async function createComponents (index: number): Promise { const peerId = await createEd25519PeerId() - const events = new TypedEventEmitter() + const events = new EventEmitter() const components = defaultComponents({ peerId, datastore: new MemoryDatastore(), diff --git a/packages/libp2p/test/peer-discovery/index.node.ts b/packages/libp2p/test/peer-discovery/index.node.ts index d3d6bd0939..7adfb0c867 100644 --- a/packages/libp2p/test/peer-discovery/index.node.ts +++ b/packages/libp2p/test/peer-discovery/index.node.ts @@ -2,7 +2,7 @@ import { bootstrap } from '@libp2p/bootstrap' import { randomBytes } from '@libp2p/crypto' -import { TypedEventEmitter } from '@libp2p/interface/events' +import { EventEmitter } from '@libp2p/interface/events' import { peerDiscovery } from '@libp2p/interface/peer-discovery' import { kadDHT } from '@libp2p/kad-dht' import { mdns } from '@libp2p/mdns' @@ -22,7 +22,7 @@ import type { KadDHT } from '@libp2p/kad-dht' const listenAddr = multiaddr('/ip4/127.0.0.1/tcp/0') -class TestPeerDiscovery extends TypedEventEmitter implements PeerDiscovery { +class TestPeerDiscovery extends EventEmitter implements PeerDiscovery { get [peerDiscovery] (): PeerDiscovery { return this } diff --git a/packages/libp2p/test/ping/index.spec.ts b/packages/libp2p/test/ping/index.spec.ts index 9b6aef1385..c37d5d0ebe 100644 --- a/packages/libp2p/test/ping/index.spec.ts +++ b/packages/libp2p/test/ping/index.spec.ts @@ -1,6 +1,6 @@ /* eslint-env mocha */ -import { TypedEventEmitter } from '@libp2p/interface/events' +import { EventEmitter } from '@libp2p/interface/events' import { start, stop } from '@libp2p/interface/startable' import { mockRegistrar, mockUpgrader, connectionPair } from '@libp2p/interface-compliance-tests/mocks' import { createEd25519PeerId } from '@libp2p/peer-id-factory' @@ -28,7 +28,7 @@ const defaultInit: PingServiceInit = { async function createComponents (index: number): Promise { const peerId = await createEd25519PeerId() - const events = new TypedEventEmitter() + const events = new EventEmitter() const components = defaultComponents({ peerId, registrar: mockRegistrar(), diff --git a/packages/libp2p/test/registrar/registrar.spec.ts b/packages/libp2p/test/registrar/registrar.spec.ts index 138b45b30e..0e5b585acf 100644 --- a/packages/libp2p/test/registrar/registrar.spec.ts +++ b/packages/libp2p/test/registrar/registrar.spec.ts @@ -2,7 +2,7 @@ import { yamux } from '@chainsafe/libp2p-yamux' import { CodeError } from '@libp2p/interface/errors' -import { TypedEventEmitter, type TypedEventTarget } from '@libp2p/interface/events' +import { EventEmitter } from '@libp2p/interface/events' import { mockDuplex, mockMultiaddrConnection, mockUpgrader, mockConnection } from '@libp2p/interface-compliance-tests/mocks' import { mplex } from '@libp2p/mplex' import { createEd25519PeerId } from '@libp2p/peer-id-factory' @@ -43,7 +43,7 @@ describe('registrar', () => { describe('errors', () => { beforeEach(() => { - const events = new TypedEventEmitter() + const events = new EventEmitter() components = defaultComponents({ peerId, events, @@ -81,13 +81,13 @@ describe('registrar', () => { let peerId: PeerId let connectionManager: StubbedInstance let peerStore: StubbedInstance - let events: TypedEventTarget + let events: EventEmitter beforeEach(async () => { peerId = await createEd25519PeerId() connectionManager = stubInterface() peerStore = stubInterface() - events = new TypedEventEmitter() + events = new EventEmitter() registrar = new DefaultRegistrar({ peerId, diff --git a/packages/libp2p/test/transports/transport-manager.node.ts b/packages/libp2p/test/transports/transport-manager.node.ts index 290414e618..7404e88bbe 100644 --- a/packages/libp2p/test/transports/transport-manager.node.ts +++ b/packages/libp2p/test/transports/transport-manager.node.ts @@ -1,6 +1,6 @@ /* eslint-env mocha */ -import { TypedEventEmitter } from '@libp2p/interface/events' +import { EventEmitter } from '@libp2p/interface/events' import { start, stop } from '@libp2p/interface/startable' import { FaultTolerance } from '@libp2p/interface/transport' import { mockUpgrader } from '@libp2p/interface-compliance-tests/mocks' @@ -33,7 +33,7 @@ describe('Transport Manager (TCP)', () => { }) beforeEach(async () => { - const events = new TypedEventEmitter() + const events = new EventEmitter() components = defaultComponents({ peerId: localPeer, events, diff --git a/packages/libp2p/test/transports/transport-manager.spec.ts b/packages/libp2p/test/transports/transport-manager.spec.ts index c71a124a92..89024dd8bc 100644 --- a/packages/libp2p/test/transports/transport-manager.spec.ts +++ b/packages/libp2p/test/transports/transport-manager.spec.ts @@ -1,6 +1,6 @@ /* eslint-env mocha */ -import { TypedEventEmitter } from '@libp2p/interface/events' +import { EventEmitter } from '@libp2p/interface/events' import { start, stop } from '@libp2p/interface/startable' import { FaultTolerance } from '@libp2p/interface/transport' import { mockUpgrader } from '@libp2p/interface-compliance-tests/mocks' @@ -26,7 +26,7 @@ describe('Transport Manager (WebSockets)', () => { let components: Components beforeEach(async () => { - const events = new TypedEventEmitter() + const events = new EventEmitter() components = { peerId: await createEd25519PeerId(), events, diff --git a/packages/libp2p/test/upgrading/upgrader.spec.ts b/packages/libp2p/test/upgrading/upgrader.spec.ts index 6f83c08ecd..f1343f128e 100644 --- a/packages/libp2p/test/upgrading/upgrader.spec.ts +++ b/packages/libp2p/test/upgrading/upgrader.spec.ts @@ -1,7 +1,7 @@ /* eslint-env mocha */ import { yamux } from '@chainsafe/libp2p-yamux' -import { TypedEventEmitter } from '@libp2p/interface/events' +import { EventEmitter } from '@libp2p/interface/events' import { mockConnectionGater, mockConnectionManager, mockMultiaddrConnPair, mockRegistrar, mockStream, mockMuxer } from '@libp2p/interface-compliance-tests/mocks' import { mplex } from '@libp2p/mplex' import { createEd25519PeerId } from '@libp2p/peer-id-factory' @@ -76,7 +76,7 @@ describe('Upgrader', () => { registrar: mockRegistrar(), datastore: new MemoryDatastore(), connectionProtector: localConnectionProtector, - events: new TypedEventEmitter() + events: new EventEmitter() }) localComponents.peerStore = new PersistentPeerStore(localComponents) localComponents.connectionManager = mockConnectionManager(localComponents) @@ -103,7 +103,7 @@ describe('Upgrader', () => { registrar: mockRegistrar(), datastore: new MemoryDatastore(), connectionProtector: remoteConnectionProtector, - events: new TypedEventEmitter() + events: new EventEmitter() }) remoteComponents.peerStore = new PersistentPeerStore(remoteComponents) remoteComponents.connectionManager = mockConnectionManager(remoteComponents) diff --git a/packages/libp2p/test/upnp-nat/upnp-nat.node.ts b/packages/libp2p/test/upnp-nat/upnp-nat.node.ts index 8e39909147..42d6cc6407 100644 --- a/packages/libp2p/test/upnp-nat/upnp-nat.node.ts +++ b/packages/libp2p/test/upnp-nat/upnp-nat.node.ts @@ -1,6 +1,6 @@ /* eslint-env mocha */ -import { TypedEventEmitter } from '@libp2p/interface/events' +import { EventEmitter } from '@libp2p/interface/events' import { start, stop } from '@libp2p/interface/startable' import { FaultTolerance } from '@libp2p/interface/transport' import { mockUpgrader } from '@libp2p/interface-compliance-tests/mocks' @@ -31,7 +31,7 @@ describe('UPnP NAT (TCP)', () => { let client: StubbedInstance async function createNatManager (addrs = DEFAULT_ADDRESSES, natManagerOptions = {}): Promise<{ natManager: any, components: Components }> { - const events = new TypedEventEmitter() + const events = new EventEmitter() const components: any = defaultComponents({ peerId: await createEd25519PeerId(), upgrader: mockUpgrader({ events }), diff --git a/packages/peer-discovery-bootstrap/src/index.ts b/packages/peer-discovery-bootstrap/src/index.ts index 7400d494f4..1debb10fc6 100644 --- a/packages/peer-discovery-bootstrap/src/index.ts +++ b/packages/peer-discovery-bootstrap/src/index.ts @@ -1,4 +1,4 @@ -import { TypedEventEmitter } from '@libp2p/interface/events' +import { EventEmitter } from '@libp2p/interface/events' import { peerDiscovery } from '@libp2p/interface/peer-discovery' import { logger } from '@libp2p/logger' import { peerIdFromString } from '@libp2p/peer-id' @@ -50,7 +50,7 @@ export interface BootstrapComponents { /** * Emits 'peer' events on a regular interval for each peer in the provided list. */ -class Bootstrap extends TypedEventEmitter implements PeerDiscovery, Startable { +class Bootstrap extends EventEmitter implements PeerDiscovery, Startable { static tag = 'bootstrap' private timer?: ReturnType diff --git a/packages/peer-discovery-mdns/src/index.ts b/packages/peer-discovery-mdns/src/index.ts index 98d568640e..7424131c06 100644 --- a/packages/peer-discovery-mdns/src/index.ts +++ b/packages/peer-discovery-mdns/src/index.ts @@ -1,4 +1,4 @@ -import { CustomEvent, TypedEventEmitter } from '@libp2p/interface/events' +import { CustomEvent, EventEmitter } from '@libp2p/interface/events' import { peerDiscovery } from '@libp2p/interface/peer-discovery' import { logger } from '@libp2p/logger' import multicastDNS from 'multicast-dns' @@ -24,7 +24,7 @@ export interface MulticastDNSComponents { addressManager: AddressManager } -class MulticastDNS extends TypedEventEmitter implements PeerDiscovery, Startable { +class MulticastDNS extends EventEmitter implements PeerDiscovery, Startable { public mdns?: multicastDNS.MulticastDNS private readonly broadcast: boolean diff --git a/packages/peer-store/src/index.ts b/packages/peer-store/src/index.ts index ec9b4632bf..d130a8a7c3 100644 --- a/packages/peer-store/src/index.ts +++ b/packages/peer-store/src/index.ts @@ -3,7 +3,7 @@ import { RecordEnvelope, PeerRecord } from '@libp2p/peer-record' import all from 'it-all' import { PersistentStore, type PeerUpdate } from './store.js' import type { Libp2pEvents } from '@libp2p/interface' -import type { TypedEventTarget } from '@libp2p/interface/events' +import type { EventEmitter } from '@libp2p/interface/events' import type { PeerId } from '@libp2p/interface/peer-id' import type { PeerStore, Peer, PeerData, PeerQuery } from '@libp2p/interface/peer-store' import type { Multiaddr } from '@multiformats/multiaddr' @@ -14,7 +14,7 @@ const log = logger('libp2p:peer-store') export interface PersistentPeerStoreComponents { peerId: PeerId datastore: Datastore - events: TypedEventTarget + events: EventEmitter } /** @@ -33,7 +33,7 @@ export interface PersistentPeerStoreInit { */ export class PersistentPeerStore implements PeerStore { private readonly store: PersistentStore - private readonly events: TypedEventTarget + private readonly events: EventEmitter private readonly peerId: PeerId constructor (components: PersistentPeerStoreComponents, init: PersistentPeerStoreInit = {}) { diff --git a/packages/peer-store/test/index.spec.ts b/packages/peer-store/test/index.spec.ts index e5fd106beb..868d811c72 100644 --- a/packages/peer-store/test/index.spec.ts +++ b/packages/peer-store/test/index.spec.ts @@ -1,7 +1,7 @@ /* eslint-env mocha */ /* eslint max-nested-callbacks: ["error", 6] */ -import { TypedEventEmitter, type TypedEventTarget } from '@libp2p/interface/events' +import { EventEmitter } from '@libp2p/interface/events' import { createEd25519PeerId } from '@libp2p/peer-id-factory' import { RecordEnvelope, PeerRecord } from '@libp2p/peer-record' import { multiaddr } from '@multiformats/multiaddr' @@ -18,12 +18,12 @@ describe('PersistentPeerStore', () => { let peerId: PeerId let otherPeerId: PeerId let peerStore: PersistentPeerStore - let events: TypedEventTarget + let events: EventEmitter beforeEach(async () => { peerId = await createEd25519PeerId() otherPeerId = await createEd25519PeerId() - events = new TypedEventEmitter() + events = new EventEmitter() peerStore = new PersistentPeerStore({ peerId, events, datastore: new MemoryDatastore() }) }) diff --git a/packages/peer-store/test/merge.spec.ts b/packages/peer-store/test/merge.spec.ts index eefeec19c7..304512781f 100644 --- a/packages/peer-store/test/merge.spec.ts +++ b/packages/peer-store/test/merge.spec.ts @@ -1,7 +1,7 @@ /* eslint-env mocha */ /* eslint max-nested-callbacks: ["error", 6] */ -import { TypedEventEmitter, type TypedEventTarget } from '@libp2p/interface/events' +import { EventEmitter } from '@libp2p/interface/events' import { createEd25519PeerId } from '@libp2p/peer-id-factory' import { multiaddr } from '@multiformats/multiaddr' import { expect } from 'aegir/chai' @@ -20,12 +20,12 @@ describe('merge', () => { let peerId: PeerId let otherPeerId: PeerId let peerStore: PersistentPeerStore - let events: TypedEventTarget + let events: EventEmitter beforeEach(async () => { peerId = await createEd25519PeerId() otherPeerId = await createEd25519PeerId() - events = new TypedEventEmitter() + events = new EventEmitter() peerStore = new PersistentPeerStore({ peerId, events, datastore: new MemoryDatastore() }) }) diff --git a/packages/peer-store/test/patch.spec.ts b/packages/peer-store/test/patch.spec.ts index 929425dcb9..a30e22e872 100644 --- a/packages/peer-store/test/patch.spec.ts +++ b/packages/peer-store/test/patch.spec.ts @@ -1,7 +1,7 @@ /* eslint-env mocha */ /* eslint max-nested-callbacks: ["error", 6] */ -import { TypedEventEmitter, type TypedEventTarget } from '@libp2p/interface/events' +import { EventEmitter } from '@libp2p/interface/events' import { createEd25519PeerId } from '@libp2p/peer-id-factory' import { multiaddr } from '@multiformats/multiaddr' import { expect } from 'aegir/chai' @@ -20,12 +20,12 @@ describe('patch', () => { let peerId: PeerId let otherPeerId: PeerId let peerStore: PersistentPeerStore - let events: TypedEventTarget + let events: EventEmitter beforeEach(async () => { peerId = await createEd25519PeerId() otherPeerId = await createEd25519PeerId() - events = new TypedEventEmitter() + events = new EventEmitter() peerStore = new PersistentPeerStore({ peerId, events, datastore: new MemoryDatastore() }) }) diff --git a/packages/peer-store/test/save.spec.ts b/packages/peer-store/test/save.spec.ts index 23a7e29905..43552cb883 100644 --- a/packages/peer-store/test/save.spec.ts +++ b/packages/peer-store/test/save.spec.ts @@ -1,7 +1,7 @@ /* eslint-env mocha */ /* eslint max-nested-callbacks: ["error", 6] */ -import { TypedEventEmitter, type TypedEventTarget } from '@libp2p/interface/events' +import { EventEmitter } from '@libp2p/interface/events' import { createEd25519PeerId, createRSAPeerId, createSecp256k1PeerId } from '@libp2p/peer-id-factory' import { multiaddr } from '@multiformats/multiaddr' import { expect } from 'aegir/chai' @@ -23,12 +23,12 @@ describe('save', () => { let peerId: PeerId let otherPeerId: PeerId let peerStore: PersistentPeerStore - let events: TypedEventTarget + let events: EventEmitter beforeEach(async () => { peerId = await createEd25519PeerId() otherPeerId = await createEd25519PeerId() - events = new TypedEventEmitter() + events = new EventEmitter() peerStore = new PersistentPeerStore({ peerId, events, datastore: new MemoryDatastore() }) }) diff --git a/packages/protocol-perf/test/index.spec.ts b/packages/protocol-perf/test/index.spec.ts index fc8299ed10..83fd6c310f 100644 --- a/packages/protocol-perf/test/index.spec.ts +++ b/packages/protocol-perf/test/index.spec.ts @@ -1,6 +1,6 @@ /* eslint-env mocha */ -import { TypedEventEmitter } from '@libp2p/interface/events' +import { EventEmitter } from '@libp2p/interface/events' import { start, stop } from '@libp2p/interface/startable' import { connectionPair, mockRegistrar, type MockNetworkComponents, mockConnectionManager } from '@libp2p/interface-compliance-tests/mocks' import { createEd25519PeerId } from '@libp2p/peer-id-factory' @@ -11,7 +11,7 @@ export async function createComponents (): Promise { const components: any = { peerId: await createEd25519PeerId(), registrar: mockRegistrar(), - events: new TypedEventEmitter() + events: new EventEmitter() } components.connectionManager = mockConnectionManager(components) diff --git a/packages/pubsub/src/index.ts b/packages/pubsub/src/index.ts index 2de4fa3fce..b8760e3a4f 100644 --- a/packages/pubsub/src/index.ts +++ b/packages/pubsub/src/index.ts @@ -1,5 +1,5 @@ import { CodeError } from '@libp2p/interface/errors' -import { TypedEventEmitter, CustomEvent } from '@libp2p/interface/events' +import { EventEmitter, CustomEvent } from '@libp2p/interface/events' import { type PubSub, type Message, type StrictNoSign, type StrictSign, type PubSubInit, type PubSubEvents, type PeerStreams, type PubSubRPCMessage, type PubSubRPC, type PubSubRPCSubscription, type SubscriptionChangeData, type PublishResult, type TopicValidatorFn, TopicValidatorResult } from '@libp2p/interface/pubsub' import { logger } from '@libp2p/logger' import { PeerMap, PeerSet } from '@libp2p/peer-collections' @@ -28,7 +28,7 @@ export interface PubSubComponents { * PubSubBaseProtocol handles the peers and connections logic for pubsub routers * and specifies the API that pubsub routers should have. */ -export abstract class PubSubBaseProtocol = PubSubEvents> extends TypedEventEmitter implements PubSub { +export abstract class PubSubBaseProtocol = PubSubEvents> extends EventEmitter implements PubSub { public started: boolean /** * Map of topics to which peers are subscribed to diff --git a/packages/pubsub/src/peer-streams.ts b/packages/pubsub/src/peer-streams.ts index 8e1646907a..c4a13387a5 100644 --- a/packages/pubsub/src/peer-streams.ts +++ b/packages/pubsub/src/peer-streams.ts @@ -1,4 +1,4 @@ -import { TypedEventEmitter, CustomEvent } from '@libp2p/interface/events' +import { EventEmitter, CustomEvent } from '@libp2p/interface/events' import { logger } from '@libp2p/logger' import { abortableSource } from 'abortable-iterator' import * as lp from 'it-length-prefixed' @@ -20,7 +20,7 @@ export interface PeerStreamsInit { /** * Thin wrapper around a peer's inbound / outbound pubsub streams */ -export class PeerStreams extends TypedEventEmitter { +export class PeerStreams extends EventEmitter { public readonly id: PeerId public readonly protocol: string /** diff --git a/packages/transport-tcp/src/listener.ts b/packages/transport-tcp/src/listener.ts index ee2d1a20f9..95792ed137 100644 --- a/packages/transport-tcp/src/listener.ts +++ b/packages/transport-tcp/src/listener.ts @@ -1,6 +1,6 @@ import net from 'net' import { CodeError } from '@libp2p/interface/errors' -import { TypedEventEmitter, CustomEvent } from '@libp2p/interface/events' +import { EventEmitter, CustomEvent } from '@libp2p/interface/events' import { logger } from '@libp2p/logger' import { CODE_P2P } from './constants.js' import { toMultiaddrConnection } from './socket-to-conn.js' @@ -71,7 +71,7 @@ type Status = { code: TCPListenerStatusCode.INACTIVE } | { netConfig: NetConfig } -export class TCPListener extends TypedEventEmitter implements Listener { +export class TCPListener extends EventEmitter implements Listener { private readonly server: net.Server /** Keep track of open connections to destroy in case of timeout */ private readonly connections = new Set() diff --git a/packages/transport-tcp/test/connection-limits.spec.ts b/packages/transport-tcp/test/connection-limits.spec.ts index 67a47c23e7..30aea96ac7 100644 --- a/packages/transport-tcp/test/connection-limits.spec.ts +++ b/packages/transport-tcp/test/connection-limits.spec.ts @@ -1,6 +1,6 @@ import net from 'node:net' import { promisify } from 'util' -import { TypedEventEmitter } from '@libp2p/interface/events' +import { EventEmitter } from '@libp2p/interface/events' import { mockUpgrader } from '@libp2p/interface-compliance-tests/mocks' import { multiaddr } from '@multiformats/multiaddr' import { expect } from 'aegir/chai' @@ -88,7 +88,7 @@ describe('closeAbove/listenBelow', () => { const trasnport = tcp({ closeServerOnMaxConnections: { listenBelow, closeAbove } })() const upgrader = mockUpgrader({ - events: new TypedEventEmitter() + events: new EventEmitter() }) const listener = trasnport.createListener({ upgrader }) as TCPListener // eslint-disable-next-line @typescript-eslint/promise-function-async @@ -115,7 +115,7 @@ describe('closeAbove/listenBelow', () => { const trasnport = tcp({ closeServerOnMaxConnections: { listenBelow, closeAbove } })() const upgrader = mockUpgrader({ - events: new TypedEventEmitter() + events: new EventEmitter() }) const listener = trasnport.createListener({ upgrader }) as TCPListener // eslint-disable-next-line @typescript-eslint/promise-function-async @@ -150,7 +150,7 @@ describe('closeAbove/listenBelow', () => { const trasnport = tcp({ closeServerOnMaxConnections: { listenBelow, closeAbove } })() const upgrader = mockUpgrader({ - events: new TypedEventEmitter() + events: new EventEmitter() }) const listener = trasnport.createListener({ upgrader }) as TCPListener // eslint-disable-next-line @typescript-eslint/promise-function-async @@ -181,7 +181,7 @@ describe('closeAbove/listenBelow', () => { const trasnport = tcp({ closeServerOnMaxConnections: { listenBelow, closeAbove } })() const upgrader = mockUpgrader({ - events: new TypedEventEmitter() + events: new EventEmitter() }) const listener = trasnport.createListener({ upgrader }) as TCPListener // eslint-disable-next-line @typescript-eslint/promise-function-async diff --git a/packages/transport-tcp/test/connection.spec.ts b/packages/transport-tcp/test/connection.spec.ts index a8cb893edb..0308d61708 100644 --- a/packages/transport-tcp/test/connection.spec.ts +++ b/packages/transport-tcp/test/connection.spec.ts @@ -1,4 +1,4 @@ -import { TypedEventEmitter } from '@libp2p/interface/events' +import { EventEmitter } from '@libp2p/interface/events' import { mockUpgrader } from '@libp2p/interface-compliance-tests/mocks' import { multiaddr } from '@multiformats/multiaddr' import { expect } from 'aegir/chai' @@ -13,7 +13,7 @@ describe('valid localAddr and remoteAddr', () => { beforeEach(() => { transport = tcp()() upgrader = mockUpgrader({ - events: new TypedEventEmitter() + events: new EventEmitter() }) }) diff --git a/packages/transport-tcp/test/listen-dial.spec.ts b/packages/transport-tcp/test/listen-dial.spec.ts index 4c7f608350..a2988bce77 100644 --- a/packages/transport-tcp/test/listen-dial.spec.ts +++ b/packages/transport-tcp/test/listen-dial.spec.ts @@ -1,6 +1,6 @@ import os from 'os' import path from 'path' -import { TypedEventEmitter } from '@libp2p/interface/events' +import { EventEmitter } from '@libp2p/interface/events' import { mockRegistrar, mockUpgrader } from '@libp2p/interface-compliance-tests/mocks' import { multiaddr } from '@multiformats/multiaddr' import { expect } from 'aegir/chai' @@ -22,7 +22,7 @@ describe('listen', () => { beforeEach(() => { transport = tcp()() upgrader = mockUpgrader({ - events: new TypedEventEmitter() + events: new EventEmitter() }) }) @@ -175,7 +175,7 @@ describe('dial', () => { }) upgrader = mockUpgrader({ registrar, - events: new TypedEventEmitter() + events: new EventEmitter() }) transport = tcp()() diff --git a/packages/transport-tcp/test/max-connections.spec.ts b/packages/transport-tcp/test/max-connections.spec.ts index 495a23e991..13d18d0c14 100644 --- a/packages/transport-tcp/test/max-connections.spec.ts +++ b/packages/transport-tcp/test/max-connections.spec.ts @@ -1,6 +1,6 @@ import net from 'node:net' import { promisify } from 'node:util' -import { TypedEventEmitter } from '@libp2p/interface/events' +import { EventEmitter } from '@libp2p/interface/events' import { mockUpgrader } from '@libp2p/interface-compliance-tests/mocks' import { multiaddr } from '@multiformats/multiaddr' import { expect } from 'aegir/chai' @@ -22,7 +22,7 @@ describe('maxConnections', () => { const transport = tcp({ maxConnections })() const upgrader = mockUpgrader({ - events: new TypedEventEmitter() + events: new EventEmitter() }) const listener = transport.createListener({ upgrader }) // eslint-disable-next-line @typescript-eslint/promise-function-async diff --git a/packages/transport-webrtc/src/private-to-private/listener.ts b/packages/transport-webrtc/src/private-to-private/listener.ts index 6a73e9e14a..53a3d299c6 100644 --- a/packages/transport-webrtc/src/private-to-private/listener.ts +++ b/packages/transport-webrtc/src/private-to-private/listener.ts @@ -1,4 +1,4 @@ -import { TypedEventEmitter } from '@libp2p/interface/events' +import { EventEmitter } from '@libp2p/interface/events' import { Circuit } from '@multiformats/mafmt' import type { PeerId } from '@libp2p/interface/peer-id' import type { ListenerEvents, Listener } from '@libp2p/interface/transport' @@ -14,7 +14,7 @@ export interface WebRTCPeerListenerInit { shutdownController: AbortController } -export class WebRTCPeerListener extends TypedEventEmitter implements Listener { +export class WebRTCPeerListener extends EventEmitter implements Listener { private readonly peerId: PeerId private readonly transportManager: TransportManager private readonly shutdownController: AbortController diff --git a/packages/transport-websockets/.aegir.js b/packages/transport-websockets/.aegir.js index d7e24c7d10..1a81ef61be 100644 --- a/packages/transport-websockets/.aegir.js +++ b/packages/transport-websockets/.aegir.js @@ -6,7 +6,7 @@ export default { async before () { const { multiaddr } = await import('@multiformats/multiaddr') const { mockRegistrar, mockUpgrader } = await import('@libp2p/interface-compliance-tests/mocks') - const { TypedEventEmitter } = await import('@libp2p/interface/events') + const { EventEmitter } = await import('@libp2p/interface/events') const { webSockets } = await import('./dist/src/index.js') const protocol = '/echo/1.0.0' @@ -19,7 +19,7 @@ export default { }) const upgrader = mockUpgrader({ registrar, - events: new TypedEventEmitter() + events: new EventEmitter() }) const ws = webSockets()() diff --git a/packages/transport-websockets/src/listener.ts b/packages/transport-websockets/src/listener.ts index 6f307c0ecb..9adb5957ae 100644 --- a/packages/transport-websockets/src/listener.ts +++ b/packages/transport-websockets/src/listener.ts @@ -1,5 +1,5 @@ import os from 'os' -import { TypedEventEmitter, CustomEvent } from '@libp2p/interface/events' +import { EventEmitter, CustomEvent } from '@libp2p/interface/events' import { logger } from '@libp2p/logger' import { ipPortToMultiaddr as toMultiaddr } from '@libp2p/utils/ip-port-to-multiaddr' import { multiaddr, protocols } from '@multiformats/multiaddr' @@ -14,7 +14,7 @@ import type { WebSocketServer } from 'it-ws/server' const log = logger('libp2p:websockets:listener') -class WebSocketListener extends TypedEventEmitter implements Listener { +class WebSocketListener extends EventEmitter implements Listener { private readonly connections: Set private listeningMultiaddr?: Multiaddr private readonly server: WebSocketServer diff --git a/packages/transport-websockets/test/browser.ts b/packages/transport-websockets/test/browser.ts index 88e311c67c..616f09e37e 100644 --- a/packages/transport-websockets/test/browser.ts +++ b/packages/transport-websockets/test/browser.ts @@ -1,6 +1,6 @@ /* eslint-env mocha */ -import { TypedEventEmitter } from '@libp2p/interface/events' +import { EventEmitter } from '@libp2p/interface/events' import { mockUpgrader } from '@libp2p/interface-compliance-tests/mocks' import { multiaddr } from '@multiformats/multiaddr' import { expect } from 'aegir/chai' @@ -23,7 +23,7 @@ describe('libp2p-websockets', () => { ws = webSockets()() conn = await ws.dial(ma, { upgrader: mockUpgrader({ - events: new TypedEventEmitter() + events: new EventEmitter() }) }) }) diff --git a/packages/transport-websockets/test/node.ts b/packages/transport-websockets/test/node.ts index 8c296900ce..32aa1b02ae 100644 --- a/packages/transport-websockets/test/node.ts +++ b/packages/transport-websockets/test/node.ts @@ -4,7 +4,7 @@ import fs from 'fs' import http from 'http' import https from 'https' -import { TypedEventEmitter } from '@libp2p/interface/events' +import { EventEmitter } from '@libp2p/interface/events' import { mockRegistrar, mockUpgrader } from '@libp2p/interface-compliance-tests/mocks' import { multiaddr } from '@multiformats/multiaddr' import { expect } from 'aegir/chai' @@ -41,7 +41,7 @@ void registrar.handle(protocol, (evt) => { }) const upgrader = mockUpgrader({ registrar, - events: new TypedEventEmitter() + events: new EventEmitter() }) describe('instantiate the transport', () => { From 50f912c2608caecc09acbcb0f46b4df4af073080 Mon Sep 17 00:00:00 2001 From: Alex Potsides Date: Wed, 25 Oct 2023 15:39:34 +0100 Subject: [PATCH 11/24] fix: rename event emitter class (#2173) We add types to a `EventEmitter` class which extends the plain js `EventTarget`. The name is chosen to give familiarity to node developers but it's not generally a good idea. This refactor: 1. Exports a new `TypedEventTarget` interface which adds types to `EventTarget` 2. Renames `EventEmitter` to `TypedEventEmitter` to draw a distinction between them 3. Re-exports `TypedEventEmitter` as `EventEmitter` to preserve backwards compatibility In the future all consuming code should rely on the `TypedEventTarget` interface while implementing code uses `TypedEventEmitter` as an implementation of a `TypedEventEmitter`. By depending on the interface and not the implementation consuming code is isolated from problems that arise when two versions of `@libp2p/interface` is in the dependency tree and the event subsystems would otherwise be compatible due to type overlap. This manifests as an error message about incompatible implementations of the private `#listeners` field in EventEmitter. Backwards compatibility is achieved by exporting the `TypedEventEmitter` class as the older `EventEmitter` name. This should be removed in a future PR to the v1.0 branch once external modules (e.g. Gossipsub) have been updated to use the new `TypedEventEmitter` symbol. ## Change checklist - [x] I have performed a self-review of my own code - [ ] I have made corresponding changes to the documentation if necessary (this includes comments as well) - [ ] I have added tests that prove my fix is effective or that my feature works --- .../src/mocks/connection-manager.ts | 6 +++--- .../src/mocks/peer-discovery.ts | 4 ++-- .../src/mocks/upgrader.ts | 6 +++--- .../src/pubsub/utils.ts | 4 ++-- .../src/transport/dial-test.ts | 4 ++-- .../src/transport/listen-test.ts | 4 ++-- packages/interface/src/events.ts | 21 ++++++++++++++++++- packages/interface/src/index.ts | 4 ++-- .../interface/src/peer-discovery/index.ts | 4 ++-- packages/interface/src/pubsub/index.ts | 6 +++--- packages/interface/src/transport/index.ts | 4 ++-- packages/kad-dht/src/dual-kad-dht.ts | 4 ++-- packages/kad-dht/src/index.ts | 4 ++-- packages/kad-dht/src/kad-dht.ts | 4 ++-- packages/kad-dht/src/network.ts | 4 ++-- packages/kad-dht/src/query/manager.ts | 4 ++-- packages/kad-dht/src/query/query-path.ts | 6 +++--- packages/kad-dht/src/routing-table/index.ts | 4 ++-- .../kad-dht/src/routing-table/k-bucket.ts | 6 ++---- packages/kad-dht/src/topology-listener.ts | 4 ++-- packages/kad-dht/test/routing-table.spec.ts | 4 ++-- .../test/rpc/handlers/get-providers.spec.ts | 4 ++-- .../test/rpc/handlers/get-value.spec.ts | 4 ++-- packages/kad-dht/test/rpc/index.node.ts | 4 ++-- packages/kad-dht/test/utils/test-dht.ts | 4 ++-- packages/libp2p/src/address-manager/index.ts | 4 ++-- packages/libp2p/src/circuit-relay/index.ts | 4 ++-- .../circuit-relay/server/advert-service.ts | 4 ++-- .../libp2p/src/circuit-relay/server/index.ts | 4 ++-- .../src/circuit-relay/transport/discovery.ts | 4 ++-- .../src/circuit-relay/transport/index.ts | 4 ++-- .../src/circuit-relay/transport/listener.ts | 4 ++-- .../transport/reservation-store.ts | 8 +++---- packages/libp2p/src/components.ts | 6 +++--- .../src/connection-manager/auto-dial.ts | 4 ++-- .../connection-manager/connection-pruner.ts | 6 +++--- .../libp2p/src/connection-manager/index.ts | 6 +++--- packages/libp2p/src/identify/identify.ts | 4 ++-- packages/libp2p/src/identify/index.ts | 4 ++-- packages/libp2p/src/libp2p.ts | 6 +++--- packages/libp2p/src/registrar.ts | 4 ++-- packages/libp2p/src/transport-manager.ts | 4 ++-- packages/libp2p/src/upgrader.ts | 6 +++--- .../test/addresses/address-manager.spec.ts | 6 +++--- .../libp2p/test/circuit-relay/hop.spec.ts | 6 +++--- .../libp2p/test/circuit-relay/stop.spec.ts | 4 ++-- .../test/connection-manager/auto-dial.spec.ts | 6 +++--- .../test/connection-manager/direct.node.ts | 6 +++--- .../test/connection-manager/direct.spec.ts | 4 ++-- .../test/connection-manager/index.node.ts | 6 +++--- .../test/connection-manager/index.spec.ts | 12 +++++------ packages/libp2p/test/fetch/index.spec.ts | 4 ++-- packages/libp2p/test/identify/index.spec.ts | 4 ++-- packages/libp2p/test/identify/push.spec.ts | 4 ++-- .../libp2p/test/peer-discovery/index.node.ts | 4 ++-- packages/libp2p/test/ping/index.spec.ts | 4 ++-- .../libp2p/test/registrar/registrar.spec.ts | 8 +++---- .../test/transports/transport-manager.node.ts | 4 ++-- .../test/transports/transport-manager.spec.ts | 4 ++-- .../libp2p/test/upgrading/upgrader.spec.ts | 6 +++--- .../libp2p/test/upnp-nat/upnp-nat.node.ts | 4 ++-- .../peer-discovery-bootstrap/src/index.ts | 4 ++-- packages/peer-discovery-mdns/src/index.ts | 4 ++-- packages/peer-store/src/index.ts | 6 +++--- packages/peer-store/test/index.spec.ts | 6 +++--- packages/peer-store/test/merge.spec.ts | 6 +++--- packages/peer-store/test/patch.spec.ts | 6 +++--- packages/peer-store/test/save.spec.ts | 6 +++--- packages/protocol-perf/test/index.spec.ts | 4 ++-- packages/pubsub/src/index.ts | 4 ++-- packages/pubsub/src/peer-streams.ts | 4 ++-- packages/transport-tcp/src/listener.ts | 4 ++-- .../test/connection-limits.spec.ts | 10 ++++----- .../transport-tcp/test/connection.spec.ts | 4 ++-- .../transport-tcp/test/listen-dial.spec.ts | 6 +++--- .../test/max-connections.spec.ts | 4 ++-- .../src/private-to-private/listener.ts | 4 ++-- packages/transport-websockets/.aegir.js | 4 ++-- packages/transport-websockets/src/listener.ts | 4 ++-- packages/transport-websockets/test/browser.ts | 4 ++-- packages/transport-websockets/test/node.ts | 4 ++-- 81 files changed, 212 insertions(+), 195 deletions(-) diff --git a/packages/interface-compliance-tests/src/mocks/connection-manager.ts b/packages/interface-compliance-tests/src/mocks/connection-manager.ts index 4f5cecbac0..81904d407f 100644 --- a/packages/interface-compliance-tests/src/mocks/connection-manager.ts +++ b/packages/interface-compliance-tests/src/mocks/connection-manager.ts @@ -6,7 +6,7 @@ import { isMultiaddr, type Multiaddr } from '@multiformats/multiaddr' import { connectionPair } from './connection.js' import type { Libp2pEvents, PendingDial } from '@libp2p/interface' import type { Connection } from '@libp2p/interface/connection' -import type { EventEmitter } from '@libp2p/interface/events' +import type { TypedEventTarget } from '@libp2p/interface/events' import type { PubSub } from '@libp2p/interface/pubsub' import type { Startable } from '@libp2p/interface/startable' import type { ConnectionManager } from '@libp2p/interface-internal/connection-manager' @@ -16,7 +16,7 @@ export interface MockNetworkComponents { peerId: PeerId registrar: Registrar connectionManager: ConnectionManager - events: EventEmitter + events: TypedEventTarget pubsub?: PubSub } @@ -51,7 +51,7 @@ export const mockNetwork = new MockNetwork() export interface MockConnectionManagerComponents { peerId: PeerId registrar: Registrar - events: EventEmitter + events: TypedEventTarget } class MockConnectionManager implements ConnectionManager, Startable { diff --git a/packages/interface-compliance-tests/src/mocks/peer-discovery.ts b/packages/interface-compliance-tests/src/mocks/peer-discovery.ts index eab17bea6d..69bd2afc29 100644 --- a/packages/interface-compliance-tests/src/mocks/peer-discovery.ts +++ b/packages/interface-compliance-tests/src/mocks/peer-discovery.ts @@ -1,4 +1,4 @@ -import { EventEmitter } from '@libp2p/interface/events' +import { TypedEventEmitter } from '@libp2p/interface/events' import { peerDiscovery } from '@libp2p/interface/peer-discovery' import * as PeerIdFactory from '@libp2p/peer-id-factory' import { multiaddr } from '@multiformats/multiaddr' @@ -12,7 +12,7 @@ interface MockDiscoveryInit { /** * Emits 'peer' events on discovery. */ -export class MockDiscovery extends EventEmitter implements PeerDiscovery { +export class MockDiscovery extends TypedEventEmitter implements PeerDiscovery { public readonly options: MockDiscoveryInit private _isRunning: boolean private _timer: any diff --git a/packages/interface-compliance-tests/src/mocks/upgrader.ts b/packages/interface-compliance-tests/src/mocks/upgrader.ts index b4ef88002d..4f69268071 100644 --- a/packages/interface-compliance-tests/src/mocks/upgrader.ts +++ b/packages/interface-compliance-tests/src/mocks/upgrader.ts @@ -1,18 +1,18 @@ import { mockConnection } from './connection.js' import type { Libp2pEvents } from '@libp2p/interface' import type { Connection, MultiaddrConnection } from '@libp2p/interface/connection' -import type { EventEmitter } from '@libp2p/interface/events' +import type { TypedEventTarget } from '@libp2p/interface/events' import type { Upgrader, UpgraderOptions } from '@libp2p/interface/transport' import type { Registrar } from '@libp2p/interface-internal/registrar' export interface MockUpgraderInit { registrar?: Registrar - events?: EventEmitter + events?: TypedEventTarget } class MockUpgrader implements Upgrader { private readonly registrar?: Registrar - private readonly events?: EventEmitter + private readonly events?: TypedEventTarget constructor (init: MockUpgraderInit) { this.registrar = init.registrar diff --git a/packages/interface-compliance-tests/src/pubsub/utils.ts b/packages/interface-compliance-tests/src/pubsub/utils.ts index 79bf894479..fdd7c2552c 100644 --- a/packages/interface-compliance-tests/src/pubsub/utils.ts +++ b/packages/interface-compliance-tests/src/pubsub/utils.ts @@ -1,4 +1,4 @@ -import { EventEmitter } from '@libp2p/interface/events' +import { TypedEventEmitter } from '@libp2p/interface/events' import { createEd25519PeerId } from '@libp2p/peer-id-factory' import { pEvent } from 'p-event' import pWaitFor from 'p-wait-for' @@ -19,7 +19,7 @@ export async function createComponents (): Promise { const components: any = { peerId: await createEd25519PeerId(), registrar: mockRegistrar(), - events: new EventEmitter() + events: new TypedEventEmitter() } components.connectionManager = mockConnectionManager(components) diff --git a/packages/interface-compliance-tests/src/transport/dial-test.ts b/packages/interface-compliance-tests/src/transport/dial-test.ts index 2139a755d0..98035d9aa5 100644 --- a/packages/interface-compliance-tests/src/transport/dial-test.ts +++ b/packages/interface-compliance-tests/src/transport/dial-test.ts @@ -1,5 +1,5 @@ import { AbortError } from '@libp2p/interface/errors' -import { EventEmitter } from '@libp2p/interface/events' +import { TypedEventEmitter } from '@libp2p/interface/events' import { expect } from 'aegir/chai' import all from 'it-all' import drain from 'it-drain' @@ -27,7 +27,7 @@ export default (common: TestSetup): void => { registrar = mockRegistrar() upgrader = mockUpgrader({ registrar, - events: new EventEmitter() + events: new TypedEventEmitter() }); ({ addrs, transport, connector } = await common.setup()) diff --git a/packages/interface-compliance-tests/src/transport/listen-test.ts b/packages/interface-compliance-tests/src/transport/listen-test.ts index d518511dc7..d9f3a17c22 100644 --- a/packages/interface-compliance-tests/src/transport/listen-test.ts +++ b/packages/interface-compliance-tests/src/transport/listen-test.ts @@ -1,5 +1,5 @@ /* eslint max-nested-callbacks: ["error", 8] */ -import { CustomEvent, EventEmitter } from '@libp2p/interface/events' +import { CustomEvent, TypedEventEmitter } from '@libp2p/interface/events' import { expect } from 'aegir/chai' import drain from 'it-drain' import { pipe } from 'it-pipe' @@ -27,7 +27,7 @@ export default (common: TestSetup): void => { registrar = mockRegistrar() upgrader = mockUpgrader({ registrar, - events: new EventEmitter() + events: new TypedEventEmitter() }); ({ transport, addrs } = await common.setup()) diff --git a/packages/interface/src/events.ts b/packages/interface/src/events.ts index 4fff7e8f91..2f4e863b0e 100644 --- a/packages/interface/src/events.ts +++ b/packages/interface/src/events.ts @@ -15,7 +15,23 @@ interface Listener { * https://github.com/microsoft/TypeScript/issues/299 * etc */ -export class EventEmitter> extends EventTarget { +export interface TypedEventTarget > extends EventTarget { + addEventListener(type: K, listener: EventHandler | null, options?: boolean | AddEventListenerOptions): void + + listenerCount (type: string): number + + removeEventListener(type: K, listener?: EventHandler | null, options?: boolean | EventListenerOptions): void + + removeEventListener (type: string, listener?: EventHandler, options?: boolean | EventListenerOptions): void + + safeDispatchEvent(type: keyof EventMap, detail: CustomEventInit): boolean +} + +/** + * An implementation of a typed event target + * etc + */ +export class TypedEventEmitter> extends EventTarget implements TypedEventTarget { #listeners = new Map() listenerCount (type: string): number { @@ -98,3 +114,6 @@ class CustomEventPolyfill extends Event { } export const CustomEvent = globalThis.CustomEvent ?? CustomEventPolyfill + +// TODO: remove this in v1 +export { TypedEventEmitter as EventEmitter } diff --git a/packages/interface/src/index.ts b/packages/interface/src/index.ts index 0dd02078f8..d50e335d69 100644 --- a/packages/interface/src/index.ts +++ b/packages/interface/src/index.ts @@ -16,7 +16,7 @@ import type { Connection, NewStreamOptions, Stream } from './connection/index.js' import type { ContentRouting } from './content-routing/index.js' -import type { EventEmitter } from './events.js' +import type { TypedEventTarget } from './events.js' import type { KeyChain } from './keychain/index.js' import type { Metrics } from './metrics/index.js' import type { PeerId } from './peer-id/index.js' @@ -303,7 +303,7 @@ export interface PendingDial { /** * Libp2p nodes implement this interface. */ -export interface Libp2p extends Startable, EventEmitter> { +export interface Libp2p extends Startable, TypedEventTarget> { /** * The PeerId is a unique identifier for a node on the network. * diff --git a/packages/interface/src/peer-discovery/index.ts b/packages/interface/src/peer-discovery/index.ts index 4b8aa9c258..55b1227eb1 100644 --- a/packages/interface/src/peer-discovery/index.ts +++ b/packages/interface/src/peer-discovery/index.ts @@ -1,4 +1,4 @@ -import type { EventEmitter } from '../events.js' +import type { TypedEventTarget } from '../events.js' import type { PeerInfo } from '../peer-info/index.js' /** @@ -26,4 +26,4 @@ export interface PeerDiscoveryEvents { 'peer': CustomEvent } -export interface PeerDiscovery extends EventEmitter {} +export interface PeerDiscovery extends TypedEventTarget {} diff --git a/packages/interface/src/pubsub/index.ts b/packages/interface/src/pubsub/index.ts index 6fd94382a1..1ce9464b6b 100644 --- a/packages/interface/src/pubsub/index.ts +++ b/packages/interface/src/pubsub/index.ts @@ -1,5 +1,5 @@ import type { Stream } from '../connection/index.js' -import type { EventEmitter } from '../events.js' +import type { TypedEventTarget } from '../events.js' import type { PeerId } from '../peer-id/index.js' import type { Pushable } from 'it-pushable' import type { Uint8ArrayList } from 'uint8arraylist' @@ -65,7 +65,7 @@ export interface PubSubRPC { messages: PubSubRPCMessage[] } -export interface PeerStreams extends EventEmitter { +export interface PeerStreams extends TypedEventTarget { id: PeerId protocol: string outboundStream?: Pushable @@ -152,7 +152,7 @@ export interface TopicValidatorFn { (peer: PeerId, message: Message): TopicValidatorResult | Promise } -export interface PubSub = PubSubEvents> extends EventEmitter { +export interface PubSub = PubSubEvents> extends TypedEventTarget { /** * The global signature policy controls whether or not we sill send and receive * signed or unsigned messages. diff --git a/packages/interface/src/transport/index.ts b/packages/interface/src/transport/index.ts index 5acbfcc50e..22ab1a803b 100644 --- a/packages/interface/src/transport/index.ts +++ b/packages/interface/src/transport/index.ts @@ -1,5 +1,5 @@ import type { Connection, MultiaddrConnection } from '../connection/index.js' -import type { EventEmitter } from '../events.js' +import type { TypedEventTarget } from '../events.js' import type { AbortOptions } from '../index.js' import type { StreamMuxerFactory } from '../stream-muxer/index.js' import type { Multiaddr } from '@multiformats/multiaddr' @@ -11,7 +11,7 @@ export interface ListenerEvents { 'close': CustomEvent } -export interface Listener extends EventEmitter { +export interface Listener extends TypedEventTarget { /** * Start a listener */ diff --git a/packages/kad-dht/src/dual-kad-dht.ts b/packages/kad-dht/src/dual-kad-dht.ts index 6d704725fb..ef06f739ea 100644 --- a/packages/kad-dht/src/dual-kad-dht.ts +++ b/packages/kad-dht/src/dual-kad-dht.ts @@ -1,6 +1,6 @@ import { type ContentRouting, contentRouting } from '@libp2p/interface/content-routing' import { CodeError } from '@libp2p/interface/errors' -import { EventEmitter, CustomEvent } from '@libp2p/interface/events' +import { TypedEventEmitter, CustomEvent } from '@libp2p/interface/events' import { type PeerDiscovery, peerDiscovery, type PeerDiscoveryEvents } from '@libp2p/interface/peer-discovery' import { type PeerRouting, peerRouting } from '@libp2p/interface/peer-routing' import { logger } from '@libp2p/logger' @@ -121,7 +121,7 @@ function multiaddrIsPublic (multiaddr: Multiaddr): boolean { * A DHT implementation modelled after Kademlia with S/Kademlia modifications. * Original implementation in go: https://github.com/libp2p/go-libp2p-kad-dht. */ -export class DefaultDualKadDHT extends EventEmitter implements DualKadDHT, PeerDiscovery { +export class DefaultDualKadDHT extends TypedEventEmitter implements DualKadDHT, PeerDiscovery { public readonly wan: DefaultKadDHT public readonly lan: DefaultKadDHT public readonly components: KadDHTComponents diff --git a/packages/kad-dht/src/index.ts b/packages/kad-dht/src/index.ts index edb1e4f679..679a7ba62f 100644 --- a/packages/kad-dht/src/index.ts +++ b/packages/kad-dht/src/index.ts @@ -1,7 +1,7 @@ import { DefaultDualKadDHT } from './dual-kad-dht.js' import type { ProvidersInit } from './providers.js' import type { Libp2pEvents, AbortOptions } from '@libp2p/interface' -import type { EventEmitter } from '@libp2p/interface/events' +import type { TypedEventTarget } from '@libp2p/interface/events' import type { Metrics } from '@libp2p/interface/metrics' import type { PeerId } from '@libp2p/interface/peer-id' import type { PeerInfo } from '@libp2p/interface/peer-info' @@ -314,7 +314,7 @@ export interface KadDHTComponents { metrics?: Metrics connectionManager: ConnectionManager datastore: Datastore - events: EventEmitter + events: TypedEventTarget } export function kadDHT (init?: KadDHTInit): (components: KadDHTComponents) => DualKadDHT { diff --git a/packages/kad-dht/src/kad-dht.ts b/packages/kad-dht/src/kad-dht.ts index f9f260452c..fb5be07aa9 100644 --- a/packages/kad-dht/src/kad-dht.ts +++ b/packages/kad-dht/src/kad-dht.ts @@ -1,4 +1,4 @@ -import { CustomEvent, EventEmitter } from '@libp2p/interface/events' +import { CustomEvent, TypedEventEmitter } from '@libp2p/interface/events' import { type Logger, logger } from '@libp2p/logger' import pDefer from 'p-defer' import { PROTOCOL_DHT, PROTOCOL_PREFIX, LAN_PREFIX } from './constants.js' @@ -39,7 +39,7 @@ export interface SingleKadDHTInit extends KadDHTInit { * A DHT implementation modelled after Kademlia with S/Kademlia modifications. * Original implementation in go: https://github.com/libp2p/go-libp2p-kad-dht. */ -export class DefaultKadDHT extends EventEmitter implements KadDHT { +export class DefaultKadDHT extends TypedEventEmitter implements KadDHT { public protocol: string public routingTable: RoutingTable public providers: Providers diff --git a/packages/kad-dht/src/network.ts b/packages/kad-dht/src/network.ts index b10ad6e592..c968b10f9b 100644 --- a/packages/kad-dht/src/network.ts +++ b/packages/kad-dht/src/network.ts @@ -1,5 +1,5 @@ import { CodeError } from '@libp2p/interface/errors' -import { EventEmitter, CustomEvent } from '@libp2p/interface/events' +import { TypedEventEmitter, CustomEvent } from '@libp2p/interface/events' import { logger } from '@libp2p/logger' import { abortableDuplex } from 'abortable-iterator' import drain from 'it-drain' @@ -35,7 +35,7 @@ interface NetworkEvents { /** * Handle network operations for the dht */ -export class Network extends EventEmitter implements Startable { +export class Network extends TypedEventEmitter implements Startable { private readonly log: Logger private readonly protocol: string private running: boolean diff --git a/packages/kad-dht/src/query/manager.ts b/packages/kad-dht/src/query/manager.ts index df830faf2d..675c9a9f81 100644 --- a/packages/kad-dht/src/query/manager.ts +++ b/packages/kad-dht/src/query/manager.ts @@ -1,6 +1,6 @@ import { setMaxListeners } from 'events' import { AbortError } from '@libp2p/interface/errors' -import { EventEmitter, CustomEvent } from '@libp2p/interface/events' +import { TypedEventEmitter, CustomEvent } from '@libp2p/interface/events' import { logger } from '@libp2p/logger' import { PeerSet } from '@libp2p/peer-collections' import { anySignal } from 'any-signal' @@ -143,7 +143,7 @@ export class QueryManager implements Startable { // query a subset of peers up to `kBucketSize / 2` in length const startTime = Date.now() - const cleanUp = new EventEmitter() + const cleanUp = new TypedEventEmitter() try { if (options.isSelfQuery !== true && this.initialQuerySelfHasRun != null) { diff --git a/packages/kad-dht/src/query/query-path.ts b/packages/kad-dht/src/query/query-path.ts index 991f1abd42..382585ae26 100644 --- a/packages/kad-dht/src/query/query-path.ts +++ b/packages/kad-dht/src/query/query-path.ts @@ -9,7 +9,7 @@ import { queryErrorEvent } from './events.js' import type { CleanUpEvents } from './manager.js' import type { QueryEvent, QueryOptions } from '../index.js' import type { QueryFunc } from '../query/types.js' -import type { EventEmitter } from '@libp2p/interface/events' +import type { TypedEventTarget } from '@libp2p/interface/events' import type { PeerId } from '@libp2p/interface/peer-id' import type { Logger } from '@libp2p/logger' import type { PeerSet } from '@libp2p/peer-collections' @@ -60,7 +60,7 @@ export interface QueryPathOptions extends QueryOptions { /** * will emit a 'cleanup' event if the caller exits the for..await of early */ - cleanUp: EventEmitter + cleanUp: TypedEventTarget /** * A timeout for queryFunc in ms @@ -185,7 +185,7 @@ export async function * queryPath (options: QueryPathOptions): AsyncGenerator, log: Logger): AsyncGenerator { +async function * toGenerator (queue: Queue, signal: AbortSignal, cleanUp: TypedEventTarget, log: Logger): AsyncGenerator { let deferred = defer() let running = true const results: QueryEvent[] = [] diff --git a/packages/kad-dht/src/routing-table/index.ts b/packages/kad-dht/src/routing-table/index.ts index b0bfbb90ff..ee7b24bcf8 100644 --- a/packages/kad-dht/src/routing-table/index.ts +++ b/packages/kad-dht/src/routing-table/index.ts @@ -1,4 +1,4 @@ -import { EventEmitter } from '@libp2p/interface/events' +import { TypedEventEmitter } from '@libp2p/interface/events' import { logger } from '@libp2p/logger' import { PeerSet } from '@libp2p/peer-collections' import Queue from 'p-queue' @@ -43,7 +43,7 @@ export interface RoutingTableEvents { * A wrapper around `k-bucket`, to provide easy store and * retrieval for peers. */ -export class RoutingTable extends EventEmitter implements Startable { +export class RoutingTable extends TypedEventEmitter implements Startable { public kBucketSize: number public kb?: KBucket public pingQueue: Queue diff --git a/packages/kad-dht/src/routing-table/k-bucket.ts b/packages/kad-dht/src/routing-table/k-bucket.ts index b8e510d0a2..57585926e9 100644 --- a/packages/kad-dht/src/routing-table/k-bucket.ts +++ b/packages/kad-dht/src/routing-table/k-bucket.ts @@ -27,7 +27,7 @@ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -import { EventEmitter } from '@libp2p/interface/events' +import { TypedEventEmitter } from '@libp2p/interface/events' import type { PeerId } from '@libp2p/interface/peer-id' function arrayEquals (array1: Uint8Array, array2: Uint8Array): boolean { @@ -122,10 +122,8 @@ export interface Bucket { /** * Implementation of a Kademlia DHT k-bucket used for storing * contact (peer node) information. - * - * @extends EventEmitter */ -export class KBucket extends EventEmitter { +export class KBucket extends TypedEventEmitter { public localNodeId: Uint8Array public root: Bucket private readonly numberOfNodesPerKBucket: number diff --git a/packages/kad-dht/src/topology-listener.ts b/packages/kad-dht/src/topology-listener.ts index 462b633a3c..8af9a210a4 100644 --- a/packages/kad-dht/src/topology-listener.ts +++ b/packages/kad-dht/src/topology-listener.ts @@ -1,4 +1,4 @@ -import { CustomEvent, EventEmitter } from '@libp2p/interface/events' +import { CustomEvent, TypedEventEmitter } from '@libp2p/interface/events' import { logger } from '@libp2p/logger' import type { KadDHTComponents } from '.' import type { PeerId } from '@libp2p/interface/peer-id' @@ -17,7 +17,7 @@ export interface TopologyListenerEvents { /** * Receives notifications of new peers joining the network that support the DHT protocol */ -export class TopologyListener extends EventEmitter implements Startable { +export class TopologyListener extends TypedEventEmitter implements Startable { private readonly log: Logger private readonly components: KadDHTComponents private readonly protocol: string diff --git a/packages/kad-dht/test/routing-table.spec.ts b/packages/kad-dht/test/routing-table.spec.ts index 669115c349..35381a044f 100644 --- a/packages/kad-dht/test/routing-table.spec.ts +++ b/packages/kad-dht/test/routing-table.spec.ts @@ -1,6 +1,6 @@ /* eslint-env mocha */ -import { EventEmitter, CustomEvent } from '@libp2p/interface/events' +import { TypedEventEmitter, CustomEvent } from '@libp2p/interface/events' import { mockConnectionManager } from '@libp2p/interface-compliance-tests/mocks' import { PeerSet } from '@libp2p/peer-collections' import { peerIdFromString } from '@libp2p/peer-id' @@ -33,7 +33,7 @@ describe('Routing Table', () => { beforeEach(async function () { this.timeout(20 * 1000) - const events = new EventEmitter() + const events = new TypedEventEmitter() components = { peerId: await createPeerId(), diff --git a/packages/kad-dht/test/rpc/handlers/get-providers.spec.ts b/packages/kad-dht/test/rpc/handlers/get-providers.spec.ts index 20cab3c7e7..18a3706f64 100644 --- a/packages/kad-dht/test/rpc/handlers/get-providers.spec.ts +++ b/packages/kad-dht/test/rpc/handlers/get-providers.spec.ts @@ -1,6 +1,6 @@ /* eslint-env mocha */ -import { EventEmitter } from '@libp2p/interface/events' +import { TypedEventEmitter } from '@libp2p/interface/events' import { PersistentPeerStore } from '@libp2p/peer-store' import { multiaddr } from '@multiformats/multiaddr' import { expect } from 'aegir/chai' @@ -43,7 +43,7 @@ describe('rpc - handlers - GetProviders', () => { peerStore = new PersistentPeerStore({ peerId, datastore: new MemoryDatastore(), - events: new EventEmitter() + events: new TypedEventEmitter() }) const components: GetProvidersHandlerComponents = { diff --git a/packages/kad-dht/test/rpc/handlers/get-value.spec.ts b/packages/kad-dht/test/rpc/handlers/get-value.spec.ts index 32cf1c9bba..ad79dda7c6 100644 --- a/packages/kad-dht/test/rpc/handlers/get-value.spec.ts +++ b/packages/kad-dht/test/rpc/handlers/get-value.spec.ts @@ -1,6 +1,6 @@ /* eslint-env mocha */ -import { EventEmitter } from '@libp2p/interface/events' +import { TypedEventEmitter } from '@libp2p/interface/events' import { PersistentPeerStore } from '@libp2p/peer-store' import { expect } from 'aegir/chai' import { MemoryDatastore } from 'datastore-core' @@ -40,7 +40,7 @@ describe('rpc - handlers - GetValue', () => { peerStore = new PersistentPeerStore({ peerId, datastore, - events: new EventEmitter() + events: new TypedEventEmitter() }) const components: GetValueHandlerComponents = { diff --git a/packages/kad-dht/test/rpc/index.node.ts b/packages/kad-dht/test/rpc/index.node.ts index da58989b23..25ced21d11 100644 --- a/packages/kad-dht/test/rpc/index.node.ts +++ b/packages/kad-dht/test/rpc/index.node.ts @@ -1,6 +1,6 @@ /* eslint-env mocha */ -import { EventEmitter } from '@libp2p/interface/events' +import { TypedEventEmitter } from '@libp2p/interface/events' import { start } from '@libp2p/interface/startable' import { mockStream } from '@libp2p/interface-compliance-tests/mocks' import { PersistentPeerStore } from '@libp2p/peer-store' @@ -51,7 +51,7 @@ describe('rpc', () => { } components.peerStore = new PersistentPeerStore({ ...components, - events: new EventEmitter() + events: new TypedEventEmitter() }) await start(...Object.values(components)) diff --git a/packages/kad-dht/test/utils/test-dht.ts b/packages/kad-dht/test/utils/test-dht.ts index 04be4041be..bfddebdaad 100644 --- a/packages/kad-dht/test/utils/test-dht.ts +++ b/packages/kad-dht/test/utils/test-dht.ts @@ -1,4 +1,4 @@ -import { EventEmitter } from '@libp2p/interface/events' +import { TypedEventEmitter } from '@libp2p/interface/events' import { start, stop } from '@libp2p/interface/startable' import { mockRegistrar, mockConnectionManager, mockNetwork } from '@libp2p/interface-compliance-tests/mocks' import { logger } from '@libp2p/logger' @@ -29,7 +29,7 @@ export class TestDHT { } async spawn (options: Partial = {}, autoStart = true): Promise { - const events = new EventEmitter() + const events = new TypedEventEmitter() const components: KadDHTComponents = { peerId: await createPeerId(), datastore: new MemoryDatastore(), diff --git a/packages/libp2p/src/address-manager/index.ts b/packages/libp2p/src/address-manager/index.ts index 44a8504f51..f6bafad41f 100644 --- a/packages/libp2p/src/address-manager/index.ts +++ b/packages/libp2p/src/address-manager/index.ts @@ -3,7 +3,7 @@ import { peerIdFromString } from '@libp2p/peer-id' import { multiaddr } from '@multiformats/multiaddr' import { debounce } from './utils.js' import type { Libp2pEvents } from '@libp2p/interface' -import type { EventEmitter } from '@libp2p/interface/events' +import type { TypedEventTarget } from '@libp2p/interface/events' import type { PeerId } from '@libp2p/interface/peer-id' import type { PeerStore } from '@libp2p/interface/peer-store' import type { TransportManager } from '@libp2p/interface-internal/transport-manager' @@ -38,7 +38,7 @@ export interface DefaultAddressManagerComponents { peerId: PeerId transportManager: TransportManager peerStore: PeerStore - events: EventEmitter + events: TypedEventTarget } /** diff --git a/packages/libp2p/src/circuit-relay/index.ts b/packages/libp2p/src/circuit-relay/index.ts index 91ab9007e4..5e8757fb10 100644 --- a/packages/libp2p/src/circuit-relay/index.ts +++ b/packages/libp2p/src/circuit-relay/index.ts @@ -35,7 +35,7 @@ */ import type { Limit } from './pb/index.js' -import type { EventEmitter } from '@libp2p/interface/events' +import type { TypedEventEmitter } from '@libp2p/interface/events' import type { PeerMap } from '@libp2p/peer-collections' import type { Multiaddr } from '@multiformats/multiaddr' @@ -51,7 +51,7 @@ export interface CircuitRelayServiceEvents { 'relay:advert:error': CustomEvent } -export interface CircuitRelayService extends EventEmitter { +export interface CircuitRelayService extends TypedEventEmitter { reservations: PeerMap } diff --git a/packages/libp2p/src/circuit-relay/server/advert-service.ts b/packages/libp2p/src/circuit-relay/server/advert-service.ts index 5d2c61990f..4e84f41c2c 100644 --- a/packages/libp2p/src/circuit-relay/server/advert-service.ts +++ b/packages/libp2p/src/circuit-relay/server/advert-service.ts @@ -1,4 +1,4 @@ -import { EventEmitter } from '@libp2p/interface/events' +import { TypedEventEmitter } from '@libp2p/interface/events' import { logger } from '@libp2p/logger' import pRetry from 'p-retry' import { codes } from '../../errors.js' @@ -31,7 +31,7 @@ export interface AdvertServiceEvents { 'advert:error': CustomEvent } -export class AdvertService extends EventEmitter implements Startable { +export class AdvertService extends TypedEventEmitter implements Startable { private readonly contentRouting: ContentRouting private timeout?: any private started: boolean diff --git a/packages/libp2p/src/circuit-relay/server/index.ts b/packages/libp2p/src/circuit-relay/server/index.ts index aed3d5be8b..8fce918570 100644 --- a/packages/libp2p/src/circuit-relay/server/index.ts +++ b/packages/libp2p/src/circuit-relay/server/index.ts @@ -1,5 +1,5 @@ import { setMaxListeners } from 'events' -import { EventEmitter } from '@libp2p/interface/events' +import { TypedEventEmitter } from '@libp2p/interface/events' import { logger } from '@libp2p/logger' import { peerIdFromBytes } from '@libp2p/peer-id' import { RecordEnvelope } from '@libp2p/peer-record' @@ -99,7 +99,7 @@ const defaults = { maxOutboundStopStreams: MAX_CONNECTIONS } -class CircuitRelayServer extends EventEmitter implements Startable, CircuitRelayService { +class CircuitRelayServer extends TypedEventEmitter implements Startable, CircuitRelayService { private readonly registrar: Registrar private readonly peerStore: PeerStore private readonly addressManager: AddressManager diff --git a/packages/libp2p/src/circuit-relay/transport/discovery.ts b/packages/libp2p/src/circuit-relay/transport/discovery.ts index 58ddc80cd9..77a4af1208 100644 --- a/packages/libp2p/src/circuit-relay/transport/discovery.ts +++ b/packages/libp2p/src/circuit-relay/transport/discovery.ts @@ -1,4 +1,4 @@ -import { EventEmitter } from '@libp2p/interface/events' +import { TypedEventEmitter } from '@libp2p/interface/events' import { logger } from '@libp2p/logger' import { RELAY_RENDEZVOUS_NS, @@ -32,7 +32,7 @@ export interface RelayDiscoveryComponents { * ReservationManager automatically makes a circuit v2 reservation on any connected * peers that support the circuit v2 HOP protocol. */ -export class RelayDiscovery extends EventEmitter implements Startable { +export class RelayDiscovery extends TypedEventEmitter implements Startable { private readonly peerId: PeerId private readonly peerStore: PeerStore private readonly contentRouting: ContentRouting diff --git a/packages/libp2p/src/circuit-relay/transport/index.ts b/packages/libp2p/src/circuit-relay/transport/index.ts index 483f9a0366..022b44c57e 100644 --- a/packages/libp2p/src/circuit-relay/transport/index.ts +++ b/packages/libp2p/src/circuit-relay/transport/index.ts @@ -17,7 +17,7 @@ import type { Libp2pEvents, AbortOptions } from '@libp2p/interface' import type { Connection, Stream } from '@libp2p/interface/connection' import type { ConnectionGater } from '@libp2p/interface/connection-gater' import type { ContentRouting } from '@libp2p/interface/content-routing' -import type { EventEmitter } from '@libp2p/interface/events' +import type { TypedEventTarget } from '@libp2p/interface/events' import type { PeerId } from '@libp2p/interface/peer-id' import type { PeerStore } from '@libp2p/interface/peer-store' import type { AddressManager } from '@libp2p/interface-internal/address-manager' @@ -50,7 +50,7 @@ export interface CircuitRelayTransportComponents extends RelayDiscoveryComponent addressManager: AddressManager contentRouting: ContentRouting connectionGater: ConnectionGater - events: EventEmitter + events: TypedEventTarget } interface ConnectOptions { diff --git a/packages/libp2p/src/circuit-relay/transport/listener.ts b/packages/libp2p/src/circuit-relay/transport/listener.ts index bb67007db9..29b6c6e608 100644 --- a/packages/libp2p/src/circuit-relay/transport/listener.ts +++ b/packages/libp2p/src/circuit-relay/transport/listener.ts @@ -1,5 +1,5 @@ import { CodeError } from '@libp2p/interface/errors' -import { EventEmitter } from '@libp2p/interface/events' +import { TypedEventEmitter } from '@libp2p/interface/events' import { logger } from '@libp2p/logger' import { PeerMap } from '@libp2p/peer-collections' import { peerIdFromString } from '@libp2p/peer-id' @@ -18,7 +18,7 @@ export interface CircuitRelayTransportListenerComponents { relayStore: ReservationStore } -class CircuitRelayTransportListener extends EventEmitter implements Listener { +class CircuitRelayTransportListener extends TypedEventEmitter implements Listener { private readonly connectionManager: ConnectionManager private readonly relayStore: ReservationStore private readonly listeningAddrs: PeerMap diff --git a/packages/libp2p/src/circuit-relay/transport/reservation-store.ts b/packages/libp2p/src/circuit-relay/transport/reservation-store.ts index 2edcd4f998..9300357240 100644 --- a/packages/libp2p/src/circuit-relay/transport/reservation-store.ts +++ b/packages/libp2p/src/circuit-relay/transport/reservation-store.ts @@ -1,4 +1,4 @@ -import { EventEmitter } from '@libp2p/interface/events' +import { TypedEventEmitter, type TypedEventTarget } from '@libp2p/interface/events' import { logger } from '@libp2p/logger' import { PeerMap } from '@libp2p/peer-collections' import { multiaddr } from '@multiformats/multiaddr' @@ -32,7 +32,7 @@ export interface RelayStoreComponents { connectionManager: ConnectionManager transportManager: TransportManager peerStore: PeerStore - events: EventEmitter + events: TypedEventTarget } export interface RelayStoreInit { @@ -76,12 +76,12 @@ export interface ReservationStoreEvents { 'relay:removed': CustomEvent } -export class ReservationStore extends EventEmitter implements Startable { +export class ReservationStore extends TypedEventEmitter implements Startable { private readonly peerId: PeerId private readonly connectionManager: ConnectionManager private readonly transportManager: TransportManager private readonly peerStore: PeerStore - private readonly events: EventEmitter + private readonly events: TypedEventTarget private readonly reserveQueue: PeerJobQueue private readonly reservations: PeerMap private readonly maxDiscoveredRelays: number diff --git a/packages/libp2p/src/components.ts b/packages/libp2p/src/components.ts index f11fb2cfb6..2d65d956dc 100644 --- a/packages/libp2p/src/components.ts +++ b/packages/libp2p/src/components.ts @@ -4,7 +4,7 @@ import type { Libp2pEvents } from '@libp2p/interface' import type { ConnectionProtector } from '@libp2p/interface/connection' import type { ConnectionGater } from '@libp2p/interface/connection-gater' import type { ContentRouting } from '@libp2p/interface/content-routing' -import type { EventEmitter } from '@libp2p/interface/events' +import type { TypedEventTarget } from '@libp2p/interface/events' import type { Metrics } from '@libp2p/interface/metrics' import type { PeerId } from '@libp2p/interface/peer-id' import type { PeerRouting } from '@libp2p/interface/peer-routing' @@ -18,7 +18,7 @@ import type { Datastore } from 'interface-datastore' export interface Components extends Record, Startable { peerId: PeerId - events: EventEmitter + events: TypedEventTarget addressManager: AddressManager peerStore: PeerStore upgrader: Upgrader @@ -35,7 +35,7 @@ export interface Components extends Record, Startable { export interface ComponentsInit { peerId?: PeerId - events?: EventEmitter + events?: TypedEventTarget addressManager?: AddressManager peerStore?: PeerStore upgrader?: Upgrader diff --git a/packages/libp2p/src/connection-manager/auto-dial.ts b/packages/libp2p/src/connection-manager/auto-dial.ts index 6d27e6f42b..a110adfd46 100644 --- a/packages/libp2p/src/connection-manager/auto-dial.ts +++ b/packages/libp2p/src/connection-manager/auto-dial.ts @@ -4,7 +4,7 @@ import { toString as uint8ArrayToString } from 'uint8arrays/to-string' import { PeerJobQueue } from '../utils/peer-job-queue.js' import { AUTO_DIAL_CONCURRENCY, AUTO_DIAL_DISCOVERED_PEERS_DEBOUNCE, AUTO_DIAL_INTERVAL, AUTO_DIAL_MAX_QUEUE_LENGTH, AUTO_DIAL_PEER_RETRY_THRESHOLD, AUTO_DIAL_PRIORITY, LAST_DIAL_FAILURE_KEY, MIN_CONNECTIONS } from './constants.js' import type { Libp2pEvents } from '@libp2p/interface' -import type { EventEmitter } from '@libp2p/interface/events' +import type { TypedEventTarget } from '@libp2p/interface/events' import type { PeerStore } from '@libp2p/interface/peer-store' import type { Startable } from '@libp2p/interface/startable' import type { ConnectionManager } from '@libp2p/interface-internal/connection-manager' @@ -24,7 +24,7 @@ interface AutoDialInit { interface AutoDialComponents { connectionManager: ConnectionManager peerStore: PeerStore - events: EventEmitter + events: TypedEventTarget } const defaultOptions = { diff --git a/packages/libp2p/src/connection-manager/connection-pruner.ts b/packages/libp2p/src/connection-manager/connection-pruner.ts index 04fb85d7fb..adbed0a56c 100644 --- a/packages/libp2p/src/connection-manager/connection-pruner.ts +++ b/packages/libp2p/src/connection-manager/connection-pruner.ts @@ -2,7 +2,7 @@ import { logger } from '@libp2p/logger' import { PeerMap } from '@libp2p/peer-collections' import { MAX_CONNECTIONS } from './constants.js' import type { Libp2pEvents } from '@libp2p/interface' -import type { EventEmitter } from '@libp2p/interface/events' +import type { TypedEventTarget } from '@libp2p/interface/events' import type { PeerStore } from '@libp2p/interface/peer-store' import type { ConnectionManager } from '@libp2p/interface-internal/connection-manager' import type { Multiaddr } from '@multiformats/multiaddr' @@ -17,7 +17,7 @@ interface ConnectionPrunerInit { interface ConnectionPrunerComponents { connectionManager: ConnectionManager peerStore: PeerStore - events: EventEmitter + events: TypedEventTarget } const defaultOptions = { @@ -33,7 +33,7 @@ export class ConnectionPruner { private readonly connectionManager: ConnectionManager private readonly peerStore: PeerStore private readonly allow: Multiaddr[] - private readonly events: EventEmitter + private readonly events: TypedEventTarget constructor (components: ConnectionPrunerComponents, init: ConnectionPrunerInit = {}) { this.maxConnections = init.maxConnections ?? defaultOptions.maxConnections diff --git a/packages/libp2p/src/connection-manager/index.ts b/packages/libp2p/src/connection-manager/index.ts index d94612fd9f..c13e49a53a 100644 --- a/packages/libp2p/src/connection-manager/index.ts +++ b/packages/libp2p/src/connection-manager/index.ts @@ -15,7 +15,7 @@ import { DialQueue } from './dial-queue.js' import type { PendingDial, AddressSorter, Libp2pEvents, AbortOptions } from '@libp2p/interface' import type { Connection, MultiaddrConnection } from '@libp2p/interface/connection' import type { ConnectionGater } from '@libp2p/interface/connection-gater' -import type { EventEmitter } from '@libp2p/interface/events' +import type { TypedEventTarget } from '@libp2p/interface/events' import type { Metrics } from '@libp2p/interface/metrics' import type { PeerId } from '@libp2p/interface/peer-id' import type { Peer, PeerStore } from '@libp2p/interface/peer-store' @@ -165,7 +165,7 @@ export interface DefaultConnectionManagerComponents { peerStore: PeerStore transportManager: TransportManager connectionGater: ConnectionGater - events: EventEmitter + events: TypedEventTarget } /** @@ -187,7 +187,7 @@ export class DefaultConnectionManager implements ConnectionManager, Startable { private readonly peerStore: PeerStore private readonly metrics?: Metrics - private readonly events: EventEmitter + private readonly events: TypedEventTarget constructor (components: DefaultConnectionManagerComponents, init: ConnectionManagerInit = {}) { this.maxConnections = init.maxConnections ?? defaultOptions.maxConnections diff --git a/packages/libp2p/src/identify/identify.ts b/packages/libp2p/src/identify/identify.ts index caa5248b45..940533ef50 100644 --- a/packages/libp2p/src/identify/identify.ts +++ b/packages/libp2p/src/identify/identify.ts @@ -21,7 +21,7 @@ import { Identify } from './pb/message.js' import type { IdentifyService, IdentifyServiceComponents, IdentifyServiceInit } from './index.js' import type { Libp2pEvents, IdentifyResult, SignedPeerRecord, AbortOptions } from '@libp2p/interface' import type { Connection, Stream } from '@libp2p/interface/connection' -import type { EventEmitter } from '@libp2p/interface/events' +import type { TypedEventTarget } from '@libp2p/interface/events' import type { PeerId } from '@libp2p/interface/peer-id' import type { Peer, PeerStore } from '@libp2p/interface/peer-store' import type { Startable } from '@libp2p/interface/startable' @@ -70,7 +70,7 @@ export class DefaultIdentifyService implements Startable, IdentifyService { private readonly maxPushOutgoingStreams: number private readonly maxIdentifyMessageSize: number private readonly maxObservedAddresses: number - private readonly events: EventEmitter + private readonly events: TypedEventTarget private readonly runOnTransientConnection: boolean constructor (components: IdentifyServiceComponents, init: IdentifyServiceInit) { diff --git a/packages/libp2p/src/identify/index.ts b/packages/libp2p/src/identify/index.ts index c74238e832..61dc2e3523 100644 --- a/packages/libp2p/src/identify/index.ts +++ b/packages/libp2p/src/identify/index.ts @@ -5,7 +5,7 @@ import { import { DefaultIdentifyService } from './identify.js' import { Identify } from './pb/message.js' import type { AbortOptions, IdentifyResult, Libp2pEvents } from '@libp2p/interface' -import type { EventEmitter } from '@libp2p/interface/events' +import type { TypedEventTarget } from '@libp2p/interface/events' import type { PeerId } from '@libp2p/interface/peer-id' import type { PeerStore } from '@libp2p/interface/peer-store' import type { Connection } from '@libp2p/interface/src/connection/index.js' @@ -58,7 +58,7 @@ export interface IdentifyServiceComponents { connectionManager: ConnectionManager registrar: Registrar addressManager: AddressManager - events: EventEmitter + events: TypedEventTarget } /** diff --git a/packages/libp2p/src/libp2p.ts b/packages/libp2p/src/libp2p.ts index 29c80f0cc7..cdc0c5caa8 100644 --- a/packages/libp2p/src/libp2p.ts +++ b/packages/libp2p/src/libp2p.ts @@ -2,7 +2,7 @@ import { setMaxListeners } from 'events' import { unmarshalPublicKey } from '@libp2p/crypto/keys' import { type ContentRouting, contentRouting } from '@libp2p/interface/content-routing' import { CodeError } from '@libp2p/interface/errors' -import { EventEmitter, CustomEvent } from '@libp2p/interface/events' +import { TypedEventEmitter, CustomEvent } from '@libp2p/interface/events' import { peerDiscovery } from '@libp2p/interface/peer-discovery' import { type PeerRouting, peerRouting } from '@libp2p/interface/peer-routing' import { DefaultKeyChain } from '@libp2p/keychain' @@ -42,7 +42,7 @@ import type { Datastore } from 'interface-datastore' const log = logger('libp2p') -export class Libp2pNode> extends EventEmitter implements Libp2p { +export class Libp2pNode> extends TypedEventEmitter implements Libp2p { public peerId: PeerId public peerStore: PeerStore public contentRouting: ContentRouting @@ -59,7 +59,7 @@ export class Libp2pNode> extends // event bus - components can listen to this emitter to be notified of system events // and also cause them to be emitted - const events = new EventEmitter() + const events = new TypedEventEmitter() const originalDispatch = events.dispatchEvent.bind(events) events.dispatchEvent = (evt: any) => { const internalResult = originalDispatch(evt) diff --git a/packages/libp2p/src/registrar.ts b/packages/libp2p/src/registrar.ts index c679888f4f..268a35c364 100644 --- a/packages/libp2p/src/registrar.ts +++ b/packages/libp2p/src/registrar.ts @@ -3,7 +3,7 @@ import { logger } from '@libp2p/logger' import merge from 'merge-options' import { codes } from './errors.js' import type { Libp2pEvents, PeerUpdate } from '@libp2p/interface' -import type { EventEmitter } from '@libp2p/interface/events' +import type { TypedEventTarget } from '@libp2p/interface/events' import type { PeerId } from '@libp2p/interface/peer-id' import type { PeerStore } from '@libp2p/interface/peer-store' import type { Topology } from '@libp2p/interface/topology' @@ -19,7 +19,7 @@ export interface RegistrarComponents { peerId: PeerId connectionManager: ConnectionManager peerStore: PeerStore - events: EventEmitter + events: TypedEventTarget } /** diff --git a/packages/libp2p/src/transport-manager.ts b/packages/libp2p/src/transport-manager.ts index 38f5359616..f18ecdcecc 100644 --- a/packages/libp2p/src/transport-manager.ts +++ b/packages/libp2p/src/transport-manager.ts @@ -5,7 +5,7 @@ import { logger } from '@libp2p/logger' import { codes } from './errors.js' import type { Libp2pEvents, AbortOptions } from '@libp2p/interface' import type { Connection } from '@libp2p/interface/connection' -import type { EventEmitter } from '@libp2p/interface/events' +import type { TypedEventTarget } from '@libp2p/interface/events' import type { Metrics } from '@libp2p/interface/metrics' import type { Startable } from '@libp2p/interface/startable' import type { Listener, Transport, Upgrader } from '@libp2p/interface/transport' @@ -23,7 +23,7 @@ export interface DefaultTransportManagerComponents { metrics?: Metrics addressManager: AddressManager upgrader: Upgrader - events: EventEmitter + events: TypedEventTarget } export class DefaultTransportManager implements TransportManager, Startable { diff --git a/packages/libp2p/src/upgrader.ts b/packages/libp2p/src/upgrader.ts index 18934e3ad0..ad27ba02db 100644 --- a/packages/libp2p/src/upgrader.ts +++ b/packages/libp2p/src/upgrader.ts @@ -11,7 +11,7 @@ import type { Libp2pEvents, AbortOptions } from '@libp2p/interface' import type { MultiaddrConnection, Connection, Stream, ConnectionProtector, NewStreamOptions } from '@libp2p/interface/connection' import type { ConnectionEncrypter, SecuredConnection } from '@libp2p/interface/connection-encrypter' import type { ConnectionGater } from '@libp2p/interface/connection-gater' -import type { EventEmitter } from '@libp2p/interface/events' +import type { TypedEventTarget } from '@libp2p/interface/events' import type { Metrics } from '@libp2p/interface/metrics' import type { PeerId } from '@libp2p/interface/peer-id' import type { PeerStore } from '@libp2p/interface/peer-store' @@ -104,7 +104,7 @@ export interface DefaultUpgraderComponents { connectionProtector?: ConnectionProtector registrar: Registrar peerStore: PeerStore - events: EventEmitter + events: TypedEventTarget } type EncryptedConn = Duplex, Source, Promise> @@ -116,7 +116,7 @@ export class DefaultUpgrader implements Upgrader { private readonly connectionEncryption: Map private readonly muxers: Map private readonly inboundUpgradeTimeout: number - private readonly events: EventEmitter + private readonly events: TypedEventTarget constructor (components: DefaultUpgraderComponents, init: UpgraderInit) { this.components = components diff --git a/packages/libp2p/test/addresses/address-manager.spec.ts b/packages/libp2p/test/addresses/address-manager.spec.ts index 7f67fa9b07..5bee38bb70 100644 --- a/packages/libp2p/test/addresses/address-manager.spec.ts +++ b/packages/libp2p/test/addresses/address-manager.spec.ts @@ -1,6 +1,6 @@ /* eslint-env mocha */ -import { EventEmitter } from '@libp2p/interface/events' +import { TypedEventEmitter, type TypedEventTarget } from '@libp2p/interface/events' import { createEd25519PeerId } from '@libp2p/peer-id-factory' import { multiaddr } from '@multiformats/multiaddr' import { expect } from 'aegir/chai' @@ -18,7 +18,7 @@ const announceAddreses = ['/dns4/peer.io'] describe('Address Manager', () => { let peerId: PeerId let peerStore: StubbedInstance - let events: EventEmitter + let events: TypedEventTarget beforeEach(async () => { peerId = await createEd25519PeerId() @@ -26,7 +26,7 @@ describe('Address Manager', () => { // @ts-expect-error incorrect return type patch: Promise.resolve({}) }) - events = new EventEmitter() + events = new TypedEventEmitter() }) it('should not need any addresses', () => { diff --git a/packages/libp2p/test/circuit-relay/hop.spec.ts b/packages/libp2p/test/circuit-relay/hop.spec.ts index 7c3405197c..b1beb7abb9 100644 --- a/packages/libp2p/test/circuit-relay/hop.spec.ts +++ b/packages/libp2p/test/circuit-relay/hop.spec.ts @@ -1,7 +1,7 @@ /* eslint-env mocha */ /* eslint max-nested-callbacks: ['error', 5] */ -import { EventEmitter } from '@libp2p/interface/events' +import { TypedEventEmitter, type TypedEventTarget } from '@libp2p/interface/events' import { isStartable } from '@libp2p/interface/startable' import { mockRegistrar, mockUpgrader, mockNetwork, mockConnectionManager, mockConnectionGater } from '@libp2p/interface-compliance-tests/mocks' import { PeerMap } from '@libp2p/peer-collections' @@ -38,7 +38,7 @@ interface Node { connectionManager: ConnectionManager circuitRelayTransport: Transport connectionGater: ConnectionGater - events: EventEmitter + events: TypedEventTarget } let peerIndex = 0 @@ -66,7 +66,7 @@ describe('circuit-relay hop protocol', function () { ]) const peerStore = stubInterface() - const events = new EventEmitter() + const events = new TypedEventEmitter() events.addEventListener('connection:open', (evt) => { const conn = evt.detail connections.set(conn.remotePeer, conn) diff --git a/packages/libp2p/test/circuit-relay/stop.spec.ts b/packages/libp2p/test/circuit-relay/stop.spec.ts index 872f01d104..f17642b951 100644 --- a/packages/libp2p/test/circuit-relay/stop.spec.ts +++ b/packages/libp2p/test/circuit-relay/stop.spec.ts @@ -1,6 +1,6 @@ /* eslint-env mocha */ -import { EventEmitter } from '@libp2p/interface/events' +import { TypedEventEmitter } from '@libp2p/interface/events' import { isStartable } from '@libp2p/interface/startable' import { mockStream } from '@libp2p/interface-compliance-tests/mocks' import { createEd25519PeerId } from '@libp2p/peer-id-factory' @@ -43,7 +43,7 @@ describe('circuit-relay stop protocol', function () { transportManager: stubInterface(), upgrader: stubInterface(), connectionGater: stubInterface(), - events: new EventEmitter() + events: new TypedEventEmitter() } transport = circuitRelayTransport({ diff --git a/packages/libp2p/test/connection-manager/auto-dial.spec.ts b/packages/libp2p/test/connection-manager/auto-dial.spec.ts index 3c5968bdf1..13634b49e1 100644 --- a/packages/libp2p/test/connection-manager/auto-dial.spec.ts +++ b/packages/libp2p/test/connection-manager/auto-dial.spec.ts @@ -1,6 +1,6 @@ /* eslint-env mocha */ -import { EventEmitter } from '@libp2p/interface/events' +import { TypedEventEmitter, type TypedEventTarget } from '@libp2p/interface/events' import { PeerMap } from '@libp2p/peer-collections' import { createEd25519PeerId } from '@libp2p/peer-id-factory' import { PersistentPeerStore } from '@libp2p/peer-store' @@ -23,13 +23,13 @@ import type { ConnectionManager } from '@libp2p/interface-internal/connection-ma describe('auto-dial', () => { let autoDialler: AutoDial - let events: EventEmitter + let events: TypedEventTarget let peerStore: PeerStore let peerId: PeerId beforeEach(async () => { peerId = await createEd25519PeerId() - events = new EventEmitter() + events = new TypedEventEmitter() peerStore = new PersistentPeerStore({ datastore: new MemoryDatastore(), events, diff --git a/packages/libp2p/test/connection-manager/direct.node.ts b/packages/libp2p/test/connection-manager/direct.node.ts index 6da375ad6b..ae5ff3aed3 100644 --- a/packages/libp2p/test/connection-manager/direct.node.ts +++ b/packages/libp2p/test/connection-manager/direct.node.ts @@ -6,7 +6,7 @@ import path from 'node:path' import { yamux } from '@chainsafe/libp2p-yamux' import { type Connection, type ConnectionProtector, isConnection } from '@libp2p/interface/connection' import { AbortError } from '@libp2p/interface/errors' -import { EventEmitter } from '@libp2p/interface/events' +import { TypedEventEmitter } from '@libp2p/interface/events' import { start, stop } from '@libp2p/interface/startable' import { mockConnection, mockConnectionGater, mockDuplex, mockMultiaddrConnection, mockUpgrader } from '@libp2p/interface-compliance-tests/mocks' import { mplex } from '@libp2p/mplex' @@ -58,7 +58,7 @@ describe('dialing (direct, TCP)', () => { createEd25519PeerId() ]) - const remoteEvents = new EventEmitter() + const remoteEvents = new TypedEventEmitter() remoteComponents = defaultComponents({ peerId: remotePeerId, events: remoteEvents, @@ -78,7 +78,7 @@ describe('dialing (direct, TCP)', () => { remoteTM = remoteComponents.transportManager = new DefaultTransportManager(remoteComponents) remoteTM.add(tcp()()) - const localEvents = new EventEmitter() + const localEvents = new TypedEventEmitter() localComponents = defaultComponents({ peerId: localPeerId, events: localEvents, diff --git a/packages/libp2p/test/connection-manager/direct.spec.ts b/packages/libp2p/test/connection-manager/direct.spec.ts index 780c45f605..305ae4e524 100644 --- a/packages/libp2p/test/connection-manager/direct.spec.ts +++ b/packages/libp2p/test/connection-manager/direct.spec.ts @@ -2,7 +2,7 @@ import { yamux } from '@chainsafe/libp2p-yamux' import { AbortError } from '@libp2p/interface/errors' -import { EventEmitter } from '@libp2p/interface/events' +import { TypedEventEmitter } from '@libp2p/interface/events' import { mockConnectionGater, mockDuplex, mockMultiaddrConnection, mockUpgrader, mockConnection } from '@libp2p/interface-compliance-tests/mocks' import { mplex } from '@libp2p/mplex' import { peerIdFromString } from '@libp2p/peer-id' @@ -45,7 +45,7 @@ describe('dialing (direct, WebSockets)', () => { let connectionManager: DefaultConnectionManager beforeEach(async () => { - const localEvents = new EventEmitter() + const localEvents = new TypedEventEmitter() localComponents = defaultComponents({ peerId: await createEd25519PeerId(), datastore: new MemoryDatastore(), diff --git a/packages/libp2p/test/connection-manager/index.node.ts b/packages/libp2p/test/connection-manager/index.node.ts index add7158a47..cac8b990d3 100644 --- a/packages/libp2p/test/connection-manager/index.node.ts +++ b/packages/libp2p/test/connection-manager/index.node.ts @@ -1,6 +1,6 @@ /* eslint-env mocha */ -import { EventEmitter } from '@libp2p/interface/events' +import { TypedEventEmitter } from '@libp2p/interface/events' import { start } from '@libp2p/interface/startable' import { mockConnection, mockDuplex, mockMultiaddrConnection } from '@libp2p/interface-compliance-tests/mocks' import { expect } from 'aegir/chai' @@ -53,7 +53,7 @@ describe('Connection Manager', () => { peerStore, transportManager: stubInterface(), connectionGater: stubInterface(), - events: new EventEmitter() + events: new TypedEventEmitter() }) const connectionManager = new DefaultConnectionManager(components, { maxConnections: 1000, @@ -91,7 +91,7 @@ describe('Connection Manager', () => { peerStore, transportManager: stubInterface(), connectionGater: stubInterface(), - events: new EventEmitter() + events: new TypedEventEmitter() }) const connectionManager = new DefaultConnectionManager(components, { maxConnections: 1000, diff --git a/packages/libp2p/test/connection-manager/index.spec.ts b/packages/libp2p/test/connection-manager/index.spec.ts index 699339da03..ee31843332 100644 --- a/packages/libp2p/test/connection-manager/index.spec.ts +++ b/packages/libp2p/test/connection-manager/index.spec.ts @@ -1,6 +1,6 @@ /* eslint-env mocha */ -import { EventEmitter } from '@libp2p/interface/events' +import { TypedEventEmitter } from '@libp2p/interface/events' import { KEEP_ALIVE } from '@libp2p/interface/peer-store/tags' import { mockConnection, mockDuplex, mockMultiaddrConnection, mockMetrics } from '@libp2p/interface-compliance-tests/mocks' import { createEd25519PeerId } from '@libp2p/peer-id-factory' @@ -365,7 +365,7 @@ describe('Connection Manager', () => { peerStore: stubInterface(), transportManager: stubInterface(), connectionGater: stubInterface(), - events: new EventEmitter() + events: new TypedEventEmitter() }, { ...defaultOptions, deny: [ @@ -393,7 +393,7 @@ describe('Connection Manager', () => { peerStore: stubInterface(), transportManager: stubInterface(), connectionGater: stubInterface(), - events: new EventEmitter() + events: new TypedEventEmitter() }, { ...defaultOptions, maxConnections: 1 @@ -425,7 +425,7 @@ describe('Connection Manager', () => { peerStore: stubInterface(), transportManager: stubInterface(), connectionGater: stubInterface(), - events: new EventEmitter() + events: new TypedEventEmitter() }, { ...defaultOptions, inboundConnectionThreshold: 1 @@ -461,7 +461,7 @@ describe('Connection Manager', () => { peerStore: stubInterface(), transportManager: stubInterface(), connectionGater: stubInterface(), - events: new EventEmitter() + events: new TypedEventEmitter() }, { ...defaultOptions, maxConnections: 1, @@ -497,7 +497,7 @@ describe('Connection Manager', () => { peerStore: stubInterface(), transportManager: stubInterface(), connectionGater: stubInterface(), - events: new EventEmitter() + events: new TypedEventEmitter() }, { ...defaultOptions, maxIncomingPendingConnections: 1 diff --git a/packages/libp2p/test/fetch/index.spec.ts b/packages/libp2p/test/fetch/index.spec.ts index 9ef87c88e5..7b90a0f7db 100644 --- a/packages/libp2p/test/fetch/index.spec.ts +++ b/packages/libp2p/test/fetch/index.spec.ts @@ -1,6 +1,6 @@ /* eslint-env mocha */ -import { EventEmitter } from '@libp2p/interface/events' +import { TypedEventEmitter } from '@libp2p/interface/events' import { start, stop } from '@libp2p/interface/startable' import { mockRegistrar, mockUpgrader, connectionPair } from '@libp2p/interface-compliance-tests/mocks' import { createEd25519PeerId } from '@libp2p/peer-id-factory' @@ -27,7 +27,7 @@ const defaultInit: FetchServiceInit = { async function createComponents (index: number): Promise { const peerId = await createEd25519PeerId() - const events = new EventEmitter() + const events = new TypedEventEmitter() const components = defaultComponents({ peerId, registrar: mockRegistrar(), diff --git a/packages/libp2p/test/identify/index.spec.ts b/packages/libp2p/test/identify/index.spec.ts index ed7d54ff09..63134a7d0c 100644 --- a/packages/libp2p/test/identify/index.spec.ts +++ b/packages/libp2p/test/identify/index.spec.ts @@ -1,7 +1,7 @@ /* eslint-env mocha */ /* eslint max-nested-callbacks: ["error", 6] */ -import { EventEmitter } from '@libp2p/interface/events' +import { TypedEventEmitter } from '@libp2p/interface/events' import { start, stop } from '@libp2p/interface/startable' import { mockConnectionGater, mockRegistrar, mockUpgrader, connectionPair } from '@libp2p/interface-compliance-tests/mocks' import { createEd25519PeerId } from '@libp2p/peer-id-factory' @@ -51,7 +51,7 @@ const protocols = [MULTICODEC_IDENTIFY, MULTICODEC_IDENTIFY_PUSH] async function createComponents (index: number): Promise { const peerId = await createEd25519PeerId() - const events = new EventEmitter() + const events = new TypedEventEmitter() const components = defaultComponents({ peerId, datastore: new MemoryDatastore(), diff --git a/packages/libp2p/test/identify/push.spec.ts b/packages/libp2p/test/identify/push.spec.ts index 2916a8e1c4..a73bdc3655 100644 --- a/packages/libp2p/test/identify/push.spec.ts +++ b/packages/libp2p/test/identify/push.spec.ts @@ -1,6 +1,6 @@ /* eslint-env mocha */ -import { EventEmitter } from '@libp2p/interface/events' +import { TypedEventEmitter } from '@libp2p/interface/events' import { start, stop } from '@libp2p/interface/startable' import { mockConnectionGater, mockRegistrar, mockUpgrader, connectionPair } from '@libp2p/interface-compliance-tests/mocks' import { createEd25519PeerId } from '@libp2p/peer-id-factory' @@ -42,7 +42,7 @@ const protocols = [MULTICODEC_IDENTIFY, MULTICODEC_IDENTIFY_PUSH] async function createComponents (index: number): Promise { const peerId = await createEd25519PeerId() - const events = new EventEmitter() + const events = new TypedEventEmitter() const components = defaultComponents({ peerId, datastore: new MemoryDatastore(), diff --git a/packages/libp2p/test/peer-discovery/index.node.ts b/packages/libp2p/test/peer-discovery/index.node.ts index 7adfb0c867..d3d6bd0939 100644 --- a/packages/libp2p/test/peer-discovery/index.node.ts +++ b/packages/libp2p/test/peer-discovery/index.node.ts @@ -2,7 +2,7 @@ import { bootstrap } from '@libp2p/bootstrap' import { randomBytes } from '@libp2p/crypto' -import { EventEmitter } from '@libp2p/interface/events' +import { TypedEventEmitter } from '@libp2p/interface/events' import { peerDiscovery } from '@libp2p/interface/peer-discovery' import { kadDHT } from '@libp2p/kad-dht' import { mdns } from '@libp2p/mdns' @@ -22,7 +22,7 @@ import type { KadDHT } from '@libp2p/kad-dht' const listenAddr = multiaddr('/ip4/127.0.0.1/tcp/0') -class TestPeerDiscovery extends EventEmitter implements PeerDiscovery { +class TestPeerDiscovery extends TypedEventEmitter implements PeerDiscovery { get [peerDiscovery] (): PeerDiscovery { return this } diff --git a/packages/libp2p/test/ping/index.spec.ts b/packages/libp2p/test/ping/index.spec.ts index c37d5d0ebe..9b6aef1385 100644 --- a/packages/libp2p/test/ping/index.spec.ts +++ b/packages/libp2p/test/ping/index.spec.ts @@ -1,6 +1,6 @@ /* eslint-env mocha */ -import { EventEmitter } from '@libp2p/interface/events' +import { TypedEventEmitter } from '@libp2p/interface/events' import { start, stop } from '@libp2p/interface/startable' import { mockRegistrar, mockUpgrader, connectionPair } from '@libp2p/interface-compliance-tests/mocks' import { createEd25519PeerId } from '@libp2p/peer-id-factory' @@ -28,7 +28,7 @@ const defaultInit: PingServiceInit = { async function createComponents (index: number): Promise { const peerId = await createEd25519PeerId() - const events = new EventEmitter() + const events = new TypedEventEmitter() const components = defaultComponents({ peerId, registrar: mockRegistrar(), diff --git a/packages/libp2p/test/registrar/registrar.spec.ts b/packages/libp2p/test/registrar/registrar.spec.ts index 0e5b585acf..138b45b30e 100644 --- a/packages/libp2p/test/registrar/registrar.spec.ts +++ b/packages/libp2p/test/registrar/registrar.spec.ts @@ -2,7 +2,7 @@ import { yamux } from '@chainsafe/libp2p-yamux' import { CodeError } from '@libp2p/interface/errors' -import { EventEmitter } from '@libp2p/interface/events' +import { TypedEventEmitter, type TypedEventTarget } from '@libp2p/interface/events' import { mockDuplex, mockMultiaddrConnection, mockUpgrader, mockConnection } from '@libp2p/interface-compliance-tests/mocks' import { mplex } from '@libp2p/mplex' import { createEd25519PeerId } from '@libp2p/peer-id-factory' @@ -43,7 +43,7 @@ describe('registrar', () => { describe('errors', () => { beforeEach(() => { - const events = new EventEmitter() + const events = new TypedEventEmitter() components = defaultComponents({ peerId, events, @@ -81,13 +81,13 @@ describe('registrar', () => { let peerId: PeerId let connectionManager: StubbedInstance let peerStore: StubbedInstance - let events: EventEmitter + let events: TypedEventTarget beforeEach(async () => { peerId = await createEd25519PeerId() connectionManager = stubInterface() peerStore = stubInterface() - events = new EventEmitter() + events = new TypedEventEmitter() registrar = new DefaultRegistrar({ peerId, diff --git a/packages/libp2p/test/transports/transport-manager.node.ts b/packages/libp2p/test/transports/transport-manager.node.ts index 7404e88bbe..290414e618 100644 --- a/packages/libp2p/test/transports/transport-manager.node.ts +++ b/packages/libp2p/test/transports/transport-manager.node.ts @@ -1,6 +1,6 @@ /* eslint-env mocha */ -import { EventEmitter } from '@libp2p/interface/events' +import { TypedEventEmitter } from '@libp2p/interface/events' import { start, stop } from '@libp2p/interface/startable' import { FaultTolerance } from '@libp2p/interface/transport' import { mockUpgrader } from '@libp2p/interface-compliance-tests/mocks' @@ -33,7 +33,7 @@ describe('Transport Manager (TCP)', () => { }) beforeEach(async () => { - const events = new EventEmitter() + const events = new TypedEventEmitter() components = defaultComponents({ peerId: localPeer, events, diff --git a/packages/libp2p/test/transports/transport-manager.spec.ts b/packages/libp2p/test/transports/transport-manager.spec.ts index 89024dd8bc..c71a124a92 100644 --- a/packages/libp2p/test/transports/transport-manager.spec.ts +++ b/packages/libp2p/test/transports/transport-manager.spec.ts @@ -1,6 +1,6 @@ /* eslint-env mocha */ -import { EventEmitter } from '@libp2p/interface/events' +import { TypedEventEmitter } from '@libp2p/interface/events' import { start, stop } from '@libp2p/interface/startable' import { FaultTolerance } from '@libp2p/interface/transport' import { mockUpgrader } from '@libp2p/interface-compliance-tests/mocks' @@ -26,7 +26,7 @@ describe('Transport Manager (WebSockets)', () => { let components: Components beforeEach(async () => { - const events = new EventEmitter() + const events = new TypedEventEmitter() components = { peerId: await createEd25519PeerId(), events, diff --git a/packages/libp2p/test/upgrading/upgrader.spec.ts b/packages/libp2p/test/upgrading/upgrader.spec.ts index f1343f128e..6f83c08ecd 100644 --- a/packages/libp2p/test/upgrading/upgrader.spec.ts +++ b/packages/libp2p/test/upgrading/upgrader.spec.ts @@ -1,7 +1,7 @@ /* eslint-env mocha */ import { yamux } from '@chainsafe/libp2p-yamux' -import { EventEmitter } from '@libp2p/interface/events' +import { TypedEventEmitter } from '@libp2p/interface/events' import { mockConnectionGater, mockConnectionManager, mockMultiaddrConnPair, mockRegistrar, mockStream, mockMuxer } from '@libp2p/interface-compliance-tests/mocks' import { mplex } from '@libp2p/mplex' import { createEd25519PeerId } from '@libp2p/peer-id-factory' @@ -76,7 +76,7 @@ describe('Upgrader', () => { registrar: mockRegistrar(), datastore: new MemoryDatastore(), connectionProtector: localConnectionProtector, - events: new EventEmitter() + events: new TypedEventEmitter() }) localComponents.peerStore = new PersistentPeerStore(localComponents) localComponents.connectionManager = mockConnectionManager(localComponents) @@ -103,7 +103,7 @@ describe('Upgrader', () => { registrar: mockRegistrar(), datastore: new MemoryDatastore(), connectionProtector: remoteConnectionProtector, - events: new EventEmitter() + events: new TypedEventEmitter() }) remoteComponents.peerStore = new PersistentPeerStore(remoteComponents) remoteComponents.connectionManager = mockConnectionManager(remoteComponents) diff --git a/packages/libp2p/test/upnp-nat/upnp-nat.node.ts b/packages/libp2p/test/upnp-nat/upnp-nat.node.ts index 42d6cc6407..8e39909147 100644 --- a/packages/libp2p/test/upnp-nat/upnp-nat.node.ts +++ b/packages/libp2p/test/upnp-nat/upnp-nat.node.ts @@ -1,6 +1,6 @@ /* eslint-env mocha */ -import { EventEmitter } from '@libp2p/interface/events' +import { TypedEventEmitter } from '@libp2p/interface/events' import { start, stop } from '@libp2p/interface/startable' import { FaultTolerance } from '@libp2p/interface/transport' import { mockUpgrader } from '@libp2p/interface-compliance-tests/mocks' @@ -31,7 +31,7 @@ describe('UPnP NAT (TCP)', () => { let client: StubbedInstance async function createNatManager (addrs = DEFAULT_ADDRESSES, natManagerOptions = {}): Promise<{ natManager: any, components: Components }> { - const events = new EventEmitter() + const events = new TypedEventEmitter() const components: any = defaultComponents({ peerId: await createEd25519PeerId(), upgrader: mockUpgrader({ events }), diff --git a/packages/peer-discovery-bootstrap/src/index.ts b/packages/peer-discovery-bootstrap/src/index.ts index 1debb10fc6..7400d494f4 100644 --- a/packages/peer-discovery-bootstrap/src/index.ts +++ b/packages/peer-discovery-bootstrap/src/index.ts @@ -1,4 +1,4 @@ -import { EventEmitter } from '@libp2p/interface/events' +import { TypedEventEmitter } from '@libp2p/interface/events' import { peerDiscovery } from '@libp2p/interface/peer-discovery' import { logger } from '@libp2p/logger' import { peerIdFromString } from '@libp2p/peer-id' @@ -50,7 +50,7 @@ export interface BootstrapComponents { /** * Emits 'peer' events on a regular interval for each peer in the provided list. */ -class Bootstrap extends EventEmitter implements PeerDiscovery, Startable { +class Bootstrap extends TypedEventEmitter implements PeerDiscovery, Startable { static tag = 'bootstrap' private timer?: ReturnType diff --git a/packages/peer-discovery-mdns/src/index.ts b/packages/peer-discovery-mdns/src/index.ts index 7424131c06..98d568640e 100644 --- a/packages/peer-discovery-mdns/src/index.ts +++ b/packages/peer-discovery-mdns/src/index.ts @@ -1,4 +1,4 @@ -import { CustomEvent, EventEmitter } from '@libp2p/interface/events' +import { CustomEvent, TypedEventEmitter } from '@libp2p/interface/events' import { peerDiscovery } from '@libp2p/interface/peer-discovery' import { logger } from '@libp2p/logger' import multicastDNS from 'multicast-dns' @@ -24,7 +24,7 @@ export interface MulticastDNSComponents { addressManager: AddressManager } -class MulticastDNS extends EventEmitter implements PeerDiscovery, Startable { +class MulticastDNS extends TypedEventEmitter implements PeerDiscovery, Startable { public mdns?: multicastDNS.MulticastDNS private readonly broadcast: boolean diff --git a/packages/peer-store/src/index.ts b/packages/peer-store/src/index.ts index d130a8a7c3..ec9b4632bf 100644 --- a/packages/peer-store/src/index.ts +++ b/packages/peer-store/src/index.ts @@ -3,7 +3,7 @@ import { RecordEnvelope, PeerRecord } from '@libp2p/peer-record' import all from 'it-all' import { PersistentStore, type PeerUpdate } from './store.js' import type { Libp2pEvents } from '@libp2p/interface' -import type { EventEmitter } from '@libp2p/interface/events' +import type { TypedEventTarget } from '@libp2p/interface/events' import type { PeerId } from '@libp2p/interface/peer-id' import type { PeerStore, Peer, PeerData, PeerQuery } from '@libp2p/interface/peer-store' import type { Multiaddr } from '@multiformats/multiaddr' @@ -14,7 +14,7 @@ const log = logger('libp2p:peer-store') export interface PersistentPeerStoreComponents { peerId: PeerId datastore: Datastore - events: EventEmitter + events: TypedEventTarget } /** @@ -33,7 +33,7 @@ export interface PersistentPeerStoreInit { */ export class PersistentPeerStore implements PeerStore { private readonly store: PersistentStore - private readonly events: EventEmitter + private readonly events: TypedEventTarget private readonly peerId: PeerId constructor (components: PersistentPeerStoreComponents, init: PersistentPeerStoreInit = {}) { diff --git a/packages/peer-store/test/index.spec.ts b/packages/peer-store/test/index.spec.ts index 868d811c72..e5fd106beb 100644 --- a/packages/peer-store/test/index.spec.ts +++ b/packages/peer-store/test/index.spec.ts @@ -1,7 +1,7 @@ /* eslint-env mocha */ /* eslint max-nested-callbacks: ["error", 6] */ -import { EventEmitter } from '@libp2p/interface/events' +import { TypedEventEmitter, type TypedEventTarget } from '@libp2p/interface/events' import { createEd25519PeerId } from '@libp2p/peer-id-factory' import { RecordEnvelope, PeerRecord } from '@libp2p/peer-record' import { multiaddr } from '@multiformats/multiaddr' @@ -18,12 +18,12 @@ describe('PersistentPeerStore', () => { let peerId: PeerId let otherPeerId: PeerId let peerStore: PersistentPeerStore - let events: EventEmitter + let events: TypedEventTarget beforeEach(async () => { peerId = await createEd25519PeerId() otherPeerId = await createEd25519PeerId() - events = new EventEmitter() + events = new TypedEventEmitter() peerStore = new PersistentPeerStore({ peerId, events, datastore: new MemoryDatastore() }) }) diff --git a/packages/peer-store/test/merge.spec.ts b/packages/peer-store/test/merge.spec.ts index 304512781f..eefeec19c7 100644 --- a/packages/peer-store/test/merge.spec.ts +++ b/packages/peer-store/test/merge.spec.ts @@ -1,7 +1,7 @@ /* eslint-env mocha */ /* eslint max-nested-callbacks: ["error", 6] */ -import { EventEmitter } from '@libp2p/interface/events' +import { TypedEventEmitter, type TypedEventTarget } from '@libp2p/interface/events' import { createEd25519PeerId } from '@libp2p/peer-id-factory' import { multiaddr } from '@multiformats/multiaddr' import { expect } from 'aegir/chai' @@ -20,12 +20,12 @@ describe('merge', () => { let peerId: PeerId let otherPeerId: PeerId let peerStore: PersistentPeerStore - let events: EventEmitter + let events: TypedEventTarget beforeEach(async () => { peerId = await createEd25519PeerId() otherPeerId = await createEd25519PeerId() - events = new EventEmitter() + events = new TypedEventEmitter() peerStore = new PersistentPeerStore({ peerId, events, datastore: new MemoryDatastore() }) }) diff --git a/packages/peer-store/test/patch.spec.ts b/packages/peer-store/test/patch.spec.ts index a30e22e872..929425dcb9 100644 --- a/packages/peer-store/test/patch.spec.ts +++ b/packages/peer-store/test/patch.spec.ts @@ -1,7 +1,7 @@ /* eslint-env mocha */ /* eslint max-nested-callbacks: ["error", 6] */ -import { EventEmitter } from '@libp2p/interface/events' +import { TypedEventEmitter, type TypedEventTarget } from '@libp2p/interface/events' import { createEd25519PeerId } from '@libp2p/peer-id-factory' import { multiaddr } from '@multiformats/multiaddr' import { expect } from 'aegir/chai' @@ -20,12 +20,12 @@ describe('patch', () => { let peerId: PeerId let otherPeerId: PeerId let peerStore: PersistentPeerStore - let events: EventEmitter + let events: TypedEventTarget beforeEach(async () => { peerId = await createEd25519PeerId() otherPeerId = await createEd25519PeerId() - events = new EventEmitter() + events = new TypedEventEmitter() peerStore = new PersistentPeerStore({ peerId, events, datastore: new MemoryDatastore() }) }) diff --git a/packages/peer-store/test/save.spec.ts b/packages/peer-store/test/save.spec.ts index 43552cb883..23a7e29905 100644 --- a/packages/peer-store/test/save.spec.ts +++ b/packages/peer-store/test/save.spec.ts @@ -1,7 +1,7 @@ /* eslint-env mocha */ /* eslint max-nested-callbacks: ["error", 6] */ -import { EventEmitter } from '@libp2p/interface/events' +import { TypedEventEmitter, type TypedEventTarget } from '@libp2p/interface/events' import { createEd25519PeerId, createRSAPeerId, createSecp256k1PeerId } from '@libp2p/peer-id-factory' import { multiaddr } from '@multiformats/multiaddr' import { expect } from 'aegir/chai' @@ -23,12 +23,12 @@ describe('save', () => { let peerId: PeerId let otherPeerId: PeerId let peerStore: PersistentPeerStore - let events: EventEmitter + let events: TypedEventTarget beforeEach(async () => { peerId = await createEd25519PeerId() otherPeerId = await createEd25519PeerId() - events = new EventEmitter() + events = new TypedEventEmitter() peerStore = new PersistentPeerStore({ peerId, events, datastore: new MemoryDatastore() }) }) diff --git a/packages/protocol-perf/test/index.spec.ts b/packages/protocol-perf/test/index.spec.ts index 83fd6c310f..fc8299ed10 100644 --- a/packages/protocol-perf/test/index.spec.ts +++ b/packages/protocol-perf/test/index.spec.ts @@ -1,6 +1,6 @@ /* eslint-env mocha */ -import { EventEmitter } from '@libp2p/interface/events' +import { TypedEventEmitter } from '@libp2p/interface/events' import { start, stop } from '@libp2p/interface/startable' import { connectionPair, mockRegistrar, type MockNetworkComponents, mockConnectionManager } from '@libp2p/interface-compliance-tests/mocks' import { createEd25519PeerId } from '@libp2p/peer-id-factory' @@ -11,7 +11,7 @@ export async function createComponents (): Promise { const components: any = { peerId: await createEd25519PeerId(), registrar: mockRegistrar(), - events: new EventEmitter() + events: new TypedEventEmitter() } components.connectionManager = mockConnectionManager(components) diff --git a/packages/pubsub/src/index.ts b/packages/pubsub/src/index.ts index b8760e3a4f..2de4fa3fce 100644 --- a/packages/pubsub/src/index.ts +++ b/packages/pubsub/src/index.ts @@ -1,5 +1,5 @@ import { CodeError } from '@libp2p/interface/errors' -import { EventEmitter, CustomEvent } from '@libp2p/interface/events' +import { TypedEventEmitter, CustomEvent } from '@libp2p/interface/events' import { type PubSub, type Message, type StrictNoSign, type StrictSign, type PubSubInit, type PubSubEvents, type PeerStreams, type PubSubRPCMessage, type PubSubRPC, type PubSubRPCSubscription, type SubscriptionChangeData, type PublishResult, type TopicValidatorFn, TopicValidatorResult } from '@libp2p/interface/pubsub' import { logger } from '@libp2p/logger' import { PeerMap, PeerSet } from '@libp2p/peer-collections' @@ -28,7 +28,7 @@ export interface PubSubComponents { * PubSubBaseProtocol handles the peers and connections logic for pubsub routers * and specifies the API that pubsub routers should have. */ -export abstract class PubSubBaseProtocol = PubSubEvents> extends EventEmitter implements PubSub { +export abstract class PubSubBaseProtocol = PubSubEvents> extends TypedEventEmitter implements PubSub { public started: boolean /** * Map of topics to which peers are subscribed to diff --git a/packages/pubsub/src/peer-streams.ts b/packages/pubsub/src/peer-streams.ts index c4a13387a5..8e1646907a 100644 --- a/packages/pubsub/src/peer-streams.ts +++ b/packages/pubsub/src/peer-streams.ts @@ -1,4 +1,4 @@ -import { EventEmitter, CustomEvent } from '@libp2p/interface/events' +import { TypedEventEmitter, CustomEvent } from '@libp2p/interface/events' import { logger } from '@libp2p/logger' import { abortableSource } from 'abortable-iterator' import * as lp from 'it-length-prefixed' @@ -20,7 +20,7 @@ export interface PeerStreamsInit { /** * Thin wrapper around a peer's inbound / outbound pubsub streams */ -export class PeerStreams extends EventEmitter { +export class PeerStreams extends TypedEventEmitter { public readonly id: PeerId public readonly protocol: string /** diff --git a/packages/transport-tcp/src/listener.ts b/packages/transport-tcp/src/listener.ts index 95792ed137..ee2d1a20f9 100644 --- a/packages/transport-tcp/src/listener.ts +++ b/packages/transport-tcp/src/listener.ts @@ -1,6 +1,6 @@ import net from 'net' import { CodeError } from '@libp2p/interface/errors' -import { EventEmitter, CustomEvent } from '@libp2p/interface/events' +import { TypedEventEmitter, CustomEvent } from '@libp2p/interface/events' import { logger } from '@libp2p/logger' import { CODE_P2P } from './constants.js' import { toMultiaddrConnection } from './socket-to-conn.js' @@ -71,7 +71,7 @@ type Status = { code: TCPListenerStatusCode.INACTIVE } | { netConfig: NetConfig } -export class TCPListener extends EventEmitter implements Listener { +export class TCPListener extends TypedEventEmitter implements Listener { private readonly server: net.Server /** Keep track of open connections to destroy in case of timeout */ private readonly connections = new Set() diff --git a/packages/transport-tcp/test/connection-limits.spec.ts b/packages/transport-tcp/test/connection-limits.spec.ts index 30aea96ac7..67a47c23e7 100644 --- a/packages/transport-tcp/test/connection-limits.spec.ts +++ b/packages/transport-tcp/test/connection-limits.spec.ts @@ -1,6 +1,6 @@ import net from 'node:net' import { promisify } from 'util' -import { EventEmitter } from '@libp2p/interface/events' +import { TypedEventEmitter } from '@libp2p/interface/events' import { mockUpgrader } from '@libp2p/interface-compliance-tests/mocks' import { multiaddr } from '@multiformats/multiaddr' import { expect } from 'aegir/chai' @@ -88,7 +88,7 @@ describe('closeAbove/listenBelow', () => { const trasnport = tcp({ closeServerOnMaxConnections: { listenBelow, closeAbove } })() const upgrader = mockUpgrader({ - events: new EventEmitter() + events: new TypedEventEmitter() }) const listener = trasnport.createListener({ upgrader }) as TCPListener // eslint-disable-next-line @typescript-eslint/promise-function-async @@ -115,7 +115,7 @@ describe('closeAbove/listenBelow', () => { const trasnport = tcp({ closeServerOnMaxConnections: { listenBelow, closeAbove } })() const upgrader = mockUpgrader({ - events: new EventEmitter() + events: new TypedEventEmitter() }) const listener = trasnport.createListener({ upgrader }) as TCPListener // eslint-disable-next-line @typescript-eslint/promise-function-async @@ -150,7 +150,7 @@ describe('closeAbove/listenBelow', () => { const trasnport = tcp({ closeServerOnMaxConnections: { listenBelow, closeAbove } })() const upgrader = mockUpgrader({ - events: new EventEmitter() + events: new TypedEventEmitter() }) const listener = trasnport.createListener({ upgrader }) as TCPListener // eslint-disable-next-line @typescript-eslint/promise-function-async @@ -181,7 +181,7 @@ describe('closeAbove/listenBelow', () => { const trasnport = tcp({ closeServerOnMaxConnections: { listenBelow, closeAbove } })() const upgrader = mockUpgrader({ - events: new EventEmitter() + events: new TypedEventEmitter() }) const listener = trasnport.createListener({ upgrader }) as TCPListener // eslint-disable-next-line @typescript-eslint/promise-function-async diff --git a/packages/transport-tcp/test/connection.spec.ts b/packages/transport-tcp/test/connection.spec.ts index 0308d61708..a8cb893edb 100644 --- a/packages/transport-tcp/test/connection.spec.ts +++ b/packages/transport-tcp/test/connection.spec.ts @@ -1,4 +1,4 @@ -import { EventEmitter } from '@libp2p/interface/events' +import { TypedEventEmitter } from '@libp2p/interface/events' import { mockUpgrader } from '@libp2p/interface-compliance-tests/mocks' import { multiaddr } from '@multiformats/multiaddr' import { expect } from 'aegir/chai' @@ -13,7 +13,7 @@ describe('valid localAddr and remoteAddr', () => { beforeEach(() => { transport = tcp()() upgrader = mockUpgrader({ - events: new EventEmitter() + events: new TypedEventEmitter() }) }) diff --git a/packages/transport-tcp/test/listen-dial.spec.ts b/packages/transport-tcp/test/listen-dial.spec.ts index a2988bce77..4c7f608350 100644 --- a/packages/transport-tcp/test/listen-dial.spec.ts +++ b/packages/transport-tcp/test/listen-dial.spec.ts @@ -1,6 +1,6 @@ import os from 'os' import path from 'path' -import { EventEmitter } from '@libp2p/interface/events' +import { TypedEventEmitter } from '@libp2p/interface/events' import { mockRegistrar, mockUpgrader } from '@libp2p/interface-compliance-tests/mocks' import { multiaddr } from '@multiformats/multiaddr' import { expect } from 'aegir/chai' @@ -22,7 +22,7 @@ describe('listen', () => { beforeEach(() => { transport = tcp()() upgrader = mockUpgrader({ - events: new EventEmitter() + events: new TypedEventEmitter() }) }) @@ -175,7 +175,7 @@ describe('dial', () => { }) upgrader = mockUpgrader({ registrar, - events: new EventEmitter() + events: new TypedEventEmitter() }) transport = tcp()() diff --git a/packages/transport-tcp/test/max-connections.spec.ts b/packages/transport-tcp/test/max-connections.spec.ts index 13d18d0c14..495a23e991 100644 --- a/packages/transport-tcp/test/max-connections.spec.ts +++ b/packages/transport-tcp/test/max-connections.spec.ts @@ -1,6 +1,6 @@ import net from 'node:net' import { promisify } from 'node:util' -import { EventEmitter } from '@libp2p/interface/events' +import { TypedEventEmitter } from '@libp2p/interface/events' import { mockUpgrader } from '@libp2p/interface-compliance-tests/mocks' import { multiaddr } from '@multiformats/multiaddr' import { expect } from 'aegir/chai' @@ -22,7 +22,7 @@ describe('maxConnections', () => { const transport = tcp({ maxConnections })() const upgrader = mockUpgrader({ - events: new EventEmitter() + events: new TypedEventEmitter() }) const listener = transport.createListener({ upgrader }) // eslint-disable-next-line @typescript-eslint/promise-function-async diff --git a/packages/transport-webrtc/src/private-to-private/listener.ts b/packages/transport-webrtc/src/private-to-private/listener.ts index 53a3d299c6..6a73e9e14a 100644 --- a/packages/transport-webrtc/src/private-to-private/listener.ts +++ b/packages/transport-webrtc/src/private-to-private/listener.ts @@ -1,4 +1,4 @@ -import { EventEmitter } from '@libp2p/interface/events' +import { TypedEventEmitter } from '@libp2p/interface/events' import { Circuit } from '@multiformats/mafmt' import type { PeerId } from '@libp2p/interface/peer-id' import type { ListenerEvents, Listener } from '@libp2p/interface/transport' @@ -14,7 +14,7 @@ export interface WebRTCPeerListenerInit { shutdownController: AbortController } -export class WebRTCPeerListener extends EventEmitter implements Listener { +export class WebRTCPeerListener extends TypedEventEmitter implements Listener { private readonly peerId: PeerId private readonly transportManager: TransportManager private readonly shutdownController: AbortController diff --git a/packages/transport-websockets/.aegir.js b/packages/transport-websockets/.aegir.js index 1a81ef61be..d7e24c7d10 100644 --- a/packages/transport-websockets/.aegir.js +++ b/packages/transport-websockets/.aegir.js @@ -6,7 +6,7 @@ export default { async before () { const { multiaddr } = await import('@multiformats/multiaddr') const { mockRegistrar, mockUpgrader } = await import('@libp2p/interface-compliance-tests/mocks') - const { EventEmitter } = await import('@libp2p/interface/events') + const { TypedEventEmitter } = await import('@libp2p/interface/events') const { webSockets } = await import('./dist/src/index.js') const protocol = '/echo/1.0.0' @@ -19,7 +19,7 @@ export default { }) const upgrader = mockUpgrader({ registrar, - events: new EventEmitter() + events: new TypedEventEmitter() }) const ws = webSockets()() diff --git a/packages/transport-websockets/src/listener.ts b/packages/transport-websockets/src/listener.ts index 9adb5957ae..6f307c0ecb 100644 --- a/packages/transport-websockets/src/listener.ts +++ b/packages/transport-websockets/src/listener.ts @@ -1,5 +1,5 @@ import os from 'os' -import { EventEmitter, CustomEvent } from '@libp2p/interface/events' +import { TypedEventEmitter, CustomEvent } from '@libp2p/interface/events' import { logger } from '@libp2p/logger' import { ipPortToMultiaddr as toMultiaddr } from '@libp2p/utils/ip-port-to-multiaddr' import { multiaddr, protocols } from '@multiformats/multiaddr' @@ -14,7 +14,7 @@ import type { WebSocketServer } from 'it-ws/server' const log = logger('libp2p:websockets:listener') -class WebSocketListener extends EventEmitter implements Listener { +class WebSocketListener extends TypedEventEmitter implements Listener { private readonly connections: Set private listeningMultiaddr?: Multiaddr private readonly server: WebSocketServer diff --git a/packages/transport-websockets/test/browser.ts b/packages/transport-websockets/test/browser.ts index 616f09e37e..88e311c67c 100644 --- a/packages/transport-websockets/test/browser.ts +++ b/packages/transport-websockets/test/browser.ts @@ -1,6 +1,6 @@ /* eslint-env mocha */ -import { EventEmitter } from '@libp2p/interface/events' +import { TypedEventEmitter } from '@libp2p/interface/events' import { mockUpgrader } from '@libp2p/interface-compliance-tests/mocks' import { multiaddr } from '@multiformats/multiaddr' import { expect } from 'aegir/chai' @@ -23,7 +23,7 @@ describe('libp2p-websockets', () => { ws = webSockets()() conn = await ws.dial(ma, { upgrader: mockUpgrader({ - events: new EventEmitter() + events: new TypedEventEmitter() }) }) }) diff --git a/packages/transport-websockets/test/node.ts b/packages/transport-websockets/test/node.ts index 32aa1b02ae..8c296900ce 100644 --- a/packages/transport-websockets/test/node.ts +++ b/packages/transport-websockets/test/node.ts @@ -4,7 +4,7 @@ import fs from 'fs' import http from 'http' import https from 'https' -import { EventEmitter } from '@libp2p/interface/events' +import { TypedEventEmitter } from '@libp2p/interface/events' import { mockRegistrar, mockUpgrader } from '@libp2p/interface-compliance-tests/mocks' import { multiaddr } from '@multiformats/multiaddr' import { expect } from 'aegir/chai' @@ -41,7 +41,7 @@ void registrar.handle(protocol, (evt) => { }) const upgrader = mockUpgrader({ registrar, - events: new EventEmitter() + events: new TypedEventEmitter() }) describe('instantiate the transport', () => { From c6db2104dbe4257e14e66cda75bd8daf6a27f3c5 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 25 Oct 2023 16:42:59 +0100 Subject: [PATCH 12/24] chore: release master (#2174) Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- .release-please-manifest.json | 2 +- interop/CHANGELOG.md | 14 +++++++ interop/package.json | 14 +++---- packages/crypto/CHANGELOG.md | 9 ++++ packages/crypto/package.json | 4 +- .../interface-compliance-tests/CHANGELOG.md | 23 +++++++++- .../interface-compliance-tests/package.json | 16 +++---- packages/interface-internal/CHANGELOG.md | 10 +++++ packages/interface-internal/package.json | 6 +-- packages/interface/CHANGELOG.md | 8 ++++ packages/interface/package.json | 2 +- packages/kad-dht/CHANGELOG.md | 26 +++++++++++- packages/kad-dht/package.json | 20 ++++----- packages/keychain/CHANGELOG.md | 14 +++++++ packages/keychain/package.json | 12 +++--- packages/libp2p/CHANGELOG.md | 35 ++++++++++++++++ packages/libp2p/package.json | 42 +++++++++---------- packages/logger/CHANGELOG.md | 11 +++++ packages/logger/package.json | 6 +-- packages/metrics-prometheus/CHANGELOG.md | 13 ++++++ packages/metrics-prometheus/package.json | 10 ++--- packages/multistream-select/CHANGELOG.md | 10 +++++ packages/multistream-select/package.json | 6 +-- packages/peer-collections/CHANGELOG.md | 12 ++++++ packages/peer-collections/package.json | 8 ++-- .../peer-discovery-bootstrap/CHANGELOG.md | 21 +++++++++- .../peer-discovery-bootstrap/package.json | 10 ++--- packages/peer-discovery-mdns/CHANGELOG.md | 24 ++++++++++- packages/peer-discovery-mdns/package.json | 16 +++---- packages/peer-id-factory/CHANGELOG.md | 11 +++++ packages/peer-id-factory/package.json | 8 ++-- packages/peer-id/CHANGELOG.md | 9 ++++ packages/peer-id/package.json | 4 +- packages/peer-record/CHANGELOG.md | 14 +++++++ packages/peer-record/package.json | 12 +++--- packages/peer-store/CHANGELOG.md | 22 +++++++++- packages/peer-store/package.json | 14 +++---- packages/protocol-perf/CHANGELOG.md | 24 ++++++++++- packages/protocol-perf/package.json | 18 ++++---- packages/pubsub-floodsub/CHANGELOG.md | 15 +++++++ packages/pubsub-floodsub/package.json | 14 +++---- packages/pubsub/CHANGELOG.md | 24 ++++++++++- packages/pubsub/package.json | 16 +++---- .../stream-multiplexer-mplex/CHANGELOG.md | 12 ++++++ .../stream-multiplexer-mplex/package.json | 8 ++-- packages/transport-tcp/CHANGELOG.md | 21 +++++++++- packages/transport-tcp/package.json | 10 ++--- packages/transport-webrtc/CHANGELOG.md | 25 ++++++++++- packages/transport-webrtc/package.json | 18 ++++---- packages/transport-websockets/CHANGELOG.md | 19 +++++++++ packages/transport-websockets/package.json | 10 ++--- packages/transport-webtransport/CHANGELOG.md | 14 +++++++ packages/transport-webtransport/package.json | 12 +++--- packages/utils/CHANGELOG.md | 10 +++++ packages/utils/package.json | 6 +-- 55 files changed, 603 insertions(+), 171 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 2d1529db7b..432a0759b8 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1 +1 @@ -{"interop":"1.0.7","packages/crypto":"2.0.5","packages/interface":"0.1.3","packages/interface-compliance-tests":"4.1.1","packages/interface-internal":"0.1.6","packages/kad-dht":"10.0.10","packages/keychain":"3.0.5","packages/libp2p":"0.46.15","packages/logger":"3.0.3","packages/metrics-prometheus":"2.0.8","packages/multistream-select":"4.0.3","packages/peer-collections":"4.0.5","packages/peer-discovery-bootstrap":"9.0.8","packages/peer-discovery-mdns":"9.0.10","packages/peer-id":"3.0.3","packages/peer-id-factory":"3.0.5","packages/peer-record":"6.0.6","packages/peer-store":"9.0.6","packages/protocol-perf":"1.1.12","packages/pubsub":"8.0.7","packages/pubsub-floodsub":"8.0.9","packages/stream-multiplexer-mplex":"9.0.8","packages/transport-tcp":"8.0.9","packages/transport-webrtc":"3.2.4","packages/transport-websockets":"7.0.9","packages/transport-webtransport":"3.1.4","packages/utils":"4.0.4"} \ No newline at end of file +{"interop":"1.0.8","packages/crypto":"2.0.6","packages/interface":"0.1.4","packages/interface-compliance-tests":"4.1.2","packages/interface-internal":"0.1.7","packages/kad-dht":"10.0.11","packages/keychain":"3.0.6","packages/libp2p":"0.46.16","packages/logger":"3.0.4","packages/metrics-prometheus":"2.0.9","packages/multistream-select":"4.0.4","packages/peer-collections":"4.0.6","packages/peer-discovery-bootstrap":"9.0.9","packages/peer-discovery-mdns":"9.0.11","packages/peer-id":"3.0.4","packages/peer-id-factory":"3.0.6","packages/peer-record":"6.0.7","packages/peer-store":"9.0.7","packages/protocol-perf":"1.1.13","packages/pubsub":"8.0.8","packages/pubsub-floodsub":"8.0.10","packages/stream-multiplexer-mplex":"9.0.9","packages/transport-tcp":"8.0.10","packages/transport-webrtc":"3.2.5","packages/transport-websockets":"7.0.10","packages/transport-webtransport":"3.1.5","packages/utils":"4.0.5"} \ No newline at end of file diff --git a/interop/CHANGELOG.md b/interop/CHANGELOG.md index 92beaecf30..e2788114ec 100644 --- a/interop/CHANGELOG.md +++ b/interop/CHANGELOG.md @@ -1,5 +1,19 @@ # Changelog +### [1.0.8](https://www.github.com/libp2p/js-libp2p/compare/multidim-interop-v1.0.7...multidim-interop-v1.0.8) (2023-10-25) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * @libp2p/mplex bumped from ^9.0.8 to ^9.0.9 + * @libp2p/tcp bumped from ^8.0.9 to ^8.0.10 + * @libp2p/webrtc bumped from ^3.2.4 to ^3.2.5 + * @libp2p/websockets bumped from ^7.0.9 to ^7.0.10 + * @libp2p/webtransport bumped from ^3.1.4 to ^3.1.5 + * libp2p bumped from ^0.46.15 to ^0.46.16 + ### [1.0.7](https://www.github.com/libp2p/js-libp2p/compare/multidim-interop-v1.0.6...multidim-interop-v1.0.7) (2023-10-25) diff --git a/interop/package.json b/interop/package.json index 6e0672d979..dd4d3fdece 100644 --- a/interop/package.json +++ b/interop/package.json @@ -1,6 +1,6 @@ { "name": "@libp2p/multidim-interop", - "version": "1.0.7", + "version": "1.0.8", "description": "Multidimensional interop tests", "author": "Glen De Cauwsemaecker / @marcopolo", "license": "Apache-2.0 OR MIT", @@ -52,15 +52,15 @@ "dependencies": { "@chainsafe/libp2p-noise": "^13.0.0", "@chainsafe/libp2p-yamux": "^5.0.0", - "@libp2p/mplex": "^9.0.8", - "@libp2p/tcp": "^8.0.9", - "@libp2p/webrtc": "^3.2.4", - "@libp2p/websockets": "^7.0.9", - "@libp2p/webtransport": "^3.1.4", + "@libp2p/mplex": "^9.0.9", + "@libp2p/tcp": "^8.0.10", + "@libp2p/webrtc": "^3.2.5", + "@libp2p/websockets": "^7.0.10", + "@libp2p/webtransport": "^3.1.5", "@multiformats/mafmt": "^12.1.2", "@multiformats/multiaddr": "^12.1.5", "aegir": "^41.0.2", - "libp2p": "^0.46.15", + "libp2p": "^0.46.16", "redis": "^4.5.1" }, "browser": { diff --git a/packages/crypto/CHANGELOG.md b/packages/crypto/CHANGELOG.md index 4f89fc5f0e..3c06dbad1d 100644 --- a/packages/crypto/CHANGELOG.md +++ b/packages/crypto/CHANGELOG.md @@ -5,6 +5,15 @@ * **dev:** bump aegir from 38.1.8 to 39.0.5 ([#320](https://github.com/libp2p/js-libp2p-crypto/issues/320)) ([f0b4c06](https://github.com/libp2p/js-libp2p-crypto/commit/f0b4c068a23d78b1376865c6adf6cce21ab91196)) +### [2.0.6](https://www.github.com/libp2p/js-libp2p/compare/crypto-v2.0.5...crypto-v2.0.6) (2023-10-25) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * @libp2p/interface bumped from ^0.1.3 to ^0.1.4 + ### [2.0.5](https://www.github.com/libp2p/js-libp2p/compare/crypto-v2.0.4...crypto-v2.0.5) (2023-10-06) diff --git a/packages/crypto/package.json b/packages/crypto/package.json index 785f3f720d..953a660bfa 100644 --- a/packages/crypto/package.json +++ b/packages/crypto/package.json @@ -1,6 +1,6 @@ { "name": "@libp2p/crypto", - "version": "2.0.5", + "version": "2.0.6", "description": "Crypto primitives for libp2p", "license": "Apache-2.0 OR MIT", "homepage": "https://github.com/libp2p/js-libp2p/tree/master/packages/crypto#readme", @@ -86,7 +86,7 @@ "generate": "protons ./src/keys/keys.proto" }, "dependencies": { - "@libp2p/interface": "^0.1.3", + "@libp2p/interface": "^0.1.4", "@noble/curves": "^1.1.0", "@noble/hashes": "^1.3.1", "multiformats": "^12.0.1", diff --git a/packages/interface-compliance-tests/CHANGELOG.md b/packages/interface-compliance-tests/CHANGELOG.md index a9ef37cb25..f5e6c0fc60 100644 --- a/packages/interface-compliance-tests/CHANGELOG.md +++ b/packages/interface-compliance-tests/CHANGELOG.md @@ -5,6 +5,27 @@ * bump aegir from 38.1.8 to 39.0.5 ([#393](https://github.com/libp2p/js-libp2p-interfaces/issues/393)) ([31f3797](https://github.com/libp2p/js-libp2p-interfaces/commit/31f3797b24f7c23f3f16e9db3a230bd5f7cd5175)) +### [4.1.2](https://www.github.com/libp2p/js-libp2p/compare/interface-compliance-tests-v4.1.1...interface-compliance-tests-v4.1.2) (2023-10-25) + + +### Bug Fixes + +* rename event emitter class ([#2173](https://www.github.com/libp2p/js-libp2p/issues/2173)) ([50f912c](https://www.github.com/libp2p/js-libp2p/commit/50f912c2608caecc09acbcb0f46b4df4af073080)) +* revert "refactor: rename event emitter class" ([#2172](https://www.github.com/libp2p/js-libp2p/issues/2172)) ([0ef5f7f](https://www.github.com/libp2p/js-libp2p/commit/0ef5f7f62d9c6d822e0a4b99cc203a1516b11f2f)) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * @libp2p/interface bumped from ^0.1.3 to ^0.1.4 + * @libp2p/interface-internal bumped from ^0.1.6 to ^0.1.7 + * @libp2p/logger bumped from ^3.0.3 to ^3.0.4 + * @libp2p/multistream-select bumped from ^4.0.3 to ^4.0.4 + * @libp2p/peer-collections bumped from ^4.0.5 to ^4.0.6 + * @libp2p/peer-id bumped from ^3.0.3 to ^3.0.4 + * @libp2p/peer-id-factory bumped from ^3.0.5 to ^3.0.6 + ### [4.1.1](https://www.github.com/libp2p/js-libp2p/compare/interface-compliance-tests-v4.1.0...interface-compliance-tests-v4.1.1) (2023-10-06) @@ -656,4 +677,4 @@ See [Conventional Commits](https://conventionalcommits.org) for commit guideline ### BREAKING CHANGES -* the tests now live in the libp2p-interfaces-compliance-tests module +* the tests now live in the libp2p-interfaces-compliance-tests module \ No newline at end of file diff --git a/packages/interface-compliance-tests/package.json b/packages/interface-compliance-tests/package.json index 3f7c9ae1c4..2080d453c8 100644 --- a/packages/interface-compliance-tests/package.json +++ b/packages/interface-compliance-tests/package.json @@ -1,6 +1,6 @@ { "name": "@libp2p/interface-compliance-tests", - "version": "4.1.1", + "version": "4.1.2", "description": "Compliance tests for JS libp2p interfaces", "license": "Apache-2.0 OR MIT", "homepage": "https://github.com/libp2p/js-libp2p/tree/master/packages/interface-compliance-tests#readme", @@ -103,13 +103,13 @@ "test:electron-main": "aegir test -t electron-main" }, "dependencies": { - "@libp2p/interface": "^0.1.3", - "@libp2p/interface-internal": "^0.1.6", - "@libp2p/logger": "^3.0.3", - "@libp2p/multistream-select": "^4.0.3", - "@libp2p/peer-collections": "^4.0.5", - "@libp2p/peer-id": "^3.0.3", - "@libp2p/peer-id-factory": "^3.0.5", + "@libp2p/interface": "^0.1.4", + "@libp2p/interface-internal": "^0.1.7", + "@libp2p/logger": "^3.0.4", + "@libp2p/multistream-select": "^4.0.4", + "@libp2p/peer-collections": "^4.0.6", + "@libp2p/peer-id": "^3.0.4", + "@libp2p/peer-id-factory": "^3.0.6", "@multiformats/multiaddr": "^12.1.5", "abortable-iterator": "^5.0.1", "aegir": "^41.0.2", diff --git a/packages/interface-internal/CHANGELOG.md b/packages/interface-internal/CHANGELOG.md index 4d159c1220..d8331595b2 100644 --- a/packages/interface-internal/CHANGELOG.md +++ b/packages/interface-internal/CHANGELOG.md @@ -1,5 +1,15 @@ # Changelog +### [0.1.7](https://www.github.com/libp2p/js-libp2p/compare/interface-internal-v0.1.6...interface-internal-v0.1.7) (2023-10-25) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * @libp2p/interface bumped from ^0.1.3 to ^0.1.4 + * @libp2p/peer-collections bumped from ^4.0.5 to ^4.0.6 + ### [0.1.6](https://www.github.com/libp2p/js-libp2p/compare/interface-internal-v0.1.5...interface-internal-v0.1.6) (2023-10-06) diff --git a/packages/interface-internal/package.json b/packages/interface-internal/package.json index f8ea476d52..8903560eae 100644 --- a/packages/interface-internal/package.json +++ b/packages/interface-internal/package.json @@ -1,6 +1,6 @@ { "name": "@libp2p/interface-internal", - "version": "0.1.6", + "version": "0.1.7", "description": "Interfaces implemented by internal libp2p components", "license": "Apache-2.0 OR MIT", "homepage": "https://github.com/libp2p/js-libp2p/tree/master/packages/interface-internal#readme", @@ -79,8 +79,8 @@ "build": "aegir build" }, "dependencies": { - "@libp2p/interface": "^0.1.3", - "@libp2p/peer-collections": "^4.0.5", + "@libp2p/interface": "^0.1.4", + "@libp2p/peer-collections": "^4.0.6", "@multiformats/multiaddr": "^12.1.5", "uint8arraylist": "^2.4.3" }, diff --git a/packages/interface/CHANGELOG.md b/packages/interface/CHANGELOG.md index 145ba5c8bc..a37155f64b 100644 --- a/packages/interface/CHANGELOG.md +++ b/packages/interface/CHANGELOG.md @@ -5,6 +5,14 @@ * add start/stop events to libp2p interface ([#407](https://github.com/libp2p/js-libp2p-interfaces/issues/407)) ([016c1e8](https://github.com/libp2p/js-libp2p-interfaces/commit/016c1e82b060c93c80546cd8c493ec6e6c97cbec)) +### [0.1.4](https://www.github.com/libp2p/js-libp2p/compare/interface-v0.1.3...interface-v0.1.4) (2023-10-25) + + +### Bug Fixes + +* rename event emitter class ([#2173](https://www.github.com/libp2p/js-libp2p/issues/2173)) ([50f912c](https://www.github.com/libp2p/js-libp2p/commit/50f912c2608caecc09acbcb0f46b4df4af073080)) +* revert "refactor: rename event emitter class" ([#2172](https://www.github.com/libp2p/js-libp2p/issues/2172)) ([0ef5f7f](https://www.github.com/libp2p/js-libp2p/commit/0ef5f7f62d9c6d822e0a4b99cc203a1516b11f2f)) + ### [0.1.3](https://www.github.com/libp2p/js-libp2p/compare/interface-v0.1.2...interface-v0.1.3) (2023-10-06) diff --git a/packages/interface/package.json b/packages/interface/package.json index 239ccc0be1..b2a5a1e909 100644 --- a/packages/interface/package.json +++ b/packages/interface/package.json @@ -1,6 +1,6 @@ { "name": "@libp2p/interface", - "version": "0.1.3", + "version": "0.1.4", "description": "The interface implemented by a libp2p node", "license": "Apache-2.0 OR MIT", "homepage": "https://github.com/libp2p/js-libp2p/tree/master/packages/interface#readme", diff --git a/packages/kad-dht/CHANGELOG.md b/packages/kad-dht/CHANGELOG.md index 9682a64034..d19f8dd633 100644 --- a/packages/kad-dht/CHANGELOG.md +++ b/packages/kad-dht/CHANGELOG.md @@ -5,6 +5,30 @@ * skip self-query if not running ([#479](https://github.com/libp2p/js-libp2p-kad-dht/issues/479)) ([7095290](https://github.com/libp2p/js-libp2p-kad-dht/commit/70952907a27fd8778773172059879656b4f08855)) +### [10.0.11](https://www.github.com/libp2p/js-libp2p/compare/kad-dht-v10.0.10...kad-dht-v10.0.11) (2023-10-25) + + +### Bug Fixes + +* rename event emitter class ([#2173](https://www.github.com/libp2p/js-libp2p/issues/2173)) ([50f912c](https://www.github.com/libp2p/js-libp2p/commit/50f912c2608caecc09acbcb0f46b4df4af073080)) +* revert "refactor: rename event emitter class" ([#2172](https://www.github.com/libp2p/js-libp2p/issues/2172)) ([0ef5f7f](https://www.github.com/libp2p/js-libp2p/commit/0ef5f7f62d9c6d822e0a4b99cc203a1516b11f2f)) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * @libp2p/crypto bumped from ^2.0.5 to ^2.0.6 + * @libp2p/interface bumped from ^0.1.3 to ^0.1.4 + * @libp2p/interface-internal bumped from ^0.1.6 to ^0.1.7 + * @libp2p/logger bumped from ^3.0.3 to ^3.0.4 + * @libp2p/peer-collections bumped from ^4.0.5 to ^4.0.6 + * @libp2p/peer-id bumped from ^3.0.3 to ^3.0.4 + * devDependencies + * @libp2p/interface-compliance-tests bumped from ^4.1.1 to ^4.1.2 + * @libp2p/peer-id-factory bumped from ^3.0.5 to ^3.0.6 + * @libp2p/peer-store bumped from ^9.0.6 to ^9.0.7 + ### [10.0.10](https://www.github.com/libp2p/js-libp2p/compare/kad-dht-v10.0.9...kad-dht-v10.0.10) (2023-10-25) @@ -1822,4 +1846,4 @@ Co-Authored-By: vasco-santos ### Features -* v0.1.0 ([4bd1fbc](https://github.com/libp2p/js-libp2p-kad-dht/commit/4bd1fbc)) +* v0.1.0 ([4bd1fbc](https://github.com/libp2p/js-libp2p-kad-dht/commit/4bd1fbc)) \ No newline at end of file diff --git a/packages/kad-dht/package.json b/packages/kad-dht/package.json index 8fbe9803a0..2578d27c08 100644 --- a/packages/kad-dht/package.json +++ b/packages/kad-dht/package.json @@ -1,6 +1,6 @@ { "name": "@libp2p/kad-dht", - "version": "10.0.10", + "version": "10.0.11", "description": "JavaScript implementation of the Kad-DHT for libp2p", "license": "Apache-2.0 OR MIT", "homepage": "https://github.com/libp2p/js-libp2p/tree/master/packages/kad-dht#readme", @@ -52,12 +52,12 @@ "dep-check": "aegir dep-check -i events" }, "dependencies": { - "@libp2p/crypto": "^2.0.5", - "@libp2p/interface": "^0.1.3", - "@libp2p/interface-internal": "^0.1.6", - "@libp2p/logger": "^3.0.3", - "@libp2p/peer-collections": "^4.0.5", - "@libp2p/peer-id": "^3.0.3", + "@libp2p/crypto": "^2.0.6", + "@libp2p/interface": "^0.1.4", + "@libp2p/interface-internal": "^0.1.7", + "@libp2p/logger": "^3.0.4", + "@libp2p/peer-collections": "^4.0.6", + "@libp2p/peer-id": "^3.0.4", "@multiformats/multiaddr": "^12.1.5", "@types/sinon": "^10.0.15", "abortable-iterator": "^5.0.1", @@ -89,9 +89,9 @@ "uint8arrays": "^4.0.6" }, "devDependencies": { - "@libp2p/interface-compliance-tests": "^4.1.1", - "@libp2p/peer-id-factory": "^3.0.5", - "@libp2p/peer-store": "^9.0.6", + "@libp2p/interface-compliance-tests": "^4.1.2", + "@libp2p/peer-id-factory": "^3.0.6", + "@libp2p/peer-store": "^9.0.7", "@types/lodash.random": "^3.2.6", "@types/lodash.range": "^3.2.6", "@types/which": "^3.0.0", diff --git a/packages/keychain/CHANGELOG.md b/packages/keychain/CHANGELOG.md index f1c352f145..b476f6b440 100644 --- a/packages/keychain/CHANGELOG.md +++ b/packages/keychain/CHANGELOG.md @@ -11,6 +11,20 @@ * **dev:** bump aegir from 38.1.8 to 39.0.10 ([#70](https://github.com/libp2p/js-libp2p-keychain/issues/70)) ([4da4a08](https://github.com/libp2p/js-libp2p-keychain/commit/4da4a08b86f436c36e2fae48ecc48817e9b8066f)) +### [3.0.6](https://www.github.com/libp2p/js-libp2p/compare/keychain-v3.0.5...keychain-v3.0.6) (2023-10-25) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * @libp2p/crypto bumped from ^2.0.5 to ^2.0.6 + * @libp2p/interface bumped from ^0.1.3 to ^0.1.4 + * @libp2p/logger bumped from ^3.0.3 to ^3.0.4 + * @libp2p/peer-id bumped from ^3.0.3 to ^3.0.4 + * devDependencies + * @libp2p/peer-id-factory bumped from ^3.0.5 to ^3.0.6 + ### [3.0.5](https://www.github.com/libp2p/js-libp2p/compare/keychain-v3.0.4...keychain-v3.0.5) (2023-10-06) diff --git a/packages/keychain/package.json b/packages/keychain/package.json index 0ac5a359f4..acb2dcbb73 100644 --- a/packages/keychain/package.json +++ b/packages/keychain/package.json @@ -1,6 +1,6 @@ { "name": "@libp2p/keychain", - "version": "3.0.5", + "version": "3.0.6", "description": "Key management and cryptographically protected messages", "license": "Apache-2.0 OR MIT", "homepage": "https://github.com/libp2p/js-libp2p/tree/master/packages/keychain#readme", @@ -54,17 +54,17 @@ "test:electron-main": "aegir test -t electron-main" }, "dependencies": { - "@libp2p/crypto": "^2.0.5", - "@libp2p/interface": "^0.1.3", - "@libp2p/logger": "^3.0.3", - "@libp2p/peer-id": "^3.0.3", + "@libp2p/crypto": "^2.0.6", + "@libp2p/interface": "^0.1.4", + "@libp2p/logger": "^3.0.4", + "@libp2p/peer-id": "^3.0.4", "interface-datastore": "^8.2.0", "merge-options": "^3.0.4", "sanitize-filename": "^1.6.3", "uint8arrays": "^4.0.6" }, "devDependencies": { - "@libp2p/peer-id-factory": "^3.0.5", + "@libp2p/peer-id-factory": "^3.0.6", "aegir": "^41.0.2", "datastore-core": "^9.1.1", "multiformats": "^12.0.1" diff --git a/packages/libp2p/CHANGELOG.md b/packages/libp2p/CHANGELOG.md index d3ae00b22e..44ec7ce1a6 100644 --- a/packages/libp2p/CHANGELOG.md +++ b/packages/libp2p/CHANGELOG.md @@ -20,6 +20,41 @@ * @libp2p/tcp bumped from ^8.0.5 to ^8.0.6 * @libp2p/websockets bumped from ^7.0.5 to ^7.0.6 +### [0.46.16](https://www.github.com/libp2p/js-libp2p/compare/libp2p-v0.46.15...libp2p-v0.46.16) (2023-10-25) + + +### Bug Fixes + +* rename event emitter class ([#2173](https://www.github.com/libp2p/js-libp2p/issues/2173)) ([50f912c](https://www.github.com/libp2p/js-libp2p/commit/50f912c2608caecc09acbcb0f46b4df4af073080)) +* revert "refactor: rename event emitter class" ([#2172](https://www.github.com/libp2p/js-libp2p/issues/2172)) ([0ef5f7f](https://www.github.com/libp2p/js-libp2p/commit/0ef5f7f62d9c6d822e0a4b99cc203a1516b11f2f)) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * @libp2p/crypto bumped from ^2.0.5 to ^2.0.6 + * @libp2p/interface bumped from ^0.1.3 to ^0.1.4 + * @libp2p/interface-internal bumped from ^0.1.6 to ^0.1.7 + * @libp2p/keychain bumped from ^3.0.5 to ^3.0.6 + * @libp2p/logger bumped from ^3.0.3 to ^3.0.4 + * @libp2p/multistream-select bumped from ^4.0.3 to ^4.0.4 + * @libp2p/peer-collections bumped from ^4.0.5 to ^4.0.6 + * @libp2p/peer-id bumped from ^3.0.3 to ^3.0.4 + * @libp2p/peer-id-factory bumped from ^3.0.5 to ^3.0.6 + * @libp2p/peer-record bumped from ^6.0.6 to ^6.0.7 + * @libp2p/peer-store bumped from ^9.0.6 to ^9.0.7 + * @libp2p/utils bumped from ^4.0.4 to ^4.0.5 + * devDependencies + * @libp2p/bootstrap bumped from ^9.0.8 to ^9.0.9 + * @libp2p/floodsub bumped from ^8.0.9 to ^8.0.10 + * @libp2p/interface-compliance-tests bumped from ^4.1.1 to ^4.1.2 + * @libp2p/kad-dht bumped from ^10.0.10 to ^10.0.11 + * @libp2p/mdns bumped from ^9.0.10 to ^9.0.11 + * @libp2p/mplex bumped from ^9.0.8 to ^9.0.9 + * @libp2p/tcp bumped from ^8.0.9 to ^8.0.10 + * @libp2p/websockets bumped from ^7.0.9 to ^7.0.10 + ### [0.46.15](https://www.github.com/libp2p/js-libp2p/compare/libp2p-v0.46.14...libp2p-v0.46.15) (2023-10-25) diff --git a/packages/libp2p/package.json b/packages/libp2p/package.json index 55345125fb..f02973ff06 100644 --- a/packages/libp2p/package.json +++ b/packages/libp2p/package.json @@ -1,6 +1,6 @@ { "name": "libp2p", - "version": "0.46.15", + "version": "0.46.16", "description": "JavaScript implementation of libp2p, a modular peer to peer network stack", "license": "Apache-2.0 OR MIT", "homepage": "https://github.com/libp2p/js-libp2p/tree/master/packages/libp2p#readme", @@ -121,18 +121,18 @@ }, "dependencies": { "@achingbrain/nat-port-mapper": "^1.0.9", - "@libp2p/crypto": "^2.0.5", - "@libp2p/interface": "^0.1.3", - "@libp2p/interface-internal": "^0.1.6", - "@libp2p/keychain": "^3.0.5", - "@libp2p/logger": "^3.0.3", - "@libp2p/multistream-select": "^4.0.3", - "@libp2p/peer-collections": "^4.0.5", - "@libp2p/peer-id": "^3.0.3", - "@libp2p/peer-id-factory": "^3.0.5", - "@libp2p/peer-record": "^6.0.6", - "@libp2p/peer-store": "^9.0.6", - "@libp2p/utils": "^4.0.4", + "@libp2p/crypto": "^2.0.6", + "@libp2p/interface": "^0.1.4", + "@libp2p/interface-internal": "^0.1.7", + "@libp2p/keychain": "^3.0.6", + "@libp2p/logger": "^3.0.4", + "@libp2p/multistream-select": "^4.0.4", + "@libp2p/peer-collections": "^4.0.6", + "@libp2p/peer-id": "^3.0.4", + "@libp2p/peer-id-factory": "^3.0.6", + "@libp2p/peer-record": "^6.0.7", + "@libp2p/peer-store": "^9.0.7", + "@libp2p/utils": "^4.0.5", "@multiformats/mafmt": "^12.1.2", "@multiformats/multiaddr": "^12.1.5", "@multiformats/multiaddr-matcher": "^1.0.0", @@ -171,17 +171,17 @@ "@chainsafe/libp2p-gossipsub": "^10.0.0", "@chainsafe/libp2p-noise": "^13.0.0", "@chainsafe/libp2p-yamux": "^5.0.0", - "@libp2p/bootstrap": "^9.0.8", + "@libp2p/bootstrap": "^9.0.9", "@libp2p/daemon-client": "^7.0.0", "@libp2p/daemon-server": "^6.0.0", - "@libp2p/floodsub": "^8.0.9", - "@libp2p/interface-compliance-tests": "^4.1.1", + "@libp2p/floodsub": "^8.0.10", + "@libp2p/interface-compliance-tests": "^4.1.2", "@libp2p/interop": "^9.0.0", - "@libp2p/kad-dht": "^10.0.10", - "@libp2p/mdns": "^9.0.10", - "@libp2p/mplex": "^9.0.8", - "@libp2p/tcp": "^8.0.9", - "@libp2p/websockets": "^7.0.9", + "@libp2p/kad-dht": "^10.0.11", + "@libp2p/mdns": "^9.0.11", + "@libp2p/mplex": "^9.0.9", + "@libp2p/tcp": "^8.0.10", + "@libp2p/websockets": "^7.0.10", "@types/xsalsa20": "^1.1.0", "aegir": "^41.0.2", "execa": "^8.0.1", diff --git a/packages/logger/CHANGELOG.md b/packages/logger/CHANGELOG.md index fbe63635f4..6fe40ded69 100644 --- a/packages/logger/CHANGELOG.md +++ b/packages/logger/CHANGELOG.md @@ -5,6 +5,17 @@ * specify updated formatter for multiaddrs ([#36](https://github.com/libp2p/js-libp2p-logger/issues/36)) ([abaefb4](https://github.com/libp2p/js-libp2p-logger/commit/abaefb490a0d9464a23b422d9fc5b80051532d10)) +### [3.0.4](https://www.github.com/libp2p/js-libp2p/compare/logger-v3.0.3...logger-v3.0.4) (2023-10-25) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * @libp2p/interface bumped from ^0.1.3 to ^0.1.4 + * devDependencies + * @libp2p/peer-id bumped from ^3.0.3 to ^3.0.4 + ### [3.0.3](https://www.github.com/libp2p/js-libp2p/compare/logger-v3.0.2...logger-v3.0.3) (2023-10-06) diff --git a/packages/logger/package.json b/packages/logger/package.json index 7933263171..a7bca3d05f 100644 --- a/packages/logger/package.json +++ b/packages/logger/package.json @@ -1,6 +1,6 @@ { "name": "@libp2p/logger", - "version": "3.0.3", + "version": "3.0.4", "description": "A logging component for use in js-libp2p modules", "license": "Apache-2.0 OR MIT", "homepage": "https://github.com/libp2p/js-libp2p/tree/master/packages/logger#readme", @@ -49,14 +49,14 @@ "test:electron-main": "aegir test -t electron-main" }, "dependencies": { - "@libp2p/interface": "^0.1.3", + "@libp2p/interface": "^0.1.4", "@multiformats/multiaddr": "^12.1.5", "debug": "^4.3.4", "interface-datastore": "^8.2.0", "multiformats": "^12.0.1" }, "devDependencies": { - "@libp2p/peer-id": "^3.0.3", + "@libp2p/peer-id": "^3.0.4", "@types/debug": "^4.1.7", "aegir": "^41.0.2", "sinon": "^17.0.0", diff --git a/packages/metrics-prometheus/CHANGELOG.md b/packages/metrics-prometheus/CHANGELOG.md index f8ec58da18..d3bf87e9a2 100644 --- a/packages/metrics-prometheus/CHANGELOG.md +++ b/packages/metrics-prometheus/CHANGELOG.md @@ -5,6 +5,19 @@ * move prom-client to deps ([#32](https://github.com/libp2p/js-libp2p-prometheus-metrics/issues/32)) ([73acad0](https://github.com/libp2p/js-libp2p-prometheus-metrics/commit/73acad0a20a9a0ad024cd47a53f154668dbae77b)) +### [2.0.9](https://www.github.com/libp2p/js-libp2p/compare/prometheus-metrics-v2.0.8...prometheus-metrics-v2.0.9) (2023-10-25) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * @libp2p/interface bumped from ^0.1.3 to ^0.1.4 + * @libp2p/logger bumped from ^3.0.3 to ^3.0.4 + * devDependencies + * @libp2p/interface-compliance-tests bumped from ^4.1.1 to ^4.1.2 + * @libp2p/peer-id-factory bumped from ^3.0.5 to ^3.0.6 + ### [2.0.8](https://www.github.com/libp2p/js-libp2p/compare/prometheus-metrics-v2.0.7...prometheus-metrics-v2.0.8) (2023-10-06) diff --git a/packages/metrics-prometheus/package.json b/packages/metrics-prometheus/package.json index f15dc7b1b2..5e1d62f67b 100644 --- a/packages/metrics-prometheus/package.json +++ b/packages/metrics-prometheus/package.json @@ -1,6 +1,6 @@ { "name": "@libp2p/prometheus-metrics", - "version": "2.0.8", + "version": "2.0.9", "description": "Collect libp2p metrics for scraping by Prometheus or Graphana", "author": "", "license": "Apache-2.0 OR MIT", @@ -43,15 +43,15 @@ "test:electron-main": "aegir test -t electron-main --cov" }, "dependencies": { - "@libp2p/interface": "^0.1.3", - "@libp2p/logger": "^3.0.3", + "@libp2p/interface": "^0.1.4", + "@libp2p/logger": "^3.0.4", "it-foreach": "^2.0.3", "it-stream-types": "^2.0.1", "prom-client": "^15.0.0" }, "devDependencies": { - "@libp2p/interface-compliance-tests": "^4.1.1", - "@libp2p/peer-id-factory": "^3.0.5", + "@libp2p/interface-compliance-tests": "^4.1.2", + "@libp2p/peer-id-factory": "^3.0.6", "@multiformats/multiaddr": "^12.1.3", "aegir": "^41.0.2", "it-drain": "^3.0.2", diff --git a/packages/multistream-select/CHANGELOG.md b/packages/multistream-select/CHANGELOG.md index b15826cbc0..27a09be593 100644 --- a/packages/multistream-select/CHANGELOG.md +++ b/packages/multistream-select/CHANGELOG.md @@ -11,6 +11,16 @@ * **dev:** bump aegir from 38.1.8 to 39.0.10 ([#70](https://github.com/libp2p/js-libp2p-multistream-select/issues/70)) ([f87b1c3](https://github.com/libp2p/js-libp2p-multistream-select/commit/f87b1c3505934ebeed6eff018af8d3042e7e6e06)) +### [4.0.4](https://www.github.com/libp2p/js-libp2p/compare/multistream-select-v4.0.3...multistream-select-v4.0.4) (2023-10-25) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * @libp2p/interface bumped from ^0.1.3 to ^0.1.4 + * @libp2p/logger bumped from ^3.0.3 to ^3.0.4 + ### [4.0.3](https://www.github.com/libp2p/js-libp2p/compare/multistream-select-v4.0.2...multistream-select-v4.0.3) (2023-10-06) diff --git a/packages/multistream-select/package.json b/packages/multistream-select/package.json index 0d095536ad..6671553658 100644 --- a/packages/multistream-select/package.json +++ b/packages/multistream-select/package.json @@ -1,6 +1,6 @@ { "name": "@libp2p/multistream-select", - "version": "4.0.3", + "version": "4.0.4", "description": "JavaScript implementation of multistream-select", "license": "Apache-2.0 OR MIT", "homepage": "https://github.com/libp2p/js-libp2p/tree/master/packages/multistream-select#readme", @@ -53,8 +53,8 @@ "test:electron-main": "aegir test -t electron-main" }, "dependencies": { - "@libp2p/interface": "^0.1.3", - "@libp2p/logger": "^3.0.3", + "@libp2p/interface": "^0.1.4", + "@libp2p/logger": "^3.0.4", "abortable-iterator": "^5.0.1", "it-first": "^3.0.1", "it-handshake": "^4.1.3", diff --git a/packages/peer-collections/CHANGELOG.md b/packages/peer-collections/CHANGELOG.md index 43cda9ddb9..59391d3e53 100644 --- a/packages/peer-collections/CHANGELOG.md +++ b/packages/peer-collections/CHANGELOG.md @@ -11,6 +11,18 @@ * **dev:** bump aegir from 38.1.8 to 39.0.10 ([#36](https://github.com/libp2p/js-libp2p-peer-collections/issues/36)) ([9fa3de6](https://github.com/libp2p/js-libp2p-peer-collections/commit/9fa3de6d85dbe1ade54fda86b597ed9ffe6d71d5)) +### [4.0.6](https://www.github.com/libp2p/js-libp2p/compare/peer-collections-v4.0.5...peer-collections-v4.0.6) (2023-10-25) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * @libp2p/interface bumped from ^0.1.3 to ^0.1.4 + * @libp2p/peer-id bumped from ^3.0.3 to ^3.0.4 + * devDependencies + * @libp2p/peer-id-factory bumped from ^3.0.5 to ^3.0.6 + ### [4.0.5](https://www.github.com/libp2p/js-libp2p/compare/peer-collections-v4.0.4...peer-collections-v4.0.5) (2023-10-06) diff --git a/packages/peer-collections/package.json b/packages/peer-collections/package.json index 615fd30416..f799605a16 100644 --- a/packages/peer-collections/package.json +++ b/packages/peer-collections/package.json @@ -1,6 +1,6 @@ { "name": "@libp2p/peer-collections", - "version": "4.0.5", + "version": "4.0.6", "description": "Stores values against a peer id", "license": "Apache-2.0 OR MIT", "homepage": "https://github.com/libp2p/js-libp2p/tree/master/packages/peer-collections#readme", @@ -49,11 +49,11 @@ "test:electron-main": "aegir test -t electron-main" }, "dependencies": { - "@libp2p/interface": "^0.1.3", - "@libp2p/peer-id": "^3.0.3" + "@libp2p/interface": "^0.1.4", + "@libp2p/peer-id": "^3.0.4" }, "devDependencies": { - "@libp2p/peer-id-factory": "^3.0.5", + "@libp2p/peer-id-factory": "^3.0.6", "aegir": "^41.0.2" } } diff --git a/packages/peer-discovery-bootstrap/CHANGELOG.md b/packages/peer-discovery-bootstrap/CHANGELOG.md index b2a127a3ef..8f408ea357 100644 --- a/packages/peer-discovery-bootstrap/CHANGELOG.md +++ b/packages/peer-discovery-bootstrap/CHANGELOG.md @@ -9,6 +9,25 @@ * update @libp2p/interface-peer-discovery to 2.0.0 ([#176](https://github.com/libp2p/js-libp2p-bootstrap/issues/176)) ([1954e75](https://github.com/libp2p/js-libp2p-bootstrap/commit/1954e75fa4b1e6b3b42f885f663f989fd0e422ab)) +### [9.0.9](https://www.github.com/libp2p/js-libp2p/compare/bootstrap-v9.0.8...bootstrap-v9.0.9) (2023-10-25) + + +### Bug Fixes + +* rename event emitter class ([#2173](https://www.github.com/libp2p/js-libp2p/issues/2173)) ([50f912c](https://www.github.com/libp2p/js-libp2p/commit/50f912c2608caecc09acbcb0f46b4df4af073080)) +* revert "refactor: rename event emitter class" ([#2172](https://www.github.com/libp2p/js-libp2p/issues/2172)) ([0ef5f7f](https://www.github.com/libp2p/js-libp2p/commit/0ef5f7f62d9c6d822e0a4b99cc203a1516b11f2f)) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * @libp2p/interface bumped from ^0.1.3 to ^0.1.4 + * @libp2p/logger bumped from ^3.0.3 to ^3.0.4 + * @libp2p/peer-id bumped from ^3.0.3 to ^3.0.4 + * devDependencies + * @libp2p/interface-compliance-tests bumped from ^4.1.1 to ^4.1.2 + ### [9.0.8](https://www.github.com/libp2p/js-libp2p/compare/bootstrap-v9.0.7...bootstrap-v9.0.8) (2023-10-06) @@ -591,4 +610,4 @@ Co-authored-by: Alan Shaw -## [0.4.2](https://github.com/libp2p/js-ipfs-railing/compare/v0.4.1...v0.4.2) (2017-03-21) +## [0.4.2](https://github.com/libp2p/js-ipfs-railing/compare/v0.4.1...v0.4.2) (2017-03-21) \ No newline at end of file diff --git a/packages/peer-discovery-bootstrap/package.json b/packages/peer-discovery-bootstrap/package.json index 7961f87940..cb98579924 100644 --- a/packages/peer-discovery-bootstrap/package.json +++ b/packages/peer-discovery-bootstrap/package.json @@ -1,6 +1,6 @@ { "name": "@libp2p/bootstrap", - "version": "9.0.8", + "version": "9.0.9", "description": "Peer discovery via a list of bootstrap peers", "license": "Apache-2.0 OR MIT", "homepage": "https://github.com/libp2p/js-libp2p/tree/master/packages/peer-discovery-bootstrap#readme", @@ -49,14 +49,14 @@ "test:electron-main": "aegir test -t electron-main" }, "dependencies": { - "@libp2p/interface": "^0.1.3", - "@libp2p/logger": "^3.0.3", - "@libp2p/peer-id": "^3.0.3", + "@libp2p/interface": "^0.1.4", + "@libp2p/logger": "^3.0.4", + "@libp2p/peer-id": "^3.0.4", "@multiformats/mafmt": "^12.1.2", "@multiformats/multiaddr": "^12.1.5" }, "devDependencies": { - "@libp2p/interface-compliance-tests": "^4.1.1", + "@libp2p/interface-compliance-tests": "^4.1.2", "aegir": "^41.0.2", "sinon-ts": "^1.0.0" } diff --git a/packages/peer-discovery-mdns/CHANGELOG.md b/packages/peer-discovery-mdns/CHANGELOG.md index 3eb7ebe38b..f13ffb2473 100644 --- a/packages/peer-discovery-mdns/CHANGELOG.md +++ b/packages/peer-discovery-mdns/CHANGELOG.md @@ -9,6 +9,28 @@ * update @libp2p/interface-peer-discovery to 2.0.0 ([#197](https://github.com/libp2p/js-libp2p-mdns/issues/197)) ([e8172af](https://github.com/libp2p/js-libp2p-mdns/commit/e8172af8b9856a934327195238b00e5fbba436a4)) +### [9.0.11](https://www.github.com/libp2p/js-libp2p/compare/mdns-v9.0.10...mdns-v9.0.11) (2023-10-25) + + +### Bug Fixes + +* rename event emitter class ([#2173](https://www.github.com/libp2p/js-libp2p/issues/2173)) ([50f912c](https://www.github.com/libp2p/js-libp2p/commit/50f912c2608caecc09acbcb0f46b4df4af073080)) +* revert "refactor: rename event emitter class" ([#2172](https://www.github.com/libp2p/js-libp2p/issues/2172)) ([0ef5f7f](https://www.github.com/libp2p/js-libp2p/commit/0ef5f7f62d9c6d822e0a4b99cc203a1516b11f2f)) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * @libp2p/interface bumped from ^0.1.3 to ^0.1.4 + * @libp2p/logger bumped from ^3.0.3 to ^3.0.4 + * @libp2p/peer-id bumped from ^3.0.3 to ^3.0.4 + * @libp2p/utils bumped from ^4.0.4 to ^4.0.5 + * devDependencies + * @libp2p/interface-compliance-tests bumped from ^4.1.1 to ^4.1.2 + * @libp2p/interface-internal bumped from ^0.1.6 to ^0.1.7 + * @libp2p/peer-id-factory bumped from ^3.0.5 to ^3.0.6 + ### [9.0.10](https://www.github.com/libp2p/js-libp2p/compare/mdns-v9.0.9...mdns-v9.0.10) (2023-10-06) @@ -645,4 +667,4 @@ Co-authored-by: Jacob Heun -## [0.6.2](https://github.com/libp2p/js-libp2p-mdns/compare/v0.6.1...v0.6.2) (2017-03-21) +## [0.6.2](https://github.com/libp2p/js-libp2p-mdns/compare/v0.6.1...v0.6.2) (2017-03-21) \ No newline at end of file diff --git a/packages/peer-discovery-mdns/package.json b/packages/peer-discovery-mdns/package.json index f362c70f69..2d618de54f 100644 --- a/packages/peer-discovery-mdns/package.json +++ b/packages/peer-discovery-mdns/package.json @@ -1,6 +1,6 @@ { "name": "@libp2p/mdns", - "version": "9.0.10", + "version": "9.0.11", "description": "Node.js libp2p mDNS discovery implementation for peer discovery", "license": "Apache-2.0 OR MIT", "homepage": "https://github.com/libp2p/js-libp2p/tree/master/packages/peer-discovery-mdns#readme", @@ -45,19 +45,19 @@ "test:electron-main": "aegir test -t electron-main" }, "dependencies": { - "@libp2p/interface": "^0.1.3", - "@libp2p/logger": "^3.0.3", - "@libp2p/peer-id": "^3.0.3", - "@libp2p/utils": "^4.0.4", + "@libp2p/interface": "^0.1.4", + "@libp2p/logger": "^3.0.4", + "@libp2p/peer-id": "^3.0.4", + "@libp2p/utils": "^4.0.5", "@multiformats/multiaddr": "^12.1.5", "@types/multicast-dns": "^7.2.1", "dns-packet": "^5.4.0", "multicast-dns": "^7.2.5" }, "devDependencies": { - "@libp2p/interface-compliance-tests": "^4.1.1", - "@libp2p/interface-internal": "^0.1.6", - "@libp2p/peer-id-factory": "^3.0.5", + "@libp2p/interface-compliance-tests": "^4.1.2", + "@libp2p/interface-internal": "^0.1.7", + "@libp2p/peer-id-factory": "^3.0.6", "aegir": "^41.0.2", "p-wait-for": "^5.0.2", "ts-sinon": "^2.0.2" diff --git a/packages/peer-id-factory/CHANGELOG.md b/packages/peer-id-factory/CHANGELOG.md index dba517b519..491b844b2f 100644 --- a/packages/peer-id-factory/CHANGELOG.md +++ b/packages/peer-id-factory/CHANGELOG.md @@ -5,6 +5,17 @@ * update README.md ([#59](https://github.com/libp2p/js-libp2p-peer-id/issues/59)) ([aba6483](https://github.com/libp2p/js-libp2p-peer-id/commit/aba6483dad028ee5c24bfc01135b77568666cfd3)) +### [3.0.6](https://www.github.com/libp2p/js-libp2p/compare/peer-id-factory-v3.0.5...peer-id-factory-v3.0.6) (2023-10-25) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * @libp2p/crypto bumped from ^2.0.5 to ^2.0.6 + * @libp2p/interface bumped from ^0.1.3 to ^0.1.4 + * @libp2p/peer-id bumped from ^3.0.3 to ^3.0.4 + ### [3.0.5](https://www.github.com/libp2p/js-libp2p/compare/peer-id-factory-v3.0.4...peer-id-factory-v3.0.5) (2023-10-06) diff --git a/packages/peer-id-factory/package.json b/packages/peer-id-factory/package.json index d2ca5bdb2f..6b4416994c 100644 --- a/packages/peer-id-factory/package.json +++ b/packages/peer-id-factory/package.json @@ -1,6 +1,6 @@ { "name": "@libp2p/peer-id-factory", - "version": "3.0.5", + "version": "3.0.6", "description": "Create PeerId instances", "license": "Apache-2.0 OR MIT", "homepage": "https://github.com/libp2p/js-libp2p/tree/master/packages/peer-id-factory#readme", @@ -53,9 +53,9 @@ "test:electron-main": "aegir test -t electron-main" }, "dependencies": { - "@libp2p/crypto": "^2.0.5", - "@libp2p/interface": "^0.1.3", - "@libp2p/peer-id": "^3.0.3", + "@libp2p/crypto": "^2.0.6", + "@libp2p/interface": "^0.1.4", + "@libp2p/peer-id": "^3.0.4", "multiformats": "^12.0.1", "protons-runtime": "^5.0.0", "uint8arraylist": "^2.4.3", diff --git a/packages/peer-id/CHANGELOG.md b/packages/peer-id/CHANGELOG.md index 986cefe7ae..3bf6b46c8a 100644 --- a/packages/peer-id/CHANGELOG.md +++ b/packages/peer-id/CHANGELOG.md @@ -5,6 +5,15 @@ * update README.md ([#59](https://github.com/libp2p/js-libp2p-peer-id/issues/59)) ([aba6483](https://github.com/libp2p/js-libp2p-peer-id/commit/aba6483dad028ee5c24bfc01135b77568666cfd3)) +### [3.0.4](https://www.github.com/libp2p/js-libp2p/compare/peer-id-v3.0.3...peer-id-v3.0.4) (2023-10-25) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * @libp2p/interface bumped from ^0.1.3 to ^0.1.4 + ### [3.0.3](https://www.github.com/libp2p/js-libp2p/compare/peer-id-v3.0.2...peer-id-v3.0.3) (2023-10-06) diff --git a/packages/peer-id/package.json b/packages/peer-id/package.json index bb910d9888..bc2fa6aea1 100644 --- a/packages/peer-id/package.json +++ b/packages/peer-id/package.json @@ -1,6 +1,6 @@ { "name": "@libp2p/peer-id", - "version": "3.0.3", + "version": "3.0.4", "description": "Implementation of @libp2p/interface-peer-id", "license": "Apache-2.0 OR MIT", "homepage": "https://github.com/libp2p/js-libp2p/tree/master/packages/peer-id#readme", @@ -49,7 +49,7 @@ "test:electron-main": "aegir test -t electron-main" }, "dependencies": { - "@libp2p/interface": "^0.1.3", + "@libp2p/interface": "^0.1.4", "multiformats": "^12.0.1", "uint8arrays": "^4.0.6" }, diff --git a/packages/peer-record/CHANGELOG.md b/packages/peer-record/CHANGELOG.md index 69281e709b..cd7020862b 100644 --- a/packages/peer-record/CHANGELOG.md +++ b/packages/peer-record/CHANGELOG.md @@ -11,6 +11,20 @@ * **dev:** bump aegir from 38.1.8 to 39.0.10 ([#64](https://github.com/libp2p/js-libp2p-peer-record/issues/64)) ([ba3ac38](https://github.com/libp2p/js-libp2p-peer-record/commit/ba3ac38c79e9449a75c0a54fefe289ee9e2c78fb)) +### [6.0.7](https://www.github.com/libp2p/js-libp2p/compare/peer-record-v6.0.6...peer-record-v6.0.7) (2023-10-25) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * @libp2p/crypto bumped from ^2.0.5 to ^2.0.6 + * @libp2p/interface bumped from ^0.1.3 to ^0.1.4 + * @libp2p/peer-id bumped from ^3.0.3 to ^3.0.4 + * @libp2p/utils bumped from ^4.0.4 to ^4.0.5 + * devDependencies + * @libp2p/peer-id-factory bumped from ^3.0.5 to ^3.0.6 + ### [6.0.6](https://www.github.com/libp2p/js-libp2p/compare/peer-record-v6.0.5...peer-record-v6.0.6) (2023-10-06) diff --git a/packages/peer-record/package.json b/packages/peer-record/package.json index a7110a82b4..d0e6c0ccbc 100644 --- a/packages/peer-record/package.json +++ b/packages/peer-record/package.json @@ -1,6 +1,6 @@ { "name": "@libp2p/peer-record", - "version": "6.0.6", + "version": "6.0.7", "description": "Used to transfer signed peer data across the network", "license": "Apache-2.0 OR MIT", "homepage": "https://github.com/libp2p/js-libp2p/tree/master/packages/peer-record#readme", @@ -56,10 +56,10 @@ "test:electron-main": "aegir test -t electron-main" }, "dependencies": { - "@libp2p/crypto": "^2.0.5", - "@libp2p/interface": "^0.1.3", - "@libp2p/peer-id": "^3.0.3", - "@libp2p/utils": "^4.0.4", + "@libp2p/crypto": "^2.0.6", + "@libp2p/interface": "^0.1.4", + "@libp2p/peer-id": "^3.0.4", + "@libp2p/utils": "^4.0.5", "@multiformats/multiaddr": "^12.1.5", "protons-runtime": "^5.0.0", "uint8-varint": "^2.0.0", @@ -67,7 +67,7 @@ "uint8arrays": "^4.0.6" }, "devDependencies": { - "@libp2p/peer-id-factory": "^3.0.5", + "@libp2p/peer-id-factory": "^3.0.6", "aegir": "^41.0.2", "protons": "^7.0.2" } diff --git a/packages/peer-store/CHANGELOG.md b/packages/peer-store/CHANGELOG.md index 0996044df8..12927a0bc2 100644 --- a/packages/peer-store/CHANGELOG.md +++ b/packages/peer-store/CHANGELOG.md @@ -11,6 +11,26 @@ * **dev:** bump p-event from 5.0.1 to 6.0.0 ([#89](https://github.com/libp2p/js-libp2p-peer-store/issues/89)) ([9d96700](https://github.com/libp2p/js-libp2p-peer-store/commit/9d9670048b5e8feeac656cba92cb2e513e4a77be)) +### [9.0.7](https://www.github.com/libp2p/js-libp2p/compare/peer-store-v9.0.6...peer-store-v9.0.7) (2023-10-25) + + +### Bug Fixes + +* rename event emitter class ([#2173](https://www.github.com/libp2p/js-libp2p/issues/2173)) ([50f912c](https://www.github.com/libp2p/js-libp2p/commit/50f912c2608caecc09acbcb0f46b4df4af073080)) +* revert "refactor: rename event emitter class" ([#2172](https://www.github.com/libp2p/js-libp2p/issues/2172)) ([0ef5f7f](https://www.github.com/libp2p/js-libp2p/commit/0ef5f7f62d9c6d822e0a4b99cc203a1516b11f2f)) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * @libp2p/interface bumped from ^0.1.3 to ^0.1.4 + * @libp2p/logger bumped from ^3.0.3 to ^3.0.4 + * @libp2p/peer-collections bumped from ^4.0.5 to ^4.0.6 + * @libp2p/peer-id bumped from ^3.0.3 to ^3.0.4 + * @libp2p/peer-id-factory bumped from ^3.0.5 to ^3.0.6 + * @libp2p/peer-record bumped from ^6.0.6 to ^6.0.7 + ### [9.0.6](https://www.github.com/libp2p/js-libp2p/compare/peer-store-v9.0.5...peer-store-v9.0.6) (2023-10-06) @@ -498,4 +518,4 @@ Co-authored-by: Alex Potsides ### Features -* add peer store/records, and streams are just streams ([#160](https://github.com/libp2p/js-libp2p-interfaces/issues/160)) ([8860a0c](https://github.com/libp2p/js-libp2p-interfaces/commit/8860a0cd46b359a5648402d83870f7ff957222fe)) +* add peer store/records, and streams are just streams ([#160](https://github.com/libp2p/js-libp2p-interfaces/issues/160)) ([8860a0c](https://github.com/libp2p/js-libp2p-interfaces/commit/8860a0cd46b359a5648402d83870f7ff957222fe)) \ No newline at end of file diff --git a/packages/peer-store/package.json b/packages/peer-store/package.json index 81f61193d0..a2896c2f05 100644 --- a/packages/peer-store/package.json +++ b/packages/peer-store/package.json @@ -1,6 +1,6 @@ { "name": "@libp2p/peer-store", - "version": "9.0.6", + "version": "9.0.7", "description": "Stores information about peers libp2p knows on the network", "license": "Apache-2.0 OR MIT", "homepage": "https://github.com/libp2p/js-libp2p/tree/master/packages/peer-store#readme", @@ -54,12 +54,12 @@ "test:electron-main": "aegir test -t electron-main" }, "dependencies": { - "@libp2p/interface": "^0.1.3", - "@libp2p/logger": "^3.0.3", - "@libp2p/peer-collections": "^4.0.5", - "@libp2p/peer-id": "^3.0.3", - "@libp2p/peer-id-factory": "^3.0.5", - "@libp2p/peer-record": "^6.0.6", + "@libp2p/interface": "^0.1.4", + "@libp2p/logger": "^3.0.4", + "@libp2p/peer-collections": "^4.0.6", + "@libp2p/peer-id": "^3.0.4", + "@libp2p/peer-id-factory": "^3.0.6", + "@libp2p/peer-record": "^6.0.7", "@multiformats/multiaddr": "^12.1.5", "interface-datastore": "^8.2.0", "it-all": "^3.0.2", diff --git a/packages/protocol-perf/CHANGELOG.md b/packages/protocol-perf/CHANGELOG.md index 6887569649..e745f44df3 100644 --- a/packages/protocol-perf/CHANGELOG.md +++ b/packages/protocol-perf/CHANGELOG.md @@ -1,5 +1,27 @@ # Changelog +### [1.1.13](https://www.github.com/libp2p/js-libp2p/compare/perf-v1.1.12...perf-v1.1.13) (2023-10-25) + + +### Bug Fixes + +* rename event emitter class ([#2173](https://www.github.com/libp2p/js-libp2p/issues/2173)) ([50f912c](https://www.github.com/libp2p/js-libp2p/commit/50f912c2608caecc09acbcb0f46b4df4af073080)) +* revert "refactor: rename event emitter class" ([#2172](https://www.github.com/libp2p/js-libp2p/issues/2172)) ([0ef5f7f](https://www.github.com/libp2p/js-libp2p/commit/0ef5f7f62d9c6d822e0a4b99cc203a1516b11f2f)) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * @libp2p/crypto bumped from ^2.0.5 to ^2.0.6 + * @libp2p/interface bumped from ^0.1.3 to ^0.1.4 + * @libp2p/interface-compliance-tests bumped from ^4.1.1 to ^4.1.2 + * @libp2p/interface-internal bumped from ^0.1.6 to ^0.1.7 + * @libp2p/logger bumped from ^3.0.3 to ^3.0.4 + * @libp2p/peer-id-factory bumped from ^3.0.5 to ^3.0.6 + * @libp2p/tcp bumped from ^8.0.9 to ^8.0.10 + * libp2p bumped from ^0.46.15 to ^0.46.16 + ### [1.1.12](https://www.github.com/libp2p/js-libp2p/compare/perf-v1.1.11...perf-v1.1.12) (2023-10-25) @@ -156,4 +178,4 @@ * @libp2p/logger bumped from ^3.0.0 to ^3.0.2 * @libp2p/peer-id-factory bumped from 3.0.0 to ^3.0.3 * @libp2p/tcp bumped from ^8.0.0 to ^8.0.3 - * libp2p bumped from ^0.46.3 to ^0.46.4 + * libp2p bumped from ^0.46.3 to ^0.46.4 \ No newline at end of file diff --git a/packages/protocol-perf/package.json b/packages/protocol-perf/package.json index b4bfb57b06..b9dd5e2c01 100644 --- a/packages/protocol-perf/package.json +++ b/packages/protocol-perf/package.json @@ -1,6 +1,6 @@ { "name": "@libp2p/perf", - "version": "1.1.12", + "version": "1.1.13", "description": "Implementation of Perf Protocol", "author": "@maschad / @marcopolo", "license": "Apache-2.0 OR MIT", @@ -50,16 +50,16 @@ "dependencies": { "@chainsafe/libp2p-noise": "^13.0.0", "@chainsafe/libp2p-yamux": "^5.0.0", - "@libp2p/crypto": "^2.0.5", - "@libp2p/interface": "^0.1.3", - "@libp2p/interface-compliance-tests": "^4.1.1", - "@libp2p/interface-internal": "^0.1.6", + "@libp2p/crypto": "^2.0.6", + "@libp2p/interface": "^0.1.4", + "@libp2p/interface-compliance-tests": "^4.1.2", + "@libp2p/interface-internal": "^0.1.7", "@libp2p/interfaces": "3.3.2", - "@libp2p/logger": "^3.0.3", - "@libp2p/peer-id-factory": "^3.0.5", - "@libp2p/tcp": "^8.0.9", + "@libp2p/logger": "^3.0.4", + "@libp2p/peer-id-factory": "^3.0.6", + "@libp2p/tcp": "^8.0.10", "@multiformats/multiaddr": "^12.1.5", - "libp2p": "^0.46.15", + "libp2p": "^0.46.16", "uint8arrays": "^4.0.6", "yargs": "^17.7.2" }, diff --git a/packages/pubsub-floodsub/CHANGELOG.md b/packages/pubsub-floodsub/CHANGELOG.md index 178ead29e1..f5f91fb1e5 100644 --- a/packages/pubsub-floodsub/CHANGELOG.md +++ b/packages/pubsub-floodsub/CHANGELOG.md @@ -11,6 +11,21 @@ * **dev:** bump aegir from 38.1.8 to 39.0.10 ([#233](https://github.com/libp2p/js-libp2p-floodsub/issues/233)) ([e073298](https://github.com/libp2p/js-libp2p-floodsub/commit/e073298f324a89656b0ca6d9a629e60eaedc7873)) +### [8.0.10](https://www.github.com/libp2p/js-libp2p/compare/floodsub-v8.0.9...floodsub-v8.0.10) (2023-10-25) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * @libp2p/interface bumped from ^0.1.3 to ^0.1.4 + * @libp2p/logger bumped from ^3.0.3 to ^3.0.4 + * @libp2p/pubsub bumped from ^8.0.7 to ^8.0.8 + * devDependencies + * @libp2p/interface-compliance-tests bumped from ^4.1.1 to ^4.1.2 + * @libp2p/peer-collections bumped from ^4.0.5 to ^4.0.6 + * @libp2p/peer-id-factory bumped from ^3.0.5 to ^3.0.6 + ### [8.0.9](https://www.github.com/libp2p/js-libp2p/compare/floodsub-v8.0.8...floodsub-v8.0.9) (2023-10-06) diff --git a/packages/pubsub-floodsub/package.json b/packages/pubsub-floodsub/package.json index 2b49e8ce8f..f00f74f793 100644 --- a/packages/pubsub-floodsub/package.json +++ b/packages/pubsub-floodsub/package.json @@ -1,6 +1,6 @@ { "name": "@libp2p/floodsub", - "version": "8.0.9", + "version": "8.0.10", "description": "libp2p-floodsub, also known as pubsub-flood or just dumbsub, this implementation of pubsub focused on delivering an API for Publish/Subscribe, but with no CastTree Forming (it just floods the network).", "license": "Apache-2.0 OR MIT", "homepage": "https://github.com/libp2p/js-libp2p/tree/master/packages/pubsub-floodsub#readme", @@ -55,17 +55,17 @@ "test:electron-main": "aegir test -t electron-main" }, "dependencies": { - "@libp2p/interface": "^0.1.3", - "@libp2p/logger": "^3.0.3", - "@libp2p/pubsub": "^8.0.7", + "@libp2p/interface": "^0.1.4", + "@libp2p/logger": "^3.0.4", + "@libp2p/pubsub": "^8.0.8", "protons-runtime": "^5.0.0", "uint8arraylist": "^2.4.3", "uint8arrays": "^4.0.6" }, "devDependencies": { - "@libp2p/interface-compliance-tests": "^4.1.1", - "@libp2p/peer-collections": "^4.0.5", - "@libp2p/peer-id-factory": "^3.0.5", + "@libp2p/interface-compliance-tests": "^4.1.2", + "@libp2p/peer-collections": "^4.0.6", + "@libp2p/peer-id-factory": "^3.0.6", "@multiformats/multiaddr": "^12.1.3", "@types/sinon": "^10.0.15", "aegir": "^41.0.2", diff --git a/packages/pubsub/CHANGELOG.md b/packages/pubsub/CHANGELOG.md index b4847adc19..c155018d78 100644 --- a/packages/pubsub/CHANGELOG.md +++ b/packages/pubsub/CHANGELOG.md @@ -5,6 +5,28 @@ * **dev:** bump delay from 5.0.0 to 6.0.0 ([#144](https://github.com/libp2p/js-libp2p-pubsub/issues/144)) ([1364ce4](https://github.com/libp2p/js-libp2p-pubsub/commit/1364ce41815d3392cfca61169e113cc5414ac2d9)) +### [8.0.8](https://www.github.com/libp2p/js-libp2p/compare/pubsub-v8.0.7...pubsub-v8.0.8) (2023-10-25) + + +### Bug Fixes + +* rename event emitter class ([#2173](https://www.github.com/libp2p/js-libp2p/issues/2173)) ([50f912c](https://www.github.com/libp2p/js-libp2p/commit/50f912c2608caecc09acbcb0f46b4df4af073080)) +* revert "refactor: rename event emitter class" ([#2172](https://www.github.com/libp2p/js-libp2p/issues/2172)) ([0ef5f7f](https://www.github.com/libp2p/js-libp2p/commit/0ef5f7f62d9c6d822e0a4b99cc203a1516b11f2f)) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * @libp2p/crypto bumped from ^2.0.5 to ^2.0.6 + * @libp2p/interface bumped from ^0.1.3 to ^0.1.4 + * @libp2p/interface-internal bumped from ^0.1.6 to ^0.1.7 + * @libp2p/logger bumped from ^3.0.3 to ^3.0.4 + * @libp2p/peer-collections bumped from ^4.0.5 to ^4.0.6 + * @libp2p/peer-id bumped from ^3.0.3 to ^3.0.4 + * devDependencies + * @libp2p/peer-id-factory bumped from ^3.0.5 to ^3.0.6 + ### [8.0.7](https://www.github.com/libp2p/js-libp2p/compare/pubsub-v8.0.6...pubsub-v8.0.7) (2023-10-06) @@ -642,4 +664,4 @@ See [Conventional Commits](https://conventionalcommits.org) for commit guideline ### BREAKING CHANGES -* not all fields from concrete classes have been added to the interfaces, some adjustment may be necessary as this gets rolled out +* not all fields from concrete classes have been added to the interfaces, some adjustment may be necessary as this gets rolled out \ No newline at end of file diff --git a/packages/pubsub/package.json b/packages/pubsub/package.json index faf89c3d97..4aef70e43c 100644 --- a/packages/pubsub/package.json +++ b/packages/pubsub/package.json @@ -1,6 +1,6 @@ { "name": "@libp2p/pubsub", - "version": "8.0.7", + "version": "8.0.8", "description": "libp2p pubsub base class", "license": "Apache-2.0 OR MIT", "homepage": "https://github.com/libp2p/js-libp2p/tree/master/packages/pubsub#readme", @@ -79,12 +79,12 @@ "test:electron-main": "aegir test -t electron-main" }, "dependencies": { - "@libp2p/crypto": "^2.0.5", - "@libp2p/interface": "^0.1.3", - "@libp2p/interface-internal": "^0.1.6", - "@libp2p/logger": "^3.0.3", - "@libp2p/peer-collections": "^4.0.5", - "@libp2p/peer-id": "^3.0.3", + "@libp2p/crypto": "^2.0.6", + "@libp2p/interface": "^0.1.4", + "@libp2p/interface-internal": "^0.1.7", + "@libp2p/logger": "^3.0.4", + "@libp2p/peer-collections": "^4.0.6", + "@libp2p/peer-id": "^3.0.4", "abortable-iterator": "^5.0.1", "it-length-prefixed": "^9.0.1", "it-pipe": "^3.0.1", @@ -95,7 +95,7 @@ "uint8arrays": "^4.0.6" }, "devDependencies": { - "@libp2p/peer-id-factory": "^3.0.5", + "@libp2p/peer-id-factory": "^3.0.6", "@types/sinon": "^10.0.15", "aegir": "^41.0.2", "delay": "^6.0.0", diff --git a/packages/stream-multiplexer-mplex/CHANGELOG.md b/packages/stream-multiplexer-mplex/CHANGELOG.md index 5f4a08412a..9b0f54c66b 100644 --- a/packages/stream-multiplexer-mplex/CHANGELOG.md +++ b/packages/stream-multiplexer-mplex/CHANGELOG.md @@ -12,6 +12,18 @@ * **dev:** bump cborg from 1.10.2 to 2.0.1 ([#282](https://github.com/libp2p/js-libp2p-mplex/issues/282)) ([4dbc590](https://github.com/libp2p/js-libp2p-mplex/commit/4dbc590d1ac92581fe2e937757567eef3854acf4)) * **dev:** bump delay from 5.0.0 to 6.0.0 ([#281](https://github.com/libp2p/js-libp2p-mplex/issues/281)) ([1e03e75](https://github.com/libp2p/js-libp2p-mplex/commit/1e03e75369722be9872f747cd83f555bc08d49fe)) +### [9.0.9](https://www.github.com/libp2p/js-libp2p/compare/mplex-v9.0.8...mplex-v9.0.9) (2023-10-25) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * @libp2p/interface bumped from ^0.1.3 to ^0.1.4 + * @libp2p/logger bumped from ^3.0.3 to ^3.0.4 + * devDependencies + * @libp2p/interface-compliance-tests bumped from ^4.1.1 to ^4.1.2 + ### [9.0.8](https://www.github.com/libp2p/js-libp2p/compare/mplex-v9.0.7...mplex-v9.0.8) (2023-10-06) diff --git a/packages/stream-multiplexer-mplex/package.json b/packages/stream-multiplexer-mplex/package.json index 67a1db3952..750f082c29 100644 --- a/packages/stream-multiplexer-mplex/package.json +++ b/packages/stream-multiplexer-mplex/package.json @@ -1,6 +1,6 @@ { "name": "@libp2p/mplex", - "version": "9.0.8", + "version": "9.0.9", "description": "JavaScript implementation of https://github.com/libp2p/mplex", "license": "Apache-2.0 OR MIT", "homepage": "https://github.com/libp2p/js-libp2p/tree/master/packages/stream-multiplexer-mplex#readme", @@ -57,8 +57,8 @@ "test:electron-main": "aegir test -t electron-main" }, "dependencies": { - "@libp2p/interface": "^0.1.3", - "@libp2p/logger": "^3.0.3", + "@libp2p/interface": "^0.1.4", + "@libp2p/logger": "^3.0.4", "abortable-iterator": "^5.0.1", "benchmark": "^2.1.4", "it-batched-bytes": "^2.0.2", @@ -70,7 +70,7 @@ "uint8arrays": "^4.0.6" }, "devDependencies": { - "@libp2p/interface-compliance-tests": "^4.1.1", + "@libp2p/interface-compliance-tests": "^4.1.2", "aegir": "^41.0.2", "cborg": "^4.0.3", "delay": "^6.0.0", diff --git a/packages/transport-tcp/CHANGELOG.md b/packages/transport-tcp/CHANGELOG.md index 58cedcc115..b9860cbed6 100644 --- a/packages/transport-tcp/CHANGELOG.md +++ b/packages/transport-tcp/CHANGELOG.md @@ -5,6 +5,25 @@ * **dev:** bump aegir from 38.1.8 to 39.0.10 ([#279](https://github.com/libp2p/js-libp2p-tcp/issues/279)) ([3ed1235](https://github.com/libp2p/js-libp2p-tcp/commit/3ed12353aa48b5a933f80042846a8f1c2337fa47)) +### [8.0.10](https://www.github.com/libp2p/js-libp2p/compare/tcp-v8.0.9...tcp-v8.0.10) (2023-10-25) + + +### Bug Fixes + +* rename event emitter class ([#2173](https://www.github.com/libp2p/js-libp2p/issues/2173)) ([50f912c](https://www.github.com/libp2p/js-libp2p/commit/50f912c2608caecc09acbcb0f46b4df4af073080)) +* revert "refactor: rename event emitter class" ([#2172](https://www.github.com/libp2p/js-libp2p/issues/2172)) ([0ef5f7f](https://www.github.com/libp2p/js-libp2p/commit/0ef5f7f62d9c6d822e0a4b99cc203a1516b11f2f)) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * @libp2p/interface bumped from ^0.1.3 to ^0.1.4 + * @libp2p/logger bumped from ^3.0.3 to ^3.0.4 + * @libp2p/utils bumped from ^4.0.4 to ^4.0.5 + * devDependencies + * @libp2p/interface-compliance-tests bumped from ^4.1.1 to ^4.1.2 + ### [8.0.9](https://www.github.com/libp2p/js-libp2p/compare/tcp-v8.0.8...tcp-v8.0.9) (2023-10-06) @@ -1038,4 +1057,4 @@ -# 0.1.0 (2015-09-16) +# 0.1.0 (2015-09-16) \ No newline at end of file diff --git a/packages/transport-tcp/package.json b/packages/transport-tcp/package.json index 117123a15c..140df64288 100644 --- a/packages/transport-tcp/package.json +++ b/packages/transport-tcp/package.json @@ -1,6 +1,6 @@ { "name": "@libp2p/tcp", - "version": "8.0.9", + "version": "8.0.10", "description": "A TCP transport for libp2p", "license": "Apache-2.0 OR MIT", "homepage": "https://github.com/libp2p/js-libp2p/tree/master/packages/transport-tcp#readme", @@ -51,16 +51,16 @@ "test:electron-main": "aegir test -t electron-main" }, "dependencies": { - "@libp2p/interface": "^0.1.3", - "@libp2p/logger": "^3.0.3", - "@libp2p/utils": "^4.0.4", + "@libp2p/interface": "^0.1.4", + "@libp2p/logger": "^3.0.4", + "@libp2p/utils": "^4.0.5", "@multiformats/mafmt": "^12.1.2", "@multiformats/multiaddr": "^12.1.5", "@types/sinon": "^10.0.15", "stream-to-it": "^0.2.2" }, "devDependencies": { - "@libp2p/interface-compliance-tests": "^4.1.1", + "@libp2p/interface-compliance-tests": "^4.1.2", "aegir": "^41.0.2", "it-all": "^3.0.1", "it-pipe": "^3.0.1", diff --git a/packages/transport-webrtc/CHANGELOG.md b/packages/transport-webrtc/CHANGELOG.md index ebb6dfbdd8..bfd78218c6 100644 --- a/packages/transport-webrtc/CHANGELOG.md +++ b/packages/transport-webrtc/CHANGELOG.md @@ -5,6 +5,29 @@ * add browser-to-browser test for bi-directional communication ([#172](https://github.com/libp2p/js-libp2p-webrtc/issues/172)) ([1ec3d8a](https://github.com/libp2p/js-libp2p-webrtc/commit/1ec3d8a8b611d5227f430037e2547fd86d115eaa)) +### [3.2.5](https://www.github.com/libp2p/js-libp2p/compare/webrtc-v3.2.4...webrtc-v3.2.5) (2023-10-25) + + +### Bug Fixes + +* rename event emitter class ([#2173](https://www.github.com/libp2p/js-libp2p/issues/2173)) ([50f912c](https://www.github.com/libp2p/js-libp2p/commit/50f912c2608caecc09acbcb0f46b4df4af073080)) +* revert "refactor: rename event emitter class" ([#2172](https://www.github.com/libp2p/js-libp2p/issues/2172)) ([0ef5f7f](https://www.github.com/libp2p/js-libp2p/commit/0ef5f7f62d9c6d822e0a4b99cc203a1516b11f2f)) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * @libp2p/interface bumped from ^0.1.3 to ^0.1.4 + * @libp2p/interface-internal bumped from ^0.1.6 to ^0.1.7 + * @libp2p/logger bumped from ^3.0.3 to ^3.0.4 + * @libp2p/peer-id bumped from ^3.0.3 to ^3.0.4 + * devDependencies + * @libp2p/interface-compliance-tests bumped from ^4.1.1 to ^4.1.2 + * @libp2p/peer-id-factory bumped from ^3.0.5 to ^3.0.6 + * @libp2p/websockets bumped from ^7.0.9 to ^7.0.10 + * libp2p bumped from ^0.46.15 to ^0.46.16 + ### [3.2.4](https://www.github.com/libp2p/js-libp2p/compare/webrtc-v3.2.3...webrtc-v3.2.4) (2023-10-25) @@ -504,4 +527,4 @@ ### Documentation -* fix 'browser to server' build config ([#66](https://github.com/libp2p/js-libp2p-webrtc/issues/66)) ([b54132c](https://github.com/libp2p/js-libp2p-webrtc/commit/b54132cecac180f0577a1b7905f79b20207c3647)) +* fix 'browser to server' build config ([#66](https://github.com/libp2p/js-libp2p-webrtc/issues/66)) ([b54132c](https://github.com/libp2p/js-libp2p-webrtc/commit/b54132cecac180f0577a1b7905f79b20207c3647)) \ No newline at end of file diff --git a/packages/transport-webrtc/package.json b/packages/transport-webrtc/package.json index 919d5c5032..a6e8d801dc 100644 --- a/packages/transport-webrtc/package.json +++ b/packages/transport-webrtc/package.json @@ -1,6 +1,6 @@ { "name": "@libp2p/webrtc", - "version": "3.2.4", + "version": "3.2.5", "description": "A libp2p transport using WebRTC connections", "license": "Apache-2.0 OR MIT", "homepage": "https://github.com/libp2p/js-libp2p/tree/master/packages/transport-webrtc#readme", @@ -46,10 +46,10 @@ }, "dependencies": { "@chainsafe/libp2p-noise": "^13.0.0", - "@libp2p/interface": "^0.1.3", - "@libp2p/interface-internal": "^0.1.6", - "@libp2p/logger": "^3.0.3", - "@libp2p/peer-id": "^3.0.3", + "@libp2p/interface": "^0.1.4", + "@libp2p/interface-internal": "^0.1.7", + "@libp2p/logger": "^3.0.4", + "@libp2p/peer-id": "^3.0.4", "@multiformats/mafmt": "^12.1.2", "@multiformats/multiaddr": "^12.1.5", "@multiformats/multiaddr-matcher": "^1.0.1", @@ -75,9 +75,9 @@ }, "devDependencies": { "@chainsafe/libp2p-yamux": "^5.0.0", - "@libp2p/interface-compliance-tests": "^4.1.1", - "@libp2p/peer-id-factory": "^3.0.5", - "@libp2p/websockets": "^7.0.9", + "@libp2p/interface-compliance-tests": "^4.1.2", + "@libp2p/peer-id-factory": "^3.0.6", + "@libp2p/websockets": "^7.0.10", "@types/sinon": "^10.0.15", "aegir": "^41.0.2", "delay": "^6.0.0", @@ -85,7 +85,7 @@ "it-length": "^3.0.2", "it-map": "^3.0.3", "it-pair": "^2.0.6", - "libp2p": "^0.46.15", + "libp2p": "^0.46.16", "p-retry": "^6.1.0", "protons": "^7.0.2", "sinon": "^17.0.0", diff --git a/packages/transport-websockets/CHANGELOG.md b/packages/transport-websockets/CHANGELOG.md index 96384c9937..90d05f6a1c 100644 --- a/packages/transport-websockets/CHANGELOG.md +++ b/packages/transport-websockets/CHANGELOG.md @@ -6,6 +6,25 @@ * **dev:** bump @libp2p/interface-mocks from 11.0.3 to 12.0.1 ([#241](https://github.com/libp2p/js-libp2p-websockets/issues/241)) ([f956836](https://github.com/libp2p/js-libp2p-websockets/commit/f95683641bda2f9b250768768451e0c121afc2a0)) * **dev:** bump aegir from 38.1.8 to 39.0.9 ([#245](https://github.com/libp2p/js-libp2p-websockets/issues/245)) ([4a35f6b](https://github.com/libp2p/js-libp2p-websockets/commit/4a35f6b39a918fb7ef779292553cb452a543afb0)) +### [7.0.10](https://www.github.com/libp2p/js-libp2p/compare/websockets-v7.0.9...websockets-v7.0.10) (2023-10-25) + + +### Bug Fixes + +* rename event emitter class ([#2173](https://www.github.com/libp2p/js-libp2p/issues/2173)) ([50f912c](https://www.github.com/libp2p/js-libp2p/commit/50f912c2608caecc09acbcb0f46b4df4af073080)) +* revert "refactor: rename event emitter class" ([#2172](https://www.github.com/libp2p/js-libp2p/issues/2172)) ([0ef5f7f](https://www.github.com/libp2p/js-libp2p/commit/0ef5f7f62d9c6d822e0a4b99cc203a1516b11f2f)) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * @libp2p/interface bumped from ^0.1.3 to ^0.1.4 + * @libp2p/logger bumped from ^3.0.3 to ^3.0.4 + * @libp2p/utils bumped from ^4.0.4 to ^4.0.5 + * devDependencies + * @libp2p/interface-compliance-tests bumped from ^4.1.1 to ^4.1.2 + ### [7.0.9](https://www.github.com/libp2p/js-libp2p/compare/websockets-v7.0.8...websockets-v7.0.9) (2023-10-06) diff --git a/packages/transport-websockets/package.json b/packages/transport-websockets/package.json index df58354214..a6b4fdfdfe 100644 --- a/packages/transport-websockets/package.json +++ b/packages/transport-websockets/package.json @@ -1,6 +1,6 @@ { "name": "@libp2p/websockets", - "version": "7.0.9", + "version": "7.0.10", "description": "JavaScript implementation of the WebSockets module that libp2p uses and that implements the interface-transport spec", "license": "Apache-2.0 OR MIT", "homepage": "https://github.com/libp2p/js-libp2p/tree/master/packages/transport-websockets#readme", @@ -69,9 +69,9 @@ "test:electron-main": "aegir test -t electron-main -f ./dist/test/node.js --cov" }, "dependencies": { - "@libp2p/interface": "^0.1.3", - "@libp2p/logger": "^3.0.3", - "@libp2p/utils": "^4.0.4", + "@libp2p/interface": "^0.1.4", + "@libp2p/logger": "^3.0.4", + "@libp2p/utils": "^4.0.5", "@multiformats/mafmt": "^12.1.2", "@multiformats/multiaddr": "^12.1.5", "@multiformats/multiaddr-to-uri": "^9.0.2", @@ -83,7 +83,7 @@ "ws": "^8.12.1" }, "devDependencies": { - "@libp2p/interface-compliance-tests": "^4.1.1", + "@libp2p/interface-compliance-tests": "^4.1.2", "aegir": "^41.0.2", "is-loopback-addr": "^2.0.1", "it-all": "^3.0.1", diff --git a/packages/transport-webtransport/CHANGELOG.md b/packages/transport-webtransport/CHANGELOG.md index d00fa59b6a..59be4b9991 100644 --- a/packages/transport-webtransport/CHANGELOG.md +++ b/packages/transport-webtransport/CHANGELOG.md @@ -11,6 +11,20 @@ * bump @chainsafe/libp2p-noise from 11.0.4 to 12.0.1 ([#80](https://github.com/libp2p/js-libp2p-webtransport/issues/80)) ([599dab1](https://github.com/libp2p/js-libp2p-webtransport/commit/599dab1b4f6ae816b0c0feefc926c1b38d24b676)) +### [3.1.5](https://www.github.com/libp2p/js-libp2p/compare/webtransport-v3.1.4...webtransport-v3.1.5) (2023-10-25) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * @libp2p/interface bumped from ^0.1.3 to ^0.1.4 + * @libp2p/logger bumped from ^3.0.3 to ^3.0.4 + * @libp2p/peer-id bumped from ^3.0.3 to ^3.0.4 + * devDependencies + * @libp2p/peer-id-factory bumped from ^3.0.5 to ^3.0.6 + * libp2p bumped from ^0.46.15 to ^0.46.16 + ### [3.1.4](https://www.github.com/libp2p/js-libp2p/compare/webtransport-v3.1.3...webtransport-v3.1.4) (2023-10-25) diff --git a/packages/transport-webtransport/package.json b/packages/transport-webtransport/package.json index 2e5df8d2c5..4cab63776a 100644 --- a/packages/transport-webtransport/package.json +++ b/packages/transport-webtransport/package.json @@ -1,6 +1,6 @@ { "name": "@libp2p/webtransport", - "version": "3.1.4", + "version": "3.1.5", "description": "JavaScript implementation of the WebTransport module that libp2p uses and that implements the interface-transport spec", "license": "Apache-2.0 OR MIT", "homepage": "https://github.com/libp2p/js-libp2p/tree/master/packages/transport-webtransport#readme", @@ -62,9 +62,9 @@ }, "dependencies": { "@chainsafe/libp2p-noise": "^13.0.0", - "@libp2p/interface": "^0.1.3", - "@libp2p/logger": "^3.0.3", - "@libp2p/peer-id": "^3.0.3", + "@libp2p/interface": "^0.1.4", + "@libp2p/logger": "^3.0.4", + "@libp2p/peer-id": "^3.0.4", "@multiformats/multiaddr": "^12.1.5", "@multiformats/multiaddr-matcher": "^1.0.1", "it-stream-types": "^2.0.1", @@ -73,9 +73,9 @@ "uint8arrays": "^4.0.6" }, "devDependencies": { - "@libp2p/peer-id-factory": "^3.0.5", + "@libp2p/peer-id-factory": "^3.0.6", "aegir": "^41.0.2", - "libp2p": "^0.46.15", + "libp2p": "^0.46.16", "p-defer": "^4.0.0" }, "browser": { diff --git a/packages/utils/CHANGELOG.md b/packages/utils/CHANGELOG.md index b432d16d92..c9b606a8f8 100644 --- a/packages/utils/CHANGELOG.md +++ b/packages/utils/CHANGELOG.md @@ -11,6 +11,16 @@ * **dev:** bump aegir from 38.1.8 to 39.0.10 ([#100](https://github.com/libp2p/js-libp2p-utils/issues/100)) ([da6547c](https://github.com/libp2p/js-libp2p-utils/commit/da6547cdd073ba1a4225be5a419c6776c4ebe6f1)) +### [4.0.5](https://www.github.com/libp2p/js-libp2p/compare/utils-v4.0.4...utils-v4.0.5) (2023-10-25) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * @libp2p/interface bumped from ^0.1.3 to ^0.1.4 + * @libp2p/logger bumped from ^3.0.3 to ^3.0.4 + ### [4.0.4](https://www.github.com/libp2p/js-libp2p/compare/utils-v4.0.3...utils-v4.0.4) (2023-10-06) diff --git a/packages/utils/package.json b/packages/utils/package.json index 89b6c0f7e5..07b12e9467 100644 --- a/packages/utils/package.json +++ b/packages/utils/package.json @@ -1,6 +1,6 @@ { "name": "@libp2p/utils", - "version": "4.0.4", + "version": "4.0.5", "description": "Package to aggregate shared logic and dependencies for the libp2p ecosystem", "license": "Apache-2.0 OR MIT", "homepage": "https://github.com/libp2p/js-libp2p/tree/master/packages/utils#readme", @@ -87,8 +87,8 @@ }, "dependencies": { "@chainsafe/is-ip": "^2.0.2", - "@libp2p/interface": "^0.1.3", - "@libp2p/logger": "^3.0.3", + "@libp2p/interface": "^0.1.4", + "@libp2p/logger": "^3.0.4", "@multiformats/multiaddr": "^12.1.5", "@multiformats/multiaddr-matcher": "^1.0.1", "is-loopback-addr": "^2.0.1", From 7903d7a5ed69cca6d3a73cbe069a40045b76bea7 Mon Sep 17 00:00:00 2001 From: Alex Potsides Date: Fri, 27 Oct 2023 08:22:50 +0100 Subject: [PATCH 13/24] chore: remove examples from repo (#2171) js-libp2p examples now live in their own repo - https://github.com/libp2p/js-libp2p-examples They are each replicated into their own repos, e.g. https://github.com/libp2p/js-libp2p-example-circuit-relay to make them easier to consume a la ipfs-examples/helia-examples. --- .github/workflows/examples.yml | 53 ++ .github/workflows/main.yml | 14 +- README.md | 15 +- doc/CONFIGURATION.md | 2 +- doc/GETTING_STARTED.md | 2 +- examples/README.md | 32 - examples/auto-relay/LICENSE | 4 - examples/auto-relay/LICENSE-APACHE | 5 - examples/auto-relay/LICENSE-MIT | 19 - examples/auto-relay/README.md | 200 ------ examples/auto-relay/dialer.js | 41 -- examples/auto-relay/listener.js | 50 -- examples/auto-relay/package.json | 47 -- examples/auto-relay/relay.js | 38 -- examples/auto-relay/test.js | 91 --- examples/chat/LICENSE | 4 - examples/chat/LICENSE-APACHE | 5 - examples/chat/LICENSE-MIT | 19 - examples/chat/README.md | 38 -- examples/chat/package.json | 53 -- examples/chat/src/dialer.js | 43 -- examples/chat/src/libp2p.js | 24 - examples/chat/src/listener.js | 39 -- examples/chat/src/peer-id-dialer.js | 5 - examples/chat/src/peer-id-listener.js | 5 - examples/chat/src/stream.js | 41 -- examples/chat/test.js | 74 -- examples/connection-encryption/1.js | 52 -- examples/connection-encryption/LICENSE | 4 - examples/connection-encryption/LICENSE-APACHE | 5 - examples/connection-encryption/LICENSE-MIT | 19 - examples/connection-encryption/README.md | 54 -- examples/connection-encryption/package.json | 46 -- examples/connection-encryption/test.js | 11 - examples/delegated-routing/LICENSE | 4 - examples/delegated-routing/LICENSE-APACHE | 5 - examples/delegated-routing/LICENSE-MIT | 19 - examples/delegated-routing/README.md | 75 --- examples/delegated-routing/package.json | 58 -- examples/delegated-routing/public/favicon.ico | Bin 3870 -> 0 bytes examples/delegated-routing/public/index.html | 16 - examples/delegated-routing/public/main.css | 67 -- examples/delegated-routing/src/App.js | 154 ----- examples/delegated-routing/src/index.js | 8 - examples/discovery-mechanisms/1.js | 36 - examples/discovery-mechanisms/2.js | 42 -- examples/discovery-mechanisms/3.js | 77 --- examples/discovery-mechanisms/LICENSE | 4 - examples/discovery-mechanisms/LICENSE-APACHE | 5 - examples/discovery-mechanisms/LICENSE-MIT | 19 - examples/discovery-mechanisms/README.md | 315 --------- .../discovery-mechanisms/bootstrappers.js | 9 - examples/discovery-mechanisms/package.json | 51 -- examples/discovery-mechanisms/test-1.js | 13 - examples/discovery-mechanisms/test-2.js | 33 - examples/discovery-mechanisms/test-3.js | 38 -- examples/discovery-mechanisms/test.js | 7 - examples/echo/LICENSE | 4 - examples/echo/LICENSE-APACHE | 5 - examples/echo/LICENSE-MIT | 19 - examples/echo/README.md | 38 -- examples/echo/package.json | 51 -- examples/echo/src/dialer.js | 58 -- examples/echo/src/id-d.js | 5 - examples/echo/src/id-l.js | 5 - examples/echo/src/libp2p.js | 24 - examples/echo/src/listener.js | 39 -- examples/echo/test.js | 58 -- .../libp2p-in-the-browser/webrtc/README.md | 4 - .../webrtc/browser-to-browser/README.md | 61 -- .../webrtc/browser-to-browser/index.html | 49 -- .../webrtc/browser-to-browser/index.js | 133 ---- .../webrtc/browser-to-browser/package.json | 27 - .../webrtc/browser-to-browser/relay.js | 26 - .../browser-to-browser/tests/test.spec.js | 129 ---- .../webrtc/browser-to-browser/vite.config.js | 11 - .../webrtc/browser-to-server/README.md | 34 - .../webrtc/browser-to-server/index.html | 41 -- .../webrtc/browser-to-server/index.js | 62 -- .../webrtc/browser-to-server/package.json | 25 - .../browser-to-server/tests/test.spec.js | 94 --- .../webrtc/browser-to-server/vite.config.js | 8 - .../webrtc/go-libp2p-server/.gitignore | 1 - .../webrtc/go-libp2p-server/go.mod | 117 ---- .../webrtc/go-libp2p-server/go.sum | 637 ------------------ .../webrtc/go-libp2p-server/main.go | 95 --- .../libp2p-in-the-browser/websockets/LICENSE | 4 - .../websockets/LICENSE-APACHE | 5 - .../websockets/LICENSE-MIT | 19 - .../websockets/README.md | 65 -- .../websockets/index.html | 23 - .../libp2p-in-the-browser/websockets/index.js | 92 --- .../websockets/package.json | 52 -- .../libp2p-in-the-browser/websockets/test.js | 40 -- .../websockets/vite.config.js | 5 - .../fetch-file-from-kubo/.gitignore | 24 - .../fetch-file-from-kubo/README.md | 121 ---- .../fetch-file-from-kubo/img/img1.png | Bin 571580 -> 0 bytes .../fetch-file-from-kubo/img/img2.png | Bin 740468 -> 0 bytes .../fetch-file-from-kubo/index.html | 37 - .../fetch-file-from-kubo/package.json | 26 - .../fetch-file-from-kubo/src/libp2p.ts | 27 - .../fetch-file-from-kubo/src/main.ts | 64 -- .../fetch-file-from-kubo/src/style.css | 109 --- .../fetch-file-from-kubo/src/vite-env.d.ts | 1 - .../fetch-file-from-kubo/tests/test.spec.js | 76 --- .../fetch-file-from-kubo/tsconfig.json | 20 - .../fetch-file-from-kubo/vite.config.js | 8 - examples/peer-and-content-routing/1.js | 59 -- examples/peer-and-content-routing/2.js | 68 -- examples/peer-and-content-routing/LICENSE | 4 - .../peer-and-content-routing/LICENSE-APACHE | 5 - examples/peer-and-content-routing/LICENSE-MIT | 19 - examples/peer-and-content-routing/README.md | 143 ---- .../peer-and-content-routing/package.json | 48 -- examples/peer-and-content-routing/test-1.js | 13 - examples/peer-and-content-routing/test-2.js | 13 - examples/peer-and-content-routing/test.js | 5 - examples/pnet/LICENSE | 4 - examples/pnet/LICENSE-APACHE | 5 - examples/pnet/LICENSE-MIT | 19 - examples/pnet/README.md | 53 -- examples/pnet/index.js | 49 -- examples/pnet/libp2p-node.js | 34 - examples/pnet/package.json | 46 -- examples/pnet/test.js | 9 - examples/protocol-and-stream-muxing/1.js | 80 --- examples/protocol-and-stream-muxing/2.js | 67 -- examples/protocol-and-stream-muxing/3.js | 69 -- examples/protocol-and-stream-muxing/LICENSE | 4 - .../protocol-and-stream-muxing/LICENSE-APACHE | 5 - .../protocol-and-stream-muxing/LICENSE-MIT | 19 - examples/protocol-and-stream-muxing/README.md | 305 --------- .../protocol-and-stream-muxing/package.json | 46 -- examples/protocol-and-stream-muxing/test-1.js | 13 - examples/protocol-and-stream-muxing/test-2.js | 13 - examples/protocol-and-stream-muxing/test-3.js | 13 - examples/protocol-and-stream-muxing/test.js | 7 - examples/pubsub/1.js | 61 -- examples/pubsub/LICENSE | 4 - examples/pubsub/LICENSE-APACHE | 5 - examples/pubsub/LICENSE-MIT | 19 - examples/pubsub/README.md | 140 ---- examples/pubsub/message-filtering/1.js | 131 ---- examples/pubsub/message-filtering/README.md | 135 ---- examples/pubsub/message-filtering/test.js | 56 -- examples/pubsub/package.json | 47 -- examples/pubsub/test-1.js | 29 - examples/pubsub/test.js | 5 - examples/transports/1.js | 33 - examples/transports/2.js | 64 -- examples/transports/3.js | 91 --- examples/transports/4.js | 81 --- examples/transports/LICENSE | 4 - examples/transports/LICENSE-APACHE | 5 - examples/transports/LICENSE-MIT | 19 - examples/transports/README.md | 336 --------- examples/transports/package.json | 48 -- examples/transports/test-1.js | 13 - examples/transports/test-2.js | 13 - examples/transports/test-3.js | 13 - examples/transports/test-4.js | 13 - examples/transports/test.js | 9 - examples/transports/test_certs/cert.pem | 32 - examples/transports/test_certs/key.pem | 52 -- package.json | 9 +- packages/libp2p/README.md | 4 +- packages/libp2p/src/pnet/README.md | 4 - packages/transport-webrtc/README.md | 8 +- 169 files changed, 64 insertions(+), 7543 deletions(-) create mode 100644 .github/workflows/examples.yml delete mode 100644 examples/README.md delete mode 100644 examples/auto-relay/LICENSE delete mode 100644 examples/auto-relay/LICENSE-APACHE delete mode 100644 examples/auto-relay/LICENSE-MIT delete mode 100644 examples/auto-relay/README.md delete mode 100644 examples/auto-relay/dialer.js delete mode 100644 examples/auto-relay/listener.js delete mode 100644 examples/auto-relay/package.json delete mode 100644 examples/auto-relay/relay.js delete mode 100644 examples/auto-relay/test.js delete mode 100644 examples/chat/LICENSE delete mode 100644 examples/chat/LICENSE-APACHE delete mode 100644 examples/chat/LICENSE-MIT delete mode 100644 examples/chat/README.md delete mode 100644 examples/chat/package.json delete mode 100644 examples/chat/src/dialer.js delete mode 100644 examples/chat/src/libp2p.js delete mode 100644 examples/chat/src/listener.js delete mode 100644 examples/chat/src/peer-id-dialer.js delete mode 100644 examples/chat/src/peer-id-listener.js delete mode 100644 examples/chat/src/stream.js delete mode 100644 examples/chat/test.js delete mode 100644 examples/connection-encryption/1.js delete mode 100644 examples/connection-encryption/LICENSE delete mode 100644 examples/connection-encryption/LICENSE-APACHE delete mode 100644 examples/connection-encryption/LICENSE-MIT delete mode 100644 examples/connection-encryption/README.md delete mode 100644 examples/connection-encryption/package.json delete mode 100644 examples/connection-encryption/test.js delete mode 100644 examples/delegated-routing/LICENSE delete mode 100644 examples/delegated-routing/LICENSE-APACHE delete mode 100644 examples/delegated-routing/LICENSE-MIT delete mode 100644 examples/delegated-routing/README.md delete mode 100644 examples/delegated-routing/package.json delete mode 100644 examples/delegated-routing/public/favicon.ico delete mode 100644 examples/delegated-routing/public/index.html delete mode 100644 examples/delegated-routing/public/main.css delete mode 100644 examples/delegated-routing/src/App.js delete mode 100644 examples/delegated-routing/src/index.js delete mode 100644 examples/discovery-mechanisms/1.js delete mode 100644 examples/discovery-mechanisms/2.js delete mode 100644 examples/discovery-mechanisms/3.js delete mode 100644 examples/discovery-mechanisms/LICENSE delete mode 100644 examples/discovery-mechanisms/LICENSE-APACHE delete mode 100644 examples/discovery-mechanisms/LICENSE-MIT delete mode 100644 examples/discovery-mechanisms/README.md delete mode 100644 examples/discovery-mechanisms/bootstrappers.js delete mode 100644 examples/discovery-mechanisms/package.json delete mode 100644 examples/discovery-mechanisms/test-1.js delete mode 100644 examples/discovery-mechanisms/test-2.js delete mode 100644 examples/discovery-mechanisms/test-3.js delete mode 100644 examples/discovery-mechanisms/test.js delete mode 100644 examples/echo/LICENSE delete mode 100644 examples/echo/LICENSE-APACHE delete mode 100644 examples/echo/LICENSE-MIT delete mode 100644 examples/echo/README.md delete mode 100644 examples/echo/package.json delete mode 100644 examples/echo/src/dialer.js delete mode 100644 examples/echo/src/id-d.js delete mode 100644 examples/echo/src/id-l.js delete mode 100644 examples/echo/src/libp2p.js delete mode 100644 examples/echo/src/listener.js delete mode 100644 examples/echo/test.js delete mode 100644 examples/libp2p-in-the-browser/webrtc/README.md delete mode 100644 examples/libp2p-in-the-browser/webrtc/browser-to-browser/README.md delete mode 100644 examples/libp2p-in-the-browser/webrtc/browser-to-browser/index.html delete mode 100644 examples/libp2p-in-the-browser/webrtc/browser-to-browser/index.js delete mode 100644 examples/libp2p-in-the-browser/webrtc/browser-to-browser/package.json delete mode 100644 examples/libp2p-in-the-browser/webrtc/browser-to-browser/relay.js delete mode 100644 examples/libp2p-in-the-browser/webrtc/browser-to-browser/tests/test.spec.js delete mode 100644 examples/libp2p-in-the-browser/webrtc/browser-to-browser/vite.config.js delete mode 100644 examples/libp2p-in-the-browser/webrtc/browser-to-server/README.md delete mode 100644 examples/libp2p-in-the-browser/webrtc/browser-to-server/index.html delete mode 100644 examples/libp2p-in-the-browser/webrtc/browser-to-server/index.js delete mode 100644 examples/libp2p-in-the-browser/webrtc/browser-to-server/package.json delete mode 100644 examples/libp2p-in-the-browser/webrtc/browser-to-server/tests/test.spec.js delete mode 100644 examples/libp2p-in-the-browser/webrtc/browser-to-server/vite.config.js delete mode 100644 examples/libp2p-in-the-browser/webrtc/go-libp2p-server/.gitignore delete mode 100644 examples/libp2p-in-the-browser/webrtc/go-libp2p-server/go.mod delete mode 100644 examples/libp2p-in-the-browser/webrtc/go-libp2p-server/go.sum delete mode 100644 examples/libp2p-in-the-browser/webrtc/go-libp2p-server/main.go delete mode 100644 examples/libp2p-in-the-browser/websockets/LICENSE delete mode 100644 examples/libp2p-in-the-browser/websockets/LICENSE-APACHE delete mode 100644 examples/libp2p-in-the-browser/websockets/LICENSE-MIT delete mode 100644 examples/libp2p-in-the-browser/websockets/README.md delete mode 100644 examples/libp2p-in-the-browser/websockets/index.html delete mode 100644 examples/libp2p-in-the-browser/websockets/index.js delete mode 100644 examples/libp2p-in-the-browser/websockets/package.json delete mode 100644 examples/libp2p-in-the-browser/websockets/test.js delete mode 100644 examples/libp2p-in-the-browser/websockets/vite.config.js delete mode 100644 examples/libp2p-in-the-browser/webtransport/fetch-file-from-kubo/.gitignore delete mode 100644 examples/libp2p-in-the-browser/webtransport/fetch-file-from-kubo/README.md delete mode 100644 examples/libp2p-in-the-browser/webtransport/fetch-file-from-kubo/img/img1.png delete mode 100644 examples/libp2p-in-the-browser/webtransport/fetch-file-from-kubo/img/img2.png delete mode 100644 examples/libp2p-in-the-browser/webtransport/fetch-file-from-kubo/index.html delete mode 100644 examples/libp2p-in-the-browser/webtransport/fetch-file-from-kubo/package.json delete mode 100644 examples/libp2p-in-the-browser/webtransport/fetch-file-from-kubo/src/libp2p.ts delete mode 100644 examples/libp2p-in-the-browser/webtransport/fetch-file-from-kubo/src/main.ts delete mode 100644 examples/libp2p-in-the-browser/webtransport/fetch-file-from-kubo/src/style.css delete mode 100644 examples/libp2p-in-the-browser/webtransport/fetch-file-from-kubo/src/vite-env.d.ts delete mode 100644 examples/libp2p-in-the-browser/webtransport/fetch-file-from-kubo/tests/test.spec.js delete mode 100644 examples/libp2p-in-the-browser/webtransport/fetch-file-from-kubo/tsconfig.json delete mode 100644 examples/libp2p-in-the-browser/webtransport/fetch-file-from-kubo/vite.config.js delete mode 100644 examples/peer-and-content-routing/1.js delete mode 100644 examples/peer-and-content-routing/2.js delete mode 100644 examples/peer-and-content-routing/LICENSE delete mode 100644 examples/peer-and-content-routing/LICENSE-APACHE delete mode 100644 examples/peer-and-content-routing/LICENSE-MIT delete mode 100644 examples/peer-and-content-routing/README.md delete mode 100644 examples/peer-and-content-routing/package.json delete mode 100644 examples/peer-and-content-routing/test-1.js delete mode 100644 examples/peer-and-content-routing/test-2.js delete mode 100644 examples/peer-and-content-routing/test.js delete mode 100644 examples/pnet/LICENSE delete mode 100644 examples/pnet/LICENSE-APACHE delete mode 100644 examples/pnet/LICENSE-MIT delete mode 100644 examples/pnet/README.md delete mode 100644 examples/pnet/index.js delete mode 100644 examples/pnet/libp2p-node.js delete mode 100644 examples/pnet/package.json delete mode 100644 examples/pnet/test.js delete mode 100644 examples/protocol-and-stream-muxing/1.js delete mode 100644 examples/protocol-and-stream-muxing/2.js delete mode 100644 examples/protocol-and-stream-muxing/3.js delete mode 100644 examples/protocol-and-stream-muxing/LICENSE delete mode 100644 examples/protocol-and-stream-muxing/LICENSE-APACHE delete mode 100644 examples/protocol-and-stream-muxing/LICENSE-MIT delete mode 100644 examples/protocol-and-stream-muxing/README.md delete mode 100644 examples/protocol-and-stream-muxing/package.json delete mode 100644 examples/protocol-and-stream-muxing/test-1.js delete mode 100644 examples/protocol-and-stream-muxing/test-2.js delete mode 100644 examples/protocol-and-stream-muxing/test-3.js delete mode 100644 examples/protocol-and-stream-muxing/test.js delete mode 100644 examples/pubsub/1.js delete mode 100644 examples/pubsub/LICENSE delete mode 100644 examples/pubsub/LICENSE-APACHE delete mode 100644 examples/pubsub/LICENSE-MIT delete mode 100644 examples/pubsub/README.md delete mode 100644 examples/pubsub/message-filtering/1.js delete mode 100644 examples/pubsub/message-filtering/README.md delete mode 100644 examples/pubsub/message-filtering/test.js delete mode 100644 examples/pubsub/package.json delete mode 100644 examples/pubsub/test-1.js delete mode 100644 examples/pubsub/test.js delete mode 100644 examples/transports/1.js delete mode 100644 examples/transports/2.js delete mode 100644 examples/transports/3.js delete mode 100644 examples/transports/4.js delete mode 100644 examples/transports/LICENSE delete mode 100644 examples/transports/LICENSE-APACHE delete mode 100644 examples/transports/LICENSE-MIT delete mode 100644 examples/transports/README.md delete mode 100644 examples/transports/package.json delete mode 100644 examples/transports/test-1.js delete mode 100644 examples/transports/test-2.js delete mode 100644 examples/transports/test-3.js delete mode 100644 examples/transports/test-4.js delete mode 100644 examples/transports/test.js delete mode 100644 examples/transports/test_certs/cert.pem delete mode 100644 examples/transports/test_certs/key.pem diff --git a/.github/workflows/examples.yml b/.github/workflows/examples.yml new file mode 100644 index 0000000000..13e3f0c970 --- /dev/null +++ b/.github/workflows/examples.yml @@ -0,0 +1,53 @@ +name: Examples +on: + push: + branches: + - master + pull_request: + branches: + - '**' + +jobs: + + build: + name: Build + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-node@v3 + with: + node-version: lts/* + - uses: ipfs/aegir/actions/cache-node-modules@master + + test-examples: + name: Test example ${{ matrix.example.name }} + runs-on: ubuntu-latest + needs: build + continue-on-error: true + strategy: + matrix: + example: + - name: js-libp2p-example-chat + repo: https://github.com/libp2p/js-libp2p-example-chat.git + deps: + - '@libp2p/peer-id-factory@$PWD/packages/peer-id-factory' + - '@libp2p/tcp@$PWD/packages/transport-tcp' + - '@libp2p/websockets@$PWD/packages/transport-websockets' + - 'libp2p@$PWD/packages/libp2p' + - name: js-libp2p-example-circuit-relay + repo: https://github.com/libp2p/js-libp2p-example-circuit-relay.git + deps: + - '@libp2p/websockets@$PWD/packages/transport-websockets' + - 'libp2p@$PWD/packages/libp2p' + - name: js-libp2p-example-connection-encryption + repo: https://github.com/libp2p/js-libp2p-example-connection-encryption.git + deps: + - '@libp2p/tcp@$PWD/packages/transport-tcp' + - 'libp2p@$PWD/packages/libp2p' + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-node@v3 + with: + node-version: lts/* + - uses: ipfs/aegir/actions/cache-node-modules@master + - run: npx xvfb-maybe aegir test-dependant ${{ matrix.example.repo }} --deps ${{ join(matrix.example.deps, ',') }} diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index a354658173..8614749237 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -1,4 +1,4 @@ -name: ci +name: CI on: push: branches: @@ -168,17 +168,6 @@ jobs: - uses: ipfs/aegir/actions/cache-node-modules@master - run: npm run test:interop -- --bail - test-examples: - needs: build - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - uses: actions/setup-node@v3 - with: - node-version: lts/* - - uses: ipfs/aegir/actions/cache-node-modules@master - - run: npm run --if-present test:example - transport-interop: needs: build runs-on: ${{ fromJSON(github.repository == 'libp2p/js-libp2p' && '["self-hosted", "linux", "x64", "4xlarge"]' || '"ubuntu-latest"') }} @@ -218,7 +207,6 @@ jobs: test-electron-main, test-electron-renderer, test-interop, - test-examples, transport-interop ] if: github.event_name == 'push' && github.ref == 'refs/heads/master' diff --git a/README.md b/README.md index 06b53a0e6b..b09ffc2614 100644 --- a/README.md +++ b/README.md @@ -43,7 +43,7 @@ This project has been used in production for years in Ethereum, IPFS, and more. The documentation in the master branch may contain changes from a pre-release. If you are looking for the documentation of the latest release, you can view the latest release on [**npm**](https://www.npmjs.com/package/libp2p), or select the tag in github that matches the version you are looking for. -**Want to get started?** Check our [GETTING\_STARTED.md](./doc/GETTING_STARTED.md) guide and [examples folder](/examples). +**Want to get started?** Check our [GETTING\_STARTED.md](./doc/GETTING_STARTED.md) guide and [examples](https://github.com/libp2p/js-libp2p-examples). **Want to update libp2p in your project?** Check our [migrations folder](./doc/migrations). @@ -114,22 +114,11 @@ If you are starting your journey with `js-libp2p`, read the [GETTING\_STARTED.md ### Tutorials and Examples -You can find multiple examples on the [examples folder](./examples) that will guide you through using libp2p for several scenarios. +You can find multiple examples on the [examples repo](https://github.com/libp2p/js-libp2p-examples) that will guide you through using libp2p for several scenarios. ## Structure - [`/doc`](./doc) Docs for libp2p -- [`/examples/auto-relay`](./examples/auto-relay) Shows how to configure relayed connections -- [`/examples/chat`](./examples/chat) An example chat app using libp2p -- [`/examples/connection-encryption`](./examples/connection-encryption) An example of how to configure connection encrypters -- [`/examples/delegated-routing`](./examples/delegated-routing) How to configure libp2p delegated routers -- [`/examples/discovery-mechanisms`](./examples/discovery-mechanisms) How to configure peer discovery mechanisms -- [`/examples/echo`](./examples/echo) An example echo app -- [`/examples/peer-and-content-routing`](./examples/peer-and-content-routing) How to use peer and content routing -- [`/examples/pnet`](./examples/pnet) How to configure a libp2p private network -- [`/examples/protocol-and-stream-muxing`](./examples/protocol-and-stream-muxing) How to use multiplex protocols streams -- [`/examples/pubsub`](./examples/pubsub) An example using libp2p pubsub -- [`/examples/transports`](./examples/transports) An example using different types of libp2p transport - [`/interop`](./interop) Multidimension Interop Test - [`/packages/crypto`](./packages/crypto) Crypto primitives for libp2p - [`/packages/interface`](./packages/interface) The interface implemented by a libp2p node diff --git a/doc/CONFIGURATION.md b/doc/CONFIGURATION.md index dcba663f72..2173ac59be 100644 --- a/doc/CONFIGURATION.md +++ b/doc/CONFIGURATION.md @@ -1017,7 +1017,7 @@ As libp2p is designed to be a modular networking library, its usage will vary ba If you have developed a project using `js-libp2p`, please consider submitting your configuration to this list so that it can be found easily by other users. -The [examples](../examples) are also a good source of help for finding a configuration that suits your needs. +The [examples repo](https://github.com/libp2p/js-libp2p-examples) is also a good source of help for finding a configuration that suits your needs. ## Limits diff --git a/doc/GETTING_STARTED.md b/doc/GETTING_STARTED.md index 49db548f8f..89fb79d784 100644 --- a/doc/GETTING_STARTED.md +++ b/doc/GETTING_STARTED.md @@ -276,7 +276,7 @@ localStorage.setItem('debug', 'libp2p:websockets,libp2p:webtransport,libp2p:kad- ## What is next -There are a lot of other concepts within `libp2p`, that are not covered in this guide. For additional configuration options we recommend checking out the [Configuration Readme](./CONFIGURATION.md) and the [examples folder](../examples). If you have any problems getting started, or if anything isn't clear, please let us know by submitting an issue! +There are a lot of other concepts within `libp2p`, that are not covered in this guide. For additional configuration options we recommend checking out the [Configuration Readme](./CONFIGURATION.md) and the [examples repo](https://github.com/libp2p/js-libp2p-examples). If you have any problems getting started, or if anything isn't clear, please let us know by submitting an issue! [transport]: https://github.com/libp2p/js-interfaces/tree/master/src/transport diff --git a/examples/README.md b/examples/README.md deleted file mode 100644 index 62762e59b4..0000000000 --- a/examples/README.md +++ /dev/null @@ -1,32 +0,0 @@ -# `js-libp2p` Examples and Tutorials - -In this folder, you can find a variety of examples to help you get started in using js-libp2p, in Node.js and in the Browser. Every example has a specific purpose and some incorporate a full tutorial that you can follow through, helping you expand your knowledge about libp2p and p2p networks in general. - -Let us know if you find any issues, or if you want to contribute and add a new tutorial, feel free to submit a PR, thank you! - -## Understanding how libp2p works - -- [Transports](./transports) -- [Protocol and Stream Muxing](./protocol-and-stream-muxing) -- [Connection Encryption](./connection-encryption) -- [Discovery Mechanisms](./discovery-mechanisms) -- [Peer and Content Routing](./peer-and-content-routing) -- [PubSub](./pubsub) -- [NAT Traversal](./nat-traversal) -- Circuit Relay (future) -- Naming (future) - -## Other examples - -- Running libp2p in the Electron (future) -- [The standard echo net example with libp2p](./echo) -- [A simple chat app with libp2p](./chat) - -## libp2p in the Browser -There are a number of ways libp2p can be used in the browser. Here are some examples: - -- [webRTC](./libp2p-in-the-browser/webrtc/README.md) -- [websockets](./libp2p-in-the-browser/websockets/README.md) -- [webtransport](./libp2p-in-the-browser/webtransport/README.md) - -There is also an tutorial of how all of these transports can be [universally connected](https://github.com/libp2p/universal-connectivity/tree/main) \ No newline at end of file diff --git a/examples/auto-relay/LICENSE b/examples/auto-relay/LICENSE deleted file mode 100644 index 20ce483c86..0000000000 --- a/examples/auto-relay/LICENSE +++ /dev/null @@ -1,4 +0,0 @@ -This project is dual licensed under MIT and Apache-2.0. - -MIT: https://www.opensource.org/licenses/mit -Apache-2.0: https://www.apache.org/licenses/license-2.0 diff --git a/examples/auto-relay/LICENSE-APACHE b/examples/auto-relay/LICENSE-APACHE deleted file mode 100644 index 14478a3b60..0000000000 --- a/examples/auto-relay/LICENSE-APACHE +++ /dev/null @@ -1,5 +0,0 @@ -Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at - -http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. diff --git a/examples/auto-relay/LICENSE-MIT b/examples/auto-relay/LICENSE-MIT deleted file mode 100644 index 72dc60d84b..0000000000 --- a/examples/auto-relay/LICENSE-MIT +++ /dev/null @@ -1,19 +0,0 @@ -The MIT License (MIT) - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/examples/auto-relay/README.md b/examples/auto-relay/README.md deleted file mode 100644 index a4479a22dc..0000000000 --- a/examples/auto-relay/README.md +++ /dev/null @@ -1,200 +0,0 @@ -# @libp2p/example-auto-relay - -[![libp2p.io](https://img.shields.io/badge/project-libp2p-yellow.svg?style=flat-square)](http://libp2p.io/) -[![Discuss](https://img.shields.io/discourse/https/discuss.libp2p.io/posts.svg?style=flat-square)](https://discuss.libp2p.io) -[![codecov](https://img.shields.io/codecov/c/github/libp2p/js-libp2p.svg?style=flat-square)](https://codecov.io/gh/libp2p/js-libp2p) -[![CI](https://img.shields.io/github/actions/workflow/status/libp2p/js-libp2p/main.yml?branch=master\&style=flat-square)](https://github.com/libp2p/js-libp2p/actions/workflows/main.yml?query=branch%3Amaster) - -> Shows how to configure relayed connections - -## Table of contents - -- [0. Setup the example](#0-setup-the-example) -- [1. Set up a relay node](#1-set-up-a-relay-node) -- [2. Set up a listener node with Auto Relay Enabled](#2-set-up-a-listener-node-with-auto-relay-enabled) -- [3. Set up a dialer node for testing connectivity](#3-set-up-a-dialer-node-for-testing-connectivity) -- [4. What is next?](#4-what-is-next) -- [License](#license) -- [Contribution](#contribution) - -## 0. Setup the example - -Before moving into the examples, you should run `npm install` and `npm run build` on the top level `js-libp2p` folder, in order to install all the dependencies needed for this example. Once the install finishes, you should move into the example folder with `cd examples/auto-relay`. - -This example comes with 3 main files. A `relay.js` file to be used in the first step, a `listener.js` file to be used in the second step and a `dialer.js` file to be used on the third step. All of these scripts will run their own libp2p node, which will interact with the previous ones. All nodes must be running in order for you to proceed. - -## 1. Set up a relay node - -In the first step of this example, we need to configure and run a relay node in order for our target node to bind to for accepting inbound connections. - -The relay node will need to have its relay subsystem enabled, as well as its HOP capability. It can be configured as follows: - -```js -import { createLibp2p } from 'libp2p' -import { webSockets } from '@libp2p/websockets' -import { noise } from '@chainsafe/libp2p-noise' -import { mplex } from '@libp2p/mplex' -import { yamux } from '@chainsafe/libp2p-yamux', - -const node = await createLibp2p({ - transports: [webSockets()], - connectionEncryption: [noise()], - streamMuxers: [yamux(), mplex()], - addresses: { - listen: ['/ip4/0.0.0.0/tcp/0/ws'] - // TODO check "What is next?" section - // announce: ['/dns4/auto-relay.libp2p.io/tcp/443/wss/p2p/QmWDn2LY8nannvSWJzruUYoLZ4vV83vfCBwd8DipvdgQc3'] - }, - relay: { - enabled: true, - hop: { - enabled: true - }, - advertise: { - enabled: true, - } - } -}) - -console.log(`Node started with id ${node.peerId.toString()}`) -console.log('Listening on:') -node.getMultiaddrs().forEach((ma) => console.log(ma.toString())) -``` - -The Relay HOP advertise functionality is **NOT** required to be enabled. However, if you are interested in advertising on the network that this node is available to be used as a HOP Relay you can enable it. A content router module or Rendezvous needs to be configured to leverage this option. - -You should now run the following to start the relay node: - -```sh -node relay.js -``` - -This should print out something similar to the following: - -```sh -Node started with id QmWDn2LY8nannvSWJzruUYoLZ4vV83vfCBwd8DipvdgQc3 -Listening on: -/ip4/127.0.0.1/tcp/61592/ws/p2p/QmWDn2LY8nannvSWJzruUYoLZ4vV83vfCBwd8DipvdgQc3 -/ip4/192.168.1.120/tcp/61592/ws/p2p/QmWDn2LY8nannvSWJzruUYoLZ4vV83vfCBwd8DipvdgQc3 -``` - -## 2. Set up a listener node with Auto Relay Enabled - -One of the typical use cases for Auto Relay is nodes behind a NAT or browser nodes due to their inability to expose a public address. For running a libp2p node that automatically binds itself to connected HOP relays, you can see the following: - -```js -import { createLibp2p } from 'libp2p' -import { webSockets } from '@libp2p/websockets' -import { noise } from '@chainsafe/libp2p-noise' -import { mplex } from '@libp2p/mplex' - -const relayAddr = process.argv[2] -if (!relayAddr) { - throw new Error('the relay address needs to be specified as a parameter') -} - -const node = await createLibp2p({ - transports: [webSockets()], - connectionEncryption: [noise()], - streamMuxers: [yamux(), mplex()], - relay: { - enabled: true, - autoRelay: { - enabled: true, - maxListeners: 2 - } - } -}) - -console.log(`Node started with id ${node.peerId.toString()}`) - -const conn = await node.dial(relayAddr) - -console.log(`Connected to the HOP relay ${conn.remotePeer.toString()}`) - -// Wait for connection and relay to be bind for the example purpose -node.addEventListener('self:peer:update', (evt) => { - // Updated self multiaddrs? - console.log(`Advertising with a relay address of ${node.getMultiaddrs()[0].toString()}`) -}) -``` - -As you can see in the code, we need to provide the relay address, `relayAddr`, as a process argument. This node will dial the provided relay address and automatically bind to it. - -You should now run the following to start the node running Auto Relay: - -```sh -node listener.js /ip4/192.168.1.120/tcp/61592/ws/p2p/QmWDn2LY8nannvSWJzruUYoLZ4vV83vfCBwd8DipvdgQc3 -``` - -This should print out something similar to the following: - -```sh -Node started with id QmerrWofKF358JE6gv3z74cEAyL7z1KqhuUoVfGEynqjRm -Connected to the HOP relay QmWDn2LY8nannvSWJzruUYoLZ4vV83vfCBwd8DipvdgQc3 -Advertising with a relay address of /ip4/192.168.1.120/tcp/61592/ws/p2p/QmWDn2LY8nannvSWJzruUYoLZ4vV83vfCBwd8DipvdgQc3/p2p-circuit/p2p/QmerrWofKF358JE6gv3z74cEAyL7z1KqhuUoVfGEynqjRm -``` - -Per the address, it is possible to verify that the auto relay node is listening on the circuit relay node address. - -Instead of dialing this relay manually, you could set up this node with the Bootstrap module and provide it in the bootstrap list. Moreover, you can use other `peer-discovery` modules to discover peers in the network and the node will automatically bind to the relays that support HOP until reaching the maximum number of listeners. - -## 3. Set up a dialer node for testing connectivity - -Now that you have a relay node and a node bound to that relay, you can test connecting to the auto relay node via the relay. - -```js -import { createLibp2p } from 'libp2p' -import { webSockets } from '@libp2p/websockets' -import { noise } from '@chainsafe/libp2p-noise' -import { mplex } from '@libp2p/mplex' -import { yamux } from '@chainsafe/libp2p-yamux', - -const autoRelayNodeAddr = process.argv[2] -if (!autoRelayNodeAddr) { - throw new Error('the auto relay node address needs to be specified') -} - -const node = await createLibp2p({ - transports: [webSockets()], - connectionEncryption: [noise()], - streamMuxers: [yamux(), mplex()] -}) - -console.log(`Node started with id ${node.peerId.toString()}`) - -const conn = await node.dial(autoRelayNodeAddr) -console.log(`Connected to the auto relay node via ${conn.remoteAddr.toString()}`) -``` - -You should now run the following to start the relay node using the listen address from step 2: - -```sh -node dialer.js /ip4/192.168.1.120/tcp/61592/ws/p2p/QmWDn2LY8nannvSWJzruUYoLZ4vV83vfCBwd8DipvdgQc3 -``` - -Once you start your test node, it should print out something similar to the following: - -```sh -Node started: Qme7iEzDxFoFhhkrsrkHkMnM11aPYjysaehP4NZeUfVMKG -Connected to the auto relay node via /ip4/192.168.1.120/tcp/61592/ws/p2p/QmWDn2LY8nannvSWJzruUYoLZ4vV83vfCBwd8DipvdgQc3/p2p-circuit/p2p/QmerrWofKF358JE6gv3z74cEAyL7z1KqhuUoVfGEynqjRm -``` - -As you can see from the output, the remote address of the established connection uses the relayed connection. - -## 4. What is next? - -Before moving into production, there are a few things that you should take into account. - -A relay node should not advertise its private address in a real world scenario, as the node would not be reachable by others. You should provide an array of public addresses in the libp2p `addresses.announce` option. If you are using websockets, bear in mind that due to browser’s security policies you cannot establish unencrypted connection from secure context. The simplest solution is to setup SSL with nginx and proxy to the node and setup a domain name for the certificate. - -## License - -Licensed under either of - -- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) -- MIT ([LICENSE-MIT](LICENSE-MIT) / ) - -## Contribution - -Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/examples/auto-relay/dialer.js b/examples/auto-relay/dialer.js deleted file mode 100644 index b797da4283..0000000000 --- a/examples/auto-relay/dialer.js +++ /dev/null @@ -1,41 +0,0 @@ -/* eslint-disable no-console */ - -import { noise } from '@chainsafe/libp2p-noise' -import { yamux } from '@chainsafe/libp2p-yamux' -import { mplex } from '@libp2p/mplex' -import { webSockets } from '@libp2p/websockets' -import { multiaddr } from '@multiformats/multiaddr' -import { createLibp2p } from 'libp2p' -import { circuitRelayTransport } from 'libp2p/circuit-relay' -import { identifyService } from 'libp2p/identify' - -async function main () { - const autoRelayNodeAddr = process.argv[2] - if (!autoRelayNodeAddr) { - throw new Error('the auto relay node address needs to be specified') - } - - const node = await createLibp2p({ - transports: [ - webSockets(), - circuitRelayTransport() - ], - connectionEncryption: [ - noise() - ], - streamMuxers: [ - yamux(), - mplex() - ], - services: { - identify: identifyService() - } - }) - - console.log(`Node started with id ${node.peerId.toString()}`) - - const conn = await node.dial(multiaddr(autoRelayNodeAddr)) - console.log(`Connected to the auto relay node via ${conn.remoteAddr.toString()}`) -} - -main() diff --git a/examples/auto-relay/listener.js b/examples/auto-relay/listener.js deleted file mode 100644 index 5ee0967372..0000000000 --- a/examples/auto-relay/listener.js +++ /dev/null @@ -1,50 +0,0 @@ -/* eslint-disable no-console */ - -import { noise } from '@chainsafe/libp2p-noise' -import { yamux } from '@chainsafe/libp2p-yamux' -import { mplex } from '@libp2p/mplex' -import { webSockets } from '@libp2p/websockets' -import { multiaddr } from '@multiformats/multiaddr' -import { createLibp2p } from 'libp2p' -import { circuitRelayTransport } from 'libp2p/circuit-relay' -import { identifyService } from 'libp2p/identify' - -async function main () { - const relayAddr = process.argv[2] - if (!relayAddr) { - throw new Error('the relay address needs to be specified as a parameter') - } - - const node = await createLibp2p({ - transports: [ - webSockets(), - circuitRelayTransport({ - discoverRelays: 2 - }) - ], - connectionEncryption: [ - noise() - ], - streamMuxers: [ - yamux(), - mplex() - ], - services: { - identify: identifyService() - } - }) - - console.log(`Node started with id ${node.peerId.toString()}`) - - const conn = await node.dial(multiaddr(relayAddr)) - - console.log(`Connected to the HOP relay ${conn.remotePeer.toString()}`) - - // Wait for connection and relay to be bind for the example purpose - node.addEventListener('self:peer:update', (evt) => { - // Updated self multiaddrs? - console.log(`Advertising with a relay address of ${node.getMultiaddrs()[0].toString()}`) - }) -} - -main() diff --git a/examples/auto-relay/package.json b/examples/auto-relay/package.json deleted file mode 100644 index fbef4c84c4..0000000000 --- a/examples/auto-relay/package.json +++ /dev/null @@ -1,47 +0,0 @@ -{ - "name": "@libp2p/example-auto-relay", - "version": "0.0.0", - "description": "Shows how to configure relayed connections", - "license": "Apache-2.0 OR MIT", - "homepage": "https://github.com/libp2p/js-libp2p/tree/master/examples/auto-relay#readme", - "repository": { - "type": "git", - "url": "git+https://github.com/libp2p/js-libp2p.git" - }, - "bugs": { - "url": "https://github.com/libp2p/js-libp2p/issues" - }, - "type": "module", - "files": [ - "src", - "dist", - "!dist/test", - "!**/*.tsbuildinfo" - ], - "eslintConfig": { - "extends": "ipfs", - "parserOptions": { - "project": true, - "sourceType": "module" - } - }, - "scripts": { - "lint": "aegir lint", - "test:example": "node test.js" - }, - "dependencies": { - "@chainsafe/libp2p-noise": "^13.0.0", - "@chainsafe/libp2p-yamux": "^5.0.0", - "@libp2p/mplex": "^9.0.0", - "@libp2p/websockets": "^7.0.0", - "@multiformats/multiaddr": "^12.1.5", - "libp2p": "^0.46.0" - }, - "devDependencies": { - "aegir": "^41.0.2", - "execa": "^8.0.1", - "p-defer": "^4.0.0", - "uint8arrays": "^4.0.4" - }, - "private": true -} diff --git a/examples/auto-relay/relay.js b/examples/auto-relay/relay.js deleted file mode 100644 index 17c0053e49..0000000000 --- a/examples/auto-relay/relay.js +++ /dev/null @@ -1,38 +0,0 @@ -/* eslint-disable no-console */ - -import { noise } from '@chainsafe/libp2p-noise' -import { yamux } from '@chainsafe/libp2p-yamux' -import { mplex } from '@libp2p/mplex' -import { webSockets } from '@libp2p/websockets' -import { createLibp2p } from 'libp2p' -import { circuitRelayServer } from 'libp2p/circuit-relay' -import { identifyService } from 'libp2p/identify' - -async function main () { - const node = await createLibp2p({ - addresses: { - listen: ['/ip4/0.0.0.0/tcp/0/ws'] - // TODO check "What is next?" section - // announce: ['/dns4/auto-relay.libp2p.io/tcp/443/wss/p2p/QmWDn2LY8nannvSWJzruUYoLZ4vV83vfCBwd8DipvdgQc3'] - }, - transports: [ - webSockets() - ], - connectionEncryption: [ - noise() - ], - streamMuxers: [ - yamux(), mplex() - ], - services: { - identify: identifyService(), - relay: circuitRelayServer() - } - }) - - console.log(`Node started with id ${node.peerId.toString()}`) - console.log('Listening on:') - node.getMultiaddrs().forEach((ma) => console.log(ma.toString())) -} - -main() diff --git a/examples/auto-relay/test.js b/examples/auto-relay/test.js deleted file mode 100644 index e0372f6f69..0000000000 --- a/examples/auto-relay/test.js +++ /dev/null @@ -1,91 +0,0 @@ -import path from 'path' -import { fileURLToPath } from 'url' -import { execa } from 'execa' -import pDefer from 'p-defer' -import { toString as uint8ArrayToString } from 'uint8arrays/to-string' - -const __dirname = path.dirname(fileURLToPath(import.meta.url)) - -function startProcess (name, args = []) { - return execa('node', [path.join(__dirname, name), ...args], { - cwd: path.resolve(__dirname), - all: true - }) -} - -let output1 = '' -let output2 = '' -let output3 = '' -let relayAddr -let autoRelayAddr - -const proc1Ready = pDefer() -const proc2Ready = pDefer() - -// Step 1 process -process.stdout.write('relay.js\n') - -const proc1 = startProcess('relay.js') -proc1.all.on('data', async (data) => { - process.stdout.write(data) - - output1 += uint8ArrayToString(data) - - if (output1.includes('Listening on:') && output1.includes('/p2p/')) { - relayAddr = output1.trim().split('Listening on:\n')[1].split('\n')[0] - proc1Ready.resolve() - } -}) - -await proc1Ready.promise -process.stdout.write('==================================================================\n') - -// Step 2 process -process.stdout.write('listener.js\n') - -const proc2 = startProcess('listener.js', [relayAddr]) -proc2.all.on('data', async (data) => { - process.stdout.write(data) - - output2 += uint8ArrayToString(data) - - if (output2.includes('Advertising with a relay address of') && output2.includes('/p2p/')) { - autoRelayAddr = output2.trim().split('Advertising with a relay address of ')[1].trim() - proc2Ready.resolve() - } -}) - -await proc2Ready.promise -process.stdout.write('==================================================================\n') - -// Step 3 process -process.stdout.write('dialer.js\n') - -const proc3 = startProcess('dialer.js', [autoRelayAddr]) -proc3.all.on('data', async (data) => { - process.stdout.write(data) - - output3 += uint8ArrayToString(data) - - if (output3.includes('Connected to the auto relay node via')) { - const remoteAddr = output3.trim().split('Connected to the auto relay node via ')[1] - - if (remoteAddr === autoRelayAddr) { - proc3.kill() - proc2.kill() - proc1.kill() - } else { - throw new Error('dialer did not dial through the relay') - } - } -}) - -await Promise.all([ - proc1, - proc2, - proc3 -]).catch((err) => { - if (err.signal !== 'SIGTERM') { - throw err - } -}) diff --git a/examples/chat/LICENSE b/examples/chat/LICENSE deleted file mode 100644 index 20ce483c86..0000000000 --- a/examples/chat/LICENSE +++ /dev/null @@ -1,4 +0,0 @@ -This project is dual licensed under MIT and Apache-2.0. - -MIT: https://www.opensource.org/licenses/mit -Apache-2.0: https://www.apache.org/licenses/license-2.0 diff --git a/examples/chat/LICENSE-APACHE b/examples/chat/LICENSE-APACHE deleted file mode 100644 index 14478a3b60..0000000000 --- a/examples/chat/LICENSE-APACHE +++ /dev/null @@ -1,5 +0,0 @@ -Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at - -http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. diff --git a/examples/chat/LICENSE-MIT b/examples/chat/LICENSE-MIT deleted file mode 100644 index 72dc60d84b..0000000000 --- a/examples/chat/LICENSE-MIT +++ /dev/null @@ -1,19 +0,0 @@ -The MIT License (MIT) - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/examples/chat/README.md b/examples/chat/README.md deleted file mode 100644 index 0115da0620..0000000000 --- a/examples/chat/README.md +++ /dev/null @@ -1,38 +0,0 @@ -# @libp2p/example-chat - -[![libp2p.io](https://img.shields.io/badge/project-libp2p-yellow.svg?style=flat-square)](http://libp2p.io/) -[![Discuss](https://img.shields.io/discourse/https/discuss.libp2p.io/posts.svg?style=flat-square)](https://discuss.libp2p.io) -[![codecov](https://img.shields.io/codecov/c/github/libp2p/js-libp2p.svg?style=flat-square)](https://codecov.io/gh/libp2p/js-libp2p) -[![CI](https://img.shields.io/github/actions/workflow/status/libp2p/js-libp2p/main.yml?branch=master\&style=flat-square)](https://github.com/libp2p/js-libp2p/actions/workflows/main.yml?query=branch%3Amaster) - -> An example chat app using libp2p - -## Table of contents - -- [Setup](#setup) -- [Running](#running) -- [License](#license) -- [Contribution](#contribution) - -## Setup - -1. Install the modules in the libp2p root directory, `npm install` and `npm run build`. -2. Open 2 terminal windows in the `./examples/chat/src` directory. - -## Running - -1. Run the listener in window 1, `node listener.js` -2. Run the dialer in window 2, `node dialer.js` -3. Type a message in either window and hit *enter* -4. Tell yourself secrets to your hearts content! - -## License - -Licensed under either of - -- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) -- MIT ([LICENSE-MIT](LICENSE-MIT) / ) - -## Contribution - -Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/examples/chat/package.json b/examples/chat/package.json deleted file mode 100644 index 4c9ca59231..0000000000 --- a/examples/chat/package.json +++ /dev/null @@ -1,53 +0,0 @@ -{ - "name": "@libp2p/example-chat", - "version": "0.0.0", - "description": "An example chat app using libp2p", - "license": "Apache-2.0 OR MIT", - "homepage": "https://github.com/libp2p/js-libp2p/tree/master/examples/chat#readme", - "repository": { - "type": "git", - "url": "git+https://github.com/libp2p/js-libp2p.git" - }, - "bugs": { - "url": "https://github.com/libp2p/js-libp2p/issues" - }, - "type": "module", - "files": [ - "src", - "dist", - "!dist/test", - "!**/*.tsbuildinfo" - ], - "eslintConfig": { - "extends": "ipfs", - "parserOptions": { - "project": true, - "sourceType": "module" - } - }, - "scripts": { - "lint": "aegir lint", - "test:example": "node test.js" - }, - "dependencies": { - "@chainsafe/libp2p-noise": "^13.0.0", - "@chainsafe/libp2p-yamux": "^5.0.0", - "@libp2p/mplex": "^9.0.0", - "@libp2p/peer-id-factory": "^3.0.0", - "@libp2p/tcp": "^8.0.0", - "@libp2p/websockets": "^7.0.0", - "@multiformats/multiaddr": "^12.1.5", - "@nodeutils/defaults-deep": "^1.1.0", - "it-length-prefixed": "^9.0.1", - "it-map": "^3.0.3", - "it-pipe": "^3.0.1", - "libp2p": "^0.46.0", - "uint8arrays": "^4.0.6" - }, - "devDependencies": { - "aegir": "^41.0.2", - "execa": "^8.0.1", - "p-defer": "^4.0.0" - }, - "private": true -} diff --git a/examples/chat/src/dialer.js b/examples/chat/src/dialer.js deleted file mode 100644 index 956492dbe4..0000000000 --- a/examples/chat/src/dialer.js +++ /dev/null @@ -1,43 +0,0 @@ -/* eslint-disable no-console */ - -import { createFromJSON } from '@libp2p/peer-id-factory' -import { multiaddr } from '@multiformats/multiaddr' -import { createLibp2p } from './libp2p.js' -import peerIdDialerJson from './peer-id-dialer.js' -import peerIdListenerJson from './peer-id-listener.js' -import { stdinToStream, streamToConsole } from './stream.js' - -async function run () { - const [idDialer, idListener] = await Promise.all([ - createFromJSON(peerIdDialerJson), - createFromJSON(peerIdListenerJson) - ]) - - // Create a new libp2p node on localhost with a randomly chosen port - const nodeDialer = await createLibp2p({ - peerId: idDialer, - addresses: { - listen: ['/ip4/0.0.0.0/tcp/0'] - } - }) - - // Output this node's address - console.log('Dialer ready, listening on:') - nodeDialer.getMultiaddrs().forEach((ma) => { - console.log(ma.toString()) - }) - - // Dial to the remote peer (the "listener") - const listenerMa = multiaddr(`/ip4/127.0.0.1/tcp/10333/p2p/${idListener.toString()}`) - const stream = await nodeDialer.dialProtocol(listenerMa, '/chat/1.0.0') - - console.log('Dialer dialed to listener on protocol: /chat/1.0.0') - console.log('Type a message and see what happens') - - // Send stdin to the stream - stdinToStream(stream) - // Read the stream and output to console - streamToConsole(stream) -} - -run() diff --git a/examples/chat/src/libp2p.js b/examples/chat/src/libp2p.js deleted file mode 100644 index 5a244b59b5..0000000000 --- a/examples/chat/src/libp2p.js +++ /dev/null @@ -1,24 +0,0 @@ -import { noise } from '@chainsafe/libp2p-noise' -import { yamux } from '@chainsafe/libp2p-yamux' -import { mplex } from '@libp2p/mplex' -import { tcp } from '@libp2p/tcp' -import { webSockets } from '@libp2p/websockets' -import defaultsDeep from '@nodeutils/defaults-deep' -import { createLibp2p as create } from 'libp2p' - -export async function createLibp2p (_options) { - const defaults = { - transports: [ - tcp(), - webSockets() - ], - streamMuxers: [ - yamux(), mplex() - ], - connectionEncryption: [ - noise() - ] - } - - return create(defaultsDeep(_options, defaults)) -} diff --git a/examples/chat/src/listener.js b/examples/chat/src/listener.js deleted file mode 100644 index 7397695424..0000000000 --- a/examples/chat/src/listener.js +++ /dev/null @@ -1,39 +0,0 @@ -/* eslint-disable no-console */ - -import { createFromJSON } from '@libp2p/peer-id-factory' -import { createLibp2p } from './libp2p.js' -import peerIdListenerJson from './peer-id-listener.js' -import { stdinToStream, streamToConsole } from './stream.js' - -async function run () { - // Create a new libp2p node with the given multi-address - const idListener = await createFromJSON(peerIdListenerJson) - const nodeListener = await createLibp2p({ - peerId: idListener, - addresses: { - listen: ['/ip4/0.0.0.0/tcp/10333'] - } - }) - - // Log a message when a remote peer connects to us - nodeListener.addEventListener('peer:connect', (evt) => { - const remotePeer = evt.detail - console.log('connected to: ', remotePeer.toString()) - }) - - // Handle messages for the protocol - await nodeListener.handle('/chat/1.0.0', async ({ stream }) => { - // Send stdin to the stream - stdinToStream(stream) - // Read the stream and output to console - streamToConsole(stream) - }) - - // Output listen addresses to the console - console.log('Listener ready, listening on:') - nodeListener.getMultiaddrs().forEach((ma) => { - console.log(ma.toString()) - }) -} - -run() diff --git a/examples/chat/src/peer-id-dialer.js b/examples/chat/src/peer-id-dialer.js deleted file mode 100644 index 79d31007f2..0000000000 --- a/examples/chat/src/peer-id-dialer.js +++ /dev/null @@ -1,5 +0,0 @@ -export default { - id: 'Qma3GsJmB47xYuyahPZPSadh1avvxfyYQwk8R3UnFrQ6aP', - privKey: 'CAASpwkwggSjAgEAAoIBAQCaNSDOjPz6T8HZsf7LDpxiQRiN2OjeyIHUS05p8QWOr3EFUCFsC31R4moihE5HN+FxNalUyyFZU//yjf1pdnlMJqrVByJSMa+y2y4x2FucpoCAO97Tx+iWzwlZ2UXEUXM1Y81mhPbeWXy+wP2xElTgIER0Tsn/thoA0SD2u9wJuVvM7dB7cBcHYmqV6JH+KWCedRTum6O1BssqP/4Lbm2+rkrbZ4+oVRoU2DRLoFhKqwqLtylrbuj4XOI3XykMXV5+uQXz1JzubNOB9lsc6K+eRC+w8hhhDuFMgzkZ4qomCnx3uhO67KaICd8yqqBa6PJ/+fBM5Xk4hjyR40bwcf41AgMBAAECggEAZnrCJ6IYiLyyRdr9SbKXCNDb4YByGYPEi/HT1aHgIJfFE1PSMjxcdytxfyjP4JJpVtPjiT9JFVU2ddoYu5qJN6tGwjVwgJEWg1UXmPaAw1T/drjS94kVsAs82qICtFmwp52Apg3dBZ0Qwq/8qE1XbG7lLyohIbfCBiL0tiPYMfkcsN9gnFT/kFCX0LVs2pa9fHCRMY9rqCc4/rWJa1w8sMuQ23y4lDaxKF9OZVvOHFQkbBDrkquWHE4r55fchCz/rJklkPJUNENuncBRu0/2X+p4IKFD1DnttXNwb8j4LPiSlLro1T0hiUr5gO2QmdYwXFF63Q3mjQy0+5I4eNbjjQKBgQDZvZy3gUKS/nQNkYfq9za80uLbIj/cWbO+ZZjXCsj0fNIcQFJcKMBoA7DjJvu2S/lf86/41YHkPdmrLAEQAkJ+5BBNOycjYK9minTEjIMMmZDTXXugZ62wnU6F46uLkgEChTqEP57Y6xwwV+JaEDFEsW5N1eE9lEVX9nGIr4phMwKBgQC1TazLuEt1WBx/iUT83ita7obXqoKNzwsS/MWfY2innzYZKDOqeSYZzLtt9uTtp4X4uLyPbYs0qFYhXLsUYMoGHNN8+NdjoyxCjQRJRBkMtaNR0lc5lVDWl3bTuJovjFCgAr9uqJrmI5OHcCIk/cDpdWb3nWaMihVlePmiTcTy9wKBgQCU0u7c1jKkudqks4XM6a+2HAYGdUBk4cLjLhnrUWnNAcuyl5wzdX8dGPi8KZb+IKuQE8WBNJ2VXVj7kBYh1QmSJVunDflQSvNYCOaKuOeRoxzD+y9Wkca74qkbBmPn/6FFEb7PSZTO+tPHjyodGNgz9XpJJRjQuBk1aDJtlF3m1QKBgE5SAr5ym65SZOU3UGUIOKRsfDW4Q/OsqDUImvpywCgBICaX9lHDShFFHwau7FA52ScL7vDquoMB4UtCOtLfyQYA9995w9oYCCurrVlVIJkb8jSLcADBHw3EmqF1kq3NqJqm9TmBfoDCh52vdCCUufxgKh33kfBOSlXuf7B8dgMbAoGAZ3r0/mBQX6S+s5+xCETMTSNv7TQzxgtURIpVs+ZVr2cMhWhiv+n0Omab9X9Z50se8cWl5lkvx8vn3D/XHHIPrMF6qk7RAXtvReb+PeitNvm0odqjFv0J2qki6fDs0HKwq4kojAXI1Md8Th0eobNjsy21fEEJT7uKMJdovI/SErI=', - pubKey: 'CAASpgIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCaNSDOjPz6T8HZsf7LDpxiQRiN2OjeyIHUS05p8QWOr3EFUCFsC31R4moihE5HN+FxNalUyyFZU//yjf1pdnlMJqrVByJSMa+y2y4x2FucpoCAO97Tx+iWzwlZ2UXEUXM1Y81mhPbeWXy+wP2xElTgIER0Tsn/thoA0SD2u9wJuVvM7dB7cBcHYmqV6JH+KWCedRTum6O1BssqP/4Lbm2+rkrbZ4+oVRoU2DRLoFhKqwqLtylrbuj4XOI3XykMXV5+uQXz1JzubNOB9lsc6K+eRC+w8hhhDuFMgzkZ4qomCnx3uhO67KaICd8yqqBa6PJ/+fBM5Xk4hjyR40bwcf41AgMBAAE=' -} diff --git a/examples/chat/src/peer-id-listener.js b/examples/chat/src/peer-id-listener.js deleted file mode 100644 index 8e5acb76c0..0000000000 --- a/examples/chat/src/peer-id-listener.js +++ /dev/null @@ -1,5 +0,0 @@ -export default { - id: 'QmcrQZ6RJdpYuGvZqD5QEHAv6qX4BrQLJLQPQUrTrzdcgm', - privKey: 'CAASqAkwggSkAgEAAoIBAQDLZZcGcbe4urMBVlcHgN0fpBymY+xcr14ewvamG70QZODJ1h9sljlExZ7byLiqRB3SjGbfpZ1FweznwNxWtWpjHkQjTVXeoM4EEgDSNO/Cg7KNlU0EJvgPJXeEPycAZX9qASbVJ6EECQ40VR/7+SuSqsdL1hrmG1phpIju+D64gLyWpw9WEALfzMpH5I/KvdYDW3N4g6zOD2mZNp5y1gHeXINHWzMF596O72/6cxwyiXV1eJ000k1NVnUyrPjXtqWdVLRk5IU1LFpoQoXZU5X1hKj1a2qt/lZfH5eOrF/ramHcwhrYYw1txf8JHXWO/bbNnyemTHAvutZpTNrsWATfAgMBAAECggEAQj0obPnVyjxLFZFnsFLgMHDCv9Fk5V5bOYtmxfvcm50us6ye+T8HEYWGUa9RrGmYiLweuJD34gLgwyzE1RwptHPj3tdNsr4NubefOtXwixlWqdNIjKSgPlaGULQ8YF2tm/kaC2rnfifwz0w1qVqhPReO5fypL+0ShyANVD3WN0Fo2ugzrniCXHUpR2sHXSg6K+2+qWdveyjNWog34b7CgpV73Ln96BWae6ElU8PR5AWdMnRaA9ucA+/HWWJIWB3Fb4+6uwlxhu2L50Ckq1gwYZCtGw63q5L4CglmXMfIKnQAuEzazq9T4YxEkp+XDnVZAOgnQGUBYpetlgMmkkh9qQKBgQDvsEs0ThzFLgnhtC2Jy//ZOrOvIAKAZZf/mS08AqWH3L0/Rjm8ZYbLsRcoWU78sl8UFFwAQhMRDBP9G+RPojWVahBL/B7emdKKnFR1NfwKjFdDVaoX5uNvZEKSl9UubbC4WZJ65u/cd5jEnj+w3ir9G8n+P1gp/0yBz02nZXFgSwKBgQDZPQr4HBxZL7Kx7D49ormIlB7CCn2i7mT11Cppn5ifUTrp7DbFJ2t9e8UNk6tgvbENgCKXvXWsmflSo9gmMxeEOD40AgAkO8Pn2R4OYhrwd89dECiKM34HrVNBzGoB5+YsAno6zGvOzLKbNwMG++2iuNXqXTk4uV9GcI8OnU5ZPQKBgCZUGrKSiyc85XeiSGXwqUkjifhHNh8yH8xPwlwGUFIZimnD4RevZI7OEtXw8iCWpX2gg9XGuyXOuKORAkF5vvfVriV4e7c9Ad4Igbj8mQFWz92EpV6NHXGCpuKqRPzXrZrNOA9PPqwSs+s9IxI1dMpk1zhBCOguWx2m+NP79NVhAoGBAI6WSoTfrpu7ewbdkVzTWgQTdLzYNe6jmxDf2ZbKclrf7lNr/+cYIK2Ud5qZunsdBwFdgVcnu/02czeS42TvVBgs8mcgiQc/Uy7yi4/VROlhOnJTEMjlU2umkGc3zLzDgYiRd7jwRDLQmMrYKNyEr02HFKFn3w8kXSzW5I8rISnhAoGBANhchHVtJd3VMYvxNcQb909FiwTnT9kl9pkjhwivx+f8/K8pDfYCjYSBYCfPTM5Pskv5dXzOdnNuCj6Y2H/9m2SsObukBwF0z5Qijgu1DsxvADVIKZ4rzrGb4uSEmM6200qjJ/9U98fVM7rvOraakrhcf9gRwuspguJQnSO9cLj6', - pubKey: 'CAASpgIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDLZZcGcbe4urMBVlcHgN0fpBymY+xcr14ewvamG70QZODJ1h9sljlExZ7byLiqRB3SjGbfpZ1FweznwNxWtWpjHkQjTVXeoM4EEgDSNO/Cg7KNlU0EJvgPJXeEPycAZX9qASbVJ6EECQ40VR/7+SuSqsdL1hrmG1phpIju+D64gLyWpw9WEALfzMpH5I/KvdYDW3N4g6zOD2mZNp5y1gHeXINHWzMF596O72/6cxwyiXV1eJ000k1NVnUyrPjXtqWdVLRk5IU1LFpoQoXZU5X1hKj1a2qt/lZfH5eOrF/ramHcwhrYYw1txf8JHXWO/bbNnyemTHAvutZpTNrsWATfAgMBAAE=' -} diff --git a/examples/chat/src/stream.js b/examples/chat/src/stream.js deleted file mode 100644 index 194a9c1da0..0000000000 --- a/examples/chat/src/stream.js +++ /dev/null @@ -1,41 +0,0 @@ -/* eslint-disable no-console */ - -import * as lp from 'it-length-prefixed' -import map from 'it-map' -import { pipe } from 'it-pipe' -import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string' -import { toString as uint8ArrayToString } from 'uint8arrays/to-string' - -export function stdinToStream (stream) { - // Read utf-8 from stdin - process.stdin.setEncoding('utf8') - pipe( - // Read from stdin (the source) - process.stdin, - // Turn strings into buffers - (source) => map(source, (string) => uint8ArrayFromString(string)), - // Encode with length prefix (so receiving side knows how much data is coming) - (source) => lp.encode(source), - // Write to the stream (the sink) - stream.sink - ) -} - -export function streamToConsole (stream) { - pipe( - // Read from the stream (the source) - stream.source, - // Decode length-prefixed data - (source) => lp.decode(source), - // Turn buffers into strings - (source) => map(source, (buf) => uint8ArrayToString(buf.subarray())), - // Sink function - async function (source) { - // For each chunk of data - for await (const msg of source) { - // Output the data as a utf8 string - console.log('> ' + msg.toString().replace('\n', '')) - } - } - ) -} diff --git a/examples/chat/test.js b/examples/chat/test.js deleted file mode 100644 index 28ca41dc1e..0000000000 --- a/examples/chat/test.js +++ /dev/null @@ -1,74 +0,0 @@ -import path from 'path' -import { fileURLToPath } from 'url' -import { execa } from 'execa' -import pDefer from 'p-defer' -import { toString as uint8ArrayToString } from 'uint8arrays/to-string' - -const __dirname = path.dirname(fileURLToPath(import.meta.url)) - -function startProcess (name) { - return execa('node', [path.join(__dirname, name)], { - cwd: path.resolve(__dirname), - all: true - }) -} - -const message = 'test message' -let listenerOutput = '' -let dialerOutput = '' - -let isListening = false -let messageSent = false -const listenerReady = pDefer() -const dialerReady = pDefer() -const messageReceived = pDefer() - -// Step 1 process -process.stdout.write('node listener.js\n') -const listenerProc = startProcess('./src/listener.js') -listenerProc.all.on('data', async (data) => { - process.stdout.write(data) - - listenerOutput += uint8ArrayToString(data) - - if (!isListening && listenerOutput.includes('Listener ready, listening on')) { - listenerReady.resolve() - isListening = true - } else if (isListening && listenerOutput.includes(message)) { - messageReceived.resolve() - } -}) - -await listenerReady.promise -process.stdout.write('==================================================================\n') - -// Step 2 process -process.stdout.write('node dialer.js\n') -const dialerProc = startProcess('./src/dialer.js') -dialerProc.all.on('data', async (data) => { - process.stdout.write(data) - dialerOutput += uint8ArrayToString(data) - - if (!messageSent && dialerOutput.includes('Type a message and see what happens')) { - dialerReady.resolve() - dialerProc.stdin.write(message) - dialerProc.stdin.write('\n') - messageSent = true - } -}) - -await dialerReady.promise -process.stdout.write('==================================================================\n') -await messageReceived.promise -process.stdout.write('chat message received\n') - -listenerProc.kill() -dialerProc.kill() -await Promise.all([ - listenerProc, - dialerProc -]).catch((err) => { - if (err.signal !== 'SIGTERM') { - throw err - } -}) diff --git a/examples/connection-encryption/1.js b/examples/connection-encryption/1.js deleted file mode 100644 index 44e1982b2a..0000000000 --- a/examples/connection-encryption/1.js +++ /dev/null @@ -1,52 +0,0 @@ -/* eslint-disable no-console */ - -import { noise } from '@chainsafe/libp2p-noise' -import { yamux } from '@chainsafe/libp2p-yamux' -import { mplex } from '@libp2p/mplex' -import { tcp } from '@libp2p/tcp' -import { pipe } from 'it-pipe' -import { createLibp2p } from 'libp2p' -import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string' -import { toString as uint8ArrayToString } from 'uint8arrays/to-string' - -const createNode = async () => { - const node = await createLibp2p({ - addresses: { - listen: ['/ip4/0.0.0.0/tcp/0'] - }, - transports: [tcp()], - streamMuxers: [yamux(), mplex()], - connectionEncryption: [noise()] - }) - - return node -} - -;(async () => { - const [node1, node2] = await Promise.all([ - createNode(), - createNode() - ]) - - await node1.peerStore.patch(node2.peerId, { - multiaddrs: node2.getMultiaddrs() - }) - - node2.handle('/a-protocol', ({ stream }) => { - pipe( - stream, - async function (source) { - for await (const msg of source) { - console.log(uint8ArrayToString(msg.subarray())) - } - } - ) - }) - - const stream = await node1.dialProtocol(node2.peerId, '/a-protocol') - - await pipe( - [uint8ArrayFromString('This information is sent out encrypted to the other peer')], - stream - ) -})() diff --git a/examples/connection-encryption/LICENSE b/examples/connection-encryption/LICENSE deleted file mode 100644 index 20ce483c86..0000000000 --- a/examples/connection-encryption/LICENSE +++ /dev/null @@ -1,4 +0,0 @@ -This project is dual licensed under MIT and Apache-2.0. - -MIT: https://www.opensource.org/licenses/mit -Apache-2.0: https://www.apache.org/licenses/license-2.0 diff --git a/examples/connection-encryption/LICENSE-APACHE b/examples/connection-encryption/LICENSE-APACHE deleted file mode 100644 index 14478a3b60..0000000000 --- a/examples/connection-encryption/LICENSE-APACHE +++ /dev/null @@ -1,5 +0,0 @@ -Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at - -http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. diff --git a/examples/connection-encryption/LICENSE-MIT b/examples/connection-encryption/LICENSE-MIT deleted file mode 100644 index 72dc60d84b..0000000000 --- a/examples/connection-encryption/LICENSE-MIT +++ /dev/null @@ -1,19 +0,0 @@ -The MIT License (MIT) - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/examples/connection-encryption/README.md b/examples/connection-encryption/README.md deleted file mode 100644 index 786c95b203..0000000000 --- a/examples/connection-encryption/README.md +++ /dev/null @@ -1,54 +0,0 @@ -# @libp2p/example-connection-encryption - -[![libp2p.io](https://img.shields.io/badge/project-libp2p-yellow.svg?style=flat-square)](http://libp2p.io/) -[![Discuss](https://img.shields.io/discourse/https/discuss.libp2p.io/posts.svg?style=flat-square)](https://discuss.libp2p.io) -[![codecov](https://img.shields.io/codecov/c/github/libp2p/js-libp2p.svg?style=flat-square)](https://codecov.io/gh/libp2p/js-libp2p) -[![CI](https://img.shields.io/github/actions/workflow/status/libp2p/js-libp2p/main.yml?branch=master\&style=flat-square)](https://github.com/libp2p/js-libp2p/actions/workflows/main.yml?query=branch%3Amaster) - -> An example of how to configure connection encrypters - -## Table of contents - -- [Set up encrypted communications](#set-up-encrypted-communications) -- [License](#license) -- [Contribution](#contribution) - -We call this usage a *connection upgrade* where given a connection between peer A to peer B, a protocol handshake can be performed that gives that connection new properties. - -A byproduct of having these encrypted communications modules is that we can authenticate the peers we are dialing to. You might have noticed that every time we dial to a peer in libp2p space, we always use its PeerId at the end (e.g /ip4/127.0.0.1/tcp/89765/p2p/QmWCbVw1XZ8hiYBwwshPce2yaTDYTqTaP7GCHGpry3ykWb), this PeerId is generated by hashing the Public Key of the peer. With this, we can create a crypto challenge when dialing to another peer and prove that peer is the owner of a PrivateKey that matches the Public Key we know. - -## Set up encrypted communications - -We will build this example on top of example for [Protocol and Stream Multiplexing](../protocol-and-stream-multiplexing). You will need the `@chainsafe/libp2p-noise` module to complete it, go ahead and `npm install @chainsafe/libp2p-noise`. - -To add them to your libp2p configuration, all you have to do is: - -```JavaScript -import { createLibp2p } from 'libp2p' -import { tcp } from '@libp2p/tcp' -import { mplex } from '@libp2p/mplex' -import { yamux } from '@chainsafe/libp2p-yamux', -import { noise } from '@chainsafe/libp2p-noise' - -const createNode = async () => { - return await createLibp2p({ - transports: [ tcp() ], - streamMuxers: [ mplex(), yamux() ], - // Attach noise as the crypto channel to use - conectionEncrypters: [ noise() ] - }) -} -``` - -And that's it, from now on, all your libp2p communications are encrypted. Try running the example [1.js](./1.js) to see it working. - -## License - -Licensed under either of - -- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) -- MIT ([LICENSE-MIT](LICENSE-MIT) / ) - -## Contribution - -Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/examples/connection-encryption/package.json b/examples/connection-encryption/package.json deleted file mode 100644 index d4c652bc1b..0000000000 --- a/examples/connection-encryption/package.json +++ /dev/null @@ -1,46 +0,0 @@ -{ - "name": "@libp2p/example-connection-encryption", - "version": "0.0.0", - "description": "An example of how to configure connection encrypters", - "license": "Apache-2.0 OR MIT", - "homepage": "https://github.com/libp2p/js-libp2p/tree/master/examples/connection-encryption#readme", - "repository": { - "type": "git", - "url": "git+https://github.com/libp2p/js-libp2p.git" - }, - "bugs": { - "url": "https://github.com/libp2p/js-libp2p/issues" - }, - "type": "module", - "files": [ - "src", - "dist", - "!dist/test", - "!**/*.tsbuildinfo" - ], - "eslintConfig": { - "extends": "ipfs", - "parserOptions": { - "project": true, - "sourceType": "module" - } - }, - "scripts": { - "lint": "aegir lint", - "test:example": "node test.js" - }, - "dependencies": { - "@chainsafe/libp2p-noise": "^13.0.0", - "@chainsafe/libp2p-yamux": "^5.0.0", - "@libp2p/mplex": "^9.0.0", - "@libp2p/tcp": "^8.0.0", - "it-pipe": "^3.0.1", - "libp2p": "^0.46.0", - "uint8arrays": "^4.0.6" - }, - "devDependencies": { - "aegir": "^41.0.2", - "test-ipfs-example": "^1.0.0" - }, - "private": true -} diff --git a/examples/connection-encryption/test.js b/examples/connection-encryption/test.js deleted file mode 100644 index 1bba4c3bf2..0000000000 --- a/examples/connection-encryption/test.js +++ /dev/null @@ -1,11 +0,0 @@ -import path from 'path' -import { fileURLToPath } from 'url' -import { waitForOutput } from 'test-ipfs-example/node' - -const __dirname = path.dirname(fileURLToPath(import.meta.url)) - -process.stdout.write('1.js\n') - -await waitForOutput('This information is sent out encrypted to the other peer', 'node', [path.join(__dirname, '1.js')], { - cwd: __dirname -}) diff --git a/examples/delegated-routing/LICENSE b/examples/delegated-routing/LICENSE deleted file mode 100644 index 20ce483c86..0000000000 --- a/examples/delegated-routing/LICENSE +++ /dev/null @@ -1,4 +0,0 @@ -This project is dual licensed under MIT and Apache-2.0. - -MIT: https://www.opensource.org/licenses/mit -Apache-2.0: https://www.apache.org/licenses/license-2.0 diff --git a/examples/delegated-routing/LICENSE-APACHE b/examples/delegated-routing/LICENSE-APACHE deleted file mode 100644 index 14478a3b60..0000000000 --- a/examples/delegated-routing/LICENSE-APACHE +++ /dev/null @@ -1,5 +0,0 @@ -Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at - -http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. diff --git a/examples/delegated-routing/LICENSE-MIT b/examples/delegated-routing/LICENSE-MIT deleted file mode 100644 index 72dc60d84b..0000000000 --- a/examples/delegated-routing/LICENSE-MIT +++ /dev/null @@ -1,19 +0,0 @@ -The MIT License (MIT) - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/examples/delegated-routing/README.md b/examples/delegated-routing/README.md deleted file mode 100644 index bebbe9dcf1..0000000000 --- a/examples/delegated-routing/README.md +++ /dev/null @@ -1,75 +0,0 @@ -# @libp2p/example-delegated-routing-example - -[![libp2p.io](https://img.shields.io/badge/project-libp2p-yellow.svg?style=flat-square)](http://libp2p.io/) -[![Discuss](https://img.shields.io/discourse/https/discuss.libp2p.io/posts.svg?style=flat-square)](https://discuss.libp2p.io) -[![codecov](https://img.shields.io/codecov/c/github/libp2p/js-libp2p.svg?style=flat-square)](https://codecov.io/gh/libp2p/js-libp2p) -[![CI](https://img.shields.io/github/actions/workflow/status/libp2p/js-libp2p/main.yml?branch=master\&style=flat-square)](https://github.com/libp2p/js-libp2p/actions/workflows/main.yml?query=branch%3Amaster) - -> How to configure libp2p delegated routers - -## Table of contents - -- [Prerequisite](#prerequisite) -- [Running this example](#running-this-example) - - [Finding Content via the Delegate](#finding-content-via-the-delegate) - - [Finding Peers via the Delegate](#finding-peers-via-the-delegate) -- [License](#license) -- [Contribution](#contribution) - -The starting [Libp2p Bundle](./src/libp2p-bundle.js) in this example starts by disabling the DHT and adding the Delegated Peer and Content Routers. -Once you've completed the example, you should try enabled the DHT and see what kind of results you get! You can also enable the various Peer Discovery modules and see the impact it has on your Peer count. - -## Prerequisite - -This example uses a publicly known delegated routing node. This aims to ease experimentation, but you should not rely on this in production. - -## Running this example - -1. Install IPFS locally if you dont already have it. [Install Guide](https://docs.ipfs.tech/install/) -2. Run the IPFS daemon: `ipfs daemon` -3. In another window output the addresses of the node: `ipfs id`. Make note of the websocket address, it will contain `/ws/` in the address. - -- If there is no websocket address, you will need to add it in the ipfs config file (`~/.ipfs/config`) -- Add to Swarm Addresses something like: `"/ip4/127.0.0.1/tcp/4010/ws"` - -4. In `./src/App.js` replace `BootstrapNode` with your nodes Websocket address from the step above. -5. Start this example - -```sh -npm install -npm start -``` - -This should open your browser to . If it does not, go ahead and do that now. - -6. Your browser should show you connected to at least 1 peer. - -### Finding Content via the Delegate - -1. Add a file to your IPFS node. From this example root you can do `ipfs add ./README.md` to add the example readme. -2. Copy the hash from line 5, it will look something like *Qmf33vz4HJFkqgH7XPP1uA6atYKTX1BWQEQthzpKcAdeyZ*. -3. In the browser, paste the hash into the *Hash* field and hit `Find`. The readme contents should display. - -This will do a few things: - -- The delegate nodes api will be queried to find providers of the content -- The content will be fetched from the providers -- Since we now have the content, we tell the delegate node to fetch the content from us and become a provider - -### Finding Peers via the Delegate - -1. Get a list of your delegate nodes peer by querying the IPFS daemon: `ipfs swarm peers` -2. Copy one of the CIDs from the list of peer addresses, this will be the last portion of the address and will look something like `QmdoG8DpzYUZMVP5dGmgmigZwR1RE8Cf6SxMPg1SBXJAQ8`. -3. In your browser, paste the CID into the *Peer* field and hit `Find`. -4. You should see information about the peer including its addresses. - -## License - -Licensed under either of - -- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) -- MIT ([LICENSE-MIT](LICENSE-MIT) / ) - -## Contribution - -Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/examples/delegated-routing/package.json b/examples/delegated-routing/package.json deleted file mode 100644 index 1dc0953e35..0000000000 --- a/examples/delegated-routing/package.json +++ /dev/null @@ -1,58 +0,0 @@ -{ - "name": "@libp2p/example-delegated-routing-example", - "version": "0.0.0", - "description": "How to configure libp2p delegated routers", - "license": "Apache-2.0 OR MIT", - "homepage": "https://github.com/libp2p/js-libp2p/tree/master/examples/delegated-routing#readme", - "repository": { - "type": "git", - "url": "git+https://github.com/libp2p/js-libp2p.git" - }, - "bugs": { - "url": "https://github.com/libp2p/js-libp2p/issues" - }, - "type": "module", - "files": [ - "src", - "dist", - "!dist/test", - "!**/*.tsbuildinfo" - ], - "eslintConfig": { - "extends": "ipfs", - "parserOptions": { - "sourceType": "module", - "parserOptions": { - "sourceType": "module" - } - } - }, - "scripts": { - "lint": "aegir lint", - "start": "react-scripts start" - }, - "dependencies": { - "@chainsafe/libp2p-noise": "^13.0.0", - "@libp2p/bootstrap": "^9.0.0", - "@libp2p/delegated-content-routing": "^4.0.0", - "@libp2p/delegated-peer-routing": "^4.0.0", - "@libp2p/kad-dht": "^10.0.0", - "@libp2p/mplex": "^9.0.0", - "@libp2p/websockets": "^7.0.0", - "kubo-rpc-client": "^3.0.1", - "libp2p": "^0.46.0", - "react": "^18.2.0", - "react-dom": "^18.2.0", - "react-scripts": "^5.0.1" - }, - "devDependencies": { - "aegir": "^41.0.2" - }, - "browserslist": [ - ">0.2%", - "not dead", - "not ie <= 11", - "not op_mini all" - ], - "private": true -} diff --git a/examples/delegated-routing/public/favicon.ico b/examples/delegated-routing/public/favicon.ico deleted file mode 100644 index a11777cc471a4344702741ab1c8a588998b1311a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3870 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 baj7?x%VD!5Cxk2YbYLNVeiXvvpMCWYo=by@ diff --git a/examples/delegated-routing/public/index.html b/examples/delegated-routing/public/index.html deleted file mode 100644 index 9082175b4e..0000000000 --- a/examples/delegated-routing/public/index.html +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - Delegated Routing - - - - -
- - diff --git a/examples/delegated-routing/public/main.css b/examples/delegated-routing/public/main.css deleted file mode 100644 index 5cd8188187..0000000000 --- a/examples/delegated-routing/public/main.css +++ /dev/null @@ -1,67 +0,0 @@ -body { - margin: 0; - padding: 0; - font-family: sans-serif; -} - -section * { - margin: 10px; -} - -header { - background-color: #222; - height: 150px; - padding: 20px; - color: white; -} - -.center { - text-align: center; -} - -pre { - background-color: bisque; - min-height: 100px; - margin: 0px; - padding: 10px; -} - -.loader { - text-align: center; - height: 64px; - margin-bottom: -64px; -} - -.loading .lds-ripple { - display: inline-block; - position: relative; - width: 64px; - height: 64px; -} -.loading .lds-ripple div { - position: absolute; - border: 4px solid #000; - opacity: 1; - border-radius: 50%; - animation: lds-ripple 1s cubic-bezier(0, 0.2, 0.8, 1) infinite; - margin: auto; -} -.loading .lds-ripple div:nth-child(2) { - animation-delay: -0.5s; -} -@keyframes lds-ripple { - 0% { - top: 28px; - left: 28px; - width: 0; - height: 0; - opacity: 1; - } - 100% { - top: -1px; - left: -1px; - width: 58px; - height: 58px; - opacity: 0; - } -} \ No newline at end of file diff --git a/examples/delegated-routing/src/App.js b/examples/delegated-routing/src/App.js deleted file mode 100644 index c092081d55..0000000000 --- a/examples/delegated-routing/src/App.js +++ /dev/null @@ -1,154 +0,0 @@ -// eslint-disable-next-line -'use strict' - -import { noise } from '@chainsafe/libp2p-noise' -import { yamux } from '@chainsafe/libp2p-yamux' -import { bootstrap } from '@libp2p/bootstrap' -import { delegatedContentRouting } from '@libp2p/delegated-content-routing' -import { delegatedPeerRouting } from '@libp2p/delegated-peer-routing' -import { mplex } from '@libp2p/mplex' -import { webSockets } from '@libp2p/websockets' -import { create as createKuboRpcClient } from 'kubo-rpc-client' -import { createLibp2p } from 'libp2p' -import { circuitRelayTransport } from 'libp2p/circuit-relay' -import { CID } from 'multiformats/cid' -import React from 'react' - -const Component = React.Component - -const BootstrapNode = '/ip4/127.0.0.1/tcp/8081/ws/p2p/QmdoG8DpzYUZMVP5dGmgmigZwR1RE8Cf6SxMPg1SBXJAQ8' - -class App extends Component { - constructor (props) { - super(props) - this.state = { - peers: 0, - // This hash is the IPFS readme - hash: 'QmPZ9gcCEpqKTo6aq61g2nXGUhM4iCL3ewB6LDXZCtioEB', - // This peer is one of the Bootstrap nodes for IPFS - peer: 'QmV6kA2fB8kTr6jc3pL5zbNsjKbmPUHAPKKHRBYe1kDEyc', - isLoading: 0 - } - this.peerInterval = null - - this.handleHashChange = this.handleHashChange.bind(this) - this.handleHashSubmit = this.handleHashSubmit.bind(this) - this.handlePeerChange = this.handlePeerChange.bind(this) - this.handlePeerSubmit = this.handlePeerSubmit.bind(this) - } - - handleHashChange (event) { - this.setState({ - hash: event.target.value - }) - } - - handlePeerChange (event) { - this.setState({ - peer: event.target.value - }) - } - - async handleHashSubmit (event) { - event.preventDefault() - this.setState({ - isLoading: this.state.isLoading + 1 - }) - - const providers = [] - - for await (const provider of this.libp2p.contentRouting.findProviders(CID.parse(this.state.hash))) { - providers.push(provider) - - this.setState({ - response: providers.toString(), - isLoading: this.state.isLoading - 1 - }) - } - } - - async handlePeerSubmit (event) { - event.preventDefault() - this.setState({ - isLoading: this.state.isLoading + 1 - }) - - const peerInfo = await this.libp2p.peerRouting.findPeer(this.state.peer) - - this.setState({ - response: JSON.stringify(peerInfo, null, 2), - isLoading: this.state.isLoading - 1 - }) - } - - async componentDidMount () { - const client = createKuboRpcClient({ - host: '0.0.0.0', - protocol: 'http', - port: '8080' - }) - - window.libp2p = this.libp2p = await createLibp2p({ - contentRouting: [ - delegatedPeerRouting(client) - ], - peerRouting: [ - delegatedContentRouting(client) - ], - peerDiscovery: [ - bootstrap({ - list: { - BootstrapNode - } - }) - ], - transports: [ - webSockets(), - circuitRelayTransport() - ], - streamMuxers: [ - yamux(), mplex() - ], - connectionEncryption: [ - noise() - ] - }) - } - - render () { - return ( -
-
-

Delegated Routing

-

There are currently {this.state.peers} peers.

-
-
-
- -
-
- -
-
-
0 ? 'loading' : '', 'loader'].join(' ')}> -
-
-
-
-            {this.state.response}
-          
-
-
- ) - } -} - -export default App diff --git a/examples/delegated-routing/src/index.js b/examples/delegated-routing/src/index.js deleted file mode 100644 index 03b5425104..0000000000 --- a/examples/delegated-routing/src/index.js +++ /dev/null @@ -1,8 +0,0 @@ -// eslint-disable-next-line -'use strict' - -import React from 'react' // eslint-disable-line no-unused-vars -import ReactDOM from 'react-dom' -import App from './App.js' // eslint-disable-line no-unused-vars - -ReactDOM.render(, document.getElementById('root')) diff --git a/examples/discovery-mechanisms/1.js b/examples/discovery-mechanisms/1.js deleted file mode 100644 index a653285945..0000000000 --- a/examples/discovery-mechanisms/1.js +++ /dev/null @@ -1,36 +0,0 @@ -/* eslint-disable no-console */ - -import { noise } from '@chainsafe/libp2p-noise' -import { yamux } from '@chainsafe/libp2p-yamux' -import { bootstrap } from '@libp2p/bootstrap' -import { mplex } from '@libp2p/mplex' -import { tcp } from '@libp2p/tcp' -import { createLibp2p } from 'libp2p' -import bootstrappers from './bootstrappers.js' - -(async () => { - const node = await createLibp2p({ - addresses: { - listen: ['/ip4/0.0.0.0/tcp/0'] - }, - transports: [tcp()], - streamMuxers: [yamux(), mplex()], - connectionEncryption: [noise()], - peerDiscovery: [ - bootstrap({ - list: bootstrappers - }) - ] - }) - - node.addEventListener('peer:connect', (evt) => { - const peerId = evt.detail - console.log('Connection established to:', peerId.toString()) // Emitted when a peer has been found - }) - - node.addEventListener('peer:discovery', (evt) => { - const peerInfo = evt.detail - - console.log('Discovered:', peerInfo.id.toString()) - }) -})() diff --git a/examples/discovery-mechanisms/2.js b/examples/discovery-mechanisms/2.js deleted file mode 100644 index 3a80cd5aeb..0000000000 --- a/examples/discovery-mechanisms/2.js +++ /dev/null @@ -1,42 +0,0 @@ -/* eslint-disable no-console */ - -import { noise } from '@chainsafe/libp2p-noise' -import { yamux } from '@chainsafe/libp2p-yamux' -import { mdns } from '@libp2p/mdns' -import { mplex } from '@libp2p/mplex' -import { tcp } from '@libp2p/tcp' -import { createLibp2p } from 'libp2p' - -const createNode = async () => { - const node = await createLibp2p({ - addresses: { - listen: ['/ip4/0.0.0.0/tcp/0'] - }, - transports: [ - tcp() - ], - streamMuxers: [ - yamux(), mplex() - ], - connectionEncryption: [ - noise() - ], - peerDiscovery: [ - mdns({ - interval: 20e3 - }) - ] - }) - - return node -} - -;(async () => { - const [node1, node2] = await Promise.all([ - createNode(), - createNode() - ]) - - node1.addEventListener('peer:discovery', (evt) => console.log('Discovered:', evt.detail.id.toString())) - node2.addEventListener('peer:discovery', (evt) => console.log('Discovered:', evt.detail.id.toString())) -})() diff --git a/examples/discovery-mechanisms/3.js b/examples/discovery-mechanisms/3.js deleted file mode 100644 index 93078517d2..0000000000 --- a/examples/discovery-mechanisms/3.js +++ /dev/null @@ -1,77 +0,0 @@ -/* eslint-disable no-console */ - -import { noise } from '@chainsafe/libp2p-noise' -import { yamux } from '@chainsafe/libp2p-yamux' -import { bootstrap } from '@libp2p/bootstrap' -import { floodsub } from '@libp2p/floodsub' -import { mplex } from '@libp2p/mplex' -import { pubsubPeerDiscovery } from '@libp2p/pubsub-peer-discovery' -import { tcp } from '@libp2p/tcp' -import { createLibp2p } from 'libp2p' -import { circuitRelayTransport, circuitRelayServer } from 'libp2p/circuit-relay' -import { identifyService } from 'libp2p/identify' - -const createNode = async (bootstrappers) => { - const node = await createLibp2p({ - addresses: { - listen: ['/ip4/0.0.0.0/tcp/0'] - }, - transports: [tcp()], - streamMuxers: [yamux(), mplex()], - connectionEncryption: [noise()], - peerDiscovery: [ - bootstrap({ - list: bootstrappers - }), - pubsubPeerDiscovery({ - interval: 1000 - }) - ], - services: { - pubsub: floodsub(), - identify: identifyService() - } - }) - - return node -} - -;(async () => { - const relay = await createLibp2p({ - addresses: { - listen: [ - '/ip4/0.0.0.0/tcp/0' - ] - }, - transports: [tcp(), circuitRelayTransport()], - streamMuxers: [yamux(), mplex()], - connectionEncryption: [noise()], - peerDiscovery: [ - pubsubPeerDiscovery({ - interval: 1000 - }) - ], - services: { - relay: circuitRelayServer(), - identify: identifyService(), - pubsub: floodsub() - } - }) - console.log(`libp2p relay started with id: ${relay.peerId.toString()}`) - - const relayMultiaddrs = relay.getMultiaddrs().map((m) => m.toString()) - - const [node1, node2] = await Promise.all([ - createNode(relayMultiaddrs), - createNode(relayMultiaddrs) - ]) - - node1.addEventListener('peer:discovery', (evt) => { - const peer = evt.detail - console.log(`Peer ${node1.peerId.toString()} discovered: ${peer.id.toString()}`) - }) - node2.addEventListener('peer:discovery', (evt) => { - const peer = evt.detail - console.log(`Peer ${node2.peerId.toString()} discovered: ${peer.id.toString()}`) - }) -})() diff --git a/examples/discovery-mechanisms/LICENSE b/examples/discovery-mechanisms/LICENSE deleted file mode 100644 index 20ce483c86..0000000000 --- a/examples/discovery-mechanisms/LICENSE +++ /dev/null @@ -1,4 +0,0 @@ -This project is dual licensed under MIT and Apache-2.0. - -MIT: https://www.opensource.org/licenses/mit -Apache-2.0: https://www.apache.org/licenses/license-2.0 diff --git a/examples/discovery-mechanisms/LICENSE-APACHE b/examples/discovery-mechanisms/LICENSE-APACHE deleted file mode 100644 index 14478a3b60..0000000000 --- a/examples/discovery-mechanisms/LICENSE-APACHE +++ /dev/null @@ -1,5 +0,0 @@ -Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at - -http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. diff --git a/examples/discovery-mechanisms/LICENSE-MIT b/examples/discovery-mechanisms/LICENSE-MIT deleted file mode 100644 index 72dc60d84b..0000000000 --- a/examples/discovery-mechanisms/LICENSE-MIT +++ /dev/null @@ -1,19 +0,0 @@ -The MIT License (MIT) - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/examples/discovery-mechanisms/README.md b/examples/discovery-mechanisms/README.md deleted file mode 100644 index 9402e1540f..0000000000 --- a/examples/discovery-mechanisms/README.md +++ /dev/null @@ -1,315 +0,0 @@ -# @libp2p/example-discovery-mechanisms - -[![libp2p.io](https://img.shields.io/badge/project-libp2p-yellow.svg?style=flat-square)](http://libp2p.io/) -[![Discuss](https://img.shields.io/discourse/https/discuss.libp2p.io/posts.svg?style=flat-square)](https://discuss.libp2p.io) -[![codecov](https://img.shields.io/codecov/c/github/libp2p/js-libp2p.svg?style=flat-square)](https://codecov.io/gh/libp2p/js-libp2p) -[![CI](https://img.shields.io/github/actions/workflow/status/libp2p/js-libp2p/main.yml?branch=master\&style=flat-square)](https://github.com/libp2p/js-libp2p/actions/workflows/main.yml?query=branch%3Amaster) - -> How to configure peer discovery mechanisms - -## Table of contents - -- [1. Bootstrap list of Peers when booting a node](#1-bootstrap-list-of-peers-when-booting-a-node) -- [2. MulticastDNS to find other peers in the network](#2-multicastdns-to-find-other-peers-in-the-network) -- [3. Pubsub based Peer Discovery](#3-pubsub-based-peer-discovery) -- [4. Where to find other Peer Discovery Mechanisms](#4-where-to-find-other-peer-discovery-mechanisms) -- [License](#license) -- [Contribution](#contribution) - -With this system, a libp2p node can both have a set of nodes to always connect on boot (bootstraper nodes), discover nodes through locality (e.g connected in the same LAN) or through serendipity (random walks on a DHT). - -These mechanisms save configuration and enable a node to operate without any explicit dials, it will just work. Once new peers are discovered, their known data is stored in the peer's PeerStore. - -## 1. Bootstrap list of Peers when booting a node - -For this demo, we will connect to IPFS default bootstrapper nodes and so, we will need to support the same set of features those nodes have, that are: TCP, mplex, and NOISE. You can see the complete example at [1.js](./1.js). - -First, we create our libp2p node. - -```JavaScript -import { createLibp2p } from 'libp2p' -import { bootstrap } from '@libp2p/bootstrap' -import { tcp } from '@libp2p/tcp' -import { mplex } from '@libp2p/mplex' -import { yamux } from '@chainsafe/libp2p-yamux' -import { noise } from '@chainsafe/libp2p-noise' - -const node = await createLibp2p({ - transports: [ - tcp() - ], - streamMuxers: [ - yamux(), - mplex() - ], - connectionEncryption: [ - noise() - ], - peerDiscovery: [ - bootstrap({ - interval: 60e3, - list: bootstrapers - }) - ] -}) -``` - -In this configuration, we use a `bootstrappers` array listing peers to connect *on boot*. Here is the list used by js-ipfs and go-ipfs. - -```JavaScript -const bootstrapers = [ - '/ip4/104.131.131.82/tcp/4001/p2p/QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ', - '/dnsaddr/bootstrap.libp2p.io/p2p/QmNnooDu7bfjPFoTZYxMNLWUQJyrVwtbZg5gBMjTezGAJN', - '/dnsaddr/bootstrap.libp2p.io/p2p/QmbLHAnMoJPWSCR5Zhtx6BHJX9KiKNN6tpvbUcqanj75Nb', - '/dnsaddr/bootstrap.libp2p.io/p2p/QmZa1sAxajnQjVM8WjWXoMbmPd7NsWhfKsPkErzpm9wGkp', - '/dnsaddr/bootstrap.libp2p.io/p2p/QmQCU2EcMqAqQPR2i9bChDtGNJchTbq5TbXJJ16u19uLTa', - '/dnsaddr/bootstrap.libp2p.io/p2p/QmcZf59bWwK5XFi76CZX8cbJ4BhTzzA3gU1ZjYZcYW3dwt' -] -``` - -Now, once we create and start the node, we can listen for events such as `peer:discovery` and `peer:connect`, these events tell us when we found a peer, independently of the discovery mechanism used and when we actually dialed to that peer. - -```JavaScript -const node = await createLibp2p({ - start: false, - addresses: { - listen: ['/ip4/0.0.0.0/tcp/0'] - }, - transports: [ - tcp() - ], - streamMuxers: [ - yamux(), - mplex() - ], - connectionEncryption: [ - noise() - ], - peerDiscovery: [ - bootstrap({ - interval: 60e3, - list: bootstrapers - }) - ] -}) - -node.addEventListener('peer:connect', (evt) => { - console.log('Connection established to:', evt.detail.remotePeer.toString()) // Emitted when a new connection has been created -}) - -node.addEventListener('peer:discovery', (evt) => { - // No need to dial, autoDial is on - console.log('Discovered:', evt.detail.id.toString()) -}) - -await node.start() -``` - -From running [1.js](./1.js), you should see the following: - -```bash -> node 1.js -Discovered: QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ -Discovered: QmNnooDu7bfjPFoTZYxMNLWUQJyrVwtbZg5gBMjTezGAJN -Discovered: QmbLHAnMoJPWSCR5Zhtx6BHJX9KiKNN6tpvbUcqanj75Nb -Discovered: QmZa1sAxajnQjVM8WjWXoMbmPd7NsWhfKsPkErzpm9wGkp -Discovered: QmQCU2EcMqAqQPR2i9bChDtGNJchTbq5TbXJJ16u19uLTa -Discovered: QmcZf59bWwK5XFi76CZX8cbJ4BhTzzA3gU1ZjYZcYW3dwt -Connection established to: QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ -Connection established to: QmNnooDu7bfjPFoTZYxMNLWUQJyrVwtbZg5gBMjTezGAJN -Connection established to: QmZa1sAxajnQjVM8WjWXoMbmPd7NsWhfKsPkErzpm9wGkp -Connection established to: QmQCU2EcMqAqQPR2i9bChDtGNJchTbq5TbXJJ16u19uLTa -Connection established to: QmcZf59bWwK5XFi76CZX8cbJ4BhTzzA3gU1ZjYZcYW3dwt -Connection established to: QmbLHAnMoJPWSCR5Zhtx6BHJX9KiKNN6tpvbUcqanj75Nb -``` - -## 2. MulticastDNS to find other peers in the network - -For this example, we need `@libp2p/mdns`, go ahead and `npm install` it. You can find the complete solution at [2.js](./2.js). - -Update your libp2p configuration to include MulticastDNS. - -```JavaScript -import { createLibp2p } from 'libp2p' -import { mdns } from '@libp2p/mdns' -import { tcp } from '@libp2p/tcp' -import { mplex } from '@libp2p/mplex' -import { yamux } from '@chainsafe/libp2p-yamux' -import { noise } from '@chainsafe/libp2p-noise' - -const createNode = () => { - return createLibp2p({ - addresses: { - listen: ['/ip4/0.0.0.0/tcp/0'] - }, - transports: [ - tcp() - ], - streamMuxers: [ - yamux(),mplex() - ], - connectionEncryption: [ - noise() - ], - peerDiscovery: [ - mdns({ - interval: 20e3 - }) - ] - }) -} -``` - -To observe it working, spawn two nodes. - -```JavaScript -const [node1, node2] = await Promise.all([ - createNode(), - createNode() -]) - -node1.addEventListener('peer:discovery', (evt) => console.log('Discovered:', evt.detail.id.toString())) -node2.addEventListener('peer:discovery', (evt) => console.log('Discovered:', evt.detail.id.toString())) -``` - -If you run this example, you will see the other peers being discovered. - -```bash -> node 2.js -Discovered: QmSSbQpuKrxkoXHm1v4Pi35hPN5hUHMZoBoawEs2Nhvi8m -Discovered: QmRcXXhtG8vTqwVBRonKWtV4ovDoC1Fe56WYtcrw694eiJ -``` - -## 3. Pubsub based Peer Discovery - -For this example, we need [`@libp2p/pubsub-peer-discovery`](https://github.com/libp2p/js-libp2p-pubsub-peer-discovery/), go ahead and `npm install` it. You also need to spin up a set of [`libp2p-relay-servers`](https://github.com/libp2p/js-libp2p-relay-server). These servers act as relay servers and a peer discovery source. - -In the context of this example, we will create and run the `libp2p-relay-server` in the same code snippet. You can find the complete solution at [3.js](./3.js). - -You can create your libp2p nodes as follows: - -```js -import { createLibp2p } from 'libp2p' -import { tcp } from '@libp2p/tcp' -import { mplex } from '@libp2p/mplex' -import { noise } from '@chainsafe/libp2p-noise' -import { GossipSub } from '@chainsafe/libp2p-gossipsub' -import { bootstrap } from '@libp2p/bootstrap' -import { PubSubPeerDiscovery } from '@libp2p/pubsub-peer-discovery' - -const createNode = async (bootstrapers) => { - const node = await createLibp2p({ - addresses: { - listen: ['/ip4/0.0.0.0/tcp/0'] - }, - transports: [ - tcp() - ], - streamMuxers: [ - yamux(),mplex() - ], - connectionEncryption: [ - noise() - ], - pubsub: gossipsub({ allowPublishToZeroPeers: true }), - peerDiscovery: [ - bootstrap({ - interval: 60e3, - list: bootstrapers - }), - new PubSubPeerDiscovery({ - interval: 1000 - }) - ] - }) - - return node -} -``` - -We will use the `libp2p-relay-server` as bootstrap nodes for the libp2p nodes, so that they establish a connection with the relay after starting. As a result, after they establish a connection with the relay, the pubsub discovery will kick in and the relay will advertise them. - -```js -const relay = await createLibp2p({ - addresses: { - listen: [ - '/ip4/0.0.0.0/tcp/0' - ] - }, - transports: [tcp()], - streamMuxers: [yamux(), mplex()], - connectionEncryption: [noise()], - pubsub: gossipsub({ allowPublishToZeroPeers: true }), - peerDiscovery: [ - new PubSubPeerDiscovery({ - interval: 1000 - }) - ], - relay: { - enabled: true, // Allows you to dial and accept relayed connections. Does not make you a relay. - hop: { - enabled: true // Allows you to be a relay for other peers - } - } -}) - -console.log(`libp2p relay starting with id: ${relay.peerId.toString()}`) - -await relay.start() - -const relayMultiaddrs = relay.getMultiaddrs() - -const [node1, node2] = await Promise.all([ - createNode(relayMultiaddrs), - createNode(relayMultiaddrs) -]) - -node1.addEventListener('peer:discovery', (evt) => { - console.log(`Peer ${node1.peerId.toString()} discovered: ${evt.detail.id.toString()}`) -}) -node2.addEventListener('peer:discovery', (evt) => { - console.log(`Peer ${node2.peerId.toString()} discovered: ${evt.detail.id.toString()}`) -}) - -;[node1, node2].forEach((node, index) => console.log(`Node ${index} starting with id: ${node.peerId.toString()}`)) - -await Promise.all([ - node1.start(), - node2.start() -]) -``` - -If you run this example, you will see the other peers being discovered. - -```bash -> node 3.js -libp2p relay starting with id: QmW6FqVV6RsyoGC5zaeFGW9gSWA3LcBRVZrjkKMruh38Bo -Node 0 starting with id: QmezqDTmEjZ5BfMgVqjSpLY19mVVLTQ9bE9mRpZwtGxL8N -Node 1 starting with id: QmYWeom2odTkm79DzB68NHULqVHDaNDqHhoyqLdcV1fqdv -Peer QmezqDTmEjZ5BfMgVqjSpLY19mVVLTQ9bE9mRpZwtGxL8N discovered: QmW6FqVV6RsyoGC5zaeFGW9gSWA3LcBRVZrjkKMruh38Bo -Peer QmYWeom2odTkm79DzB68NHULqVHDaNDqHhoyqLdcV1fqdv discovered: QmW6FqVV6RsyoGC5zaeFGW9gSWA3LcBRVZrjkKMruh38Bo -Peer QmYWeom2odTkm79DzB68NHULqVHDaNDqHhoyqLdcV1fqdv discovered: QmezqDTmEjZ5BfMgVqjSpLY19mVVLTQ9bE9mRpZwtGxL8N -Peer QmezqDTmEjZ5BfMgVqjSpLY19mVVLTQ9bE9mRpZwtGxL8N discovered: QmYWeom2odTkm79DzB68NHULqVHDaNDqHhoyqLdcV1fqdv -``` - -Taking into account the output, after the relay and both libp2p nodes start, both libp2p nodes will discover the bootstrap node (relay) and connect with it. After establishing a connection with the relay, they will discover each other. - -This is really useful when running libp2p in constrained environments like a browser. You can run a set of `libp2p-relay-server` nodes that will be responsible for both relaying websocket connections between browser nodes and for discovering other browser peers. - -## 4. Where to find other Peer Discovery Mechanisms - -There are plenty more Peer Discovery Mechanisms out there, you can: - -- Any DHT will offer you a discovery capability. You can simple _random-walk_ the routing tables to find other peers to connect to. For example [@libp2p/kad-dht](https://github.com/libp2p/js-libp2p/tree/master/packages/kad-dht) can be used for peer discovery. An example of how to configure it to enable random walks can be found [here](https://github.com/libp2p/js-libp2p/blob/v0.28.4/doc/CONFIGURATION.md#customizing-dht). -- You can create your own Discovery service, a registry, a list, a radio beacon, you name it! - -## License - -Licensed under either of - -- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) -- MIT ([LICENSE-MIT](LICENSE-MIT) / ) - -## Contribution - -Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/examples/discovery-mechanisms/bootstrappers.js b/examples/discovery-mechanisms/bootstrappers.js deleted file mode 100644 index 85c5e73151..0000000000 --- a/examples/discovery-mechanisms/bootstrappers.js +++ /dev/null @@ -1,9 +0,0 @@ -// Find this list at: https://github.com/ipfs/js-ipfs/blob/master/packages/ipfs-core-config/src/config.js -export default [ - '/ip4/104.131.131.82/tcp/4001/p2p/QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ', - '/dnsaddr/bootstrap.libp2p.io/p2p/QmNnooDu7bfjPFoTZYxMNLWUQJyrVwtbZg5gBMjTezGAJN', - '/dnsaddr/bootstrap.libp2p.io/p2p/QmbLHAnMoJPWSCR5Zhtx6BHJX9KiKNN6tpvbUcqanj75Nb', - '/dnsaddr/bootstrap.libp2p.io/p2p/QmZa1sAxajnQjVM8WjWXoMbmPd7NsWhfKsPkErzpm9wGkp', - '/dnsaddr/bootstrap.libp2p.io/p2p/QmQCU2EcMqAqQPR2i9bChDtGNJchTbq5TbXJJ16u19uLTa', - '/dnsaddr/bootstrap.libp2p.io/p2p/QmcZf59bWwK5XFi76CZX8cbJ4BhTzzA3gU1ZjYZcYW3dwt' -] diff --git a/examples/discovery-mechanisms/package.json b/examples/discovery-mechanisms/package.json deleted file mode 100644 index 934710d4a3..0000000000 --- a/examples/discovery-mechanisms/package.json +++ /dev/null @@ -1,51 +0,0 @@ -{ - "name": "@libp2p/example-discovery-mechanisms", - "version": "0.0.0", - "description": "How to configure peer discovery mechanisms", - "license": "Apache-2.0 OR MIT", - "homepage": "https://github.com/libp2p/js-libp2p/tree/master/examples/discovery-mechanisms#readme", - "repository": { - "type": "git", - "url": "git+https://github.com/libp2p/js-libp2p.git" - }, - "bugs": { - "url": "https://github.com/libp2p/js-libp2p/issues" - }, - "type": "module", - "files": [ - "src", - "dist", - "!dist/test", - "!**/*.tsbuildinfo" - ], - "eslintConfig": { - "extends": "ipfs", - "parserOptions": { - "project": true, - "sourceType": "module" - } - }, - "scripts": { - "lint": "aegir lint", - "start": "react-scripts start", - "test:example": "node test.js" - }, - "dependencies": { - "@chainsafe/libp2p-noise": "^13.0.0", - "@chainsafe/libp2p-yamux": "^5.0.0", - "@libp2p/bootstrap": "^9.0.0", - "@libp2p/floodsub": "^8.0.0", - "@libp2p/mdns": "^9.0.0", - "@libp2p/mplex": "^9.0.0", - "@libp2p/pubsub-peer-discovery": "^9.0.0", - "@libp2p/tcp": "^8.0.0", - "libp2p": "^0.46.0" - }, - "devDependencies": { - "aegir": "^41.0.2", - "execa": "^8.0.1", - "p-wait-for": "^5.0.2", - "uint8arrays": "^4.0.4" - }, - "private": true -} diff --git a/examples/discovery-mechanisms/test-1.js b/examples/discovery-mechanisms/test-1.js deleted file mode 100644 index e8570adb48..0000000000 --- a/examples/discovery-mechanisms/test-1.js +++ /dev/null @@ -1,13 +0,0 @@ -import path from 'path' -import { fileURLToPath } from 'url' -import { waitForOutput } from 'test-ipfs-example/node' - -const __dirname = path.dirname(fileURLToPath(import.meta.url)) - -export async function test () { - process.stdout.write('1.js\n') - - await waitForOutput('Connection established to:', 'node', [path.join(__dirname, '1.js')], { - cwd: __dirname - }) -} diff --git a/examples/discovery-mechanisms/test-2.js b/examples/discovery-mechanisms/test-2.js deleted file mode 100644 index 24f3a0b476..0000000000 --- a/examples/discovery-mechanisms/test-2.js +++ /dev/null @@ -1,33 +0,0 @@ -import path from 'path' -import { fileURLToPath } from 'url' -import { execa } from 'execa' -import pWaitFor from 'p-wait-for' -import { toString as uint8ArrayToString } from 'uint8arrays/to-string' - -const __dirname = path.dirname(fileURLToPath(import.meta.url)) - -export async function test () { - let discoveredNodes = 0 - - process.stdout.write('2.js\n') - - const proc = execa('node', [path.join(__dirname, '2.js')], { - cwd: path.resolve(__dirname), - all: true - }) - - proc.all.on('data', async (data) => { - process.stdout.write(data) - const str = uint8ArrayToString(data) - - str.split('\n').forEach(line => { - if (line.includes('Discovered:')) { - discoveredNodes++ - } - }) - }) - - await pWaitFor(() => discoveredNodes > 1, 600000) - - proc.kill() -} diff --git a/examples/discovery-mechanisms/test-3.js b/examples/discovery-mechanisms/test-3.js deleted file mode 100644 index cd7e58a5d6..0000000000 --- a/examples/discovery-mechanisms/test-3.js +++ /dev/null @@ -1,38 +0,0 @@ -import path from 'path' -import { fileURLToPath } from 'url' -import { execa } from 'execa' -import pWaitFor from 'p-wait-for' -import { toString as uint8ArrayToString } from 'uint8arrays/to-string' - -const __dirname = path.dirname(fileURLToPath(import.meta.url)) - -export async function test () { - const discoveredPeers = [] - - process.stdout.write('3.js\n') - - const proc = execa('node', [path.join(__dirname, '3.js')], { - cwd: path.resolve(__dirname), - all: true - }) - - proc.all.on('data', async (data) => { - process.stdout.write(data) - const str = uint8ArrayToString(data) - const discoveredPeersRegex = /Peer\s+(?[^\s]+)\s+discovered:\s+(?[^\s]+)/ - str.split('\n').forEach(line => { - const peers = line.match(discoveredPeersRegex) - if (peers != null) { - // sort so we don't count reversed pair twice - const match = [peers.groups.Peer1, peers.groups.Peer2].sort().join(',') - if (!discoveredPeers.includes(match)) { - discoveredPeers.push(match) - } - } - }) - }) - - await pWaitFor(() => discoveredPeers.length > 2, 600000) - - proc.kill() -} diff --git a/examples/discovery-mechanisms/test.js b/examples/discovery-mechanisms/test.js deleted file mode 100644 index fd441b83ed..0000000000 --- a/examples/discovery-mechanisms/test.js +++ /dev/null @@ -1,7 +0,0 @@ -import { test as test1 } from './test-1.js' -import { test as test2 } from './test-2.js' -import { test as test3 } from './test-3.js' - -await test1() -await test2() -await test3() diff --git a/examples/echo/LICENSE b/examples/echo/LICENSE deleted file mode 100644 index 20ce483c86..0000000000 --- a/examples/echo/LICENSE +++ /dev/null @@ -1,4 +0,0 @@ -This project is dual licensed under MIT and Apache-2.0. - -MIT: https://www.opensource.org/licenses/mit -Apache-2.0: https://www.apache.org/licenses/license-2.0 diff --git a/examples/echo/LICENSE-APACHE b/examples/echo/LICENSE-APACHE deleted file mode 100644 index 14478a3b60..0000000000 --- a/examples/echo/LICENSE-APACHE +++ /dev/null @@ -1,5 +0,0 @@ -Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at - -http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. diff --git a/examples/echo/LICENSE-MIT b/examples/echo/LICENSE-MIT deleted file mode 100644 index 72dc60d84b..0000000000 --- a/examples/echo/LICENSE-MIT +++ /dev/null @@ -1,19 +0,0 @@ -The MIT License (MIT) - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/examples/echo/README.md b/examples/echo/README.md deleted file mode 100644 index 098e613025..0000000000 --- a/examples/echo/README.md +++ /dev/null @@ -1,38 +0,0 @@ -# @libp2p/example-echo - -[![libp2p.io](https://img.shields.io/badge/project-libp2p-yellow.svg?style=flat-square)](http://libp2p.io/) -[![Discuss](https://img.shields.io/discourse/https/discuss.libp2p.io/posts.svg?style=flat-square)](https://discuss.libp2p.io) -[![codecov](https://img.shields.io/codecov/c/github/libp2p/js-libp2p.svg?style=flat-square)](https://codecov.io/gh/libp2p/js-libp2p) -[![CI](https://img.shields.io/github/actions/workflow/status/libp2p/js-libp2p/main.yml?branch=master\&style=flat-square)](https://github.com/libp2p/js-libp2p/actions/workflows/main.yml?query=branch%3Amaster) - -> An example echo app - -## Table of contents - -- [Setup](#setup) -- [Running](#running) -- [License](#license) -- [Contribution](#contribution) - -## Setup - -1. Install the modules from libp2p root, `npm install` and `npm run build`. -2. Open 2 terminal windows in the `./src` directory. - -## Running - -1. Run the listener in window 1, `node listener.js` -2. Run the dialer in window 2, `node dialer.js` -3. You should see console logs showing the dial, and the received echo of *hey* -4. If you look at the listener window, you will see it receiving the dial - -## License - -Licensed under either of - -- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) -- MIT ([LICENSE-MIT](LICENSE-MIT) / ) - -## Contribution - -Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/examples/echo/package.json b/examples/echo/package.json deleted file mode 100644 index fe6e07a54b..0000000000 --- a/examples/echo/package.json +++ /dev/null @@ -1,51 +0,0 @@ -{ - "name": "@libp2p/example-echo", - "version": "0.0.0", - "description": "An example echo app", - "license": "Apache-2.0 OR MIT", - "homepage": "https://github.com/libp2p/js-libp2p/tree/master/examples/echo#readme", - "repository": { - "type": "git", - "url": "git+https://github.com/libp2p/js-libp2p.git" - }, - "bugs": { - "url": "https://github.com/libp2p/js-libp2p/issues" - }, - "type": "module", - "files": [ - "src", - "dist", - "!dist/test", - "!**/*.tsbuildinfo" - ], - "eslintConfig": { - "extends": "ipfs", - "parserOptions": { - "project": true, - "sourceType": "module" - } - }, - "scripts": { - "lint": "aegir lint", - "test:example": "node test.js" - }, - "dependencies": { - "@chainsafe/libp2p-noise": "^13.0.0", - "@chainsafe/libp2p-yamux": "^5.0.0", - "@libp2p/mplex": "^9.0.0", - "@libp2p/peer-id-factory": "^3.0.0", - "@libp2p/tcp": "^8.0.0", - "@libp2p/websockets": "^7.0.0", - "@multiformats/multiaddr": "^12.1.5", - "@nodeutils/defaults-deep": "^1.1.0", - "it-pipe": "^3.0.1", - "libp2p": "^0.46.0", - "uint8arrays": "^4.0.6" - }, - "devDependencies": { - "aegir": "^41.0.2", - "execa": "^8.0.1", - "p-defer": "^4.0.0" - }, - "private": true -} diff --git a/examples/echo/src/dialer.js b/examples/echo/src/dialer.js deleted file mode 100644 index 07eb3d1584..0000000000 --- a/examples/echo/src/dialer.js +++ /dev/null @@ -1,58 +0,0 @@ -/* eslint-disable no-console */ - -/* - * Dialer Node - */ - -import { createFromJSON } from '@libp2p/peer-id-factory' -import { multiaddr } from '@multiformats/multiaddr' -import { pipe } from 'it-pipe' -import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string' -import { toString as uint8ArrayToString } from 'uint8arrays/to-string' -import idd from './id-d.js' -import idl from './id-l.js' -import { createLibp2p } from './libp2p.js' - -async function run () { - const [dialerId, listenerId] = await Promise.all([ - createFromJSON(idd), - createFromJSON(idl) - ]) - - // Dialer - const dialerNode = await createLibp2p({ - addresses: { - listen: ['/ip4/0.0.0.0/tcp/0'] - }, - peerId: dialerId - }) - - // Add peer to Dial (the listener) into the PeerStore - const listenerMultiaddr = multiaddr('/ip4/127.0.0.1/tcp/10333/p2p/' + listenerId.toString()) - - console.log('Dialer ready, listening on:') - dialerNode.getMultiaddrs().forEach((ma) => console.log(ma.toString())) - - // Dial the listener node - console.log('Dialing to peer:', listenerMultiaddr) - const stream = await dialerNode.dialProtocol(listenerMultiaddr, '/echo/1.0.0') - - console.log('nodeA dialed to nodeB on protocol: /echo/1.0.0') - - pipe( - // Source data - [uint8ArrayFromString('hey')], - // Write to the stream, and pass its output to the next function - stream, - // Sink function - async function (source) { - // For each chunk of data - for await (const data of source) { - // Output the data - console.log('received echo:', uint8ArrayToString(data.subarray())) - } - } - ) -} - -run() diff --git a/examples/echo/src/id-d.js b/examples/echo/src/id-d.js deleted file mode 100644 index 79d31007f2..0000000000 --- a/examples/echo/src/id-d.js +++ /dev/null @@ -1,5 +0,0 @@ -export default { - id: 'Qma3GsJmB47xYuyahPZPSadh1avvxfyYQwk8R3UnFrQ6aP', - privKey: 'CAASpwkwggSjAgEAAoIBAQCaNSDOjPz6T8HZsf7LDpxiQRiN2OjeyIHUS05p8QWOr3EFUCFsC31R4moihE5HN+FxNalUyyFZU//yjf1pdnlMJqrVByJSMa+y2y4x2FucpoCAO97Tx+iWzwlZ2UXEUXM1Y81mhPbeWXy+wP2xElTgIER0Tsn/thoA0SD2u9wJuVvM7dB7cBcHYmqV6JH+KWCedRTum6O1BssqP/4Lbm2+rkrbZ4+oVRoU2DRLoFhKqwqLtylrbuj4XOI3XykMXV5+uQXz1JzubNOB9lsc6K+eRC+w8hhhDuFMgzkZ4qomCnx3uhO67KaICd8yqqBa6PJ/+fBM5Xk4hjyR40bwcf41AgMBAAECggEAZnrCJ6IYiLyyRdr9SbKXCNDb4YByGYPEi/HT1aHgIJfFE1PSMjxcdytxfyjP4JJpVtPjiT9JFVU2ddoYu5qJN6tGwjVwgJEWg1UXmPaAw1T/drjS94kVsAs82qICtFmwp52Apg3dBZ0Qwq/8qE1XbG7lLyohIbfCBiL0tiPYMfkcsN9gnFT/kFCX0LVs2pa9fHCRMY9rqCc4/rWJa1w8sMuQ23y4lDaxKF9OZVvOHFQkbBDrkquWHE4r55fchCz/rJklkPJUNENuncBRu0/2X+p4IKFD1DnttXNwb8j4LPiSlLro1T0hiUr5gO2QmdYwXFF63Q3mjQy0+5I4eNbjjQKBgQDZvZy3gUKS/nQNkYfq9za80uLbIj/cWbO+ZZjXCsj0fNIcQFJcKMBoA7DjJvu2S/lf86/41YHkPdmrLAEQAkJ+5BBNOycjYK9minTEjIMMmZDTXXugZ62wnU6F46uLkgEChTqEP57Y6xwwV+JaEDFEsW5N1eE9lEVX9nGIr4phMwKBgQC1TazLuEt1WBx/iUT83ita7obXqoKNzwsS/MWfY2innzYZKDOqeSYZzLtt9uTtp4X4uLyPbYs0qFYhXLsUYMoGHNN8+NdjoyxCjQRJRBkMtaNR0lc5lVDWl3bTuJovjFCgAr9uqJrmI5OHcCIk/cDpdWb3nWaMihVlePmiTcTy9wKBgQCU0u7c1jKkudqks4XM6a+2HAYGdUBk4cLjLhnrUWnNAcuyl5wzdX8dGPi8KZb+IKuQE8WBNJ2VXVj7kBYh1QmSJVunDflQSvNYCOaKuOeRoxzD+y9Wkca74qkbBmPn/6FFEb7PSZTO+tPHjyodGNgz9XpJJRjQuBk1aDJtlF3m1QKBgE5SAr5ym65SZOU3UGUIOKRsfDW4Q/OsqDUImvpywCgBICaX9lHDShFFHwau7FA52ScL7vDquoMB4UtCOtLfyQYA9995w9oYCCurrVlVIJkb8jSLcADBHw3EmqF1kq3NqJqm9TmBfoDCh52vdCCUufxgKh33kfBOSlXuf7B8dgMbAoGAZ3r0/mBQX6S+s5+xCETMTSNv7TQzxgtURIpVs+ZVr2cMhWhiv+n0Omab9X9Z50se8cWl5lkvx8vn3D/XHHIPrMF6qk7RAXtvReb+PeitNvm0odqjFv0J2qki6fDs0HKwq4kojAXI1Md8Th0eobNjsy21fEEJT7uKMJdovI/SErI=', - pubKey: 'CAASpgIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCaNSDOjPz6T8HZsf7LDpxiQRiN2OjeyIHUS05p8QWOr3EFUCFsC31R4moihE5HN+FxNalUyyFZU//yjf1pdnlMJqrVByJSMa+y2y4x2FucpoCAO97Tx+iWzwlZ2UXEUXM1Y81mhPbeWXy+wP2xElTgIER0Tsn/thoA0SD2u9wJuVvM7dB7cBcHYmqV6JH+KWCedRTum6O1BssqP/4Lbm2+rkrbZ4+oVRoU2DRLoFhKqwqLtylrbuj4XOI3XykMXV5+uQXz1JzubNOB9lsc6K+eRC+w8hhhDuFMgzkZ4qomCnx3uhO67KaICd8yqqBa6PJ/+fBM5Xk4hjyR40bwcf41AgMBAAE=' -} diff --git a/examples/echo/src/id-l.js b/examples/echo/src/id-l.js deleted file mode 100644 index 8e5acb76c0..0000000000 --- a/examples/echo/src/id-l.js +++ /dev/null @@ -1,5 +0,0 @@ -export default { - id: 'QmcrQZ6RJdpYuGvZqD5QEHAv6qX4BrQLJLQPQUrTrzdcgm', - privKey: 'CAASqAkwggSkAgEAAoIBAQDLZZcGcbe4urMBVlcHgN0fpBymY+xcr14ewvamG70QZODJ1h9sljlExZ7byLiqRB3SjGbfpZ1FweznwNxWtWpjHkQjTVXeoM4EEgDSNO/Cg7KNlU0EJvgPJXeEPycAZX9qASbVJ6EECQ40VR/7+SuSqsdL1hrmG1phpIju+D64gLyWpw9WEALfzMpH5I/KvdYDW3N4g6zOD2mZNp5y1gHeXINHWzMF596O72/6cxwyiXV1eJ000k1NVnUyrPjXtqWdVLRk5IU1LFpoQoXZU5X1hKj1a2qt/lZfH5eOrF/ramHcwhrYYw1txf8JHXWO/bbNnyemTHAvutZpTNrsWATfAgMBAAECggEAQj0obPnVyjxLFZFnsFLgMHDCv9Fk5V5bOYtmxfvcm50us6ye+T8HEYWGUa9RrGmYiLweuJD34gLgwyzE1RwptHPj3tdNsr4NubefOtXwixlWqdNIjKSgPlaGULQ8YF2tm/kaC2rnfifwz0w1qVqhPReO5fypL+0ShyANVD3WN0Fo2ugzrniCXHUpR2sHXSg6K+2+qWdveyjNWog34b7CgpV73Ln96BWae6ElU8PR5AWdMnRaA9ucA+/HWWJIWB3Fb4+6uwlxhu2L50Ckq1gwYZCtGw63q5L4CglmXMfIKnQAuEzazq9T4YxEkp+XDnVZAOgnQGUBYpetlgMmkkh9qQKBgQDvsEs0ThzFLgnhtC2Jy//ZOrOvIAKAZZf/mS08AqWH3L0/Rjm8ZYbLsRcoWU78sl8UFFwAQhMRDBP9G+RPojWVahBL/B7emdKKnFR1NfwKjFdDVaoX5uNvZEKSl9UubbC4WZJ65u/cd5jEnj+w3ir9G8n+P1gp/0yBz02nZXFgSwKBgQDZPQr4HBxZL7Kx7D49ormIlB7CCn2i7mT11Cppn5ifUTrp7DbFJ2t9e8UNk6tgvbENgCKXvXWsmflSo9gmMxeEOD40AgAkO8Pn2R4OYhrwd89dECiKM34HrVNBzGoB5+YsAno6zGvOzLKbNwMG++2iuNXqXTk4uV9GcI8OnU5ZPQKBgCZUGrKSiyc85XeiSGXwqUkjifhHNh8yH8xPwlwGUFIZimnD4RevZI7OEtXw8iCWpX2gg9XGuyXOuKORAkF5vvfVriV4e7c9Ad4Igbj8mQFWz92EpV6NHXGCpuKqRPzXrZrNOA9PPqwSs+s9IxI1dMpk1zhBCOguWx2m+NP79NVhAoGBAI6WSoTfrpu7ewbdkVzTWgQTdLzYNe6jmxDf2ZbKclrf7lNr/+cYIK2Ud5qZunsdBwFdgVcnu/02czeS42TvVBgs8mcgiQc/Uy7yi4/VROlhOnJTEMjlU2umkGc3zLzDgYiRd7jwRDLQmMrYKNyEr02HFKFn3w8kXSzW5I8rISnhAoGBANhchHVtJd3VMYvxNcQb909FiwTnT9kl9pkjhwivx+f8/K8pDfYCjYSBYCfPTM5Pskv5dXzOdnNuCj6Y2H/9m2SsObukBwF0z5Qijgu1DsxvADVIKZ4rzrGb4uSEmM6200qjJ/9U98fVM7rvOraakrhcf9gRwuspguJQnSO9cLj6', - pubKey: 'CAASpgIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDLZZcGcbe4urMBVlcHgN0fpBymY+xcr14ewvamG70QZODJ1h9sljlExZ7byLiqRB3SjGbfpZ1FweznwNxWtWpjHkQjTVXeoM4EEgDSNO/Cg7KNlU0EJvgPJXeEPycAZX9qASbVJ6EECQ40VR/7+SuSqsdL1hrmG1phpIju+D64gLyWpw9WEALfzMpH5I/KvdYDW3N4g6zOD2mZNp5y1gHeXINHWzMF596O72/6cxwyiXV1eJ000k1NVnUyrPjXtqWdVLRk5IU1LFpoQoXZU5X1hKj1a2qt/lZfH5eOrF/ramHcwhrYYw1txf8JHXWO/bbNnyemTHAvutZpTNrsWATfAgMBAAE=' -} diff --git a/examples/echo/src/libp2p.js b/examples/echo/src/libp2p.js deleted file mode 100644 index 85b569490a..0000000000 --- a/examples/echo/src/libp2p.js +++ /dev/null @@ -1,24 +0,0 @@ -import { noise } from '@chainsafe/libp2p-noise' -import { yamux } from '@chainsafe/libp2p-yamux' -import { mplex } from '@libp2p/mplex' -import { tcp } from '@libp2p/tcp' -import { webSockets } from '@libp2p/websockets' -import defaultsDeep from '@nodeutils/defaults-deep' -import { createLibp2p as createNode } from 'libp2p' - -export async function createLibp2p (_options) { - const defaults = { - transports: [ - tcp(), - webSockets() - ], - streamMuxers: [ - yamux(), mplex() - ], - connectionEncryption: [ - noise() - ] - } - - return createNode(defaultsDeep(_options, defaults)) -} diff --git a/examples/echo/src/listener.js b/examples/echo/src/listener.js deleted file mode 100644 index 1ff193cf33..0000000000 --- a/examples/echo/src/listener.js +++ /dev/null @@ -1,39 +0,0 @@ -/* eslint-disable no-console */ - -/* - * Listener Node - */ - -import { createFromJSON } from '@libp2p/peer-id-factory' -import { pipe } from 'it-pipe' -import idl from './id-l.js' -import { createLibp2p } from './libp2p.js' - -async function run () { - const listenerId = await createFromJSON(idl) - - // Listener libp2p node - const listenerNode = await createLibp2p({ - addresses: { - listen: ['/ip4/0.0.0.0/tcp/10333'] - }, - peerId: listenerId - }) - - // Log a message when we receive a connection - listenerNode.addEventListener('peer:connect', (evt) => { - const remotePeer = evt.detail - console.log('received dial to me from:', remotePeer.toString()) - }) - - // Handle incoming connections for the protocol by piping from the stream - // back to itself (an echo) - await listenerNode.handle('/echo/1.0.0', ({ stream }) => pipe(stream.source, stream.sink)) - - console.log('Listener ready, listening on:') - listenerNode.getMultiaddrs().forEach((ma) => { - console.log(ma.toString()) - }) -} - -run() diff --git a/examples/echo/test.js b/examples/echo/test.js deleted file mode 100644 index 5bdb55c3a6..0000000000 --- a/examples/echo/test.js +++ /dev/null @@ -1,58 +0,0 @@ -import path from 'path' -import { fileURLToPath } from 'url' -import { execa } from 'execa' -import pDefer from 'p-defer' -import { toString as uint8ArrayToString } from 'uint8arrays/to-string' - -const __dirname = path.dirname(fileURLToPath(import.meta.url)) - -function startProcess (name) { - return execa('node', [path.join(__dirname, name)], { - cwd: path.resolve(__dirname), - all: true - }) -} - -const listenerReady = pDefer() -const messageReceived = pDefer() - -// Step 1 process -process.stdout.write('node src/listener.js\n') -const listenerProc = startProcess('src/listener.js') -listenerProc.all.on('data', async (data) => { - process.stdout.write(data) - const s = uint8ArrayToString(data) - - if (s.includes('Listener ready, listening on:')) { - listenerReady.resolve() - } -}) - -await listenerReady.promise -process.stdout.write('==================================================================\n') - -// Step 2 process -process.stdout.write('node src/dialer.js\n') -const dialerProc = startProcess('src/dialer.js') -dialerProc.all.on('data', async (data) => { - process.stdout.write(data) - const s = uint8ArrayToString(data) - - if (s.includes('received echo:')) { - messageReceived.resolve() - } -}) - -await messageReceived.promise -process.stdout.write('echo message received\n') - -listenerProc.kill() -dialerProc.kill() -await Promise.all([ - listenerProc, - dialerProc -]).catch((err) => { - if (err.signal !== 'SIGTERM') { - throw err - } -}) diff --git a/examples/libp2p-in-the-browser/webrtc/README.md b/examples/libp2p-in-the-browser/webrtc/README.md deleted file mode 100644 index 8b78f83bbe..0000000000 --- a/examples/libp2p-in-the-browser/webrtc/README.md +++ /dev/null @@ -1,4 +0,0 @@ -# Examples - -* [Browser to Server Echo](browser-to-server/README.md): connect to a go-libp2p-webrtc server with a browser - diff --git a/examples/libp2p-in-the-browser/webrtc/browser-to-browser/README.md b/examples/libp2p-in-the-browser/webrtc/browser-to-browser/README.md deleted file mode 100644 index e7449a0a1e..0000000000 --- a/examples/libp2p-in-the-browser/webrtc/browser-to-browser/README.md +++ /dev/null @@ -1,61 +0,0 @@ -# js-libp2p-webrtc Browser to Browser - -This example leverages the [vite bundler](https://vitejs.dev/) to compile and serve the libp2p code in the browser. You can use other bundlers such as Webpack, but we will not be covering them here. - -## Build the `@libp2p/webrtc` package - -Build the `@libp2p/webrtc` package by calling `npm i && npm run build` in the repository root. - -## Running the Relay Server - -For browsers to communicate, we first need to run the LibP2P relay server: - -```shell -npm run relay -``` - -Copy one of the multiaddresses in the output. - -## Running the Example - -In a separate console tab, install dependencies and start the Vite server: - -```shell -npm i && npm run start -``` - -The browser window will automatically open. Let's call this `Browser A`. -Using the copied multiaddress from the Go or NodeJS relay server, paste it into the `Remote MultiAddress` input and click the `Connect` button. -`Browser A` is now connected to the relay server. -Copy the multiaddress located after the `Listening on` message. - -Now open a second browser with the url `http://localhost:5173/`. Let's call this `Browser B`. -Using the copied multiaddress from `Listening on` section in `Browser A`, paste it into the `Remote MultiAddress` input and click the `Connect` button. -`Browser B` is now connected to `Browser A`. -Copy the multiaddress located after the `Listening on` message. - -Using the copied multiaddress from `Listening on` section in `Browser B`, paste it into the `Remote MultiAddress` input in `Browser A` and click the `Connect` button. -`Browser A` is now connected to `Browser B`. - -The peers are now connected to each other. Enter a message and click the `Send` button in either/both browsers and see the echo'd messages. - -The output should look like: - -`Browser A` -```text -Dialing '/ip4/127.0.0.1/tcp/57708/ws/p2p/12D3KooWRqAUEzPwKMoGstpfJVqr3aoinwKVPu4DLo9nQncbnuLk' -Listening on /ip4/127.0.0.1/tcp/57708/ws/p2p/12D3KooWRqAUEzPwKMoGstpfJVqr3aoinwKVPu4DLo9nQncbnuLk/p2p-circuit/p2p/12D3KooW9wFiWFELqGJTbzEwtByXsPiHJdHB8n7Kin71VMYyERmC/p2p-circuit/webrtc/p2p/12D3KooW9wFiWFELqGJTbzEwtByXsPiHJdHB8n7Kin71VMYyERmC -Dialing '/ip4/127.0.0.1/tcp/57708/ws/p2p/12D3KooWRqAUEzPwKMoGstpfJVqr3aoinwKVPu4DLo9nQncbnuLk/p2p-circuit/p2p/12D3KooWBZyVLJfQkofqLK4op9TPkHuUumCZt1ybQrPvNm7TVQV9/p2p-circuit/webrtc/p2p/12D3KooWBZyVLJfQkofqLK4op9TPkHuUumCZt1ybQrPvNm7TVQV9' -Sending message 'helloa' -Received message 'helloa' -Received message 'hellob' -``` - -`Browser B` -```text -Dialing '/ip4/127.0.0.1/tcp/57708/ws/p2p/12D3KooWRqAUEzPwKMoGstpfJVqr3aoinwKVPu4DLo9nQncbnuLk/p2p-circuit/p2p/12D3KooW9wFiWFELqGJTbzEwtByXsPiHJdHB8n7Kin71VMYyERmC/p2p-circuit/webrtc/p2p/12D3KooW9wFiWFELqGJTbzEwtByXsPiHJdHB8n7Kin71VMYyERmC' -Listening on /ip4/127.0.0.1/tcp/57708/ws/p2p/12D3KooWRqAUEzPwKMoGstpfJVqr3aoinwKVPu4DLo9nQncbnuLk/p2p-circuit/p2p/12D3KooWBZyVLJfQkofqLK4op9TPkHuUumCZt1ybQrPvNm7TVQV9/p2p-circuit/webrtc/p2p/12D3KooWBZyVLJfQkofqLK4op9TPkHuUumCZt1ybQrPvNm7TVQV9 -Received message 'helloa' -Sending message 'hellob' -Received message 'hellob' -``` diff --git a/examples/libp2p-in-the-browser/webrtc/browser-to-browser/index.html b/examples/libp2p-in-the-browser/webrtc/browser-to-browser/index.html deleted file mode 100644 index 8da321d9d0..0000000000 --- a/examples/libp2p-in-the-browser/webrtc/browser-to-browser/index.html +++ /dev/null @@ -1,49 +0,0 @@ - - - - - - js-libp2p WebRTC - - - -
-
- - - -
-
- - - -
-
-

Active Connections:

-
    -
    -
    -

    Listening addresses:

    -
      -
      -
      -
      - - - diff --git a/examples/libp2p-in-the-browser/webrtc/browser-to-browser/index.js b/examples/libp2p-in-the-browser/webrtc/browser-to-browser/index.js deleted file mode 100644 index 36edf09efd..0000000000 --- a/examples/libp2p-in-the-browser/webrtc/browser-to-browser/index.js +++ /dev/null @@ -1,133 +0,0 @@ -import { multiaddr, protocols } from "@multiformats/multiaddr" -import { pipe } from "it-pipe" -import { fromString, toString } from "uint8arrays" -import { webRTC } from "@libp2p/webrtc" -import { webSockets } from "@libp2p/websockets" -import * as filters from "@libp2p/websockets/filters" -import { pushable } from "it-pushable" -import { mplex } from "@libp2p/mplex" -import { createLibp2p } from "libp2p" -import { circuitRelayTransport } from 'libp2p/circuit-relay' -import { noise } from "@chainsafe/libp2p-noise" -import { identifyService } from 'libp2p/identify' - -const WEBRTC_CODE = protocols('webrtc').code - -const output = document.getElementById("output") -const sendSection = document.getElementById("send-section") -const appendOutput = (line) => { - const div = document.createElement("div") - div.appendChild(document.createTextNode(line)) - output.append(div) -} -const clean = (line) => line.replaceAll("\n", "") -const sender = pushable() - -const node = await createLibp2p({ - addresses: { - listen: [ - '/webrtc' - ] - }, - transports: [ - webSockets({ - filter: filters.all, - }), - webRTC(), - circuitRelayTransport({ - discoverRelays: 1, - }), - ], - connectionEncryption: [noise()], - streamMuxers: [mplex()], - connectionGater: { - denyDialMultiaddr: () => { - // by default we refuse to dial local addresses from the browser since they - // are usually sent by remote peers broadcasting undialable multiaddrs but - // here we are explicitly connecting to a local node so do not deny dialing - // any discovered address - return false - } - }, - services: { - identify: identifyService() - } -}) - -await node.start() - -// handle the echo protocol -await node.handle("/echo/1.0.0", ({ stream }) => { - pipe( - stream, - async function* (source) { - for await (const buf of source) { - const incoming = toString(buf.subarray()) - appendOutput(`Received message '${clean(incoming)}'`) - yield buf - } - }, - stream - ) -}) - -function updateConnList() { - // Update connections list - const connListEls = node.getConnections() - .map((connection) => { - if (connection.remoteAddr.protoCodes().includes(WEBRTC_CODE)) { - sendSection.style.display = "block" - } - - const el = document.createElement("li") - el.textContent = connection.remoteAddr.toString() - return el - }) - document.getElementById("connections").replaceChildren(...connListEls) -} - -node.addEventListener("connection:open", (event) => { - updateConnList() -}) -node.addEventListener("connection:close", (event) => { - updateConnList() -}) - -node.addEventListener("self:peer:update", (event) => { - // Update multiaddrs list - const multiaddrs = node.getMultiaddrs() - .map((ma) => { - const el = document.createElement("li") - el.textContent = ma.toString() - return el - }) - document.getElementById("multiaddrs").replaceChildren(...multiaddrs) -}) - -const isWebrtc = (ma) => { - return ma.protoCodes().includes(WEBRTC_CODE) -} - -window.connect.onclick = async () => { - const ma = multiaddr(window.peer.value) - appendOutput(`Dialing '${ma}'`) - const connection = await node.dial(ma) - - if (isWebrtc(ma)) { - const outgoing_stream = await connection.newStream(["/echo/1.0.0"]) - pipe(sender, outgoing_stream, async (src) => { - for await (const buf of src) { - const response = toString(buf.subarray()) - appendOutput(`Received message '${clean(response)}'`) - } - }) - } - - appendOutput(`Connected to '${ma}'`) -} - -window.send.onclick = async () => { - const message = `${window.message.value}\n` - appendOutput(`Sending message '${clean(message)}'`) - sender.push(fromString(message)) -} diff --git a/examples/libp2p-in-the-browser/webrtc/browser-to-browser/package.json b/examples/libp2p-in-the-browser/webrtc/browser-to-browser/package.json deleted file mode 100644 index 050ca2ce6a..0000000000 --- a/examples/libp2p-in-the-browser/webrtc/browser-to-browser/package.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "name": "js-libp2p-webrtc-private-to-private", - "version": "1.0.0", - "description": "Connect a browser to another browser", - "type": "module", - "scripts": { - "start": "vite", - "build": "vite build", - "relay": "node relay.js", - "test:firefox": "npm run build && playwright test --browser=firefox tests", - "test:chrome": "npm run build && playwright test tests", - "test": "npm run build && test-browser-example tests" - }, - "dependencies": { - "@chainsafe/libp2p-noise": "^13.0.0", - "@libp2p/websockets": "^6.0.1", - "@libp2p/mplex": "^8.0.1", - "@libp2p/webrtc": "file:../../", - "@multiformats/multiaddr": "^12.0.0", - "it-pushable": "^3.2.0", - "libp2p": "^0.46.0", - "vite": "^4.2.1" - }, - "devDependencies": { - "test-ipfs-example": "^1.0.0" - } -} diff --git a/examples/libp2p-in-the-browser/webrtc/browser-to-browser/relay.js b/examples/libp2p-in-the-browser/webrtc/browser-to-browser/relay.js deleted file mode 100644 index 15754c2bc9..0000000000 --- a/examples/libp2p-in-the-browser/webrtc/browser-to-browser/relay.js +++ /dev/null @@ -1,26 +0,0 @@ -import { mplex } from "@libp2p/mplex" -import { createLibp2p } from "libp2p" -import { noise } from "@chainsafe/libp2p-noise" -import { circuitRelayServer } from 'libp2p/circuit-relay' -import { webSockets } from '@libp2p/websockets' -import * as filters from '@libp2p/websockets/filters' -import { identifyService } from 'libp2p/identify' - -const server = await createLibp2p({ - addresses: { - listen: ['/ip4/127.0.0.1/tcp/0/ws'] - }, - transports: [ - webSockets({ - filter: filters.all - }), - ], - connectionEncryption: [noise()], - streamMuxers: [mplex()], - services: { - identify: identifyService(), - relay: circuitRelayServer() - } -}) - -console.log("p2p addr: ", server.getMultiaddrs().map((ma) => ma.toString())) diff --git a/examples/libp2p-in-the-browser/webrtc/browser-to-browser/tests/test.spec.js b/examples/libp2p-in-the-browser/webrtc/browser-to-browser/tests/test.spec.js deleted file mode 100644 index 703ae688cc..0000000000 --- a/examples/libp2p-in-the-browser/webrtc/browser-to-browser/tests/test.spec.js +++ /dev/null @@ -1,129 +0,0 @@ -/* eslint-disable no-console */ -import { setup, expect } from 'test-ipfs-example/browser' -import { createLibp2p } from 'libp2p' -import { circuitRelayServer } from 'libp2p/circuit-relay' -import { webSockets } from '@libp2p/websockets' -import * as filters from '@libp2p/websockets/filters' -import { mplex } from '@libp2p/mplex' -import { noise } from '@chainsafe/libp2p-noise' -import { identifyService } from 'libp2p/identify' - -// Setup -const test = setup() - -// DOM -const connectBtn = '#connect' -const connectAddr = '#peer' -const messageInput = '#message' -const sendBtn = '#send' -const output = '#output' -const listeningAddresses = '#multiaddrs' - -let url - -// we spawn a js libp2p relay -async function spawnRelay() { - const relayNode = await createLibp2p({ - addresses: { - listen: ['/ip4/127.0.0.1/tcp/0/ws'] - }, - transports: [ - webSockets({ - filter: filters.all - }), - ], - connectionEncryption: [noise()], - streamMuxers: [mplex()], - services: { - identify: identifyService(), - relay: circuitRelayServer() - } - }) - - const relayNodeAddr = relayNode.getMultiaddrs()[0].toString() - - return { relayNode, relayNodeAddr } -} - -test.describe('browser to browser example:', () => { - let relayNode - let relayNodeAddr - - // eslint-disable-next-line no-empty-pattern - test.beforeAll(async ({ servers }, testInfo) => { - testInfo.setTimeout(5 * 60_000) - const r = await spawnRelay() - relayNode = r.relayNode - relayNodeAddr = r.relayNodeAddr - console.log('Server addr:', relayNodeAddr) - url = servers[0].url - }, {}) - - test.afterAll(() => { - relayNode.stop() - }) - - test.beforeEach(async ({ page }) => { - await page.goto(url) - }) - - test('should connect to a relay node', async ({ page: pageA, context }) => { - // load second page - const pageB = await context.newPage() - await pageB.goto(url) - - // connect both pages to the relay - const relayedAddressA = await dialRelay(pageA, relayNodeAddr) - const relayedAddressB = await dialRelay(pageB, relayNodeAddr) - - // dial first page from second page over relay - await dialPeerOverRelay(pageA, relayedAddressB) - await dialPeerOverRelay(pageB, relayedAddressA) - - // stop the relay - await relayNode.stop() - - await echoMessagePeer(pageB, 'hello B') - - await echoMessagePeer(pageA, 'hello A') - }) -}) - -async function echoMessagePeer (page, message) { - // send the message to the peer over webRTC - await page.fill(messageInput, message) - await page.click(sendBtn) - - // check the message was echoed back - const outputLocator = page.locator(output) - await expect(outputLocator).toContainText(`Sending message '${message}'`) - await expect(outputLocator).toContainText(`Received message '${message}'`) -} - -async function dialRelay (page, address) { - // add the go libp2p multiaddress to the input field and submit - await page.fill(connectAddr, address) - await page.click(connectBtn) - - const outputLocator = page.locator(output) - await expect(outputLocator).toContainText(`Dialing '${address}'`) - await expect(outputLocator).toContainText(`Connected to '${address}'`) - - const multiaddrsLocator = page.locator(listeningAddresses) - await expect(multiaddrsLocator).toHaveText(/webrtc/) - - const multiaddrs = await page.textContent(listeningAddresses) - const addr = multiaddrs.split(address).filter(str => str.includes('webrtc')).pop() - - return address + addr -} - -async function dialPeerOverRelay (page, address) { - // add the go libp2p multiaddr to the input field and submit - await page.fill(connectAddr, address) - await page.click(connectBtn) - - const outputLocator = page.locator(output) - await expect(outputLocator).toContainText(`Dialing '${address}'`) - await expect(outputLocator).toContainText(`Connected to '${address}'`) -} diff --git a/examples/libp2p-in-the-browser/webrtc/browser-to-browser/vite.config.js b/examples/libp2p-in-the-browser/webrtc/browser-to-browser/vite.config.js deleted file mode 100644 index 353f32b6ef..0000000000 --- a/examples/libp2p-in-the-browser/webrtc/browser-to-browser/vite.config.js +++ /dev/null @@ -1,11 +0,0 @@ -export default { - build: { - target: 'es2022' - }, - optimizeDeps: { - esbuildOptions: { target: 'es2022', supported: { bigint: true } } - }, - server: { - open: true - } -} \ No newline at end of file diff --git a/examples/libp2p-in-the-browser/webrtc/browser-to-server/README.md b/examples/libp2p-in-the-browser/webrtc/browser-to-server/README.md deleted file mode 100644 index fb3d997503..0000000000 --- a/examples/libp2p-in-the-browser/webrtc/browser-to-server/README.md +++ /dev/null @@ -1,34 +0,0 @@ -# js-libp2p-webrtc Browser to Server - -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. - -## Running the Go Server - -To run the Go LibP2P WebRTC server: - -```shell -npm run go-libp2p-server -``` - -Copy the multiaddress in the output. - -## Running the Example - -In a separate console tab, install dependencies and start the Vite server: - -```shell -npm i && npm run start -``` - -The browser window will automatically open. -Using the copied multiaddress from the Go server, paste it into the `Server MultiAddress` input and click the `Connect` button. -Once the peer is connected, click the message section will appear. Enter a message and click the `Send` button. - -The output should look like: - -```text -Dialing /ip4/10.0.1.5/udp/54375/webrtc/certhash/uEiADy8JubdWrAzseyzfXFyCpdRN02eWZg86tjCrTCA5dbQ/p2p/12D3KooWEG7N4bnZfFBNZE7WG6xm2P4Sr6sonMwyD4HCAqApEthb -Peer connected '/ip4/10.0.1.5/udp/54375/webrtc/certhash/uEiADy8JubdWrAzseyzfXFyCpdRN02eWZg86tjCrTCA5dbQ/p2p/12D3KooWEG7N4bnZfFBNZE7WG6xm2P4Sr6sonMwyD4HCAqApEthb' -Sending message 'hello' -Received message 'hello' -``` \ No newline at end of file diff --git a/examples/libp2p-in-the-browser/webrtc/browser-to-server/index.html b/examples/libp2p-in-the-browser/webrtc/browser-to-server/index.html deleted file mode 100644 index 24ff11f5bd..0000000000 --- a/examples/libp2p-in-the-browser/webrtc/browser-to-server/index.html +++ /dev/null @@ -1,41 +0,0 @@ - - - - - - js-libp2p WebRTC - - - -
      -
      - - - -
      -
      - - - -
      -
      -
      - - - diff --git a/examples/libp2p-in-the-browser/webrtc/browser-to-server/index.js b/examples/libp2p-in-the-browser/webrtc/browser-to-server/index.js deleted file mode 100644 index 5b9c14d03c..0000000000 --- a/examples/libp2p-in-the-browser/webrtc/browser-to-server/index.js +++ /dev/null @@ -1,62 +0,0 @@ -import { createLibp2p } from 'libp2p' -import { noise } from '@chainsafe/libp2p-noise' -import { multiaddr } from '@multiformats/multiaddr' -import { pipe } from "it-pipe"; -import { fromString, toString } from "uint8arrays"; -import { webRTCDirect } from '@libp2p/webrtc' -import { pushable } from 'it-pushable'; - -let stream; -const output = document.getElementById('output') -const sendSection = document.getElementById('send-section') -const appendOutput = (line) => { - const div = document.createElement("div") - div.appendChild(document.createTextNode(line)) - output.append(div) -} -const clean = (line) => line.replaceAll('\n', '') -const sender = pushable() - -const node = await createLibp2p({ - transports: [webRTCDirect()], - connectionEncryption: [noise()], - connectionGater: { - denyDialMultiaddr: () => { - // by default we refuse to dial local addresses from the browser since they - // are usually sent by remote peers broadcasting undialable multiaddrs but - // here we are explicitly connecting to a local node so do not deny dialing - // any discovered address - return false - } - } -}); - -await node.start() - -node.addEventListener('peer:connect', (connection) => { - appendOutput(`Peer connected '${node.getConnections().map(c => c.remoteAddr.toString())}'`) - sendSection.style.display = 'block' -}) - -window.connect.onclick = async () => { - // TODO!!(ckousik): hack until webrtc is renamed in Go. Remove once - // complete - let candidateMa = window.peer.value - candidateMa = candidateMa.replace(/\/webrtc\/certhash/, "/webrtc-direct/certhash") - const ma = multiaddr(candidateMa) - - appendOutput(`Dialing '${ma}'`) - stream = await node.dialProtocol(ma, ['/echo/1.0.0']) - pipe(sender, stream, async (src) => { - for await(const buf of src) { - const response = toString(buf.subarray()) - appendOutput(`Received message '${clean(response)}'`) - } - }) -} - -window.send.onclick = async () => { - const message = `${window.message.value}\n` - appendOutput(`Sending message '${clean(message)}'`) - sender.push(fromString(message)) -} diff --git a/examples/libp2p-in-the-browser/webrtc/browser-to-server/package.json b/examples/libp2p-in-the-browser/webrtc/browser-to-server/package.json deleted file mode 100644 index 7abaa793c5..0000000000 --- a/examples/libp2p-in-the-browser/webrtc/browser-to-server/package.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "name": "js-libp2p-webrtc-browser-to-server", - "version": "1.0.0", - "description": "Connect a browser to a server", - "type": "module", - "scripts": { - "start": "vite", - "build": "vite build", - "go-libp2p-server": "cd ../go-libp2p-server && go run ./main.go", - "test:chrome": "npm run build && playwright test tests", - "test:firefox": "npm run build && playwright test --browser firefox tests", - "test": "npm run build && test-browser-example tests" - }, - "dependencies": { - "@chainsafe/libp2p-noise": "^13.0.0", - "@libp2p/webrtc": "file:../../", - "@multiformats/multiaddr": "^12.0.0", - "it-pushable": "^3.2.0", - "libp2p": "^0.46.0", - "vite": "^4.2.1" - }, - "devDependencies": { - "test-ipfs-example": "^1.0.0" - } -} diff --git a/examples/libp2p-in-the-browser/webrtc/browser-to-server/tests/test.spec.js b/examples/libp2p-in-the-browser/webrtc/browser-to-server/tests/test.spec.js deleted file mode 100644 index dcdd25d348..0000000000 --- a/examples/libp2p-in-the-browser/webrtc/browser-to-server/tests/test.spec.js +++ /dev/null @@ -1,94 +0,0 @@ -/* eslint-disable no-console */ -import { setup, expect } from 'test-ipfs-example/browser' -import { spawn, exec } from 'child_process' -import { existsSync } from 'fs' - -// Setup -const test = setup() - -async function spawnGoLibp2p() { - if (!existsSync('../../examples/go-libp2p-server/go-libp2p-server')) { - await new Promise((resolve, reject) => { - exec('go build', - { cwd: '../../examples/go-libp2p-server' }, - (error, stdout, stderr) => { - if (error) { - throw (`exec error: ${error}`) - } - resolve() - }) - }) - } - - const server = spawn('./go-libp2p-server', [], { cwd: '../../examples/go-libp2p-server', killSignal: 'SIGINT' }) - server.stderr.on('data', (data) => { - console.log(`stderr: ${data}`, typeof data) - }) - const serverAddr = await (new Promise(resolve => { - server.stdout.on('data', (data) => { - console.log(`stdout: ${data}`, typeof data) - const addr = String(data).match(/p2p addr: ([^\s]*)/) - if (addr !== null && addr.length > 0) { - resolve(addr[1]) - } - }) - })) - return { server, serverAddr } -} - -test.describe('bundle ipfs with parceljs:', () => { - // DOM - const connectBtn = '#connect' - const connectAddr = '#peer' - const messageInput = '#message' - const sendBtn = '#send' - const output = '#output' - - let server - let serverAddr - - // eslint-disable-next-line no-empty-pattern - test.beforeAll(async ({ }, testInfo) => { - testInfo.setTimeout(5 * 60_000) - const s = await spawnGoLibp2p() - server = s.server - serverAddr = s.serverAddr - console.log('Server addr:', serverAddr) - }, {}) - - test.afterAll(() => { - server.kill('SIGINT') - }) - - test.beforeEach(async ({ servers, page }) => { - await page.goto(servers[0].url) - }) - - test('should connect to a go-libp2p node over webrtc', async ({ page }) => { - const message = 'hello' - - // add the go libp2p multiaddress to the input field and submit - await page.fill(connectAddr, serverAddr) - await page.click(connectBtn) - - // send the relay message to the go libp2p server - await page.fill(messageInput, message) - await page.click(sendBtn) - - await page.waitForSelector('#output:has(div)') - - // Expected output: - // - // Dialing '${serverAddr}' - // Peer connected '${serverAddr}' - // Sending message '${message}' - // Received message '${message}' - const connections = await page.textContent(output) - - expect(connections).toContain(`Dialing '${serverAddr}'`) - expect(connections).toContain(`Peer connected '${serverAddr}'`) - - expect(connections).toContain(`Sending message '${message}'`) - expect(connections).toContain(`Received message '${message}'`) - }) -}) diff --git a/examples/libp2p-in-the-browser/webrtc/browser-to-server/vite.config.js b/examples/libp2p-in-the-browser/webrtc/browser-to-server/vite.config.js deleted file mode 100644 index 9b2e2a7b1f..0000000000 --- a/examples/libp2p-in-the-browser/webrtc/browser-to-server/vite.config.js +++ /dev/null @@ -1,8 +0,0 @@ -export default { - build: { - target: 'es2022' - }, - optimizeDeps: { - esbuildOptions: { target: 'es2022', supported: { bigint: true } } - }, -} \ No newline at end of file diff --git a/examples/libp2p-in-the-browser/webrtc/go-libp2p-server/.gitignore b/examples/libp2p-in-the-browser/webrtc/go-libp2p-server/.gitignore deleted file mode 100644 index baadac2c80..0000000000 --- a/examples/libp2p-in-the-browser/webrtc/go-libp2p-server/.gitignore +++ /dev/null @@ -1 +0,0 @@ -go-libp2p-server \ No newline at end of file diff --git a/examples/libp2p-in-the-browser/webrtc/go-libp2p-server/go.mod b/examples/libp2p-in-the-browser/webrtc/go-libp2p-server/go.mod deleted file mode 100644 index 4df488ec10..0000000000 --- a/examples/libp2p-in-the-browser/webrtc/go-libp2p-server/go.mod +++ /dev/null @@ -1,117 +0,0 @@ -module github.com/libp2p/js-libp2p-webrtc/examples/go-libp2p-server - -go 1.18 - -// TODO: Remove this once webrtc is merged into Go libp2p -replace github.com/libp2p/go-libp2p => github.com/libp2p/go-libp2p v0.26.1-0.20230404184453-257fbfba50c3 - -require github.com/libp2p/go-libp2p v0.26.3 - -require ( - github.com/benbjohnson/clock v1.3.0 // indirect - github.com/beorn7/perks v1.0.1 // indirect - github.com/cespare/xxhash/v2 v2.2.0 // indirect - github.com/containerd/cgroups v1.1.0 // indirect - github.com/coreos/go-systemd/v22 v22.5.0 // indirect - github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c // indirect - github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0 // indirect - github.com/docker/go-units v0.5.0 // indirect - github.com/elastic/gosigar v0.14.2 // indirect - github.com/flynn/noise v1.0.0 // indirect - github.com/francoispqt/gojay v1.2.13 // indirect - github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 // indirect - github.com/godbus/dbus/v5 v5.1.0 // indirect - github.com/gogo/protobuf v1.3.2 // indirect - github.com/golang/mock v1.6.0 // indirect - github.com/golang/protobuf v1.5.3 // indirect - github.com/google/gopacket v1.1.19 // indirect - github.com/google/pprof v0.0.0-20230309165930-d61513b1440d // indirect - github.com/google/uuid v1.3.0 // indirect - github.com/gorilla/websocket v1.5.0 // indirect - github.com/huin/goupnp v1.1.0 // indirect - github.com/ipfs/go-cid v0.4.1 // indirect - github.com/ipfs/go-log/v2 v2.5.1 // indirect - github.com/jackpal/go-nat-pmp v1.0.2 // indirect - github.com/jbenet/go-temp-err-catcher v0.1.0 // indirect - github.com/klauspost/compress v1.16.3 // indirect - github.com/klauspost/cpuid/v2 v2.2.4 // indirect - github.com/koron/go-ssdp v0.0.4 // indirect - github.com/libp2p/go-buffer-pool v0.1.0 // indirect - github.com/libp2p/go-cidranger v1.1.0 // indirect - github.com/libp2p/go-flow-metrics v0.1.0 // indirect - github.com/libp2p/go-libp2p-asn-util v0.3.0 // indirect - github.com/libp2p/go-msgio v0.3.0 // indirect - github.com/libp2p/go-nat v0.1.0 // indirect - github.com/libp2p/go-netroute v0.2.1 // indirect - github.com/libp2p/go-reuseport v0.2.0 // indirect - github.com/libp2p/go-yamux/v4 v4.0.0 // indirect - github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd // indirect - github.com/mattn/go-isatty v0.0.17 // indirect - github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect - github.com/miekg/dns v1.1.52 // indirect - github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b // indirect - github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc // indirect - github.com/minio/sha256-simd v1.0.0 // indirect - github.com/mr-tron/base58 v1.2.0 // indirect - github.com/multiformats/go-base32 v0.1.0 // indirect - github.com/multiformats/go-base36 v0.2.0 // indirect - github.com/multiformats/go-multiaddr v0.9.0 // indirect - github.com/multiformats/go-multiaddr-dns v0.3.1 // indirect - github.com/multiformats/go-multiaddr-fmt v0.1.0 // indirect - github.com/multiformats/go-multibase v0.2.0 // indirect - github.com/multiformats/go-multicodec v0.8.1 // indirect - github.com/multiformats/go-multihash v0.2.1 // indirect - github.com/multiformats/go-multistream v0.4.1 // indirect - github.com/multiformats/go-varint v0.0.7 // indirect - github.com/onsi/ginkgo/v2 v2.9.1 // indirect - github.com/opencontainers/runtime-spec v1.0.2 // indirect - github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 // indirect - github.com/pion/datachannel v1.5.5 // indirect - github.com/pion/dtls/v2 v2.2.4 // indirect - github.com/pion/ice/v2 v2.2.13 // indirect - github.com/pion/interceptor v0.1.12 // indirect - github.com/pion/logging v0.2.2 // indirect - github.com/pion/mdns v0.0.5 // indirect - github.com/pion/randutil v0.1.0 // indirect - github.com/pion/rtcp v1.2.10 // indirect - github.com/pion/rtp v1.7.13 // indirect - github.com/pion/sctp v1.8.6 // indirect - github.com/pion/sdp/v3 v3.0.6 // indirect - github.com/pion/srtp/v2 v2.0.11 // indirect - github.com/pion/stun v0.4.0 // indirect - github.com/pion/transport v0.14.1 // indirect - github.com/pion/transport/v2 v2.0.0 // indirect - github.com/pion/turn/v2 v2.0.9 // indirect - github.com/pion/udp v0.1.4 // indirect - github.com/pion/webrtc/v3 v3.1.51 // indirect - github.com/pkg/errors v0.9.1 // indirect - github.com/prometheus/client_golang v1.14.0 // indirect - github.com/prometheus/client_model v0.3.0 // indirect - github.com/prometheus/common v0.42.0 // indirect - github.com/prometheus/procfs v0.9.0 // indirect - github.com/quic-go/qpack v0.4.0 // indirect - github.com/quic-go/qtls-go1-19 v0.2.1 // indirect - github.com/quic-go/qtls-go1-20 v0.1.1 // indirect - github.com/quic-go/quic-go v0.33.0 // indirect - github.com/quic-go/webtransport-go v0.5.2 // indirect - github.com/raulk/go-watchdog v1.3.0 // indirect - github.com/rogpeppe/go-internal v1.9.0 // indirect - github.com/spaolacci/murmur3 v1.1.0 // indirect - github.com/stretchr/testify v1.8.2 // indirect - go.uber.org/atomic v1.10.0 // indirect - go.uber.org/dig v1.16.1 // indirect - go.uber.org/fx v1.19.2 // indirect - go.uber.org/multierr v1.10.0 // indirect - go.uber.org/zap v1.24.0 // indirect - golang.org/x/crypto v0.14.0 // indirect - golang.org/x/exp v0.0.0-20230321023759-10a507213a29 // indirect - golang.org/x/mod v0.9.0 // indirect - golang.org/x/net v0.17.0 // indirect - golang.org/x/sync v0.1.0 // indirect - golang.org/x/sys v0.13.0 // indirect - golang.org/x/text v0.13.0 // indirect - golang.org/x/tools v0.7.0 // indirect - google.golang.org/protobuf v1.30.0 // indirect - lukechampine.com/blake3 v1.1.7 // indirect - nhooyr.io/websocket v1.8.7 // indirect -) diff --git a/examples/libp2p-in-the-browser/webrtc/go-libp2p-server/go.sum b/examples/libp2p-in-the-browser/webrtc/go-libp2p-server/go.sum deleted file mode 100644 index e19e647d1d..0000000000 --- a/examples/libp2p-in-the-browser/webrtc/go-libp2p-server/go.sum +++ /dev/null @@ -1,637 +0,0 @@ -cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.31.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.37.0/go.mod h1:TS1dMSSfndXH133OKGwekG838Om/cQT0BUHV3HcBgoo= -dmitri.shuralyov.com/app/changes v0.0.0-20180602232624-0a106ad413e3/go.mod h1:Yl+fi1br7+Rr3LqpNJf1/uxUdtRUV+Tnj0o93V2B9MU= -dmitri.shuralyov.com/html/belt v0.0.0-20180602232347-f7d459c86be0/go.mod h1:JLBrvjyP0v+ecvNYvCpyZgu5/xkfAUhi6wJj28eUfSU= -dmitri.shuralyov.com/service/change v0.0.0-20181023043359-a85b471d5412/go.mod h1:a1inKt/atXimZ4Mv927x+r7UpyzRUf4emIoiiSC2TN4= -dmitri.shuralyov.com/state v0.0.0-20180228185332-28bcc343414c/go.mod h1:0PRwlb0D6DFvNNtx+9ybjezNCa8XF0xaYcETyp6rHWU= -git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg= -github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= -github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= -github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A= -github.com/benbjohnson/clock v1.3.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= -github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= -github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= -github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= -github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBTaaSFSlLx/70C2HPIMNZpVV8+vt/A+FMnYP11g= -github.com/buger/jsonparser v0.0.0-20181115193947-bf1c66bbce23/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s= -github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= -github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/cilium/ebpf v0.2.0/go.mod h1:To2CFviqOWL/M0gIMsvSMlqe7em/l1ALkX1PyjrX2Qs= -github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/containerd/cgroups v0.0.0-20201119153540-4cbc285b3327/go.mod h1:ZJeTFisyysqgcCdecO57Dj79RfL0LNeGiFUqLYQRYLE= -github.com/containerd/cgroups v1.1.0 h1:v8rEWFl6EoqHB+swVNjVoCJE8o3jX7e8nqBGPLaDFBM= -github.com/containerd/cgroups v1.1.0/go.mod h1:6ppBcbh/NOOUU+dMKrykgaBnK9lCIBxHqJDGwsa1mIw= -github.com/coreos/go-systemd v0.0.0-20181012123002-c6f51f82210d/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/coreos/go-systemd/v22 v22.1.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk= -github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs= -github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= -github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= -github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= -github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c h1:pFUpOrbxDR6AkioZ1ySsx5yxlDQZ8stG2b88gTPxgJU= -github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c/go.mod h1:6UhI8N9EjYm1c2odKpFpAYeR8dsBeM7PtzQhRgxRr9U= -github.com/decred/dcrd/crypto/blake256 v1.0.0 h1:/8DMNYp9SGi5f0w7uCm6d6M4OU2rGFK09Y2A4Xv7EE0= -github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0 h1:HbphB4TFFXpv7MNrT52FGrrgVXF1owhMVTHFZIlnvd4= -github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0/go.mod h1:DZGJHZMqrU4JJqFAWUS2UO1+lbSKsdiOoYi9Zzey7Fc= -github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= -github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= -github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= -github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= -github.com/elastic/gosigar v0.12.0/go.mod h1:iXRIGg2tLnu7LBdpqzyQfGDEidKCfWcCMS0WKyPWoMs= -github.com/elastic/gosigar v0.14.2 h1:Dg80n8cr90OZ7x+bAax/QjoW/XqTI11RmA79ZwIm9/4= -github.com/elastic/gosigar v0.14.2/go.mod h1:iXRIGg2tLnu7LBdpqzyQfGDEidKCfWcCMS0WKyPWoMs= -github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= -github.com/flynn/noise v1.0.0 h1:DlTHqmzmvcEiKj+4RYo/imoswx/4r6iBlCMfVtrMXpQ= -github.com/flynn/noise v1.0.0/go.mod h1:xbMo+0i6+IGbYdJhF31t2eR1BIU0CYc12+BNAKwUTag= -github.com/francoispqt/gojay v1.2.13 h1:d2m3sFjloqoIUQU3TsHBgj6qg/BVGlTBeHDUmyJnXKk= -github.com/francoispqt/gojay v1.2.13/go.mod h1:ehT5mTG4ua4581f1++1WLG0vPdaA9HaiDsoyrBGkyDY= -github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= -github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= -github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= -github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= -github.com/gin-gonic/gin v1.6.3 h1:ahKqKTFpO5KTPHxWZjEdPScmYaGtLo8Y4DMHoEsnp14= -github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M= -github.com/gliderlabs/ssh v0.1.1/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= -github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= -github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0= -github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= -github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q= -github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8= -github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD876Lmtgy7VtROAbHHXk8no= -github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA= -github.com/go-playground/validator/v10 v10.2.0 h1:KgJ0snyC2R9VXYN2rneOtQcw5aHQB1Vv0sFl1UcHBOY= -github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI= -github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 h1:p104kn46Q8WdvHunIJ9dAyjPVtrBPhSr3KT2yUst43I= -github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= -github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee h1:s+21KNqlpePfkah2I+gwHF8xmJWRjooY+5248k6m4A0= -github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo= -github.com/gobwas/pool v0.2.0 h1:QEmUOlnSjWtnpRGHF3SauEiOsy82Cup83Vf2LcMlnc8= -github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= -github.com/gobwas/ws v1.0.2 h1:CoAavW/wd/kulfZmSIBt6p24n4j7tHgNVCjsfHVNUbo= -github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM= -github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= -github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= -github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= -github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= -github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= -github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= -github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= -github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E= -github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= -github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= -github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= -github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= -github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= -github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= -github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= -github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= -github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= -github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= -github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= -github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ= -github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= -github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/gopacket v1.1.17/go.mod h1:UdDNZ1OO62aGYVnPhxT1U6aI7ukYtA/kB8vaU0diBUM= -github.com/google/gopacket v1.1.19 h1:ves8RnFZPGiFnTS0uPQStjwru6uO6h+nlr9j6fL7kF8= -github.com/google/gopacket v1.1.19/go.mod h1:iJ8V8n6KS+z2U1A8pUwu8bW5SyEMkXJB8Yo/Vo+TKTo= -github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= -github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20230309165930-d61513b1440d h1:um9/pc7tKMINFfP1eE7Wv6PRGXlcCSJkVajF7KJw3uQ= -github.com/google/pprof v0.0.0-20230309165930-d61513b1440d/go.mod h1:79YE0hCXdHag9sBkw2o+N/YnZtTkXi0UT9Nnixa5eYk= -github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= -github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/googleapis/gax-go v2.0.0+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY= -github.com/googleapis/gax-go/v2 v2.0.3/go.mod h1:LLvjysVCY1JZeum8Z6l8qUty8fiNwE08qbEPm1M08qg= -github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= -github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= -github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= -github.com/grpc-ecosystem/grpc-gateway v1.5.0/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw= -github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= -github.com/huin/goupnp v1.0.0/go.mod h1:n9v9KO1tAxYH82qOn+UTIFQDmx5n1Zxd/ClZDMX7Bnc= -github.com/huin/goupnp v1.1.0 h1:gEe0Dp/lZmPZiDFzJJaOfUpOvv2MKUkoBX8lDrn9vKU= -github.com/huin/goupnp v1.1.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFckNX8= -github.com/huin/goutil v0.0.0-20170803182201-1ca381bf3150/go.mod h1:PpLOETDnJ0o3iZrZfqZzyLl6l7F3c6L1oWn7OICBi6o= -github.com/ipfs/go-cid v0.4.1 h1:A/T3qGvxi4kpKWWcPC/PgbvDA2bjVLO7n4UeVwnbs/s= -github.com/ipfs/go-cid v0.4.1/go.mod h1:uQHwDeX4c6CtyrFwdqyhpNcxVewur1M7l7fNU7LKwZk= -github.com/ipfs/go-detect-race v0.0.1 h1:qX/xay2W3E4Q1U7d9lNs1sU9nvguX0a7319XbyQ6cOk= -github.com/ipfs/go-detect-race v0.0.1/go.mod h1:8BNT7shDZPo99Q74BpGMK+4D8Mn4j46UU0LZ723meps= -github.com/ipfs/go-log/v2 v2.5.1 h1:1XdUzF7048prq4aBjDQQ4SL5RxftpRGdXhNRwKSAlcY= -github.com/ipfs/go-log/v2 v2.5.1/go.mod h1:prSpmC1Gpllc9UYWxDiZDreBYw7zp4Iqp1kOLU9U5UI= -github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus= -github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= -github.com/jbenet/go-temp-err-catcher v0.1.0 h1:zpb3ZH6wIE8Shj2sKS+khgRvf7T7RABoLk/+KKHggpk= -github.com/jbenet/go-temp-err-catcher v0.1.0/go.mod h1:0kJRvmDZXNMIiJirNPEYfhpPwbGVtZVWC34vc5WLsDk= -github.com/jellevandenhooff/dkim v0.0.0-20150330215556-f50fe3d243e1/go.mod h1:E0B/fFc00Y+Rasa88328GlI/XbtyysCtTHZS8h7IrBU= -github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= -github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= -github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= -github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= -github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= -github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/klauspost/compress v1.10.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= -github.com/klauspost/compress v1.16.3 h1:XuJt9zzcnaz6a16/OU53ZjWp/v7/42WcR5t2a0PcNQY= -github.com/klauspost/compress v1.16.3/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= -github.com/klauspost/cpuid/v2 v2.0.4/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= -github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= -github.com/klauspost/cpuid/v2 v2.2.4 h1:acbojRNwl3o09bUq+yDCtZFc1aiwaAAxtcn8YkZXnvk= -github.com/klauspost/cpuid/v2 v2.2.4/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY= -github.com/koron/go-ssdp v0.0.0-20191105050749-2e1c40ed0b5d/go.mod h1:5Ky9EC2xfoUKUor0Hjgi2BJhCSXJfMOFlmyYrVKGQMk= -github.com/koron/go-ssdp v0.0.4 h1:1IDwrghSKYM7yLf7XCzbByg2sJ/JcNOZRXS2jczTwz0= -github.com/koron/go-ssdp v0.0.4/go.mod h1:oDXq+E5IL5q0U8uSBcoAXzTzInwy5lEgC91HoKtbmZk= -github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= -github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= -github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/pty v1.1.3/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= -github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y= -github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= -github.com/libp2p/go-buffer-pool v0.1.0 h1:oK4mSFcQz7cTQIfqbe4MIj9gLW+mnanjyFtc6cdF0Y8= -github.com/libp2p/go-buffer-pool v0.1.0/go.mod h1:N+vh8gMqimBzdKkSMVuydVDq+UV5QTWy5HSiZacSbPg= -github.com/libp2p/go-cidranger v1.1.0 h1:ewPN8EZ0dd1LSnrtuwd4709PXVcITVeuwbag38yPW7c= -github.com/libp2p/go-cidranger v1.1.0/go.mod h1:KWZTfSr+r9qEo9OkI9/SIEeAtw+NNoU0dXIXt15Okic= -github.com/libp2p/go-flow-metrics v0.1.0 h1:0iPhMI8PskQwzh57jB9WxIuIOQ0r+15PChFGkx3Q3WM= -github.com/libp2p/go-flow-metrics v0.1.0/go.mod h1:4Xi8MX8wj5aWNDAZttg6UPmc0ZrnFNsMtpsYUClFtro= -github.com/libp2p/go-libp2p v0.26.1-0.20230404184453-257fbfba50c3 h1:PbtmtrIDY1Us9qeGJdHO1nfp0Jik1KZIP64/KYK43YI= -github.com/libp2p/go-libp2p v0.26.1-0.20230404184453-257fbfba50c3/go.mod h1:PwdLfPiWNhYkb96Wqc2uDFd/+0SGE07/IvjAoFiYG70= -github.com/libp2p/go-libp2p-asn-util v0.3.0 h1:gMDcMyYiZKkocGXDQ5nsUQyquC9+H+iLEQHwOCZ7s8s= -github.com/libp2p/go-libp2p-asn-util v0.3.0/go.mod h1:B1mcOrKUE35Xq/ASTmQ4tN3LNzVVaMNmq2NACuqyB9w= -github.com/libp2p/go-libp2p-testing v0.12.0 h1:EPvBb4kKMWO29qP4mZGyhVzUyR25dvfUIK5WDu6iPUA= -github.com/libp2p/go-msgio v0.3.0 h1:mf3Z8B1xcFN314sWX+2vOTShIE0Mmn2TXn3YCUQGNj0= -github.com/libp2p/go-msgio v0.3.0/go.mod h1:nyRM819GmVaF9LX3l03RMh10QdOroF++NBbxAb0mmDM= -github.com/libp2p/go-nat v0.1.0 h1:MfVsH6DLcpa04Xr+p8hmVRG4juse0s3J8HyNWYHffXg= -github.com/libp2p/go-nat v0.1.0/go.mod h1:X7teVkwRHNInVNWQiO/tAiAVRwSr5zoRz4YSTC3uRBM= -github.com/libp2p/go-netroute v0.1.2/go.mod h1:jZLDV+1PE8y5XxBySEBgbuVAXbhtuHSdmLPL2n9MKbk= -github.com/libp2p/go-netroute v0.2.1 h1:V8kVrpD8GK0Riv15/7VN6RbUQ3URNZVosw7H2v9tksU= -github.com/libp2p/go-netroute v0.2.1/go.mod h1:hraioZr0fhBjG0ZRXJJ6Zj2IVEVNx6tDTFQfSmcq7mQ= -github.com/libp2p/go-reuseport v0.2.0 h1:18PRvIMlpY6ZK85nIAicSBuXXvrYoSw3dsBAR7zc560= -github.com/libp2p/go-reuseport v0.2.0/go.mod h1:bvVho6eLMm6Bz5hmU0LYN3ixd3nPPvtIlaURZZgOY4k= -github.com/libp2p/go-sockaddr v0.0.2/go.mod h1:syPvOmNs24S3dFVGJA1/mrqdeijPxLV2Le3BRLKd68k= -github.com/libp2p/go-yamux/v4 v4.0.0 h1:+Y80dV2Yx/kv7Y7JKu0LECyVdMXm1VUoko+VQ9rBfZQ= -github.com/libp2p/go-yamux/v4 v4.0.0/go.mod h1:NWjl8ZTLOGlozrXSOZ/HlfG++39iKNnM5wwmtQP1YB4= -github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI= -github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd h1:br0buuQ854V8u83wA0rVZ8ttrq5CpaPZdvrK0LP2lOk= -github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd/go.mod h1:QuCEs1Nt24+FYQEqAAncTDPJIuGs+LxK1MCiFL25pMU= -github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= -github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= -github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng= -github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= -github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= -github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= -github.com/microcosm-cc/bluemonday v1.0.1/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00vh2OMYv+xgHpAMF4= -github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI= -github.com/miekg/dns v1.1.52 h1:Bmlc/qsNNULOe6bpXcUTsuOajd0DzRHwup6D9k1An0c= -github.com/miekg/dns v1.1.52/go.mod h1:uInx36IzPl7FYnDcMeVWxj9byh7DutNykX4G9Sj60FY= -github.com/mikioh/tcp v0.0.0-20190314235350-803a9b46060c h1:bzE/A84HN25pxAuk9Eej1Kz9OUelF97nAc82bDquQI8= -github.com/mikioh/tcp v0.0.0-20190314235350-803a9b46060c/go.mod h1:0SQS9kMwD2VsyFEB++InYyBJroV/FRmBgcydeSUcJms= -github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b h1:z78hV3sbSMAUoyUMM0I83AUIT6Hu17AWfgjzIbtrYFc= -github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b/go.mod h1:lxPUiZwKoFL8DUUmalo2yJJUCxbPKtm8OKfqr2/FTNU= -github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc h1:PTfri+PuQmWDqERdnNMiD9ZejrlswWrCpBEZgWOiTrc= -github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc/go.mod h1:cGKTAVKx4SxOuR/czcZ/E2RSJ3sfHs8FpHhQ5CWMf9s= -github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1/go.mod h1:pD8RvIylQ358TN4wwqatJ8rNavkEINozVn9DtGI3dfQ= -github.com/minio/sha256-simd v0.1.1-0.20190913151208-6de447530771/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM= -github.com/minio/sha256-simd v1.0.0 h1:v1ta+49hkWZyvaKwrQB8elexRqm6Y0aMLjCNsrYxo6g= -github.com/minio/sha256-simd v1.0.0/go.mod h1:OuYzVNI5vcoYIAmbIvHPl3N3jUzVedXbKy5RFepssQM= -github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= -github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= -github.com/mr-tron/base58 v1.1.2/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= -github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o= -github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= -github.com/multiformats/go-base32 v0.1.0 h1:pVx9xoSPqEIQG8o+UbAe7DNi51oej1NtK+aGkbLYxPE= -github.com/multiformats/go-base32 v0.1.0/go.mod h1:Kj3tFY6zNr+ABYMqeUNeGvkIC/UYgtWibDcT0rExnbI= -github.com/multiformats/go-base36 v0.2.0 h1:lFsAbNOGeKtuKozrtBsAkSVhv1p9D0/qedU9rQyccr0= -github.com/multiformats/go-base36 v0.2.0/go.mod h1:qvnKE++v+2MWCfePClUEjE78Z7P2a1UV0xHgWc0hkp4= -github.com/multiformats/go-multiaddr v0.1.1/go.mod h1:aMKBKNEYmzmDmxfX88/vz+J5IU55txyt0p4aiWVohjo= -github.com/multiformats/go-multiaddr v0.2.0/go.mod h1:0nO36NvPpyV4QzvTLi/lafl2y95ncPj0vFwVF6k6wJ4= -github.com/multiformats/go-multiaddr v0.9.0 h1:3h4V1LHIk5w4hJHekMKWALPXErDfz/sggzwC/NcqbDQ= -github.com/multiformats/go-multiaddr v0.9.0/go.mod h1:mI67Lb1EeTOYb8GQfL/7wpIZwc46ElrvzhYnoJOmTT0= -github.com/multiformats/go-multiaddr-dns v0.3.1 h1:QgQgR+LQVt3NPTjbrLLpsaT2ufAA2y0Mkk+QRVJbW3A= -github.com/multiformats/go-multiaddr-dns v0.3.1/go.mod h1:G/245BRQ6FJGmryJCrOuTdB37AMA5AMOVuO6NY3JwTk= -github.com/multiformats/go-multiaddr-fmt v0.1.0 h1:WLEFClPycPkp4fnIzoFoV9FVd49/eQsuaL3/CWe167E= -github.com/multiformats/go-multiaddr-fmt v0.1.0/go.mod h1:hGtDIW4PU4BqJ50gW2quDuPVjyWNZxToGUh/HwTZYJo= -github.com/multiformats/go-multibase v0.2.0 h1:isdYCVLvksgWlMW9OZRYJEa9pZETFivncJHmHnnd87g= -github.com/multiformats/go-multibase v0.2.0/go.mod h1:bFBZX4lKCA/2lyOFSAoKH5SS6oPyjtnzK/XTFDPkNuk= -github.com/multiformats/go-multicodec v0.8.1 h1:ycepHwavHafh3grIbR1jIXnKCsFm0fqsfEOsJ8NtKE8= -github.com/multiformats/go-multicodec v0.8.1/go.mod h1:L3QTQvMIaVBkXOXXtVmYE+LI16i14xuaojr/H7Ai54k= -github.com/multiformats/go-multihash v0.0.8/go.mod h1:YSLudS+Pi8NHE7o6tb3D8vrpKa63epEDmG8nTduyAew= -github.com/multiformats/go-multihash v0.2.1 h1:aem8ZT0VA2nCHHk7bPJ1BjUbHNciqZC/d16Vve9l108= -github.com/multiformats/go-multihash v0.2.1/go.mod h1:WxoMcYG85AZVQUyRyo9s4wULvW5qrI9vb2Lt6evduFc= -github.com/multiformats/go-multistream v0.4.1 h1:rFy0Iiyn3YT0asivDUIR05leAdwZq3de4741sbiSdfo= -github.com/multiformats/go-multistream v0.4.1/go.mod h1:Mz5eykRVAjJWckE2U78c6xqdtyNUEhKSM0Lwar2p77Q= -github.com/multiformats/go-varint v0.0.1/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE= -github.com/multiformats/go-varint v0.0.7 h1:sWSGR+f/eu5ABZA2ZpYKBILXTTs9JWpdEM/nEGOHFS8= -github.com/multiformats/go-varint v0.0.7/go.mod h1:r8PUYw/fD/SjBCiKOoDlGF6QawOELpZAu9eioSos/OU= -github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo= -github.com/neelance/sourcemap v0.0.0-20151028013722-8c68805598ab/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM= -github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= -github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= -github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= -github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= -github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= -github.com/onsi/ginkgo/v2 v2.9.1 h1:zie5Ly042PD3bsCvsSOPvRnFwyo3rKe64TJlD6nu0mk= -github.com/onsi/ginkgo/v2 v2.9.1/go.mod h1:FEcmzVcCHl+4o9bQZVab+4dC9+j+91t2FHSzmGAPfuo= -github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= -github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= -github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= -github.com/onsi/gomega v1.27.3 h1:5VwIwnBY3vbBDOJrNtA4rVdiTZCsq9B5F12pvy1Drmk= -github.com/opencontainers/runtime-spec v1.0.2 h1:UfAcuLBJB9Coz72x1hgl8O5RVzTdNiaglX6v2DM6FI0= -github.com/opencontainers/runtime-spec v1.0.2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= -github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8= -github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 h1:onHthvaw9LFnH4t2DcNVpwGmV9E1BkGknEliJkfwQj0= -github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58/go.mod h1:DXv8WO4yhMYhSNPKjeNKa5WY9YCIEBRbNzFFPJbWO6Y= -github.com/pion/datachannel v1.5.5 h1:10ef4kwdjije+M9d7Xm9im2Y3O6A6ccQb0zcqZcJew8= -github.com/pion/datachannel v1.5.5/go.mod h1:iMz+lECmfdCMqFRhXhcA/219B0SQlbpoR2V118yimL0= -github.com/pion/dtls/v2 v2.1.5/go.mod h1:BqCE7xPZbPSubGasRoDFJeTsyJtdD1FanJYL0JGheqY= -github.com/pion/dtls/v2 v2.2.4 h1:YSfYwDQgrxMYXLBc/m7PFY5BVtWlNm/DN4qoU2CbcWg= -github.com/pion/dtls/v2 v2.2.4/go.mod h1:WGKfxqhrddne4Kg3p11FUMJrynkOY4lb25zHNO49wuw= -github.com/pion/ice/v2 v2.2.13 h1:NvLtzwcyob6wXgFqLmVQbGB3s9zzWmOegNMKYig5l9M= -github.com/pion/ice/v2 v2.2.13/go.mod h1:eFO4/1zCI+a3OFVt7l7kP+5jWCuZo8FwU2UwEa3+164= -github.com/pion/interceptor v0.1.11/go.mod h1:tbtKjZY14awXd7Bq0mmWvgtHB5MDaRN7HV3OZ/uy7s8= -github.com/pion/interceptor v0.1.12 h1:CslaNriCFUItiXS5o+hh5lpL0t0ytQkFnUcbbCs2Zq8= -github.com/pion/interceptor v0.1.12/go.mod h1:bDtgAD9dRkBZpWHGKaoKb42FhDHTG2rX8Ii9LRALLVA= -github.com/pion/logging v0.2.2 h1:M9+AIj/+pxNsDfAT64+MAVgJO0rsyLnoJKCqf//DoeY= -github.com/pion/logging v0.2.2/go.mod h1:k0/tDVsRCX2Mb2ZEmTqNa7CWsQPc+YYCB7Q+5pahoms= -github.com/pion/mdns v0.0.5 h1:Q2oj/JB3NqfzY9xGZ1fPzZzK7sDSD8rZPOvcIQ10BCw= -github.com/pion/mdns v0.0.5/go.mod h1:UgssrvdD3mxpi8tMxAXbsppL3vJ4Jipw1mTCW+al01g= -github.com/pion/randutil v0.1.0 h1:CFG1UdESneORglEsnimhUjf33Rwjubwj6xfiOXBa3mA= -github.com/pion/randutil v0.1.0/go.mod h1:XcJrSMMbbMRhASFVOlj/5hQial/Y8oH/HVo7TBZq+j8= -github.com/pion/rtcp v1.2.9/go.mod h1:qVPhiCzAm4D/rxb6XzKeyZiQK69yJpbUDJSF7TgrqNo= -github.com/pion/rtcp v1.2.10 h1:nkr3uj+8Sp97zyItdN60tE/S6vk4al5CPRR6Gejsdjc= -github.com/pion/rtcp v1.2.10/go.mod h1:ztfEwXZNLGyF1oQDttz/ZKIBaeeg/oWbRYqzBM9TL1I= -github.com/pion/rtp v1.7.13 h1:qcHwlmtiI50t1XivvoawdCGTP4Uiypzfrsap+bijcoA= -github.com/pion/rtp v1.7.13/go.mod h1:bDb5n+BFZxXx0Ea7E5qe+klMuqiBrP+w8XSjiWtCUko= -github.com/pion/sctp v1.8.5/go.mod h1:SUFFfDpViyKejTAdwD1d/HQsCu+V/40cCs2nZIvC3s0= -github.com/pion/sctp v1.8.6 h1:CUex11Vkt9YS++VhLf8b55O3VqKrWL6W3SDwX4jAqsI= -github.com/pion/sctp v1.8.6/go.mod h1:SUFFfDpViyKejTAdwD1d/HQsCu+V/40cCs2nZIvC3s0= -github.com/pion/sdp/v3 v3.0.6 h1:WuDLhtuFUUVpTfus9ILC4HRyHsW6TdugjEX/QY9OiUw= -github.com/pion/sdp/v3 v3.0.6/go.mod h1:iiFWFpQO8Fy3S5ldclBkpXqmWy02ns78NOKoLLL0YQw= -github.com/pion/srtp/v2 v2.0.11 h1:6cEEgT1oCLWgE+BynbfaSMAxtsqU0M096x9dNH6olY0= -github.com/pion/srtp/v2 v2.0.11/go.mod h1:vzHprzbuVoYJ9NfaRMycnFrkHcLSaLVuBZDOtFQNZjY= -github.com/pion/stun v0.3.5/go.mod h1:gDMim+47EeEtfWogA37n6qXZS88L5V6LqFcf+DZA2UA= -github.com/pion/stun v0.4.0 h1:vgRrbBE2htWHy7l3Zsxckk7rkjnjOsSM7PHZnBwo8rk= -github.com/pion/stun v0.4.0/go.mod h1:QPsh1/SbXASntw3zkkrIk3ZJVKz4saBY2G7S10P3wCw= -github.com/pion/transport v0.12.2/go.mod h1:N3+vZQD9HlDP5GWkZ85LohxNsDcNgofQmyL6ojX5d8Q= -github.com/pion/transport v0.13.0/go.mod h1:yxm9uXpK9bpBBWkITk13cLo1y5/ur5VQpG22ny6EP7g= -github.com/pion/transport v0.13.1/go.mod h1:EBxbqzyv+ZrmDb82XswEE0BjfQFtuw1Nu6sjnjWCsGg= -github.com/pion/transport v0.14.1 h1:XSM6olwW+o8J4SCmOBb/BpwZypkHeyM0PGFCxNQBr40= -github.com/pion/transport v0.14.1/go.mod h1:4tGmbk00NeYA3rUa9+n+dzCCoKkcy3YlYb99Jn2fNnI= -github.com/pion/transport/v2 v2.0.0 h1:bsMYyqHCbkvHwj+eNCFBuxtlKndKfyGI2vaQmM3fIE4= -github.com/pion/transport/v2 v2.0.0/go.mod h1:HS2MEBJTwD+1ZI2eSXSvHJx/HnzQqRy2/LXxt6eVMHc= -github.com/pion/turn/v2 v2.0.9 h1:jcDPw0Vfd5I4iTc7s0Upfc2aMnyu2lgJ9vV0SUrNC1o= -github.com/pion/turn/v2 v2.0.9/go.mod h1:DQlwUwx7hL8Xya6TTAabbd9DdKXTNR96Xf5g5Qqso/M= -github.com/pion/udp v0.1.1/go.mod h1:6AFo+CMdKQm7UiA0eUPA8/eVCTx8jBIITLZHc9DWX5M= -github.com/pion/udp v0.1.4 h1:OowsTmu1Od3sD6i3fQUJxJn2fEvJO6L1TidgadtbTI8= -github.com/pion/udp v0.1.4/go.mod h1:G8LDo56HsFwC24LIcnT4YIDU5qcB6NepqqjP0keL2us= -github.com/pion/webrtc/v3 v3.1.51 h1:uU9vHdY63O3uRFJiDskH0qFJ+219bAH28qOt5csSWcM= -github.com/pion/webrtc/v3 v3.1.51/go.mod h1:sbRNshM9l0zRDQgZRP9K5RTzlsdBmqmyO8KbxngG8jQ= -github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= -github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/prometheus/client_golang v0.8.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= -github.com/prometheus/client_golang v1.14.0 h1:nJdhIvne2eSX/XRAFV9PcvFFRbrjbcTUj0VP62TMhnw= -github.com/prometheus/client_golang v1.14.0/go.mod h1:8vpkKitgIVNcqrRBWh1C4TIUQgYNtG/XQE4E/Zae36Y= -github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= -github.com/prometheus/client_model v0.3.0 h1:UBgGFHqYdG/TPFD1B1ogZywDqEkwp3fBMvqdiQ7Xew4= -github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w= -github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= -github.com/prometheus/common v0.42.0 h1:EKsfXEYo4JpWMHH5cg+KOUWeuJSov1Id8zGR8eeI1YM= -github.com/prometheus/common v0.42.0/go.mod h1:xBwqVerjNdUDjgODMpudtOMwlOwf2SaTr1yjz4b7Zbc= -github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.9.0 h1:wzCHvIvM5SxWqYvwgVL7yJY8Lz3PKn49KQtpgMYJfhI= -github.com/prometheus/procfs v0.9.0/go.mod h1:+pB4zwohETzFnmlpe6yd2lSc+0/46IYZRB/chUwxUZY= -github.com/quic-go/qpack v0.4.0 h1:Cr9BXA1sQS2SmDUWjSofMPNKmvF6IiIfDRmgU0w1ZCo= -github.com/quic-go/qpack v0.4.0/go.mod h1:UZVnYIfi5GRk+zI9UMaCPsmZ2xKJP7XBUvVyT1Knj9A= -github.com/quic-go/qtls-go1-19 v0.2.1 h1:aJcKNMkH5ASEJB9FXNeZCyTEIHU1J7MmHyz1Q1TSG1A= -github.com/quic-go/qtls-go1-19 v0.2.1/go.mod h1:ySOI96ew8lnoKPtSqx2BlI5wCpUVPT05RMAlajtnyOI= -github.com/quic-go/qtls-go1-20 v0.1.1 h1:KbChDlg82d3IHqaj2bn6GfKRj84Per2VGf5XV3wSwQk= -github.com/quic-go/qtls-go1-20 v0.1.1/go.mod h1:JKtK6mjbAVcUTN/9jZpvLbGxvdWIKS8uT7EiStoU1SM= -github.com/quic-go/quic-go v0.33.0 h1:ItNoTDN/Fm/zBlq769lLJc8ECe9gYaW40veHCCco7y0= -github.com/quic-go/quic-go v0.33.0/go.mod h1:YMuhaAV9/jIu0XclDXwZPAsP/2Kgr5yMYhe9oxhhOFA= -github.com/quic-go/webtransport-go v0.5.2 h1:GA6Bl6oZY+g/flt00Pnu0XtivSD8vukOu3lYhJjnGEk= -github.com/quic-go/webtransport-go v0.5.2/go.mod h1:OhmmgJIzTTqXK5xvtuX0oBpLV2GkLWNDA+UeTGJXErU= -github.com/raulk/go-watchdog v1.3.0 h1:oUmdlHxdkXRJlwfG0O9omj8ukerm8MEQavSiDTEtBsk= -github.com/raulk/go-watchdog v1.3.0/go.mod h1:fIvOnLbF0b0ZwkB9YU4mOW9Did//4vPZtDqv66NfsMU= -github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= -github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= -github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= -github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/sclevine/agouti v3.0.0+incompatible/go.mod h1:b4WX9W9L1sfQKXeJf1mUTLZKJ48R1S7H23Ji7oFO5Bw= -github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= -github.com/shurcooL/component v0.0.0-20170202220835-f88ec8f54cc4/go.mod h1:XhFIlyj5a1fBNx5aJTbKoIq0mNaPvOagO+HjB3EtxrY= -github.com/shurcooL/events v0.0.0-20181021180414-410e4ca65f48/go.mod h1:5u70Mqkb5O5cxEA8nxTsgrgLehJeAw6Oc4Ab1c/P1HM= -github.com/shurcooL/github_flavored_markdown v0.0.0-20181002035957-2122de532470/go.mod h1:2dOwnU2uBioM+SGy2aZoq1f/Sd1l9OkAeAUvjSyvgU0= -github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk= -github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041/go.mod h1:N5mDOmsrJOB+vfqUK+7DmDyjhSLIIBnXo9lvZJj3MWQ= -github.com/shurcooL/gofontwoff v0.0.0-20180329035133-29b52fc0a18d/go.mod h1:05UtEgK5zq39gLST6uB0cf3NEHjETfB4Fgr3Gx5R9Vw= -github.com/shurcooL/gopherjslib v0.0.0-20160914041154-feb6d3990c2c/go.mod h1:8d3azKNyqcHP1GaQE/c6dDgjkgSx2BZ4IoEi4F1reUI= -github.com/shurcooL/highlight_diff v0.0.0-20170515013008-09bb4053de1b/go.mod h1:ZpfEhSmds4ytuByIcDnOLkTHGUI6KNqRNPDLHDk+mUU= -github.com/shurcooL/highlight_go v0.0.0-20181028180052-98c3abbbae20/go.mod h1:UDKB5a1T23gOMUJrI+uSuH0VRDStOiUVSjBTRDVBVag= -github.com/shurcooL/home v0.0.0-20181020052607-80b7ffcb30f9/go.mod h1:+rgNQw2P9ARFAs37qieuu7ohDNQ3gds9msbT2yn85sg= -github.com/shurcooL/htmlg v0.0.0-20170918183704-d01228ac9e50/go.mod h1:zPn1wHpTIePGnXSHpsVPWEktKXHr6+SS6x/IKRb7cpw= -github.com/shurcooL/httperror v0.0.0-20170206035902-86b7830d14cc/go.mod h1:aYMfkZ6DWSJPJ6c4Wwz3QtW22G7mf/PEgaB9k/ik5+Y= -github.com/shurcooL/httpfs v0.0.0-20171119174359-809beceb2371/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg= -github.com/shurcooL/httpgzip v0.0.0-20180522190206-b1c53ac65af9/go.mod h1:919LwcH0M7/W4fcZ0/jy0qGght1GIhqyS/EgWGH2j5Q= -github.com/shurcooL/issues v0.0.0-20181008053335-6292fdc1e191/go.mod h1:e2qWDig5bLteJ4fwvDAc2NHzqFEthkqn7aOZAOpj+PQ= -github.com/shurcooL/issuesapp v0.0.0-20180602232740-048589ce2241/go.mod h1:NPpHK2TI7iSaM0buivtFUc9offApnI0Alt/K8hcHy0I= -github.com/shurcooL/notifications v0.0.0-20181007000457-627ab5aea122/go.mod h1:b5uSkrEVM1jQUspwbixRBhaIjIzL2xazXp6kntxYle0= -github.com/shurcooL/octicon v0.0.0-20181028054416-fa4f57f9efb2/go.mod h1:eWdoE5JD4R5UVWDucdOPg1g2fqQRq78IQa9zlOV1vpQ= -github.com/shurcooL/reactions v0.0.0-20181006231557-f2e0b4ca5b82/go.mod h1:TCR1lToEk4d2s07G3XGfz2QrgHXg4RJBvjrOozvoWfk= -github.com/shurcooL/sanitized_anchor_name v0.0.0-20170918181015-86672fcb3f95/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= -github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= -github.com/shurcooL/users v0.0.0-20180125191416-49c67e49c537/go.mod h1:QJTqeLYEDaXHZDBsXlPCDqdhQuJkuw4NOtaxYe3xii4= -github.com/shurcooL/webdavfs v0.0.0-20170829043945-18c3829fa133/go.mod h1:hKmq5kWdCj2z2KEozexVbfEZIWiTjhE0+UjmZgPqehw= -github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= -github.com/sourcegraph/annotate v0.0.0-20160123013949-f4cad6c6324d/go.mod h1:UdhH50NIW0fCiwBSr0co2m7BnFLdv4fQTgdqdJTHFeE= -github.com/sourcegraph/syntaxhighlight v0.0.0-20170531221838-bd320f5d308e/go.mod h1:HuIsMU8RRBOtsCgI77wP899iHVBQpCmg4ErYMZB+2IA= -github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= -github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= -github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= -github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= -github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA= -github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo= -github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= -github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs= -github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= -github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= -github.com/viant/assertly v0.4.8/go.mod h1:aGifi++jvCrUaklKEKT0BU95igDNaqkvz+49uaYMPRU= -github.com/viant/toolbox v0.24.0/go.mod h1:OxMCG57V0PXuIP2HNQrtJf2CjqdmbrOx5EkMILuUhzM= -github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= -github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= -go.opencensus.io v0.18.0/go.mod h1:vKdFvxhtzZ9onBp9VKHK8z/sRpBMnKAsufL7wlDrCOA= -go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= -go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ= -go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= -go.uber.org/dig v1.16.1 h1:+alNIBsl0qfY0j6epRubp/9obgtrObRAc5aD+6jbWY8= -go.uber.org/dig v1.16.1/go.mod h1:557JTAUZT5bUK0SvCwikmLPPtdQhfvLYtO5tJgQSbnk= -go.uber.org/fx v1.19.2 h1:SyFgYQFr1Wl0AYstE8vyYIzP4bFz2URrScjwC4cwUvY= -go.uber.org/fx v1.19.2/go.mod h1:43G1VcqSzbIv77y00p1DRAsyZS8WdzuYdhZXmEUkMyQ= -go.uber.org/goleak v1.1.11-0.20210813005559-691160354723/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= -go.uber.org/goleak v1.1.12 h1:gZAh5/EyT/HQwlpkCy6wTpqfH9H8Lz8zbm3dZh+OyzA= -go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= -go.uber.org/multierr v1.10.0 h1:S0h4aNzvfcFsC3dRF1jLoaov7oRaKqRGC/pUEJ2yvPQ= -go.uber.org/multierr v1.10.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= -go.uber.org/zap v1.19.1/go.mod h1:j3DNczoxDZroyBnOT1L/Q79cfUMGZxlv/9dzN7SM1rI= -go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60= -go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg= -go4.org v0.0.0-20180809161055-417644f6feb5/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE= -golang.org/x/build v0.0.0-20190111050920-041ab4dc3f9d/go.mod h1:OWs+y06UdEOHN4y+MfF/py+xQ/tYqIWW03b70/CG9Rw= -golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20200602180216-279210d13fed/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= -golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20220427172511-eb4f295cb31f/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.0.0-20221010152910-d6f0a8c073c2/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.5.0/go.mod h1:NK/OQwhpMQP3MwtdjgLlYHnH9ebylxKWv3e0fK+mkQU= -golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc= -golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= -golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20230321023759-10a507213a29 h1:ooxPy7fPvB4kwsA2h+iBNHkAbp/4JxTSwCmvdjEYmug= -golang.org/x/exp v0.0.0-20230321023759-10a507213a29/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= -golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= -golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= -golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.9.0 h1:KENHtAZL2y3NLMYZeHY9DW8HW8V+kQyJsY/V9JlKvCs= -golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181011144130-49bb7cea24b1/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181029044818-c44066c5c816/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181106065722-10aee1819953/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190313220215-9f648a60d977/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201201195509-5d6afe98e0b7/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= -golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= -golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20211201190559-0a0e4e1bb54c/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220531201128-c960675eff93/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= -golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= -golang.org/x/net v0.4.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE= -golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws= -golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= -golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= -golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/perf v0.0.0-20180704124530-6e6d33e29852/go.mod h1:JLpeXjPJfIyPr5TlbXLkXWLhP8nz10XfvxElABhCtcw= -golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= -golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20180810173357-98c5dad5d1a0/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181029174526-d69651ed3497/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190228124157-a34e9553db1e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190316082340-a2f829d7f35f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190405154228-4b34438f7a67/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200602225109-6fdc65e7d980/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220608164250-635b8c9b7f68/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= -golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= -golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA= -golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= -golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= -golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= -golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20181030000716-a0a13e073c7b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= -golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.7.0 h1:W4OVu8VVOaIO0yzWMNdepAulS7YfoS3Zabrm8DOXXU4= -golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s= -golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/api v0.0.0-20180910000450-7ca32eb868bf/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= -google.golang.org/api v0.0.0-20181030000543-1d582fd0359e/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= -google.golang.org/api v0.1.0/go.mod h1:UGEZY7KEX120AnNLIHFMKIo4obdJhkp2tPbaPlQx13Y= -google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= -google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20181029155118-b69ba1387ce2/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20181202183823-bd91e49a0898/go.mod h1:7Ep/1NZk928CDR8SjdVbjWNpdIf6nzjE3BTgJDr2Atg= -google.golang.org/genproto v0.0.0-20190306203927-b5d61aea6440/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= -google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio= -google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= -google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= -google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= -google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= -google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= -google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= -google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng= -google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= -gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= -gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= -gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= -gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= -gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= -gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -grpc.go4.org v0.0.0-20170609214715-11d0a25b4919/go.mod h1:77eQGdRu53HpSqPFJFmuJdjuHRquDANNeA4x7B8WQ9o= -honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -lukechampine.com/blake3 v1.1.7 h1:GgRMhmdsuK8+ii6UZFDL8Nb+VyMwadAgcJyfYHxG6n0= -lukechampine.com/blake3 v1.1.7/go.mod h1:tkKEOtDkNtklkXtLNEOGNq5tcV90tJiA1vAA12R78LA= -nhooyr.io/websocket v1.8.7 h1:usjR2uOr/zjjkVMy0lW+PPohFok7PCow5sDjLgX4P4g= -nhooyr.io/websocket v1.8.7/go.mod h1:B70DZP8IakI65RVQ51MsWP/8jndNma26DVA/nFSCgW0= -sourcegraph.com/sourcegraph/go-diff v0.5.0/go.mod h1:kuch7UrkMzY0X+p9CRK03kfuPQ2zzQcaEFbx8wA8rck= -sourcegraph.com/sqs/pbtypes v0.0.0-20180604144634-d3ebe8f20ae4/go.mod h1:ketZ/q3QxT9HOBeFhu6RdvsftgpsbFHBF5Cas6cDKZ0= diff --git a/examples/libp2p-in-the-browser/webrtc/go-libp2p-server/main.go b/examples/libp2p-in-the-browser/webrtc/go-libp2p-server/main.go deleted file mode 100644 index a5f99e6f25..0000000000 --- a/examples/libp2p-in-the-browser/webrtc/go-libp2p-server/main.go +++ /dev/null @@ -1,95 +0,0 @@ -package main - -import ( - "bufio" - "fmt" - "log" - "net" - "os" - "os/signal" - "syscall" - - "github.com/libp2p/go-libp2p" - "github.com/libp2p/go-libp2p/core/host" - "github.com/libp2p/go-libp2p/core/network" - "github.com/libp2p/go-libp2p/core/peer" - webrtc "github.com/libp2p/go-libp2p/p2p/transport/webrtc" -) - -var listenerIp = net.IPv4(127, 0, 0, 1) - -func init() { - ifaces, err := net.Interfaces() - if err != nil { - return - } - for _, iface := range ifaces { - if iface.Flags&net.FlagUp == 0 { - continue - } - addrs, err := iface.Addrs() - if err != nil { - return - } - for _, addr := range addrs { - // bind to private non-loopback ip - if ipnet, ok := addr.(*net.IPNet); ok && !ipnet.IP.IsLoopback() && ipnet.IP.IsPrivate() { - if ipnet.IP.To4() != nil { - listenerIp = ipnet.IP.To4() - return - } - } - } - } -} - -func echoHandler(stream network.Stream) { - for { - reader := bufio.NewReader(stream) - str, err := reader.ReadString('\n') - log.Printf("err: %s", err) - if err != nil { - return - } - log.Printf("echo: %s", str) - _, err = stream.Write([]byte(str)) - if err != nil { - log.Printf("err: %v", err) - return - } - } -} - -func main() { - host := createHost() - host.SetStreamHandler("/echo/1.0.0", echoHandler) - defer host.Close() - remoteInfo := peer.AddrInfo{ - ID: host.ID(), - Addrs: host.Network().ListenAddresses(), - } - - remoteAddrs, _ := peer.AddrInfoToP2pAddrs(&remoteInfo) - fmt.Println("p2p addr: ", remoteAddrs[0]) - - fmt.Println("press Ctrl+C to quit") - ch := make(chan os.Signal, 1) - signal.Notify(ch, syscall.SIGTERM, syscall.SIGINT) - <-ch -} - -func createHost() host.Host { - h, err := libp2p.New( - libp2p.Transport(webrtc.New), - libp2p.ListenAddrStrings( - fmt.Sprintf("/ip4/%s/udp/0/webrtc-direct", listenerIp), - ), - libp2p.DisableRelay(), - libp2p.Ping(true), - ) - if err != nil { - panic(err) - } - - return h -} diff --git a/examples/libp2p-in-the-browser/websockets/LICENSE b/examples/libp2p-in-the-browser/websockets/LICENSE deleted file mode 100644 index 20ce483c86..0000000000 --- a/examples/libp2p-in-the-browser/websockets/LICENSE +++ /dev/null @@ -1,4 +0,0 @@ -This project is dual licensed under MIT and Apache-2.0. - -MIT: https://www.opensource.org/licenses/mit -Apache-2.0: https://www.apache.org/licenses/license-2.0 diff --git a/examples/libp2p-in-the-browser/websockets/LICENSE-APACHE b/examples/libp2p-in-the-browser/websockets/LICENSE-APACHE deleted file mode 100644 index 14478a3b60..0000000000 --- a/examples/libp2p-in-the-browser/websockets/LICENSE-APACHE +++ /dev/null @@ -1,5 +0,0 @@ -Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at - -http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. diff --git a/examples/libp2p-in-the-browser/websockets/LICENSE-MIT b/examples/libp2p-in-the-browser/websockets/LICENSE-MIT deleted file mode 100644 index 72dc60d84b..0000000000 --- a/examples/libp2p-in-the-browser/websockets/LICENSE-MIT +++ /dev/null @@ -1,19 +0,0 @@ -The MIT License (MIT) - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/examples/libp2p-in-the-browser/websockets/README.md b/examples/libp2p-in-the-browser/websockets/README.md deleted file mode 100644 index 427409863c..0000000000 --- a/examples/libp2p-in-the-browser/websockets/README.md +++ /dev/null @@ -1,65 +0,0 @@ -# @libp2p/example-libp2p-in-the-browser - -[![libp2p.io](https://img.shields.io/badge/project-libp2p-yellow.svg?style=flat-square)](http://libp2p.io/) -[![Discuss](https://img.shields.io/discourse/https/discuss.libp2p.io/posts.svg?style=flat-square)](https://discuss.libp2p.io) -[![codecov](https://img.shields.io/codecov/c/github/libp2p/js-libp2p.svg?style=flat-square)](https://codecov.io/gh/libp2p/js-libp2p) -[![CI](https://img.shields.io/github/actions/workflow/status/libp2p/js-libp2p/main.yml?branch=master\&style=flat-square)](https://github.com/libp2p/js-libp2p/actions/workflows/main.yml?query=branch%3Amaster) - -> A libp2p node running in the browser - -## Table of contents - -- [Setup](#setup) -- [Running the examples](#running-the-examples) -- [License](#license) -- [Contribution](#contribution) - -## Setup - -In order to run the example: - -- Install dependencey at the root of the js-libp2p repository (if not already done), -- then, install the dependencies from same directory as this README: - - - - npm install - npm run build - cd ./examples/libp2p-in-the-browser - npm install - -## Running the examples - -Start by running the vite server: - - npm start - -The output should look something like this: - -```log -$ npm start - -> libp2p-in-browser@1.0.0 start -> vite index.html - -Server running at http://localhost:1234 -✨ Built in 1000ms. -``` - -This will compile the code and start a server listening on port . Now open your browser to `http://localhost:1234`. You should see a log of your node's Peer ID, the discovered peers from the Bootstrap module, and connections to those peers as they are created. - -Now, if you open a second browser tab to `http://localhost:1234`, you should discover your node from the previous tab. - -**Note**: In the example we assign libp2p to `window.libp2p`, in case you would like to play around with the API directly in the browser. You can of course make changes to `index.js` and vite will automatically rebuild and reload the browser tabs. - - -## License - -Licensed under either of - -- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) -- MIT ([LICENSE-MIT](LICENSE-MIT) / ) - -## Contribution - -Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/examples/libp2p-in-the-browser/websockets/index.html b/examples/libp2p-in-the-browser/websockets/index.html deleted file mode 100644 index 2a1fbe7820..0000000000 --- a/examples/libp2p-in-the-browser/websockets/index.html +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - js-libp2p vite browser example - - - -
      -

      Starting libp2p...

      -
      - -
      -
      
      -    
      - - - - - - \ No newline at end of file diff --git a/examples/libp2p-in-the-browser/websockets/index.js b/examples/libp2p-in-the-browser/websockets/index.js deleted file mode 100644 index 28ea0a93bd..0000000000 --- a/examples/libp2p-in-the-browser/websockets/index.js +++ /dev/null @@ -1,92 +0,0 @@ -import { noise } from '@chainsafe/libp2p-noise' -import { yamux } from '@chainsafe/libp2p-yamux' -import { bootstrap } from '@libp2p/bootstrap' -import { kadDHT } from '@libp2p/kad-dht' -import { webRTCDirect, webRTC } from '@libp2p/webrtc' -import { webSockets } from '@libp2p/websockets' -import { webTransport } from '@libp2p/webtransport' -import { createLibp2p } from 'libp2p' -import { circuitRelayTransport } from 'libp2p/circuit-relay' -import { identifyService } from 'libp2p/identify' - -document.addEventListener('DOMContentLoaded', async () => { - // Create our libp2p node - const libp2p = await createLibp2p({ - // transports allow us to dial peers that support certain types of addresses - transports: [ - webSockets(), - webTransport(), - webRTC(), - webRTCDirect(), - circuitRelayTransport({ - // use content routing to find a circuit relay server we can reserve a - // slot on - discoverRelays: 1 - }) - ], - connectionEncryption: [noise()], - streamMuxers: [yamux()], - peerDiscovery: [ - bootstrap({ - list: [ - '/dnsaddr/bootstrap.libp2p.io/p2p/QmNnooDu7bfjPFoTZYxMNLWUQJyrVwtbZg5gBMjTezGAJN', - '/dnsaddr/bootstrap.libp2p.io/p2p/QmbLHAnMoJPWSCR5Zhtx6BHJX9KiKNN6tpvbUcqanj75Nb', - '/dnsaddr/bootstrap.libp2p.io/p2p/QmZa1sAxajnQjVM8WjWXoMbmPd7NsWhfKsPkErzpm9wGkp', - '/dnsaddr/bootstrap.libp2p.io/p2p/QmQCU2EcMqAqQPR2i9bChDtGNJchTbq5TbXJJ16u19uLTa', - '/dnsaddr/bootstrap.libp2p.io/p2p/QmcZf59bWwK5XFi76CZX8cbJ4BhTzzA3gU1ZjYZcYW3dwt' - ] - }) - ], - services: { - // the identify service is used by the DHT and the circuit relay transport - // to find peers that support the relevant protocols - identify: identifyService(), - - // the DHT is used to find circuit relay servers we can reserve a slot on - dht: kadDHT({ - // browser node ordinarily shouldn't be DHT servers - clientMode: true - }) - } - }) - - // UI elements - const status = document.getElementById('status') - const output = document.getElementById('output') - - output.textContent = '' - - function log (txt) { - console.info(txt) - output.textContent += `${txt.trim()}\n` - } - - // Listen for new peers - libp2p.addEventListener('peer:discovery', (evt) => { - const peerInfo = evt.detail - log(`Found peer ${peerInfo.id.toString()}`) - - // dial them when we discover them - libp2p.dial(peerInfo.id).catch(err => { - log(`Could not dial ${peerInfo.id.toString()}`, err) - }) - }) - - // Listen for new connections to peers - libp2p.addEventListener('peer:connect', (evt) => { - const peerId = evt.detail - log(`Connected to ${peerId.toString()}`) - }) - - // Listen for peers disconnecting - libp2p.addEventListener('peer:disconnect', (evt) => { - const peerId = evt.detail - log(`Disconnected from ${peerId.toString()}`) - }) - - status.innerText = 'libp2p started!' - log(`libp2p id is ${libp2p.peerId.toString()}`) - - // Export libp2p to the window so you can play with the API - window.libp2p = libp2p -}) diff --git a/examples/libp2p-in-the-browser/websockets/package.json b/examples/libp2p-in-the-browser/websockets/package.json deleted file mode 100644 index e42fa7b487..0000000000 --- a/examples/libp2p-in-the-browser/websockets/package.json +++ /dev/null @@ -1,52 +0,0 @@ -{ - "name": "@libp2p/example-libp2p-in-the-browser", - "version": "1.0.0", - "description": "A libp2p node running in the browser", - "license": "Apache-2.0 OR MIT", - "homepage": "https://github.com/libp2p/js-libp2p/tree/master/examples/libp2p-in-the-browser#readme", - "repository": { - "type": "git", - "url": "git+https://github.com/libp2p/js-libp2p.git" - }, - "bugs": { - "url": "https://github.com/libp2p/js-libp2p/issues" - }, - "type": "module", - "files": [ - "src", - "dist", - "!dist/test", - "!**/*.tsbuildinfo" - ], - "eslintConfig": { - "extends": "ipfs", - "parserOptions": { - "project": true, - "sourceType": "module" - } - }, - "scripts": { - "lint": "aegir lint", - "start": "vite", - "test:example": "node test.js" - }, - "dependencies": { - "@chainsafe/libp2p-gossipsub": "^10.0.0", - "@chainsafe/libp2p-noise": "^13.0.0", - "@chainsafe/libp2p-yamux": "^5.0.0", - "@libp2p/bootstrap": "^9.0.0", - "@libp2p/kad-dht": "^10.0.0", - "@libp2p/mplex": "^9.0.0", - "@libp2p/webrtc": "^3.0.0", - "@libp2p/websockets": "^7.0.0", - "@libp2p/webtransport": "^3.0.0", - "libp2p": "^0.46.0" - }, - "devDependencies": { - "aegir": "^40.0.1", - "execa": "^7.1.1", - "playwright": "^1.35.1", - "vite": "^2.8.6" - }, - "private": true -} diff --git a/examples/libp2p-in-the-browser/websockets/test.js b/examples/libp2p-in-the-browser/websockets/test.js deleted file mode 100644 index 4e639cc419..0000000000 --- a/examples/libp2p-in-the-browser/websockets/test.js +++ /dev/null @@ -1,40 +0,0 @@ -/* eslint-disable no-console */ - -import path from 'path' -import { fileURLToPath } from 'url' -import { execa } from 'execa' -import { chromium } from 'playwright' - -const __dirname = path.dirname(fileURLToPath(import.meta.url)) - -const url = 'http://localhost:3000' - -const proc = execa('vite', [], { - preferLocal: true, - localDir: __dirname, - cwd: __dirname, - all: true -}) - -proc.all.on('data', async (chunk) => { - /** @type {string} */ - const out = chunk.toString() - - if (out.includes('ready in')) { - try { - const browser = await chromium.launch() - const page = await browser.newPage() - await page.goto(url) - await page.waitForFunction(selector => document.querySelector(selector).innerText === 'libp2p started!', '#status') - await page.waitForFunction(selector => document.querySelector(selector).innerText.includes('libp2p id is'), '#output') - await page.waitForFunction(selector => document.querySelector(selector).innerText.includes('Found peer'), '#output') - await page.waitForFunction(selector => document.querySelector(selector).innerText.includes('Connected to'), '#output') - await browser.close() - } catch (err) { - console.error(err) - process.exit(1) - } finally { - proc.cancel() - } - } -}) diff --git a/examples/libp2p-in-the-browser/websockets/vite.config.js b/examples/libp2p-in-the-browser/websockets/vite.config.js deleted file mode 100644 index b40b89518d..0000000000 --- a/examples/libp2p-in-the-browser/websockets/vite.config.js +++ /dev/null @@ -1,5 +0,0 @@ -export default { - build: { - target: 'es2020' - } -} diff --git a/examples/libp2p-in-the-browser/webtransport/fetch-file-from-kubo/.gitignore b/examples/libp2p-in-the-browser/webtransport/fetch-file-from-kubo/.gitignore deleted file mode 100644 index a547bf36d8..0000000000 --- a/examples/libp2p-in-the-browser/webtransport/fetch-file-from-kubo/.gitignore +++ /dev/null @@ -1,24 +0,0 @@ -# Logs -logs -*.log -npm-debug.log* -yarn-debug.log* -yarn-error.log* -pnpm-debug.log* -lerna-debug.log* - -node_modules -dist -dist-ssr -*.local - -# Editor directories and files -.vscode/* -!.vscode/extensions.json -.idea -.DS_Store -*.suo -*.ntvs* -*.njsproj -*.sln -*.sw? diff --git a/examples/libp2p-in-the-browser/webtransport/fetch-file-from-kubo/README.md b/examples/libp2p-in-the-browser/webtransport/fetch-file-from-kubo/README.md deleted file mode 100644 index c02db34408..0000000000 --- a/examples/libp2p-in-the-browser/webtransport/fetch-file-from-kubo/README.md +++ /dev/null @@ -1,121 +0,0 @@ -

      - - IPFS in JavaScript logo - -

      - -

      js-libp2p with WebTransport

      - -

      - js-libp2p using WebTransport! -
      -
      - -
      - Explore the docs - · - Report Bug - · - Request Feature/Example -

      - -## Table of Contents - -- [About The Project](#about-the-project) -- [Getting Started](#getting-started) - - [Prerequisites](#prerequisites) - - [Installation and Running example](#installation-and-running-example) -- [Usage](#usage) -- [References](#references) -- [Documentation](#documentation) -- [Contributing](#contributing) -- [Want to hack on IPFS?](#want-to-hack-on-ipfs) - -## About The Project - -- Read the [docs](https://github.com/ipfs/js-ipfs/tree/master/docs) -- Look into other [examples](https://github.com/ipfs-examples/js-ipfs-examples) to learn how to spawn an IPFS node in Node.js and in the Browser -- Consult the [Core API docs](https://github.com/ipfs/js-ipfs/tree/master/docs/core-api) to see what you can do with an IPFS node -- Visit https://dweb-primer.ipfs.io to learn about IPFS and the concepts that underpin it -- Head over to https://proto.school to take interactive tutorials that cover core IPFS APIs -- Check out https://docs.ipfs.io for tips, how-tos and more -- See https://blog.ipfs.io for news and more -- Need help? Please ask 'How do I?' questions on https://discuss.ipfs.io - -## Getting Started - -### Prerequisites - -Make sure you have installed all of the following prerequisites on your development machine: - -- Git - [Download & Install Git](https://git-scm.com/downloads). OSX and Linux machines typically have this already installed. -- Node.js - [Download & Install Node.js](https://nodejs.org/en/download/) and the npm package manager. - -### Installation and Running example - -**Pre-requisite**: Because this example is in a subfolder of @libp2p/webtransport, if you are running the example inside https://github.com/libp2p/js-libp2p-webtransport, you must build at the root first. If you are running the code outside of https://github.com/libp2p/js-libp2p-webtransport, you must run `npm install --save @libp2p/webtransport` first. - -```console -> npm install -> npm start -``` - -Now open your browser at `http://localhost:8888` - -## Usage - -In this example, you will find a boilerplate you can use to guide yourself into bundling js-ipfs with [browserify](http://browserify.org/), so that you can use it in your own web app! - -You should see the following: - -![](./img/img1.png) -![](./img/img2.png) - -This example demonstrates the `Regular API`, top-level API for add, cat, get and ls Files on IPFS - -_For more examples, please refer to the [Documentation](#documentation)_ - -## References - -- Documentation: - - [IPFS CONFIG](https://github.com/ipfs/js-ipfs/blob/master/docs/CONFIG.md) - - [MISCELLANEOUS](https://github.com/ipfs/js-ipfs/blob/master/docs/core-api/MISCELLANEOUS.md) - - [FILES](https://github.com/ipfs/js-ipfs/blob/master/docs/core-api/FILES.md) -- Tutorials: - - [MFS API](https://proto.school/mutable-file-system) - - [Regular File API](https://proto.school/regular-files-api) - -## Documentation - -- [Config](https://docs.ipfs.io/) -- [Core API](https://github.com/ipfs/js-ipfs/tree/master/docs/core-api) -- [Examples](https://github.com/ipfs-examples/js-ipfs-examples) -- [Development](https://github.com/ipfs/js-ipfs/blob/master/docs/DEVELOPMENT.md) -- [Tutorials](https://proto.school) - -## Contributing - -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**. - -1. Fork the IPFS Project -2. Create your Feature Branch (`git checkout -b feature/amazing-feature`) -3. Commit your Changes (`git commit -a -m 'feat: add some amazing feature'`) -4. Push to the Branch (`git push origin feature/amazing-feature`) -5. Open a Pull Request - -## Want to hack on IPFS? - -[![](https://cdn.rawgit.com/jbenet/contribute-ipfs-gif/master/img/contribute.gif)](https://github.com/ipfs/community/blob/master/CONTRIBUTING.md) - -The IPFS implementation in JavaScript needs your help! There are a few things you can do right now to help out: - -Read the [Code of Conduct](https://github.com/ipfs/community/blob/master/code-of-conduct.md) and [JavaScript Contributing Guidelines](https://github.com/ipfs/community/blob/master/CONTRIBUTING_JS.md). - -- **Check out existing issues** The [issue list](https://github.com/ipfs/js-ipfs/issues) has many that are marked as ['help wanted'](https://github.com/ipfs/js-ipfs/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc+label%3A%22help+wanted%22) or ['difficulty:easy'](https://github.com/ipfs/js-ipfs/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc+label%3Adifficulty%3Aeasy) which make great starting points for development, many of which can be tackled with no prior IPFS knowledge -- **Look at the [IPFS Roadmap](https://github.com/ipfs/roadmap)** This are the high priority items being worked on right now -- **Perform code reviews** More eyes will help - a. speed the project along - b. ensure quality, and - c. reduce possible future bugs. -- **Add tests**. There can never be enough tests. -- **Join the [Weekly Core Implementations Call](https://github.com/ipfs/team-mgmt/issues/992)** it's where everyone discusses what's going on with IPFS and what's next diff --git a/examples/libp2p-in-the-browser/webtransport/fetch-file-from-kubo/img/img1.png b/examples/libp2p-in-the-browser/webtransport/fetch-file-from-kubo/img/img1.png deleted file mode 100644 index 6460e274466a53645168269943943ee195491457..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 571580 zcmeFYc|27A`#-D{m1Rl`vJ6V}2{jzb$hJnl51wVyt-@v)SXQchp%yGQQQyT4_AQQ3Cwg!(~8 z*NgKZ1#jQwMs2QKI+M5;a!+U`=-Fkw<4Ubn4S_2`Lb(k=IsH(EE}f4Y$tKe)fXK>42V!`zn1 zbA>`ym79W2??8zCowH&*uTBv=C6uGBwAxO>HAUztINIIW_tfSisf}%{Hs|?9*7S}2 zy`JsY+D_eQ3j49qOEF*;d>sQiEHOWXqjGOuZBKsO*gPf9^w$n>EEoS`GIY4*+4HA1 zVicGOen`jSr9q(&kjc>*|F7|1M9n`$> ziD_&vvpriT>T*Mn=DFY@`#5Qp@pfhZBL|;b$225t8+&wRdi*uz$E!`J(gM9Cb=6Pr zfZ@eY3h8XwB(C)2xbXQ+`X~Cj2K&TlyNqfditSet+w$=JOIi7Nb=r_!BnqPLrKfpt$T9y2|I)WNjex zX3`2692&>(_@=Zo)A>WVqU>yVa=ntHl4hdJ`QkbWFU*i!>_cn7#^L^fMSZntDk&)CVr;L@PoK**cGMJ_`S{u?=AXaX{HA8c1^+`M1x*nO*F6U{(btz zMR(s#Ehla7=)HLuV_MXC_Kv0j+~HB)sV`j)cZ45otbTaIw6atB4qD{s?(@>xb@G}A z8XMmg98=$!a8tYBQm*`$#@TPT*=hMV9c&P*JJcw?X<^78yXBv&Q4FzCsGXQ->ro_K zq)LMD2wlUadv4lW`)u?CUFH6kLyy&eIGb$EO#AlYe%$?Si&^)6AXVaX%!`#D)KtGZ z*QRW-PvbzITF=hdoyf@8XZ-zA%?~F|EGeH#DF0w`X{(!poAjqAzOR2>SUYh|IrXJO zQ|-jD!e@pl_7)>&QK#|eL(d7$cfGZ_Saq;#7s}-?mqRXxvtE10|GdCC|NFy$RY=a( zU-Gl^v)BJtSlP9rvGU^i^XK26XP?V`Zsk(iay`lDFW0MzIoK<|FO^uke2KZ5^jYKL zaNYy^mE>8uy)SNGU}k4^ZF4ifbG$gAm|G0{+xNKI@tD0BkL2rF*TV-~N>XNb`5pF4 zUJG1tT=8Dv&r1IeK7Md-&)&Ndd5z~^oO@xqSNGW3@tHUKj=w+7JTC3N_{%Vxb3W>W z%h%l>8hYR4mzedIem53ScoY=DY%G^r+ z44`#WW|Qp1UUl6&$I4xw$qmRg?zPYvx*6E=E#TGaQQEDlTUm9h5|tj0_x8&*$X?JM zaQt=em*-tac}I1f8?M-&<-I3+>&g3x&PmOh35u61KIMPv^i6V$n(=um8Q#$3l(1A63-6Rn7ac2!E>62=>mD@t+_9m! zrS!U!U*l|b$qT>2m5pR6)edUUO%KXJ( zUG81(Ic}6>PIzT_=dEf}>ir-0Nn`KEe%E>GeKshRkCJy+fa}c|oYHIe``h<{{txey z1J5S+bwsnL=BLuARlhkMXTHYY+DDDKtH>E>7MrRQ88`aIk}db1|DR61CM8>qBLM#^Sy-;NKv6J@UK@J06->K!iEDM!>FalYQf zurj$5IK9*6Rx~>aN`S`|{pHM-F+|T?b#i)%-&AjrEhW(^_5AOZB?k zm@en3hw|igZJpg&zH>Eu=g)-hfRDh~X`e6O`Lb!zpQBNVsbx=Dk7y)J18oO;%e5^T zx7VEWny|@}2_;%z)CLiihLzS$d#-K4Og^5v+ZKeAORqEvP(tYEqi|`s4B*TM)t22Q z7mmHwb8*b>GqzV*d^2&}ZRG>%Y`L@DhD%5D-hQ%@6Eu~Xdt?#Lz;|)>T-_7$D(zSh zxU2opyF&|?7qT_ptQG5(v&-Dr$3}{KW^Q*=&jUxpk2^8XJKt_>>#^NaG)0=tP|yk{ z%Fm_^=@UqP8I_KUgF(&AH&i(i&Is&6C=-4q=OmpucTb&u}4j;4Ll^Z|vrq1zeZC#0RCGRmF$k|4LR$$L<6dWJvw9W2 z8Cdzng?=mE;Pz^uv-j0--|xhMUqJ`wt=x+On6-5l5oK^qK7q9;Di3iyIzM9&>uTLucn_M!VHW-#UuZR`i1>(t5v}QeRW$5apOV zcLLne?8-r!C~^q7SL1>G-HM5zPv3ofsRgZ}DVFwItGw6#qRu{Xzu0S#uXckFx zFO`={x;Huez^`(8m5MB)Ni8OibeCI)lBYvg;Qqj`fbRhcA=}w+`L}p=$k@Qx8-^Nz zysTis&Vhub?2nf28Q%?&KX(rK%y3>&hY|G%6f2qciR1d)d@w~+umpaoMr7r4lO}%G z%r$t5kK6_3)=EpzA3;GSF91hQ2|ddGHolKJ{@St`ml2x5d$R1ZU|pHtPX0j{R%n9D zZ1+*M=j02C9Deh9Yt7t(Q0Ju$Z|j({e$f=38sZtH?Ju)Y^sNTji#LWg^*)(l=SzKPgd^sG5wpDfAvQ5#Oa>TDQz6nA#~Y^ zkF(oC?}3~92-urx4`W>+gW|c1&Dq-*E(rYvU2hTEv|+E%X6R}Ibf7lK{pb4hhJ!-F zf9`J-5{hsW+VpQ33+TN5iGz;yI{%!7Up^HQg?>pvN8sCy|5JK%)m!2JTsuQ~LdKU( z&z^$edqN`H#@x*Mt3T(D9y z_4Ia8($P4oaa0AhO-V_~(A)X8!KIU@|E&)FGE%wY>wDh-fd~i)&?XzJ_h zBaUhzw6u;uC64$6-SfQ_c;ueXzJD6|pLR~V_&9mH-S>6#yr;C@?kz`8KVKsimGuYx z=kw2dx&*rY@00HN{M#+4gNXGUgr>$(#DCg`sv54}HL!9Ebh&GL(#-=JGw2y8O>MoS zhJPyj-?IMqk^fcI=D(^Q)6x6ys{fVsf314e$Hm*!(*t^_FY13M?BB}&o%wG?L&SRD z|7$G%8R$QEp^-*yGerDn)==A?K6=*(O{BcrNy{tH8CquRpN)mk*TH|z(DkOziO;^B zdLkrrLg?&C<12w1=Bp*X<=I{%`z==UHHVGJbw{hC7~?fr-QH^KpnC)Bc&Pp0^g~$vL97idz&W50)4Ym-;P#3V1}^ z$xEj#Te5bqu+fZ^l@wkAFO{#xr46b22>Q}L>Ft}~9UtF_nTE~j1B;F>58N^i`3O2# zW_W`C_wEwok+>Wx_b?d~FwXr#%w)XM`m+Q?TZHe{Y|kRy`~^c{lle=d3FXQzJgY(v zoIx`E>tXX5Q}hRMKkh`ABq}2kjNJUJ@8MlL-P`J8cGk&1BSO!}&aO7UPiNO@BY|leQIry5gOU|HLtUoW-)nCx4yB!~&GpB97miu2lhyfXG9b~r14_zt0klSZ* zelCYXrXvzF@8Jvw80d_CjvV;}`}Dg!lKMpvtU;JM zyCIxm|Dv%kgtkE{34C*&KlQO)#JHNp%wIa7eQsrfXKf27e<(V?32*Ak7wY{}LtwD9wQNX0H|3E~fEE^l$l-;3dMisz3@b zQjAV2DK8*N$-)EqvbAM1)+2@gW;}?tAzSYaPHb9MW9S;a^}I7fT%_d^atZ(4RK48) zb5ozD-X2HNm0IdClzgIT>=Eddmaz}!4|zuSm(B-95=3C3ZLJOcA9 z#ZwvDqzQ2Of-kSpIIk2sACM4{&*eVa=^vpxi2gSN&u`m-Z32xv`tDtz znt)qjlPBBzQ|nrxpm9kSy(}vca<(HmKYw2CTq@iaK;p(;W|5?Te$Yqoy7?V-o6k9n zc8`O0Ye^z6foT~lN68{4GWLLdM~fy z=F#s6;D>_KQM@e66$LE@*kQf48JIadyR;Lq1?o4> zHNH|pJrm2x|9&GI7UXnp_)C>Q#^)d;i#3{s4@BdeeebXjh_ioP_^bM>LSUTtf%Fc! zjj8b2%|KbRA6O4YqI$Z9CC&)7iE_mD0 zlu&I;RdBxW1*+f6pOFk@C-92wV0rNqJLgd*DQm@H4>m zth!4$9F*JH8u-#PcfSCVACVLALeC|d7Uq>&A=t*g`PCU5=4=GiS&39_>jP~iPPytNOpz`+KT&ju zm-p+fBE9z8!$1UobYO1(UUI4`|Ca;y>hOS#`9MoR<-lx(`wDjl2B(eLg7GCUuMP0{ zaNX-`aD1dyZ=mr@9}UqXmwf6Py*a3w-9x0%og~^DQ zz_Yls&4kL5M`q9vmqUZbm2rMC!HZ{FukZf+bTw~5TJUK+=ua-y2dKP-@3-<|INi)r z!@2sjrh`wm;0&-$o98l{p5%JC92|=bQ*bGEBL|Hmr5hW;OTIX? z;r$~s$W8E|rl9#$w2!#p{%^V$565m@8=RD2#<;92m{r_xMzbIiy%uU-U1ntct+mE% zr0CQtIUT|HvlRP*B5-Zk#G;91i3g*@)6hNw?Dh^EKl+S@p*znf?{RSvO<*Q_j`S%6 zT){rDWk>JxjZ{=RVUj}K0MlMee=@1EqLSQI!`gn*?z&x{hRyt2wf;tn{HVw@Kk15! zvT)CLKTi|q{WRl!<|8Oyz8IloFgc=xmM^nPgKF)N&8}Bx`4i8AgCsreQYmNyL&}ZN z4-|qGYUL3F9gy6W%h((0#}uJ0^c+6blrX z(N9zXvuTw^rZPJl_BwMvFjF`aoqVbaLm{9=Y+1;7M}-Yc9maY4UB>pC`n$;u#LyO( zY8ztUbmh$g;Y?xAPnPfx?L`!A=`$f-H4WE@0TxZK5mR?1r8?C16yXVB*q`DO~U{ARQ^Z9jMbN{S>{Gl9sYE_cMF zKv*)C>$*x#LwgGh@DRZGK6rS@oMF{L{tnuVfZO4G-dPPV{z3Ek6OANW8lf}%SN5g| zY8Aab%tgz0M3KHZqinb@RZIxrb&~D0*?IfF-*W*xheOEN;y5E|NH`o=ZF&0F7ExaXEYPm)jYkKNEjWS>ejPs${Be$zH?7XXOo(KJuq<<> zpV`kU?D6n@E8quJvK`Myae_3UcTJBfkdalSOTB#fn~qJ(`43F?}kv^pLXg zME;=NfZq=PV22xcc66_S>V!$Q2Hwy)u)gF2yuX{CR41}BN(Ad4dD;H1$8dyjCv1Uk z7&NX2o{1?k^Rj}Da{|^rQWF*t{7ne1G4g9EA!}n;Mo&J#MFSJD_Fbr)Y>M@%8D>Ut=RBAJ*e}WCrC+;y zf3gCu3#={Ly6FmLEk1N13s`!r=(4JqkXD>SPC}(!?sB)Np94Ei%+0p&X50?Zev2j6 z*cbC=Ptf?6vTty@SGq1<2eA<|*tVHlY`FyTb%3dm0dB9E^cV>BEfRgr_@6yGPgsYW zB}j4+0y=R!nmDP?^aSk<_^n3>m3PTAEDQy~FjJr8(gc;@QBSK3D#xyJB8IC89z`_y z-5R#v54}>Ug zNz$G!u~RX<#vLfcLHpjTFScs+le@Li#C$dkyY|iWEN%gBQKP^+mqbb zJZfr-KHkw|;W8neBMMNhvE>NCIGB!;0<=B1Bl0|Fp*ccKwVN(^E|Kmz>@aOcSMrDT z9351_Maq7TE+?gAgA4dtePPn#^K`-3M5-U=A>orqG>b-{u+rA}=4spyva z&V`_xvh^B&hs%F4dbss(e)X?Y$)S^OhsEIUj>Ohr2HwJKrS<)Y?{e2l%_nSBOcV!W zvRLrvh}*;nGw!`HBzcs1+Vh1%U==Is0muL-=s7e8!AUuv%9{&)h-ebCf|TXWEFKVC=V>cGD?o+@c0{5G9)}9XT*{fo zmajjLyc3Is-YIG`{5r+*UT8+Mu))gtbFlJn#^3kQMM`VG0!T7y=uS23GEpb$se#xt z;OnK^kudV+obzRN!*&krmLFyKUq~^$zYO)Kq(=_3;jt%F7=0KIz9}s>m7B$Cj@i-p zzruk)-WZV$gI^i3 zX)LYG?}>Xa_nfi3Trw; z8HGfE+5yuyUK0uuIXKckya#d=y;=n(K*vVu>~x0(3lU<>+!r z{AzGJ)t!Zi1ZTorcyowF*>ZA44mUp%--;fgeG|0`us6rDN5+HhJ&aKFpiw?oR7=;3 zd{8WWSzbI0eA{8rAUqtI{S4JPyvYSdxk1!ii!T(_4M{J4Uu8VJuw%6E;k-2oui>c> zG{4$I=7NM|Dnyo5i5L+f9C z3xn2P(EdnSm%%>iw?UEsxIxC8ys}F8p4Ws})aIua^~SfYwL)o-@15lSNXlEGz(R>> zjJw*-}&F~|D%#q29Ye4Z)BGk=Ul?l`R|8=7j@ ze;gYaz2n_IJG<$hF!;Oq@gj>)G2Uh2`7x!7A}FSWK*Jxw5uXy3hY%(mie#1p+@{=&shw9_lwK1GDzBG9}yM5f|psHWmdo8La zfPGgzO2h5|L59(+4<;~_`j-m8APmMWo-;prUe1952241WK ztVSIN>sSsKP0X=@%bd5uPgmn;#r4?=1A!;hh|1l<>~JCFXIs?I1&O#8h{Wm`M;NZC za?nz4Z-3^e=}25_32nYB$8C9_56M(>p5ip5NMHc5N&kvpRM*N_H)A zgKB*m3dwO|Lje$PVm~ja3+cLQ15|ON0zpC0ZqhN=YG6}6( zdfwYr`NJR`8Ag(iyNYL_Vb$SF`(<~*dWzp1N=t@tz>+ks7Od(QHT^?D}u5wppv}?liTj(7n2eOC<+J( zkgjZW83DI|^*|4>M7|9_BOohWHv-CaSNUizX#s~`-x4nTb=yKzv1y%99CGr3tfO$B zlmNM*aTz&%puLYSI1P_C{bV|fas3YbB)U2PJ6H7Z0k&n~v@~@tc5#C5l+C>pB&gBR za%YxV^1FHYY4{)|^BaQj^KH0@n@Zo5!lNpTDJq&LJbVt$YW26ulHylH8zcq_mk5d zGF!z0C_`1QL6w}?B7^a|11!(PxGI$Y(K|@QL^7NH&C8Y*O9|)J#3QI-seu>zPJAdH z2@kueTE6upd#%O5_;cQd!I=C1AYT1@>mp93Ug;qzeqN26WO;?ct9=g|?0yJLhA=|q)n)Z-2sQbZr z>@EADW`Sk2Dum&s%%@V1mf%zK9(>2N zG#2+JmG9(b9bsh^WdL2se9pKjLzWywM$eYrc*H!h12Jd3UwA0|Ranp9FJzjNH; z@aU5`0}<&EI!_utTNb zInFszH(IXuER)T?5Iss83E-i}fAp2-uq}Bmd|9V;rf{)rUG`3F_Ay<>1^J_BOvnIn zh<1TAI7Bt(ldurTk7p8XJK#gwXGa3kiTngA{BDsoc}76fD~PHtS_E^&rZ(TIGuny# znaMQE8}IhVhotqb@YLXng|og`k6CaeVno;&|3TET@c3Eb0nXl|YhfpD`RLx1*dM+r zWOmtnU_L}dI%~Cad?xI6s?_y5Ym(B(BPc^K_bjnDhTr5)Eo7uH^E2;8YHBK;Yx086 z0@R2XAxsPf=O>7cVubzH9F4N9X6eIPkqmUHWgTIV2@4$oC_vujo{G57? ze)qD;FlNGIz-o!SddOsYogGWL;Ypaz8t7IvUJ!UDvHVGNS|E9qb4-i0YZ16Se{ zl*|;>7vWSsfob^YZ6eg4wy31(%V{C~(bsy|8QF9r)CDxxnw{2TCoz`F|xWijrC`fA2 z=zC#(AYrpdlm11thoCGx*5M$#yO#k*KdC3%OWOjKQ0IJ>1PMH()1*3=Z13`qf_2Gn zhBh0_+j!lM8w*=E>?aI2Px3;zR8NFswi?xve{Qadgz2kC&85&bjtncaFd?8d*(+m` zFFoWj9$r)m*7!(9H|zLi2>6%Vjp>2Qw22N}M^y4!h=3j}Fny|Xa=6q~OJl#a z!W~A)YHhzWXxY!*Y9G|JQ>OHb!E9+sZ@A2Bm$#0%h??RUi8FFNtTCkI@-IJm*ILmC zO?8hNS9P_qZUkQEAn6fsgNa69Lu|VB`~)2i3a!Z31f5545LXIu&Qu&wD3BZklev~l zwCD!pFen8?q8$%%fmLuGR0AN@o4}0KjQb;M(wF$vm39>QFm#{!{+?~50e%ANx21%N!{Xpkld|``~idr*K(T_WMIDniqyp=UP zG4NP?+d0fVm^`~!*~QgeFduee_=IuK2O%6eZ530StT*7W&x5+;Iq(?1zv^s{0`>I7TJR6r@3D-F5%EdGRj;k+C39 zrqWiJWh|>uW=1bR!qtIyt%-d zdJ(6e2Mh<)#;jRA2nRC5P9=c6qvJcgS?T6Ikr3cJ{rqan!08U5!o2f{k_%gv2hTce zd{(h~Xw3HS?$DLwagC%MZ4Q#MZjms!twv!l{lX>6zHZH62icYwlHmtc{HyG-sO|*~ zVj&Ft0LkP01ywvv0@)Ijs%*%1^ql&ZOBjddi8$;U0vfdn%G$tYLU;E123_x> zlj3xc76c{XMklbo@6!1!I*o?UqdTlSpSFt{mKA|gmeyYUAe!^cP=^#ao8|&;fCb$z zAJmt?M4R$shb^YlCjdligMKS7o#@7NHEdEJ&zZwLCZz3LU37CSWXW+ha-XOohFbdt zQWCeZClpj-cdJQ3CTz1*Kx2MJs9#;PsjUu)g2E*PFpYiTP81p$hvT4TRc~ z8ZnAgBHVpNA5A-u`mOf^~o%t<@$pj`w_I8D8_0018>mdQyC0n z=Mcd-!eF)IypG=98thn$-h>G;_bU#o-tESYtYM-iFN3 z#dT)wPn)XCaLlofc0VXr1jK}fV@wrpKofj~t)VU~hxNtf6V2Jjv3JpzNXqQ!4JNMo zAhMRmBnsS^=v{ETHaIs1=Ad|#j$VoJ#1xcy(jY?_BE+2+-CQLP2Ux7H>q(w|X$uxilC!7;nmAm6 z0Z=5J!CIr{di5}Mxt+Fnpdi+Q7~e|+UXhilWK#y?w=Etm*?=e_F2Y|6J9)?Sg_TP$ zQ-)CNo;gv9gYLu*SZ&2XY_NZl-eRbV~RZRk|q(iHLGl}#Hg`nvb^V{K% zLm9!}+=3;@no66waBgH3pugD?UH(ZjQ$An!dsskY|8cLvHTDwdJ`Nu&GO1` z$Jm=QY9ERoS()gHt*UURffjVyDleRr+QGHtkz|f~%I&lT*Oz@iSO}72nmDeDJLh3k zFF_ke%yNpC^oO`U(SfVvJx6;BP#oTcs-XpLgko8%;S_S2H^F@jD*$WlX1lT%mv|T8 zz5{}&Xr0AfkRJ9I?CAD`f}x!%()n=l>0-{@Wh$z~AOEqszU=F~k*yXZINjz~m3TN= zdfeP4l%D9*QFYf>31g`GAy;SY$ik;^apN{sZNqPgyQ4xUzey-ZNNNofp6t=A3-9b! z3~{)IotO@n7hZ{p^*Do_9Vncao}vTToL}Kt$ct2TDcu0&>(kI9X9T4h=eAe)Oh|X)`xZjl~u67IfDgSs& zQF>HMTHwK;MPI&qc8Xd$Ar5&AY->B-n>}uy0V4BOR8c&EQNh#L7$@PfRu&D$-mX)Q z46iTQ1-A{fDl2;$dxUW)WvNZhh!MX*^xdMVU4ID^=JVaPxtaWB=X7nWJ@#T-gbpHb zA&Wyfr0iUY$k{0r=bu|=-SbjO$TiaCZGhc?Pww)?-fLH5Z~dhPM8@7A(tM=g4qI#) zM+(eFyOZbN56^X2+O{6YIyYca3H~X}2v4#UTmU($a>w=s??sg+v->L5u_IUMmNDRD zr5*`#T&O|rxI%%&0FVGo>9>SvasmRbspz~NGy>LTd;-MzTdv|9EL3qCtRcY#h@PT; znMa>AUnLi1pyL8wI4lds(|6Fep7%P!8q+>~Mt{zIj*OPwc#X8XkFK&es}J ziy!OD*wJ;IAD9j}7HoJH>PF^W_{)9VfpR#iJz)wacw@BOWw(Ya_}YwMtXz#G>!2!X z(fR^pXKM3){`3H}c! zRATcS5)oAe$%yD3yhOgM^kMcsF6>4h$p5~_vLE0*il*1XNKP%jT`loZ97D5%#04RI19HKJ<-&;`UJsnb1(Zm z2zlQE2Y!ec4>LXmcU8kMZBoM`7&wfVFa=2Ao!(VBV5#}IgX!qWbc%b~`L7)q?AmM5 zzzE7Xu(KV{!R-ds|AjttI&(BSKbs1=2+ScGgCr=63QOpKc1sb|!*)UNPnIR*;6lw_ zo_R~lhupZqFz)?TxQc6I=K$Yqi8kC$zy_oT27su-94m6R(gBnP`(i;{cNjbP|HB0B&;HN*;xIk*Ei)u zgTm*66MOpQ*(nFk1zlBeu8j4Nz=cu?7l&hZqx?Ti@?f>1MX{&k`sSHt76x-Xu6&8| zZ6YQWU4={sPf?KYb0O5BWdL##e+zoqkvTH7HA zG)sak@AZUP`uzR)I$FX5On#Bw&c&3xcxaIDLEAgvBeD*wTo%?J$)JYBR+OekVHcw; zTEW@*RD#a8@BZLp!NRB$%*ZVgu}5p!c&TQ;jsh3O%QNS9^7BuY`CK2ksZQA^x=p3q0SjDfpsmrBxxa1eQX=N1;6{z2DCRV~$(>xWRvJuzOs9c}h}^ZS z3Y#pkG732VGV;nN(`q<2BgT>-psh71I)eke9n-6oD8C$5emhPuN|Su2Rt@l7)e(F- zkk(^KiJfj*GZ*wP#7@OdfHOOL&DL4^h%|ydBz>v+KUeBrCmOD!XLtt2N8so;@sAE# zge~G=KR7;l0;Cs%+ch&cAl;App*-FZ4LUzBSFuUt~V35qE0 zl_U%{RIYj)ZUEfXppwd!*y(G$t~n-pE11iqvGJyjUK#AZ0V+6Hi@^i)$kmd6&}aMc zkV^tDiS$xIkzkbyPT+O#*G7u;9BLgh0o}QyuVbX`b`f6YgZ(Iut3P zLB<7XSkb4f12_7zmn4R>uNmieyUl@CJT3jkv(5ObHbOCL5=Z?ElYdt5=?f3fLF%jw zfurtqsB`n_I>5v)hbUmJwzdP$B%Wn2f91dxPaZ<4E`*@WPBJ}93+C^m-O z#Pa%kPMvA(8VR!~yO64Xfe|0I( z@uo2pZ3{-h;n1trj0I7jNJ}_rFTRiR{!1FW!9a#U0I0woET2q;^VnqefjvDvIDRAn z5;Xr>glTbn&kXZ*MeYZ*|6|%~Bi0t`QDbXO9BnEI2}KrgxFaYaK@6g?nN(9rBOt-2 z$yjX??u;$A%k={5t6%E3apB{!`nl;q(%ge4FHBJt=#8_XypPIVEjeY!o8-r?nosnx z(4}4P?I}Lsew|5g0i~N-^-A}FId;LiceZ>%7u?rN^^~jZ9N@WrBm3uPXQr#1)#$6<5M~>0JSeze+MMoMQwN#=|0_eJ(W?JfE>y zdt~<1^;6V~Zu;-5{%+$|*yWUpfqA^C$WL@FjwXp4YUY}u1>}Y#MiLvHQCTRkIaH~4 z7Qzb3B5x@qrn$xHfuq`oDqNdRt~g(DBY+1-QJJ;P#?={wQ{o^ z6)LT}@oWcaTdo4EN)@F=iQ4L^4|u2(V=hdLImulr9dAW$1^&i#;Ved^R&SVpbc9&h#8+V>hLKj(sc2x#7{ zvLa?L7Bv(wB`G^=AGO7&*#y$7~W|&{*_R z3jR2DQl90;9yp>t4EA)UB9hTr*zuHf5dg*RXv zS^^%-rC=P)r-Z{|JG>Q3A%OwC?ffMg``35y($i9J1>6d(cHB6_>?N&l40miXga%I? zu%RGN6V>q8iQk(Ey$bNc5J5y5&~++*{0eh+hj7*GKNER*%r1X+)#a@z!Po>oVOZj1#~set5T3!G^*cW|`&<~G zBDSPn(#`nfURMz1{z=hkj+u>d(Cnc%bW3`8b#;qm$t)dOY4+}LXRAvh%DQ%^8mz?` zE-N$A(JpY@_zg+`=4ONdUp^Lj$^p4#@xyE+bj9Ka@c?P~hig^sdIb3#CuL>K0RL5B{y>dNe+bVf@O7!NoC`@z>HeFnkngMfLGFvx1Ux#P#2FVD0rz{o%0|#$zny%) z;-k?TDU%+bzmPF~v#V?Tojy;K8HA~*L*E600+<_-(FCcK6?7w!>Dn}2G~1|5tq^M-G9O?XImizyB-Xx z%?h6%9!_*&arsi zi#st46Z8ho1W!M zj_)K8Jbi2Ee6HMdX+!oxT8h9rd(c1vfRvrgzSS8~OYC6N5k|VTpG1(yzAuoi_(+C# zbsy0=Zu={PSd^lCKgQ&E8FnIQ>vq41PDVpc?1iJ^9|Vu0jM&r9VhvaF)`_wW8)Hui zU4$%bdNO->4?o6SfWn5icn0+xuB2(xnJoT$SPf=2QFEttQO43N_Y_fd1Fi^qePP5yq~3!D-Rq?j@Y} zpIWT3{05i}Ju?H~FL+Xt;*-T{8d;^E4Vwc3-=RV8pv9t~u$OF_Lb{$6+T{-j_zyTxHiPl?*X? zP=Ff8sVx7GM_#{+7MliAWxv?Jq~R{u-|uOIFbhp|hFkZ2u@dNK@t-t zrFce;F0UKHz8M6TJjFPMPj_qh=hXR(td-l8wZSv`Vs<<5BfnZKE1Ml!si>;Fr1kB~ zNrP=_Yf=+k{#A*^UIrZ>@cT8KIVpSYejl0;bU_l;cUekr%yhPlpVo7?XD{60G0-@||Y*!a9J zuh;8&`+ON${pP2(|2tkfzn@u7wqD($&sH7#hC)*_T*C<4y9JNIF}MG;ZuF#^80=Zt zj=yMZg%WOI1=)8-FHkVq)f>qL0l!ShHP0R@WrxeO3fx76`zf5YcaH1Nn_rgs#bef5 zpmEt_GIe=u=xc&4D}y->(B~ky{c?4;#$EYJbFK-$UJ)LO>k&-|{3PJs;~lZi^!Snw zX@JsyCna!0{t>~BR<4Vw(en}WTl8=vv}tBwQ$W11Lyu7?NZ2Jip|cK&W?)6a8r|M; zh+l_mAkb+ZA2Za$q-B*=HSVL}P(hI7P!xrKPi>m1TZua#FX@boPzix((M-ApJBvO`djoAWddkh2EJ-D_9v~NYZmca{M%T*J`Z>v23cgE> z?4sN$sl+{q8pcD2l8pT(LJ&Nur#=F$H+3}r|4z2TAc!Bj2M1u*Xns#wAj?VB&~A4Z zx2#L&lPIA7jAt;-EE3=)R|UZy8w1joRgi0^8pz8sTKIWN|1VmLa2r&hK>6^EYqy%` zcB$?W1vm$_vjxdc2a^ZY)Gx~CVKmUFtFf{+ z_Dh8fKi=yt?te}&edRZ>FP01kezCf!xgL9Hn&y4Qq?Q_r)62Bntz&yOXBcQCUy&n6 z7POhnYIPSGCkH<4!mD9xRs>56c!w(b>uFuzCJ<%zsz>f4m)=(RtUmEJ-Pn-9ay;Sm zn_cuRc~Xd~&7gEpK2WF5T2-C_(Y0$tggCWrzk-Ugq00@#7O0=gH~WBDT*FUxG?UvK zUR6(xZ;~X_({h3O-B5#-RPpuC#L%k)%ZTtmGPh%#mx`2ZYg8PIU)K8^-pdU(##dS8f)_e}i3^ zX3S_fC}114^BJU`+2CUW+E;T2&t8b9LL!%p85q~R)L5*nwaZH}Z|s)NdvDOsD0P#u zsRVvblChkTLl(80yn%0GC8w3gF`kEvz%dh@8EAokHOZ`%DYzzunb*^1kAX8EK^hyS z3u+Z7!%@GdN!EROC&=1r6*;3FK0&T4CPGR$yXf5&p+W}&9AUAK9h36b)?sf@i~ULq z9D=Fx74e`*)W>(9{;V)n%7m^4{&HO=2VL3#xv)MH69QTXQtqSI<+C6;Qr%#=OmIlR za;+a2V-jU+<5@<=csp7+Ec*}3{{=H>{B^zAPF`O zH7?l0WRE>i*#*mt?tNY$``;x4m397VOgxgpZG{>*aal=e#ov|4*#7ftw$(mlA1Cp; z)@_ygu%77a2Y~Sa@8{Mn1{H)|+dw%IFl5}KJSYMVuc1ZBpnhfDmue5c465LiHyvCr z=t%&FG^Z|L^2JWA?+KOmx+DSqmk?*b&6ZtR8^%3X1>2c~<%^MeO4D~n4`skAafd<= zUS&(B1s?n+jg9f0x$a}wsB7lw;&Y9eSdFBSv!1dQS`KkX^%Pl{x(pYaGP?*tMkMSD z{rn|N!+hna0owEH@~giUyFvL9E61s$n7b66K^hE|4AZponN^V>57zCMmy8_0$cynh zBGQl67wwX6cprG}XNH1_uR_L$;L%i*Er*yC=auI-q}3SU1aFv*?cY%{XpBnAlFoPe zJy~yoN-Rt!EVb|k&G9!4cKeC<^xZU?4@Sv-LR)orXaSRk<)+SE`_OM}%{luhg8guJ z6W~;FE(HP=VY%&4gB|YO^*&+~48M;xcHg)X{8ZB|dW(bgR5O-O;Jmm_hcAaVE>=y| za2=}7Ad-KLAlyMC8DW^n4W+K4dtBt;-IE{y1QEW#{bx$?P>-@d)LVB*fLH=CYD_ru z;Ii8ia|Og+3$VEVIZ6R>2M^~H$>g0DFrQMAE823gAe(1MuAEth=C$}FD8Ji5x2i=h zeqJRhG*1dRBh>s0#ifiOM;vwfh0F`dK&ElY+$kvRWim2v)9)`YyXTZam8utTD)$WL z`=~(lTDrV{2Ptb^=G1PC8Nj!qW#>NzfQZr017b3Vl0?yd2h~m>r!MG%eT7_tIb+5| z!uqcuQo%9539lQzhMO)hZ%L+zHp#g(CcKbJ>Np(Kxte|*U)QIhyw;sA-4)thARW(L zTc|}kK;hWPhhZ>nt>o%KJV}0ex})f9W3cPbo5UETyz@;a`P-EGgmn_arSbCx8`DC|y-`Oz>v8 zVgar)xY5hZ^2KXR9Cs#4Nc|AAa$;eEI6<5gn^>1L(qsCC!P~>+?Jn032mdOvuecLDx_r!7VX*V3H+45{mnAVbJTjq?1@6*tl!C$f z7tnnLzIB%(0|(-on~f!9T|CA_gABi0My{FDZL5`eDSbW5&HgE0@p)C1ikjbhsB~Qr zn*&eeLAJwOucp2kKQBYkn^OgVf7e46fod*9*vD~Syn-qAp~qblmBwbVY_k>etW5Wj|ba z{hJAm3jU5npwPg;M^AaM{q&kpN^^P8oht2!mK}&Ge(WQh^zA-pt6=i*ZR%%KjH}>h zGyIi_#PDB1Il;&LRHKByKOicCzsealF8$mLUnzSqg-~T(e3GzB;cBw$j>oQ2P`}4v zv;}*a;YjAg60V&SN_-c+4!!7Bjr*K}8a5>2=nWAlzgjsOYeFTk zS;cT!6PTeIt_+R{y9ng9RT6eS%)&^VuVTyQ+Uw-fO4<2TDE4;*UeSMM=I*(wf4?+0 z7xCFYO<+%@D4xsdX>*XhoPnaWL|EmWRR+%ORAGXxez~{kZc`e?&F+2KrHYAfY0mB9 zxxQv@)P4W$6$f^d)(`_FqsMRD6Q>6mt^Y56`k(!3QgDh!E5rFlG0_Y+n2Jl-S4qP`v zSab|Bc+ZTi_1$>g8XvRH5C+n2B1)ZB#1KUvrxC;tj<_vc?ds)Pt0Eav!(UM$e2{GZ}X?@0YeFi%|vIPW61_U z5eYpE`wlq!^_ltKU(kMxcH&J8;|;Tb!D}tA5Raq8DxfI~DzpGb>BP0)Kpl11ccP&d zM!tSDm*Tl{-p1TRQZ#O&^R4nmEGClyi)dju_5593`Z3g^XRgoW%gW{46-r}0M@pl1 z>}^gK#dmjNUuaGO!%lD@p|3Ct`dv$NH4B1;QAsuwc#@&>+p2Yo7U*G^Al}{hU+1{4 zl>OuVoE9k2&^&P~$7d1h4*XmsYWv)HD@Sr&jLCBMObg768T^{qLE#EJM0Fiibdm@{ z16F8)Sqg_yE)K6@kmi>G_p!OG&1b=y6?H7Jef*S8b z6=0RWzJF*YJk7>yj8jhUlzvDh{#?%R@b@?aJhSn{bumRE%Jh4fh=H5jZObmVAT!Ej zQb=e}U%s+}Pto&V<2evgC_Id5mY6x!=GKJG2~6Wph3_R5MN1D@=Q|tSZXG_z&?=sw z!tN7j4Y`j0W-_{A294XR^dc;wRkgjF9QR-HvHgZxH21dJ5-4Q;xB?28*JsAwlqgZg z+VB4ya&MQX4XvhyZAc_mcVc}FUjCSJD!^Wy5)=quAU5^jACf6PZZA;9dHFe=L}rJd zn^zH;!c%T_g4vJ+3;dAg@`B8H3ugugE;)Wv9GDd)I zS1||RaVqIZpn+h-|FI1wT=mbv6{VnuDs2}hrb2oawPaGFM~7|lLgn*!C`0mxx-5|? z;rD!PH#@a>C-j(wLF5`W*t5Z-KIdf;oj63S{CFCKxXWhxlFj>AR`lG1fVN0o8!=cf zMxREN>c?t&O8$1;(fLIK>X&qB5Z4q%-9{g~Xxu-^c7I1U8+eIQ(DNG)_BsI9Ctqf5 zKRvBXUf3mjWFN-mp5%sKY~A>-8;B&_v{H-V_tlN7!bKfyYa(1QM_zD310M*O9=Vi& zv9dIWlmPzBtV{~rpUlufW5#BVQqI}D2+q3M_GCFNFfx2j|M0yWU!kC%yL@Ej?R=*k zw#PKU`VD09q|QH~OB09mH6AsL#p0Y2gNL8|tIRFc0!#P$8a;CZ*;WyL;k3Z@Kh&;F zPp;R}FDcPOd{j@`VL}i*H?+{#y*&yvl8$~Q^2FIu$5h^+qcU|5-K<>s%6OH4!O=ra zBilq&EJsu$n=ejcmaYT}qp5@xU+$zAPc+jNOJR$BaJ3d9Dw9{_BOW01UFGKai#h)M z;ZGdgVrh?2{0^<7Hq0%S=0kv=3_jAwf9ds^o4b_%fiBq+%DMeaU6A)LT8P;PwPsi1 z3M1g6NCmi;%WbbAgudc51bv>o9Nh!=?dQyL>lH81(qm$){_Wf#AtTA%iJ&1yDucr zWm%E>7_m8ra;L)q2!io`pfGcNnBN)L8J#gs@dEY8!jJOh5aH zruc3&_+)Ej^J9p&XcQf!gM0trYG)13uIXsdK>TBuP^+H2vBT#!4($0COa)L8Yk$Lg zX=V*JKPH%q)};YgK>uF#nP{-0|5*?h@9U9q7Yp6R@`1-JCWLJ&)P|ieB@?NkOQPs? zcdv8)wC=xoCyU=kpEq=x1Wy%|v&4}E3_OJ$zl_}JUEmqoMZz!Qj~O+B6jAs^I$xFAUd-+ixdMxVn8l|H?H5 zlCeG-&p7sQ)Y#hGShqFdY*>Ht69MQhQX_EEUErG(H!BaR$@nQ*3#`FykxiFz5nSNLm@69+nccIL*3T@bd%JGvm9TrfE zTlV=>(BC9Nnc@k1h#$AV6YizRE(4Zre+n-0yDs8;w!+;oU}( zwd<$Fw`JML1~szwr~y>)`pmPMmp+aYM_>{=sL!V-lAVbs4XK}NC)5XLyi|UXG+-~a z-zk9B*01)p8CkU{+U4?w^Y2bLo`c}6oqf`4VNS*Qu##5J$>by%l6SM3?M*Qzo{3$OL%#JyoT&R)1D4MN9 zMlW-nBE`KN(M*S^1h+UiVm_#X>l5JT*otnp@7e^~OdeNvEc)cN#GkbBse79o@%qJ4 zX{QfXSm#lLq*J^{&w*y7o&_%Whz7e8xc$FE>7RyIv-AeWPav&+L@qOZho!wd%TxF= z<{SJiCrozS!Ur+yk}LD$mO7Vb%^J#dds-a$al6CC;$2yKwwv{DLM1@^7Tjwg=m z!)Gv_2dT(R1?P{!rqeU~M}Lt5Z%axmFRf%MiBeJ1pqf3?h$38t&qQHx$!Mi}zRBPPc-b znB$RYlwA_=`dx6%y z{`bsZSCeOtEO^K_cP_5BIeO1s<{z{@hFz;o>yUBj>?9ePJea(Nf6U3tBuIPl4-FWC zhO;q~97a@6aq)LB73XrI$u)i_2oz7F$m|jdn<$u~EKSouW~2(3c@IH&tPF(xj>)6-5P`uxlHOFC( zgOKnY%l{t}hOpCL1~{$%bw%}>hU-x9vM7&NzN8dRDjI-KQ?{6WvEhmBn00cox(_GT zCx}1k4US-HLj-c}ryvgrMffk!q3m%Ye;Qcn0B{t3F2!7Rf|7*~fHO6|l`F$yuIP`* z{hY132Xvm>M9y#Y=u8`)ELWIgT=(8Z4dj14r2+didBYB6c`|eP^4jl3Zu75<$mREv zy_xA!zU|vmFeaZfPZ$e+Z2s7CSf$AGFE077hwm^xidt)aLGvbGP>CiPju~?&PCzOY zpzvamx)Wb{o<};|sJqX_8yo|RQq@H8(OL_haBCVVRtqidb8n31jXof!hnZKwxa$V>SHUyYP^S|hS$i*W=o#TyPi~| zHqy&Fd9n@iTUA@u)VX$ZV3{G<$lN|~Kyr1x*Po!xBkWO)Vgr)cLtG63FKSEG|DLWU z;&bC>o_Jg$3wviu;9={?8nz)fa)3uUt=sSmXD%*6LnYk-ccFN)!B{6!k;3M7?Iw_g zGsY-52LjZ|08Jb+>&G_WzTO;i?*5r`w(h&lSfvDd(CE35t{ZrVnN@x4kaA4nHR};| zjfK?djoMnd&L$Jl(I9sG_HW28yfzjz6BlGzC9e2QtHMPfHXU2{F@kKL?n30UG~)iL zydD+ers&y3*4fN=oe+0fL(x!-Z&6({F$Z*0ogOsshnWuHWH@a#z zr_~V2Nr9?;qvw)dC2qQ{B!&@>h&R73^UoK1Q%VZh7ePyt!N{fTE!$G5W+O*V5Ze(*x^b*(sssT4Y(kIyZ->=p--qy$ZRze?6?Esq6mrdgFFl zA`tUY-W^5*SjVnbsk;P^-~fDEksvSPaWtgEd`zV6#}WT!UKrm(6b zO*$`RsWTHM&p%3!5aUd6)|52cNrVp8sC818W^<0>eoFzO}7f;nb^@^w)$86Rx;&I>Y5FL zjK_A2Ky8*j7V<*^zf19m*tv~3a7#vktr~zhV0YuLLlRbcw6=C%`h>5ufd;p`h#JB} z1cFF~E6~dX;``t$ukp4#D=0rF4PpeeMwOe(Qh_%P!o|mqPWP0qZ*R@RCd^Nvn>3{Z zwtqSfa}l$CajE0?(*on>JLL=BoAb8ZcUl3BJEX^>2&Jn+7je+zY(m*pZ@}~kDC+-{ z8B{h43X(zlAgDstL!mqVyRHw=VtL{t&?p%lTHjmf<_NZeCZ(MBy^&KQZW0+ULKjEH zV|hqLgny3`N#B2LHWA8ghH>erkxIX1TK43s5A|>&$9L$r-~BePcQPH$!^L{-obrUm zMqgkCt7O<{aDHHE6if(WLaPieK+a3bF8nAMaS0~~x$|egU;Z6wYGdQ#gQ1?@-VJ#O zVx2`nNvn}*;*hxQj89=(3^emRLldg>Yr_UnVPseXdo9q@_j`!Kt3c1uRMhnYd%*On ziICLr6#Gm@C!V072uud+7bg9>Nz?Sfd_N*6`|d4d>3{L!D$q2410*cN0nk@|CXTP z6E;Ap*YPt2xwWI`;`Mjf*cxJ3TjYHU{q)KES58PomfQVw7~ZyQ=i+jhQinuho*ncZ zJ%K`ak1aQXf++(a?+I>@!ZF1$?BP5g>`xV=+mvC^$}&{#TOy5|+kP%xldQ1SB|t+_ z;fF;U*1Gdy$FUw#48s1$#QuLEq6(lt?{2Ux277B!79Iw)NbOY&qm*5^WbJHWS(Gns z*3ABJWnyn%Cl`XctX_ZlKZQwO=$w*(gmXT)?mT}&Z{+z@_(TpD?z-4cT%M0wo*puY zB<9~al_=3W-=A`gs@KYGTBlaGzFH>)$LE`j1542z#J;)UCWP+?#=)Y%kZ=nHZQOsYufY3vulRLm!+<)ZlDM5RL^3hurG6HkvB zbwpwoWr$9g`EMp+Iq;`!)dl;?rEmIN?BYt-K1$0A=AEo^DJWy+q%Bo~dH&VkHb)%M z$m?3FSLa$3&f4fT)HC&CBFYV%$hgCyb7!+U54CyJyk)hE00T%-h<+Ze2z zqV0GBza0azq_gs46xZOn;-n@{AeDfbo69xAER3ljxFcy08YXamL!-B675N-C zQ#|-}ZdJ0e0jJm_xG~O>IKKJ%Tl&u}!!>m36prKXd9W~Xhh1>-Qcu2_Wr6g6{Wd5^ zKVrFTzvSv7JsCTXNUSPeYjH=e(cEjj|35H|4ym6MR<*?@qQcpk;M}>^7ILaJSx#kA z04Aoc_ktE=ikVpK&uyqhg1D>KTR6!G=feT`nYr`V1CGaz4ZM-AeGLvCPn=>tQ3jLhn(X;P({g@ zOet&m`l@>8#pOM31(M=H{t%`0xh_GFkv69jX?qLTI}wdnG~$22&CcP(Hk7qFv{f%a z@UM(ZPIcJ4$h~ls;Dc%2>ooGpg+CggQks3jDa>ebcZDG~YE2bX)Zsg)@S-fL-|BG)WN zXVc8UP^rM^A&Kfh@!J=aXmxNraU_O%ca7aQT!XQ{IjwX7myJNqF7NOAl9n#!#J{{62+-^OS5JxZo-e^KX~L$R z`j@yp1Rf>S?HXQVCcRm{?|675VQ1B;l}8kW#htVhTsB}yXZ8>%YcoXz$`^5{xe=;z zs+W6e=B{5RyYE@fCS1Z_t6L^RvH|JunN)y{$SVdTGdIp7OjIlk=9o`N6cwT$(B%pj zkkioqOjw&w{g3^yoWKd8&-~=74Z}*5dB`5;$NxOKrK({8Jph3!3{C}P@9R8vW~Xl z*HVzuf-*oNSljy;w(y&@_snhy8!;w~LyRQdF^=4I-b`VoDA*9&8WhM>O#q?bsYS!W z$$r%;TskEG^9Xy)N2r0HFWa%Z;__XyvxW-)6z`tf9ZJ~#08!2mxQA9>3WYy#`vjvH zRQ6k8U21=cKjez+tn6qBA=@YV>t0UZsk=qf){5cA^+soqyMyr&BtcAxIJJW-;VOE8 z5>yvJb^WKx92#65muU!Bad1a!Bd%CWJn3rx^|ha0#9qd#E_X}6p78^v(*cC0Zq?Dd z3oj0y6~>!`dKZH*iVm)hs#wMIf>O3rnrfb3(x#K_mhR?+DfZA=ThqQS6YAIIQxL(3 z-ZLZmQ)$M%xId%5LA*l@?s)PMAhK%m={$n6GGP!o!b|b7mKOJ)S{xV436p>p32d^> z6R|0ne6`Nz77eyr#qeKeHK!+ocJsw!fT1mp3L+}xr5O^g4g$x4P@cd1%damtH%Ce%w93G+`1W2(Nl({4>{>V>$Ck;R8T=BdaRlzq zit6&dO%+zZj4A^A!#J$;xUTssDD}RcvKA60QM#Gl-wRJ~|D|{DE*Phktm_qgNmekL z2I1vL1(n+j=&jb50C zNjeJ@t}BjiLFV}c);Ls7Hf1oFJ`~oNo#}Xtz+VK#O}iR+YN@^Vj?y^ZG;RaaP68

      3>-))F@-M~F(+loY{x$X2aZ(m_ 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

      ouA>`ftUm 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%0DHb zGnzN)7+1`J8%fp7Z*_@6ugrwK0sPEXVyDwI*#ARtDT1U`o~L)=d%kt2V?5am#rQFF|m2YG){ySnj>bel1tG(nx!| zqcif|Y`^q)HKQWk_$5W%w(UihQw-5wX8dzaI^rvATM9(V4;@}*Ur&JmZn>+?c^h71 zYxHyx#k_c1BKNm5Hla<$DHcf=%*>G%p;<)2JJtBaU6K8N9a&Rlk)=`=UwWv4SmI65 z2GFeD4`_COIyGi*RdCgI$1d!P^{4Rz=*tC(!n{M)zOP1Ef~ z(|G{AV{f8K(-heWJl7kEx#?by4s<4wMK@SDd0DpY1gCTPjnc1GEzl2wUYDc7hPhb3 zv|j$OEVU4vOz&m($XLX+kgklLRU)bvOFn!(^!F#z>-U_TR%~hp+U>N4<|>LQF%m(p zP+(j=<(qoNBhW)I4Mz-$SBJC(EA6q(8;V!!_B<`qB<}13ggmpko|KPm?K76?z#01` zV&7AqRQ+MxHh&G`&6)i@9hk4*Ej)|1l^b9j`EsX(I%xqt5#64>?vK& z-kyl>Oh1_gT5`Tsh z)tW9b3Sjd?n~`53P*-|mIY~W&g#PLp=HvQ(Uj<1iAU3TWpR_UrEN58-+@ z^bhZ(mIsbKLxu!Jqm~h50-~PZn}UbrDys*;^B-P2_i*4zMuEZBOQGn~$hcMI^wV9~ z{TzxUQaDn;_a^4eOON|&2sy`?wMps%8(XxxAKEjr6>=MHyX8U=}^Z+Aw|%+hl{t=s!jU+Ivb zPRQ)=RP%ZNO$5$;t?I#>Kc(&HU%$BY;Aa(^4Q>PDaHS5BMmjSr5CH(%n4bXcC;({l z9{&VrFa82(i~a-9A`V=qi2Sj&z#p5W%oNF(IgzfhYMYfg%7T%&fvc#K97lXFG-S9C8xLau+% z!1`hymP+fjXCz^ARu&xnzyl77&#|ZUW)#E4V@mtW<%mOnC-rMz`EPwJd~lJU4FLSC z`Urm3NY#x2Dz3|Vt0^s?Kwq#W+ZE(ENA#0r zPl;=TXKjn0N|cy_erz2`9aAcpvM34>U3C`=+s8MJToQF||KMkttvu@k+5dt+7ke=^s(O;^|8%xIz~dFKC+S`nO;{T^G|-@ z-ZTHv$70p0O>NFjxiY}+V<0IRtoev}*cZya_JGrCh6xU9Y1~9*bN+B-!NbLAX_(K3 z5?S_*-;DO_=yEqy(^bA&B(DFuQvSX89eGFNMSELH)OjBOEts<;F98wD*9cQt?H4Gg-sMw?Q-}YD?V2_Ou*<&sD zIkbek@3^ARR>&WnH3Rn8loJQ2NzP3mt0b^dmP%?pe_yIcn+~o6fS(2B>r27xRClMB(4=$$|LwET_o>`7mGhs5Kd%GvSr+sHR5*(F}E`M;MWMZccQUiDNk_s8ekhY%r+bngzpn1O6 ziA_#ns4#R6yFsG_B4;-6B4rcOTIr`fmZ;&L_>e5st0OR(Gd?L+sI-XBA_tWd6>-s1 zG*@}&{f8PfkQXvk`Uv|e;t zp-D>bt=f2FM??{w-)INM+{fp+@%jT@Ue_NK35Q#Lb_T2=Jy=0q;QyAN&9)OcBSArs zYoz0MJAOd#oB8se_idm`7me2Wk3#&>T!-a#U{L8S!yJ) zA4?6t-d~|Eh?W{zunUY_A@Auy)HrA$sILecjcBMi22=FJWgn2_4jO(SD;&qwG(95? zX>Ub~DZ8kDE;x$YR46Pv&MBA%hQ^fbZL1R);|I>x8p?$MhmR#QvbNyHj$(vq<`gF4 zKm6=bz|TGw@v~d?&c_ro$*t5Le1YHs;Ab0?3w{i=g7`ZESkUZkZSX?Z-TT%_;i^0M ztyAPwXB~?wAGbp5?O}ndQa}Fil?-G)w2i$Pv`nNv1(ygeGDtW#RqK~6!|Ru&^5}eF z-0nVMQfl!91JCNCZ;j1kXVu(%;DL|VW4N0F-kz$Yq(4pLZiCLUjS1Fn(NyyZ-gr~W z^xW>*H+B!{FU7H%QyA=gau+ZT>5@kqE*lY|D$S=@dT#pz)!xre@p#cG@o#6p*pL_X zv1j+p5Ps@o*PoP33qmdOvtA!C=0Eva&pn8M8%!)~oej^UI2#D5=xsN7S$n1QYUop( zep)#Mz7^@MRXpqBzl|tDNec?5kQjb52|stmG=!Su=TCU#?0|Kf%?rp{Zv)pO?AvY% zO$~ii8Q?FT55?NdRbvo2PMg*eD?+4#2GH5grb=dv&tV_IQzou<5bIc&#t|oej184) z%Pn`#bM(i{r;v3`|0_SsOqhsXjMp9u>uThXyB1@EA&0D(`DGS z;qUH@evv*_^QS(RHK01h)hyvWdz(4FzqsnuX49~u$4ELubMPMibw=o{y*wtC3-lE>%VDlGRFza=RX{=9UuOQW&CW!ibxmG z5->0GjaHU0s2_Z&5wWh&B1dIOJ7*j$L9Xf$3{^97U^R@=EYo& z#UT{;)Qr3gs&aJwvu%_KVcf2Ra*6%D_Uh>u~DLpJ?tgw4`_!9q1yF^ zkdDZ?-f2D!r@38pIS4Yan&&uR+i0Y}`>aSIp>+Vem9*sw4m zh=(RU0o&28f||ffIQt1EK!HZVf+}?ecK}ceDPR)(u_^dSY{apns;4`hUolHpSN1$(-i)tkKMGWkKOdY)5r1`^|5#=pSh@yod^@)R*?Utj}82xk2NpCubu5Bd|_ql z>j~>IBg`roB{U@0eI&A?lB`_o-C;ZhE(eQ)F45hV7Pub{OfQNqG29<237fyrPn#$H%_6;_(OfM;DjQJb>o6uL%fFxA(}8^W!Vu5;9U^ zNd4yZS8AOwd{3Cg7HIt>;bMP;xb~gxkQr2}IMyM=kVB7$V2Z0tz&HjgNFEA!N42Uatzh9*^xaKsxgwYTe7~jtsW-D z53=_8>5tuNF(>lJx}Wx+9sl8vb&7n+YrIFXIQSK|hTVwUxJ9`46C|Pd@xULJWcU>hMU^3-#e{?ZN_ zWe(mW0tb^`QhtZMbZ$>CKFyykR{U}PXssVOzhC3AOaVct2X5dl7neJI;$Aw|U2LP) zeC^q$!bJZOpc6FYtEcOuZQEPV+!8HuJAZ&p}tF1fkYeV3H{|>d6=fsgFe!v zAj3#JeU_;Yyr+J)SDz0k_7p$h^Lc&-n|0;2!@oP!^gRpX;@A$H7kNIulUgQGnOB>hI6yRbHpcuEjQR zwfz3X?muX7+b&qraT}REK{_TZbDgO$Qc01jW>C<1uM`=lQX8Bos6$7UEOFC$PDU1H zX@#AS^b>^O*SHght9VhRWKt*j4`hjaT_RtX$k!$Eb%}gk%q}iYXqU*>CGvHNd|e`6 zm&n&8@^y)P{i%yxB43xt*Cq0GiF{omUzf<&AArCT`MN~DE|ITGb%}OeqFsS^7tpOswCfV>`e})FU7}r=XxAm$b%}OeqFtA0*CpC@iFQ4> zM7u80t{~yMM7u6|UY9(tOP<&N!#%Grm}k0vxd4`&uS?F?uS?F?CFkps^L5Gjx;P+M za=tD(U;qDcz6y~+ezCqaHxzu6B3H+J@ZI6#ns3oTI0A!yY`Nxj5$zJvar< zHkoH%5K1~%;VUnRJf~k*iWb%fwMZTqcqc1LgO3O5Sb_ZaVm!G(w3SBpa^k@E$&hSjH-dt0RW&g!vpT~0Xtv9DcfLu9 z$LcuWV98ycCSN>*JhT-3jcv8Cdj1p965dVjS*^J40}>tJ#>_>}%Z2jZ zq-gGXpcpOHZcbfTTUY6l&|^dV3RUjopECT9IyPT(PWN=<79En}6LfZ6s76kGYQ2O{ zmZS~kiS0S<_JYPxeeL+C*_E0d}Zjyuz5uS{+gs< zqsGZ}ag@@eR^q#;8yC*W+6L95Bqa^>XGdtT&Rls7@8rtyh$9DrN&IItVjZEq1}R@r z`T<`e`b3`L;zk8D0s81}X%bfTnT%6O(qM)7{91{>7uF_Sz9E|5dR*!RFC`MBz(p%-zv|Ly6l4*0;iHp) zGt38y$Qt%XGuLyQP?%7!!9=jq;KAD%!w6ciAo1_A^{K}2fQh?Jlx5erC_9(stBP=(M-FmwV5 zC6MI)-{{Qzp6hzwk9-Q(&dE7@ueJ7C;Qu_&E|KOL^`}QD9b*T6XxKZjIIL7%%g7FF z5p{j@V5RouAt3P0V9)~5RhU2gV9908HFbFYiV1k(dP`#9e!&}TE9g(dnm*zM7Yd(w2Y76w*tl}PTB7u-(EOs7n<@&=J+;`wI7Ok zSvpIhR)^$^{CQn3V&zuZ<6=)n70H! zusXB03>bF(a8K8ddro-{W4_Zb=}AFjPZBscS(+Bns62kW zlZEYsx^V+$Y2LVaf+?wmbLJml9GW7g`08HQV%Rdj(X?T{Of){f{M`y~zikVa-NXNy=;r3TfZ6!U-uxQ(hCFvXLJIr- zv@o9|>V#38?w@d;9u{4)aCNDk?=GX@aIeM3+pcqn)-~rFm&KeO@62}pnB zgs>|MbUJk3hHR7>U{NWje4HORfxfZ#&U~ndIPlvyc7oTGOr}6*WUc=YwJG554Zcr0 zrkW$n+G{B49o4PtYTEtpb>J)PU!=aym|g{U!#V7q>#^0mS37+H1a2IGPg)!HFPJn2 zSHiV5yTM$i1ta>>B%cFsN-5 z`qlQ(bnXj8P)Nh|pCrvh6$9OV z{W~!RdY4~jbhem=0~VR=x6%{#h959 z@R*IoNCl|8HcTZ->A)AbL-XPY?nndFKGv>a{1TU?Y35*?G1$65%3MYNRfj+ORcix^ z$~Kg6Z}CZK--uHxWx9iI6LF@JTP`PmDFLQCdCc6z!`vH|;h4beld77}y7= zP7ppTyY7qqjC_;ydC@Y~!gGan=b`H96^X2OB&A_5!Q9H+A}i%S)N-*f2uvd>y3Qgc zO!$EZ_E*Y!w-rL~1}mJhbmdo!gq@@&nD~cr+Wzgk)V6+<2>PksQ!~WS%B7RChGdr%<|OX=y8w7h~m4CT?_JP;!KmE!&W+;V^`W6 zZr{A}naP1@sbjO-Xws`rZ$gj_iZ`q#AL*q{TpX?TLXJbkHd5jPA4uvc+v}q?q`(y~ zaKw)fu??frTeLsaCY9>heR+P_3Ziw5pp-X0+{w?41IAq~973IG7dQ!;Np_{|y@*BH z&?xw5alSvFl5l@!xQQ}!*3WEZvZjx(ibtSN7=}=s?a$jaqQr_|ZC-x`T(AljjF-U^ zI2rF3-4A8Oao^8?)ddY;no%iEeY|g-tgA)7f;(_uf$skp!yS$T!zf)cegzo)da!bD zm8;jL*ELc4w6EZk`RyfIgH6xY&Q+DbO5e9{%`YZri6dzCI@|1x{0-Hfb$%CovXDj? z(I6A`pGLE7;(Nmk-~kyhL+8M3@tnxru_Co1=oGu))<^|t@bcprO&i`-Gb3AmYl-Lp zEAS^;>SHbuSoJXPM_L!g3HM+1FnAMEN1KZ7H?sapYimFmVByI#5#uJ1cUlHpP{nhJQtmr+CDr5 z!Qeq_t!vQowb|OW?YO{QF)$6fWcjIKFOPvTg!v5TX?!aJ5{yTQH=9n42fcSgPjxGj z_p#p~&)n64P7R(;+U1`z-8YYtZIFxag5m^4;9>3MIXP_4U(W%48Tn5Gz*x74T%7=2 zW0e&c9IBlZ*q_R--qhky9>v%lJTo0{^8#iS%Nk9(r;_utOKr=B$2P? zT>0|q#hIR}*1It6cd+EGD%AynD!B29PeDbK@e{4%Wd)y-`Ki=`zP*NJsfEQJD=)sC zfDu0z_o+Hy^%zoZ7Gg@kz)#3Ko6oe9ly{lv)eTw#*I+B*AIoun&Coj?J>Sao$ejv5 zu7dTzT=HxU^TsmXcBRIXWxw>Kwvh?RfzlHz=2-==?L*8Ql=|Gvl{qFzBWE`DMp|0P zbjExLcFwJMWHYVfrv@C;+C9;Ep!Ng`SvEbt9G-=rQ5pd4f`(7n_e^ifkfq8v9#Ez! zL)_B~B7~dL{ZqP;HFuKmxZux8m4(4DLbOPXY5l9U)B9g7ty0>2jf7rqh11QOMH%ZZ zhDFl<(^$1;PJI038hb@~=6Q4ao#jF8tvF#}^VP1R?+I>n%xnw-p8~CHl*I{sP3(@0 zg1O*LD6H!^SYv;`9Ru#c^D_+^mdwczrbon`8PAt57sef1cWpy!X4UuvTEh|c2Qs4T z#1M}^>jeb#c;_*iSgC0HQf(b;7`a)PToO-kk9|$oo`@JXji)W4UOdEnd z9cRra0zYVQYxm3{Upc!vW*IVeG>;oMr5MTswcquSf|9L9G=j+d#LLD@p^hD{7puY7 z6c9{hsShJ09?gNq$BO(-bLNvgBXPQDZEZ~IEnZSYo0wP5^M{;ml@rq{P~808KlM40 zljgA`WsL37WRXJ;7x8Y5L$|BfKlyC2$r_UeDB^`JA9@aDRmUY}t3w*@!dd?)C! z$$=!|4S4Di@29p3IIQ1JvCn|zK{)2l`SU$SWlAF=uXQeGeBDtuKdYOtLQ7nDn|l!T zbhi>jdi=ZSnRTbwjuk&!Zsg$rT_e|)lNQotrH6`rk?l%tt#P?bN+2_tv~_JburFvV zT)-c^#fcQVOL)vljB?gQ`yg4H=<$QN3SJH`yyuvl26kMJysFDAowHaj}a3e}@ ze1asORsLaDLH8pnG|vx9ml?qGt)v5GHo$v0whrDK=B?o6lkau;M9ne%}eESkAmq zrzGx!IcLW?J!)vku*?}}?^e;Tur`jkvAX36$zE5b;bpwAUtNG*Vec3YMUGk=zv^Gd z}G+cMv++V1o9_2I}i=#@Y?w@yv@YIX%cgMP`Qf!$VvNAOV- zdt1uhlt1WYYvYv-6`sb)#BZnARhPibIEH|_-qnHw>_1_^GrJYlLBC@b_&1W@I$UOoL?d0fTZ14 zO)*6BW$M|m8k?w%jejV;m%h|Rd-$Z;F1SPL9+qam$~$&?T&1T!SUB46_MV7C(Y zcHthmfm>1Ex{l<*nf#}mpQkKU4x*WqwaBsMQnM(2(h zuuIeT!6(avzn(AF;JRI`8)4o~L+pP`Xs7UVy`^f;agG9w&#G*lUG zd8rRiU<-+ID}$DCs(F81Bz7ycy*cSeeb}?3W!ACSdq^c{p-laKN%FLP3>>Gjw&H84 z(mUK)i(5WO`lDMT(={$;H|fw5n`a{|N^&oYIq`;YUA7rtD4#06m=PR*ZUJMj$edec z82Csd_YTN!#`{%xa1+O6c5T4+#|7Ssj4Ee}B`XKSPP4qHoZ*JUcYU9WZTxaGq#2m&1SQ(Dt_zT+b zyH7cglTPUNrCm>(zyFGr6^KskQwX=1mKYr!3imxAJC{bvx02oGVA&k=ClmVK={ zOFVV(jiN?RzpU+!-qg#C;!!Lk%0{tghziyN2WR}9*!}d2x#sHElCq1mNtyWW7wZZc)$Mj)gQ|^^J0ZUObCdYR_t~LC0vT0a#8vvPrm?P_Hfii&)Upnz%e&Xc&>gv zMqM%J#7k!`fIppMQJpo+=#ZWLU`}0A8A8jsn zM@Yu6V+5?Dh$Mp>;PHj}0{1UPy2vhdU;IBDHign`$k^+$ZgzYKHh=k-QS3hdBHsUx zQEZd0Cv4(R_sa_x-EfzV!R?}0=lA2?&4_)Ax*u{)FTLry6}T*$Whl3LW@)9NE|m({ zi^r5ErO9Vm>@(2IAY1q)ke=hX-?fp38ge+YICX?p-K zjK89O9w8f=Xs&gRPe`xU%!wN7LD_s*TF^I>^vZoQj%Hsrc{7YPtY*YgqIw(yt|~~? zXc$YBSY zQ`dd=|ImQ0S=6tDE(AV7qE~m8=S3g%I_xUE&d~y*d1Sx2a`-4P!;%@;(Kp6nZrpWk zpV!*M@v-x*gvc0Q%V3-4UCsB4x_CHualdQ^}FFlY(7~gOPE7S zc3j9%N}Yex7gR+XgGOH>F-@x(6%D6?JGeWsTocshjbJcW$D0yY>G1)je$hANC^XYCmVc$L4dU)@%==5g51?4*0-T=PpqW1?ETWD-iG$aKWH#H3O z&Qd!V?b>onoCNg_k**1IINP%&br~DJ%y0dU3dTCi)^+$BEOyq%GV}XDr`V}r2yzQK zUY9zS~Hxj!Pv)5v#l~igT`+gYTs6O_3bhA4aPhO9!S zChdeZi$wBFWYh;Qb({OOsA4F2CQHMPyYlKR1Xom6SRvQ;T+sHVlKmAgjZR$%O@{dR zzRi}YNox>GSi!0!@bS^;Z_EJXMAh1{?t@`ihVS*hnKT#)85}VlxSxurx#<|v`tHMH zXZSgik3p`fTuDf7SJ!ZFkmB02;;0fk5o9 z8^ChiD0aucMzKXhuYViGuA|$hkzi3_V5~v#y?Xzul1JZqt@nL{lP#Z}U$}f&c8`*D zd{;RU%Xn{gDN2l}!Q|YNjK(x&!QU|T?Eem;w&oBrU&r8{@ocCTR!S*~_QG0`nlSOI zPL+USS6bZ1))9`R4OJ4_mTemaq{WUxWuD;u!d`0oU^XdizH;N$wEb~}&at7)>Pt#` z&S0Wi@^w`s$96gHhAXro$L(_qQh%(~nyK6J4!^M^HjVexI()wCZCrr58_^tIjNBR! z5(MAuJQXRw6I#MBc9MkfukRROL9Pa`96@7I!|zh5Z!#Tz(pe|iarv+-r)2>`o_^bY zm%&D@tE`Og%I_6CjfIkd>cJbP@WC6q=kY}?nV(#L#rOT@1*kco&-uDb^sTkRH8k$$ z)K&e?S;{}oZ_T>wBGaXR!9Xp5yEM~F7z@CwmEuuS5l$ZXyS75<{)4jjLbD3K5;tgG zkJ=4rh6;O58Cdv)iydRkT!;$SM12rTE?C*nvqfp4HZ^EjgZ_%b>b?z~Jk(xcrLwbC;h=N;12`TLn?+#)1d zQ@+eYSA`n>uucrO1rCHNx1?7)-0xpxoc3!W_jer~Mm%_c68C)9>>sA^X!;LkzP%2u z$Iw#T(#Xyd9YpTRUg^1U4ShITg~I5#w19RnQgX{tSzG^IC_@k><0+rjVbZZk_?q*U z1NWoJUvXVd;+9RpOK)yZ+1veU|O|p7Sq6-Nn#$u%+fUl?E#f z2w3Y!^M3NzOis7!ekZ8^aAwr6F`&~!@1myokw*x;J4gng0Net`ox=CLcWjOwT;6s9 znYq6Jo??6cu%BF}{e5ygHIzWuBjynTqJLJvYi`zSX+waGWo~d-Vrc9xGWDI`xxi(Z zJGE3d%p#V!^?xor_ba<$9DB`Tc8~#OD{{+`NNssFD_mn)0t;rIgn-Yl#@_dz$%I zp5v{zWgmI)M72ki0@OG!d0WtD1Ze~*KN|KHLMx8rt!&<$HU3Io9C~L`i>>vTSAzkJ zgk6jG?bS0?yK0|(H`w z1lxg{v0h)W9YCSMS%8Q??(`$3ta{DQOZ;W&i_y>qdO~V`r>A#{7=&$sO>2#7Fcn|k z|IK%4cw%5|ZZ+`F^O~KGxc={{;%Bffv8po6n5^jN13m<+q3?HV4`e6kO)Zw;(k7~@f>WA%KSTAEaiSC>0`zW%fx=gn=7vf2H1sw#fqy})^t6+Y)p zs}@1H#Zo*BYwJ)*`BbR;jsc2L?I*CpHY;tIP#v8N>W_B`{}5d9xcSqWu=#kb{N(r@ zBS+;A;?`@bwtv+XeKmy}_6X~@gb?pzfV!EZ2V(Xjsz-0uxvZb*GT?UIk-;Qr=YK#U zG;)k_w(-2d;w)-w-7LkSz?$_|A7`nWyGEZ%Il8+92=3Fs2|-l0;n8rjzDNJTU$IE* zB&~rT0{ zWj|ZRne4oY@`75;0JtYZJrS9thUqbljMY`^+3au((UQEu#tlx9dbsM2z%G5%Go-0Xnl1RU0dPn8IuLi3cV> zWdYTRw2#3n?EX&4-O6WT6c-uXK$OILEvvs2tetIc46ll-yiOahqgvdrmmQKymoJ*K zsg3ly@O={L=h5RsA=5)LzZaj62_)sXx1Dek@73Jl-wG!yl#lA&BTiQm)WK z%ay&}>TtCDrP2?PKtui~o|$ORLVSK&+~)DIqjSNL5UpOv$Xz5UUE~K#btS&*elOM= z!GBl#>w78}AEoVPe!gMC>)5{xPA6+RyDMK9!n1ACY0?C!jk| zuVA{uB}bXs_PcO`AkX$`!E)jL_2az!S>-<(eCB@^!vB#IBvn^7Q0dR{0n1ASKP+%> zBb%%3;Y~cUJL0Os>9yE{0#)J@8>^l6=E?|pyXY8XN!C~xmsvTd#~{E?XrxdNC}DWk zxsl=v+wG-ugUep3(t`~eS31YpBj15otF1hyWM(Xdnhx+z-#d*K1inv1&rHVxn~vbO z9P^yp!|Rb_!B3Olxq6$V?ovtaI+jm(|EYa~w{eJwV@)TwO$NG-P&rG-r-lh!+M)#M}KV4{+8Gz)bxEi2F zqANO!_68>5xd!+T$3O(5f}uJWv@=>5ikq+dt|}v}GD;#xX)r&nzi*T&*DRD@-2i@l zK=?(yev$kZRn3^57T!F?%zhuhxQRF|=Cq8-T1qbg;GzqqaSnAimj}H{?9Ad2K+>IC z>*Q=7`1pb28KanOr`PLiAMw-%_lzj$>h+tGo)dfn;iAEq*LI4BizxAf&c?RE(pp9F z)CuRoTlH6JCJuPyF{{GC3a6ni!QY{|tuLkrgV<2?7fY)MBCr=BGvpd_W2gJyq&73U z_*KKe=aRK_JQn%%)(I=SyS^I|T%lEgL#@0+j@;bFy>&LMJ;LJ9%?fB+r^%f>!${d! zwCrKTLVWS&VB$>}z{Ks4FKfPS)?_7|Z|%0e8@X#gU8`gnIZ9|SE8fvOQLEaZRc}@7 zH^|JN??@HCLyMuH!{d0A#2h7I6`akS=%=Mm=LNz2Rw|{}ZafRIpHHhoMB#j-uMl4# zp|@l59vr;J7u}?+mj@Eu;84(IdDNzA0Phrkt4h6 zH`A+}Jt?yX7ePn=M3(&X^?~8$Iu3K>;IGMH_K_%9UJmdRr3Y}__3`DnwI$aq)(iE4 zPXZEI|KankFEP_k_A!*~qcZgb2OK-O5A<4^tt2>HcCNW>N@?J=f|a+Qq@2(xv4Qiu z!sYv10%*CmpP3_-3{mGXRR-NDXP$$G;n_DnT9p^(iv;U&?(gC3bb$0oqfX&oUGfv%yju}F+^gNQ|0Ws$?c#^s9ZO5a0M1MXNn%LL>gra9nS1qMs~ zmJvSvm4Eh|4Y-4I4#igH<5KAV1oV*l6lP<+@Y6ibt(?MB%)2DIi`WA&A$gtaN?5Br zJTJo|YSE2K@oY1VI|kXJ`2~SvQ~UMgRjf@$&n0ULTtA4|s_=R`WtY{^ugj)ZxHqx} z;70+Q z5QJ8sMZ|~hr5bl|CC}K3uig+t@Hg(aF`gV}e2M~At+wK)MtX&1cHe1d-RtYBH^bre7%u?z9si~- z%q02ams9N`i--?~?=`~=L8?b9VZ<5aX1Qz)MqI2kj813mXyZYbM2=;-l`l0o+>FKe z=!EUh5nWK}oy0+_7}%)xk|_eOdVeYYVEx?B7wSU)Hm!lP$J3GF=JKMfd{vIi5C3gp zyL)y9q+0z*oib>*m{iBv1b9#<3vt~JfcE8oc>;QZC7s$#`KAjNbn5jhx;;J%$Gk

      w*!UMi7Dj1&6eu0Cx2lm8iA3}N; z@*VGgeQ*kjU>G5pqoetlV}YUpe)U#Gmu3PZA}F3owIsw0ZmBRHtxd0smHsuV|Qb2R7)Ovlu%c#pSp2jvDct()7E3 zKmuHMM*4bA43FVkST1Ju8zYuIbp2zM^m`Bz4t+A1~XpRA}^^*>a%FOa`RUr$EG(V^0=zh@~>mHCxNG=K^DJn}bpV5t!`Sc(U< zwB^9_Y58#^!rddf)Y@XdhNsU$_!$E;UF9o<@k(5k9>hWA;I6%Ra<5LdsaOic$DpPJ zS$eZj-{>XCK^@lFM(K_pBWZC<(8Bm8iXOZr*o_2A-Hrqc=-ovMUeh>Y~;pDX2pG1P1oGeDZH4lY~%?nSKS$!t#rJKbHa6#Wl{Uyh z8Rf zYcNIpBqazCVpu(^O*>)n3&e#-NgZLLT+dfn@4N?+);W8mQmNq$>BFKq&Yr>3eYa@y z;V&@@u6H#0H#zefkjkfzCkGDSf75QjvlZ|)bc3$@sgt0D2s;cTcf zB3mSDCynA8JTx5{T4tmag$S$&j&O6+S1wuhb4PPF*c-YEJ)d5F${VoJs~_s0XooM& zA=_beSU<4Z*@Xe5s>1!N*7z%3AEXbn8|RnXEhTp8Z@=ZxA9QbIFM?9U;V!2MZfvW?g^)m%5v!)?nM3)x| zPQRpdV2STjH&zVKZ1sdspgUJp%G`E2aNl^K3Ekc6$tX_$-7fE25y&&XKB!(h&)0Tk9=IEWK_o z+?f|?V_#Y;Uv@$lsT@!+H?tSD_PmkBoHT>yzY^X_VW%*c6W6tbkCsK46AS*_)$L0e z$}5jXAy-mt2uWWbsY={eOM8^ayak~)oUKdmFFZgYsX4artY1NF{iIe_2j~4Bz%wJQ z5guJ#>s$fP$CX8r3r)uRt-JHCH~jIhjz9~nU)9~2`=6QB={Be!_zBem7IHxqQIm#c zBWeyj!1UaMy#D74uO^>X_nqx`1Kw zXXgHN5#ID2CygsQM?0Iv4Hc$wlk!7x)@{SYq}Oi34OjKjGFlntOZjEjl@x%X7wYmm z2B5IGafps$r|lz_eo%a8sO6^kPS|roez}CFxikQ`^w=bU8h*jeRSo<{*P=a}mZAKO zK7iLgKF!zG7OWrGb#XSNH-ma=n$PY+{t7rva;Y5qx;8g;Xyj5+rJJqK;Ekx7-x4hl zE=+(g^LBBJE*Bob1p)oH1R*sKGbek%KU0(^ChdB6GBULKY6%m^r0wbSUzL`6|EDYu{ew@_5Bb_~S055M^D z!SX0*?0VPTQOG0W)TgotAgVG}l5ih&2D|*|oA>KCmzKGUsj#9*v9~TTH2G2X)grtP z?Tr(Rw^zyE2flR1v-e22nbzV7@hB~jA8FlqELDGqMrhCqxIbDwSI%x7`x7(e>=cO# z@T*u$qVqFMe3lk4P|b{9r!B|ZNGBvUVLMy&{rj_VPFwV@1n^+uG2~ptcEtDtu3ETB zsDD?3l`l;WT(VhdF9Cxt^B2?nykHo6&!ns!bnNsPMepi@pI|Sk{Ow8lC0_^F_tstB zhJk|NsVvIsuIXyO!7?oBMoiYoyyKXEW!Hf~>E@Deu#6ywbH|EVm2-2f3V&y%vaGzB zJ4%V87d9a~%*>;H-V`WAxUH-w`;upwMyU#0)FeQm9A|= zKi&Z)m=^ZlR0RV$KY>lD*T&!^BPHbW`sCV#g3pSQr*xuTdw?t1@7C63Kv$ra|rakN~np>OSzKl`cI)HhiNyF^-kha z%4k>bov{dAdA6S6XG#(K zi>|5Q1T%u;U6udSSoP@IFRsg03>wms+ZZ}CLLA6nLk;4E&;IoS=(;jxXk(BIYTgCe zEILQ^74HUpQ1gl8ZMYuTe~HIP3Gz8wb5>PrOTs zc8ok){(5UjgG!P_@Cqu#a6z;#l>M5Ny;U+Zq;->GhlI~U zYfhqOGIPiWj(29DqZ<(iLDKti`JT~!aha&7>5DMiDmkSO3~RGd%4J3!8Be?p^FOA7 z?2l*MjeYj|%U%5ztDh85xV^s=_JG|VK9>?o8bX*O@T?*K)WVhRd51{a=X$PLy*%%s zyiY$_iFs4Y!E&=x@HvFULi?zTM!I&$$*;n!sD%0TO_(g`^USrhM01xp%5SyHuLXnu zmA8Pq84(Zv;b35c`?I~1-{6J(_TKf_$$3DS$kMPpa|TELW(qeZh-vJ)RHZ*qrY?i> zw|4N>8#8NtJ6b7X?{92ApL^@IJa8{EIQwMQ?Qp4LXWAPg@nl!CQ?aR`q326JF{YG5 zxQ^R_!L7z1(jA-|H?tQpHbkoEr@@|?iK0x0FZ;<;&xp#Rf>FAN^#I;Ud-mTW-X0Ne|LV8t)VoAwA;TN`Fk^!)kKQ|aLN@Q?VFt~*+g zIj{u9G=o~v*NsM{Wo=A9Yv!iIdJE4y{0;KWcPkBS+$4_Oa^T!qjL3ZMCoxCH`8G=L zJ17L|urIL1DRANxNPHvlywZl<8YSTN2w6xD)kH2us$onGb&w6fZm)ugoz}>XErsn* zd9y(LYNL}FvN|BX{*Ox=RGd7lwwyP@8UF3GHlpS?huO&R?qp76N02ky=fPX4S_;%R z-hu>wtE60xKR37+dKaz>+N;}yVvf5$spI$k3)T;vBuVC7bdPx!DIN2!rslY5u64rO7wH4nCxuFRbz zRR5-4aIBCu>dazcMlm&W?V`)If6pxS0{cLd3@lF9NHm;dkB_439$Oc@{Y!#bCjRFwFXM^qvdG|OTt}Z4uGG`Y_^1%{o&p#t;LG?DdAzPr-)GU@wW;{ zZ5gw8V29CHHV7E^GYWLpFbP$uh$*g=(kik*VZDj4?m!*yYz+`RQm3#GhGXh0e= zO3#|c-%d$!ZZ86*+xF_>DP0#HnU(#E75<_M+>WKV)T;b%30+SSIN0#tm6U@ma3ft;D|6c2h{aAnBe`lo`yf zDZ0%#^`aPJUiXMvej04K_;$?TY8a;UuGL%@xCL?EsQD)L*T$3}v&y0%SziRA;I}00K zs@I1sa2eJm#$$HNajMVrK7QnN1Hws&op7!JRhDe?Is}y5q0ozK2R;2fBX_k{q@l_) zSOiAa*eNc%g;r+ED?~3t)EsW9oJ{SbHI?58w4nyxSqzA91P#9P+d!?jeszl!<)X10BWN1^c43=^;4`s}jc(*xlB z`iCAw%T~g=<^eQ*9ec?#mv8R8Z?B+bQ(u|#?9R+@(goZ2uIv4fvdH?n94LMjf_+=r z+CqP$C}pMg+h8d`(pKZ6teLV6X3_y32DF9vl(v^tRi{5qV3_!CrH)+gcmMB@9Fyo| zCL3IcbE|7E*E3jf!2Fe|sIF|grRC?SRaZLXDFUDk=O!v%31HSA@U9J}x7Vq5b)1>C zqDv!7v(IF9=W|G|z8$D72EwBv{H+xP)@9@Q4%$Gd1Wd9GNYYGH^Jk<jkG}pjQuEi-# zS%UQt6h!LHBEPkk>#a7z&9gP-6U?6fc?$Z`+9E2Kz0naBV7JH)M80zZhse4I;{F0m zn)6v@(}m9vH?Ybm*}9OsbCk89oOOXwi4dM1u5C6A9^dL&RP){YGgZnZPyfSYL0tO^ z%*YYU_NJ4@_A6`LBGwgI?bkXE%zHL~WCEE^nkx?kA#QLAqZFN*-ETi8Wl{dojeaI9 z{L{SMQzl4j$Cs3g`G7KBZt=4@;mAdpDTbzuXYApwP^O0Bh+Y>)ea!b$PxOqt{F2td^&<$@$8w15=DLejHqALEp0IR=6kw^5KkXC{= z)c+Js0UYz@^y+mkJ3gHL@FGN0!MQf0zasZs;#ssy+5@Z_nZ`kD0^FRmOS4D6KB$8k z^~?`D*V66@)CibGRG@B_PMjj|NS01fb?4CrWM}xqR0n^X>I0ZSH$f6=UYk zEOtVTWGQ|I?nxVPfg7q#=P|??51qtQ0Pm4b%u+7lEHYnI2l>1NtzX2iZk;3qI_oQ7 z8TB!*Q#QsR$H~S+XpwM3Z(@^3e@Plng_}1&L9tRie%f#Y46T=J0%4LAPoGk7IILc* z_NcYBgNL69cMA;Qp~Kx&W=oU}<${MMDml=g)8R3*`TJ|*q>879IHA%l54u|-&22@v z%5&@#P)|yQKxV358ETQs<>lf_U*hh!-0q*NG#kDEQJgbbMn`19K7%{))vo}?25ODz z*xiX{H3CDU)yu#2!J<3dkH5U?rM&{&7flAYinEouWk8>nnBzKSkd=R{3(BbmXW7SI zhm&{fcE9RjkSa8^p~*#qgV-|ITCHQ+?vdeu9}x7T5%hF8GR>PR!Uy!p0%Q;- z5PX4^4ubs^W!_8!uf6%SchTjYg*ACmVQ|vbx4Y49y{*u+6BfQLuoTy&?sr6`9Or3K zPm!y^X)rTP`PZ(`OtWXx#II1UOfPc*y*o8KQh8_>u}>|*d6LhuzNf9gpeq|qNCz;d zhG&93OgRNoCuzWbH)rrAoz_aWAsp&|o?>?Z(paNW(0 z4ztH%#EfdUY4vJ8D+%H<+o@XHlVg}GT18Q(UTl(R{|qIeg8g@k z^`x{YL@nZ_UJmCG`u=xIo^@3&C2}H@;siT7`VT9UJ8^w^@YD@D^cP~FD{H46n)Z)q zQp!**c|HytaI2jE z#CrjI-j^=+|XUSS=<6*`KBD>KN{77^n{bD<+Qk1LG34nIJh z1+iC?1_<=0#2hSXCs)6tvw_b``U9D>v|n;!1RuZK?6u=eBJboB{30XG+f=$9|A1Zt zxh9~aHy8=EWP5yG%=}(9UfCff z%b0j)YWr@evF#hv@;!NT!DDh9VyQe^!IJXbJ?C*VKIku1i~=-D`ZW3IC#_oIS?_|X z&gqXLw%=nmj-fU$M-yz0CEe6}OK|s4_@h+pKv9qDR~ry_neG!1%rhT+37vi@W@ML) zFNjYgH!0U^md7heIG0!0J0zYB5pSu_J$K%y*D+p!JH+_=xHOY?hqxh}V3Gv^bimaj zE1b}IEZj+4+HW6L`%>nkyur(;9V$mYDYp@>=w+7WJ|J&d8b>###9e-WeeVC{(?s951Rm!?l8TTO2{EeJu9$oMw*jP5a3-*-SC!%HJ*B*U%4GpiZ;L z8(iZmK`MYt7kO)j>ZPzFY?g6!hXLIqG*;YeaU6B%<{!`&F$tprH0|P)1@P=h0{v& zygk=kemM&)7vlR2ysW1M-+t+c7e}sM@%V4W3Sq=p}`w> zl#1yqc+01jAm1Bi+(!4S^a}>vhKa6W*jUqa;MupzCQC=Uhn7o`Nnji`4f@&Fzm=q z7id9Tp1n7vQ1I=jI8YOCz#!1fO*nm%4Tji{Hbnr(=TUfHuS_Uqj+cFvP)t2LXyrC| zYEkWy(Lpdib3{(%?D)toTfT(gjUJW_P*}nWXkKeWAf+M|2nfnQEere&fMS6tXqnyD zR2VrgXwz=A*Qa_|G z$3(WM^q{qp98H_j2jCN}s;`?=ra(VwNW zJ&Ewx4mk{T?EKW|2l^MGOz2K9JK&4k&E{;9kD%a$s>~dhLKkSY)Y@cwn&LVX#TKyHhpJ z(QkH3H>j*5$H9GsgbmzhgW9C+=4 zKz>F1@;Q7}oJ?b8_x~Fjy5&RC9$ng>JIs%+1JZ!jpr20LJa9MMfiB~rLrqs%ehQZK{bFUBt_M^PgF zSh4#d)62w>%FPv3d$*e+-HobyAl!%@8HPhWCA~)ztaJw4yP^wskuE;=q)CVRa@`qH zy2lDeBUL#)8)m`;fSqX6!c3)z_hBBAFJ{t-ygsfs2YxEt@m73CcgV58gVC&r-p5!S zrM;;EU0rq;RDec=&desw?dE^lI~UNUk5mM2=SlvKN_e(IGEhNflAYh*1pp73rc0bXu`k;JQ>WR~Q$R3{u#ZL?2muDsr65SZU|lt2a>$21 zdM(X6f2=U8NvfFmIuaY_J_jiRTh#F*?(FhCv!!KpyN5Umlry6IxL+cJ>^%_~9-&h{ zVBzWE)LgS0jDljHbk=m*S zwrYaCZGenL3)#ko&;x-~0NRQJ2qUhq>q}(LhpRZe{p}akLe-Q8(Q?j^`%g(+lnw%L z!G9ld{>BIn`#HmYei+4&nJ3$>%RouS&uwk`^R$=v4e-G?Xv$Xlmq)KOiP=_>t@KV0 zR`FnB282DdCya65vyrLzW?U0}Gl*^hebwsv1J~n6>C=tgj#pA~apHi#JyOFW>*N@$ z-bEOgC{25Z#RV|mrK>Qo>n80FADdIz1veXiDMfqwG*0LDqV=ztmve#&0s>9V;p>3T zP50jO3x(!WS?~H5)#d$f87O5c4`P0Bw37RIU2z#gZ!ZmkPFeu{FnxEl6iLRpz?}aH z9k9GZl(WY7r{!wOXbU%Ta0HuP?9|Ql8H4dXxC)9VMeRYQ~hPcdLW3(u%&^cC3lR|(udGrA3{pb>4trjB96=mrn`p& zSXd8>45M$Yh#5iH?Ud=g1yt;zPcuNF_8<7wQ6Z!C`aquMY5L6sdVw%>Wo~G+TDT0v zMJuN-=&d1T!tvlBCGnF@lKVjnz4C7U#` zf9@c_gFjyxzcFo-{wLgnzMesQ^~TEOOlj@B-wXwdv_F#F(>L=LFup;R!cN}GzenL* zV-0&C{W!-R>P@NqBc$>{^CyG5PNubKW zdR^g<|M;wlI#-r^2iLAPUGR-cn0aETC-E2^QA>zgUcH9RSL~ZS*}F1tvvp5Ya|06q z-plQ)67~g9$zD5EKYYD)$>gasT9wdc{$_ZIb%*H`Ss=o=R^it@4@B8PSGw;N7B);k z<~2{E1=3Vfun#$7cB$%HLs+qpxy>pusg4n=a(Z`V_J_{y9PopWFQ6Tg{eAmfGgMKA zw0cYm=&L+Dpm=nKD4V2PGj=L6%vLufDE65X#5io-C*rfdtXhUm`>F`i`dd#;f_t7lE`O*GyZaAO zloS1L@nv}%$+qbiq4iwx`m-Xi6sRcdnn<7b3nUB&Bt)wrfwpjQVs};g6d5mEhI_mb z%x-H|Ito2KTjuy@uXb$S5M9G$!;O&YMPjdXvj;Uk7hFx-iDfCt^m?SIgsKqeoeQ1C z&)A;pX5*Qcuj=et*o{ zwheJuU$2-}@8#e>n3?p)+n@;Hrv+t zY~1yD5O7uv{QdJMUC#fvr)v&&3v_FXZdnkC39xPE0Ps4E2_vZZi9|UyHu60Woo1OK zZ96-D)w=v)W$LIug^UTHn*k*7RM*xB%KVXxL#8(z6L;V533=c32I#7|vS~NGk~>yI zIZ+s_f_0hcHe)pU-ujdm6g2h$NLdgu3JG!7`;hO5qu0VZJZ6?od}?uv0)_5Wp5nyj zq{ERB3V74uKg!Ts*!xD-4N7l&_yTqK#4vwO@Wyhl(ovEAKio)V|NN~*6Qq(awyD_EXEKbHHqqH!!D9E>V@zr845AGfFq0$obZ5=S+fqQ4)k-{6*7m|xNH4zKt~%~?Du zo@5dA9V>N)xt|WKQna&C-gBL_azl~Q4cJ%*q&wU4ne%QLsrh|>JIR3kbVgwY{L3~{ z<^6gV3dc4QmTB{Ei#Xv6oCoAFQpcE$lKL zok)S0OGxudr&Wdl4(_&A=ot6RGcdWfcyZO$ zTS2rzzAdw;yAcBckKvr*-`$yT?5o_|c66X1dg(X%-Uz#cHw`;uLOQ@lzQ8C>PoJVc zPVRntwz%8VG_ywPeD3$gQ@KD4qkeXWbgwg36{T*r_1h?g!*M!dDkMNHCX3s8P<>vT z86V=C68{RaP<3|;0yuh0nDD;m_}>*PSrc%Hc}Pjj%qUn z)ps08I|BMnR0=Tn2t6_6K7SH4cTpu6G%$^p{M7*$BrqwYae6tdl4HOF%UPCLK0P0p zP&K2Uclejhh2!S{DIKz>RQTjg-nu=+XNh9i0~jEU1p>mhCs5#DM<7TH*Ll2hhFkDW z#!Cr1fIf+^1}*Z3uPys$U( zi)xIPNx^E#732|3D?R3nmcpxrv_V-IW>8g2qKn3Dfl^S)iX`5lh$?1uN3n^&n4^lY47oc(T%Y|V* zPckQkx98_H(=&GBe5Qiax%-pH&X8v@8o|1p`bcq8F)kUJkZqTB3*3rMC=36hwG~bglIRSS#a(#-hg8J%$kFrhb`Kw9*+ip+r`c3qXGV7@u zFEL~F4x_1ay&S5NB$iZufq<-J&bOwDwt&AWq7@sn_rLD?J>etqzYc$XuaW)I`Y^#T zj{wg=BUUB`n3+?h^JL+)lOz85*k5M^XEG8o{k{<{GO`KrhQ6*R<+H^W*}i@HNDFzu z)RSJRWg_TcSZ8S8dXu(J8{O9|PRqgQR?TG5v)v0n!bAJ}zQTbAm7ur~gl@}qz)Oa= zdj~KqHOhI3{1cgrXA>hg8||I4Xx_A0yO||({0BE_jEeC-JYMI;B-}13?jxc%TnSRY z+ZlVKBU{689pQM}JSc19P8>*Ss(QRom^%}3feyAkbLS9pif-?lD zBDjs(W~V+zG`lhU%i|UpPxo&tOC?j9JTo zAh{hMLIMg7%cEE)6414`^FNa=EH8@bL_bGYc;BOZ4-lWdY8kB|Yc3o+DH-Q<4cK1W z(JdiaiKqRdvfCCCOdjc^N`mZgL596zH{mj-5A!}Pfb;B79g*YINR?Z6UPn7XfLOd@ zMvT#Cd|yf%O@AL-dNDiYZBw%)X}Q{*;(<-#ymaC}%$4tgwaE@+c&I}FSD3K?jes~q z6I@{R&~9<8FHfzNc{52i*>|^Ep8Hc@Ox4UN;yJOmNLgWmRd|21DS9K*bvjQ>)Yz?) z*c^E0z0@4HUzE<`<7at?+&=%^!L`~8vsHGI5VWz&c=o^FtY06muHH#FY8jAd0vr~H z$}gQ4h8U{j)6S@#b-t6D_K554+7aQdTYGlyRsrSx&`{q)=xgys@3@xryhF-1aeL}^ zz)_!ri2jh0Sg(%k6qw=EUC*BpE`}WoEnSh#;KhzuU7%*_*Z0b?6I;0>D^U_dqV6s%>*ta;ic;{tz@+KUI{Fj6BIg7F{Ili9kB)~D0-uO z+{*_2oj`wrw|eZJoPLglM`XCYvpB@>q$w}yY+)PNqV>AIfvFj>ro`x@+c>!D+h3OT zE91Mj^6y4vhsG}K$h9vB{rt$HfP3Gs;D^y+9pWf9cSHQnQH`o3RM36WFRrC2T)%sK zxo^d1GAbQ?J%{{{JloZ5srO+zSkUh=EAV1r{k6+>0LN1L(ZT&jWw$=eIevW7%WM`g z@x@eK46tbDFyk38A%jVE1pcri{1sNldqLYa6Ii2!#&+$VTQi`&>wXLMg$WA3VPs0i<{rNfAV0*FgD}vne)O)#tzHfWLiBe0& z#+@zCJZyE-;;!Ww+B(6jz!P^42o)(A$4MJ# zr%gCZ*(`>8dv5X%e16rjZz&~z*I&(qh>SZ_@&&BdME_DQy?3c+^M9I)O8=S!GVV94 zUD&G!R(mq%#kMphBcUJ3ogWCKDu6iS(45tV`HY2RyF=f9X4I%I?hfv>2$-eNp6XrD zWZ`s77H4+DUhl%iH@lp;tvtCf^(JE~limo_M=o1PZj*w9_;HTv-bS*A6rdGO6J9E_ z-gK*Z83dO39BAZjcM(hz)B{&+MvrkZo^=!V*DGn@%!1}^>h@Uc3MnJ>fD(;YQs#*@ z6g^M9`OrS1j)}O;D>-zi0;>^Uf?B*iNBLkK&pbc2J)xS{bIe+h2cvX36ixMgX`lYf zq~e}kG!BO3FFD}vg|p`>73QsG=;t9BA0fJIr3a+C5Z3bUVv^>`V=M@p&);DT`jpLj zR$~6i&HrUgZ8Uf9yH4as^sYM>C?P-BDnm zI~w31&A3UtUVQb!{u`UDKBRw5%m_Fbv3Y=TcP1+rw>#!T)t?sxu>J#n(Nl}} z#(vh1It*`3cPjYlmw*`Ub2mD!yFGvxmIh07$={>EPpW{@082(8$Aq(M&}w5b%mG7u zWasIjs4^TeQWt)ScvSh@=(Sjv$def^MK>c)V(o$$Ca=des{3ySiK&JJ`j)DPe3jzN zWYii=-gklQ3aR$WSqQP_Pp4YzXz$}y-k+SUMy%PgKGrEfQaM`F#9N=6o0y!E7EOMQ2UZa)!_(png4W>g7z`?@?loE{84iLQuaQ zg3oXUB<|EbZWi?wjO1ql-*{r^1Om@#EY$@Vh7aON1ofQa)=QVaWMhsxSU}3Fw)W6% z>5BnbuT7Pd7q=DkPtk64bzV2ZMnVJW?HxAhFHKj1m6XTUu_JseWGJ}a0^1bt15FMX zG2al|l8&NhS4oCs+UH9jBcV$I^zxieThh33hyLAIHG^u|toNnseZ|HezNDRR>pFw^ zX1>w!kB!wB)e}Z<^LxgT8rfSVw(uX`({Yz%AMjrZCjAZyZaw>C;;6i>K-_aDYzssY zH(}D6PdTY*Uw=3df6&bxF_*YMKa6I*a}2aN3P7_;HYiqO&EQxxXEajVC6wKL zjlLB7eD-sE+>1Bt?p^bY0Cs}>xatREo`NvX(Ft-2t8;k}NeR1XZ@y^d3t~JO=~N?~ z*6&Q$`23?mJ;BQ1jO|H3h-^@)hPd}aEKTaHt8vDoO8Y&+z7Z-I=>M8K)KlZC0-A*3 zJyCsKjri8-)`>amJUTZk(WBKaj~)dXk0dH>`bcloFy$mx6T)gn`Ln?{JH{6eNc4pL zdF&`yY1CuzxLP_bu9VZ$MYx9iy3tSWJ`cJ}g*n^`hq=CiQR zCd(g|{k2+v#KKm1Ky_S81kENymn2sTkuzBt_Ft7dcbhNF;DUs=LMK&2^VDYzq5w|z zdGZiC!)rVw&c^58ycSD(Jm4?##a;z`vAIOR2&!p|g4x=35RRq)@kvL@(VgCD9?=nD zBQ6)y=e08gqUJ$2KU4!7`k~I2k6Bo?uJedX|FQA^clQiA|(Ck-?2%6o6c+QS$2$Phy7WmeHujGG1vpxVc>kQaUho}i}MmjHR*r|C1Ny<=Hcm}YZ zucDL|{;TS{I#?oTlZ-5|ikYkoyfBG6uPX@MI9w>q@Ih!Igl+o8rbg*XY8AK4Dqd)0 z_(X_Tbh7(uyG{D;o^jBXxEbE*zSuiT=0D8BN%Xzb{E}`f=#mBFAyE)cvi(8i7P$67 zFfs0wVK)gRmII zySo2+wpb-w&ynuR8SS1Dh;*@DPk_Z?i5BGW?;I>>P4mRLBEXXgC?r&OU6@YnwXc`y zwhi7=fG##2wNc|sz_uHc1G2YFjRfuZR!S}NMGU=G)TB@;c$JD~B|LLd! zM)VZBt}3|9<;{1oc;Vd!B?4dP&5mf!(VzA{`_K0x|Bq!lVCp#nSRPMU)N0cd2fGa{m7C<%rjjm zSIvkvvk(~oyEb5f$$u2Z>3s2fRez!eeoxM;Al{;jo1o#AH)Ueew79-XTn&oRv_FT< zmMf0tJ=C!?bmd;PC0HFVe+ghdpFc8Zb@K zS)h4eojxi24^zvBA%POGoQJZPX5!{kWXyy;B6NOmJ2k^U7U(N3ZTfpZrG_rdF@t|Z ziV6qQ{fFoN>6}aHqDW)__ITi)_5++}USF;`xTEK^-?VPdgqD2xD1(d>EM9lHu^ym3 zgpesv*Y~;a@?Hgpo6)@28RW01Pe$*pqU?=KPytXn`;EgBCu~)drP z(}`2j<<7CapvoO-)&uxLEV5R<#Lw$VEbNs>Ua+!&f`L}|SO~4|MqhH_rX>S!9%*6->ie0Og_JAci}gcfXP@SLRXJ)$9g}R&6C*+O^Cvn-)Q{ zU1R+Z%!B0qg_8h&hWTWh7aC|~-IFLtGI{Mnu!@F(7ofq(AQ``Z`k zawX;;6jh}$<=bfF6}nt7UvY%j(cK%kojk6-DVN~VibZe~84dV>#7+nQ`^1Xf-^O>r zIPDsnM=BGhX5zmgDUPs#G4lA(L}PO$HO1~g%p;*VkmXpk*YQh#OXBB8NErMc$^ngg zm{Bk__UneOX2xRU1w&Hldt&Vp!5266GVVHLaBU&rCEDVxTad($WBTEAnjF>{b!9d~ z9E`Zi$j0u7bI9Nsx|lXT5DHp>XZ={q%Bn8*Zph4`@Uj}aHjsf5n|bABw~(oJXUBfH z;Q4{`^AcE6{?bMa(3Bo_Y5Zs>{>u1@*gS7_I){IE?^5&nFh@09pnnfJTrk7@C5Zb6 zn$`RdH2VqW&7XjM762Kef`hIa5+g1kK_v??;6a>3NOw@5^6tW(Nj| z1=cXE%v1NpZ`E!G4drGQIZ~V>R4HekcanjNfQhj?up|ySP!wjPUpVw@m zdu6`bSvG?iZkYhrWg%WMEgvy!-eLYn5SKCoSBOvBEpE}3o7R>n6=M&2ot+@l`skK~ zD-u%1#*Hu7w&$_?7NjZRrG(sFGNxt$^l{L13%xq|HH1-@4EDRTAO=lTMw!sOB8J9Q zh5<(;&<^}rC$8?O3HvAIIQ{Z$l)SuR?bf9qm1rDmH#7gz#+d}^ZT=&#PuUg70KXP7XqyV8G^to=vzQ zxUF<*$}iv3^T7>e=|JektmMrlvr`GD$KC+z$<7FkENBHeLj+>gfD)G8<%V?)0XgK3=+IW!YZ?wptfizn#X`BUR;S9z6iVw3Tyyf>_1yB z5aB}6c^U+!YXym1h)LxD@@-K%-pBa7;&UjU3KSe?In2wO@}AY54kM8r(Y@T*u`XRW znsE{{PmOx%gKz+#+5MCY05sdVUzKq4F1>SSI6urf86Fhi3Msmrl^P89WPC3Bc|T^r z`!L&Xd_u$V;^VOR#%RnNDXZM(3&@alXw&z8edxc98cEcBpkVm zwo&7lE4tK;ptc~Nx<7EO2p*VOn2M;BhD-OpesXtFIx2zJ(RRH>JU}k8tFda@NR5{Q zPDjd>-ZONBj!&nAmDjT)Zlk|%g>No9usI|GeNcKzdDG@E31s95^QfdiUt*pqrA@|T zeE?hR(@c%bESEVF)qUY^sfOdp6kc|L@sDj@ur#t~y3hIL^A)aAi!cr9nAB%F)nT2P z@ITD#ugd_vcZj;0iT_6z>-ldzoT|kBuJ-FAw(2^dLz$Cp@BFGOHx8pyiaU5QKK_cf-@V|-%&@s;XKX#<7l zPz315Qsvq7fljw`u&+%kS|6u4l17@U@qMGV)J~s7E7$SAw^8hav5!ikKKd2J-^}dC zaDfwPJY1xUz4TwY*t7rYVwa*n;dxfyu{8)YKo`sHF`BOttm39s?>RqussFWI5)gvEtxn-og8KrA}`ejQ-Z5`?E`Z@{H9ZVwlQPpy6 z?!|%3z7d)gVP?b(e^?CHFom35pH|Zc4a9kE)V* zkF*ee5aQQNv%va_cDKSOFT*KED-A_&DSHP(-?{P~wR*t(jirQ7Lf*=E{4kQ4x`mlHT(#yZ#-)xjoorjz1r!O3J^n&FKxQ_P1Vv?>wy zPKg@ha%#pZGIJ;7E_S$EqJG<0wZ|Cj{UWo{JX>-DFpBF0iyaK7$fb4mNr%i3Z9ebd z?A_z^at3biGJY?cW90#(JQDWnLe0mGTn;o;CTx&SlG{aQH#JxtP}X&X=#du$ejDep z{4c<~(YtLLx|rDqlT7bqy{KhjB9(QYJwD6Po^w0ks>nU{Q8^uiJ+u%LU$>ibF%qVM z-#m#y0-qY*(;WD`EZ#|>Ynf|S+C7ZUi)s#Br8vT4=@6@Bj(-lo%&z7HqCNFSVYLY6 z=(U;`v4lN$ZvMTWw(6b*wt_}<`l0D)-~+Fei)#+Qr)PCjwK}+;mC}78r6_V$^xn4< zqmf}x9AUtav3YKA*Z~9e6ulvr(u0({8;4C7r+#ac)r1l0-|(tO9PFBoUvRUM!JHSW zFf0zV^qp(|Zr|iGI5vTSDh?7X-7o4MG~f)ZL-Os!ksVVu6Zsw#)0-6b+Vl=&c;%c)PBpJveL2bjgc{QyuI6<)pQ)2`e7 zZ}<`p(IQ>Hs`@N4Sm+7}_?8ONO%)pZyk0yPHPSpT2Wn>HE`3Z=2Fyi%b8yq$X}i9^ zCDXthuaFD8$4sh7rjoHAj;|tAUiCZby<}o=)WFjEaa5Dr<^1hn+|>nVDY)}f8RY|v zv>~tUVHOEC*jX<)Z%iXQ#iyb#n{(Pj%c^Q73Zfro+Gv@wYiLR>K`_03xmsXd%J$5} zO1scUD{XFD*cPR7jPI>Tjbp{7EixrZ?+(i^xU8=X`^N>4u?0&kY!p|=+zR5->ghD2 z?Y1`yVmh-KMQ_puce{u6sQKLMU^&t9JC!t*+|R;!nS%urm>uAU{yr1!xyD>#TCA&z z%bnO15^&15;sgn#ocCM-Ke%Tv0-ceh8!nz-!F#;_dk9W2bxjSA2eC9nz3bd7k2oc9FMZ z`qd6@7MtZ(lCb6W?WPA)8lY%uiD+QQow5$(oWN@m0Ot0LhQ0=P5Ro?)fW-TZfCLz# zw#tcP!vq%=O5VKykQ$~F1dqK?r0T&07+$)d23N(f@B6A;MRJSV)GF=^=E{b!?R*sQ3jrCn8Ma{$7fL`W9 zYzHzR#MyzuZoev{=e^Yq9nkKx1X=tYe5`q!7sB(%fVf05D0>`yZma6jE;Mon7+hXq zZ6x^G)GiDRFVnL#?>Y|%`mBuFhS3Sut2Q~3toyHIQM6;>;#WZ1J~}cnuJ9fh zMa%32{sXWL>}9|l>!6ps;Unm2_|!SUY3tn|_Qc@cB!EGmnwm4nJ)wlqFCD>H-aFZ` zXC${|yN_dayrjEV8ypDUPPnBhCS3YZh$7h8r4jstn3Z}p%Ye%oe2iD5Nl)K^fAo%h zhXr%NVx#tl?dHU@;V|kwslIbh<8(JvZFOf}&P7#tOPiX()&HLq>KaY4FQH^2zwNT5Mr#k%@NYSJ>leW6>Q<^wP9O;@ zqd$xs+jZ|)jVcZ5LBGPdFJb4lqyMtsGIN>*m24KMRlAQ*oZf(bqC)Iye#S8P2t*%UncF`xA#lWn=?ogmcoY_{Bs_o8oc!}z!qS!JFNe_8{b|5hKbscjvC!uL;z^qI zQ#rcK^G|*zs`maOXgx>|sBVR~dd|N^6gMOK(A6O;%Pqs<{y=CPec)`Y+nZ$vx-w|$ z1L?^d2fDE`zf#5=bjMIhNw<2+)%@BNJ3&MBht)FsvS9u|gT3T*S67l8`XXt)F*tL_ zgtC6l3_bR4N}OW%5n?RZ`LW;jXBdUApiIm>Ar*Ac5PSb6>WuMMitpV{oYchv;-YlU z;ZC2=?qYmzdOaj*IV#2;?{j3_sFzpE+Xh_mV4rH74s*vCVc~n=5LWTODHFR0vl4UY@3MzKU@r$ zo7z#JqZ!%8 zI^xTqs%CT{3ER9FU|+Yw3m=5^y#D2l?d3-wbrq$v0UA4c`P2+ysUUv|D~w}O2aJ5$ zmqP*Iyt*HKsO^u}S3h&FT5W5bW9vb^Ih|AWGk2jKBzp9`>F`EABn;Xc)hm-V!iQs_>S$AS1OP)e)D%NbR- zUR{e(>N@jJnZaq5{`%E>vhJ(PD%vzUaRU~a1c5=DOXYwatKpt_&{bwL4vKEHVrIR4 zEV;P<;50dq=1%e{Z?evCro&g+79WA#D|kp4gnu})dh<2G9p}c>SR!LrFWXEg%3wW0dPNMPC?Y5| zZ}i9fQ`?n~3OU)I5GmDHUGVP&v@ikGdi)2tM8E)FKy$Bd9JX7W9}Z{Yn6Cu`H{uOm zg#I~G=BNhXvp6zc!(8Gt)R;IQ3`^>=3e%LLATVymmkM3$%Hv}EFO2uIBZPk6WCkN^n z!2eupyI*QM-wBY%yNA73ApV^sI5k32g5TcivQd2+Ggyra||NTu@b8YISd=ggl zR9Gzw6qy$tt{Uk#C;bXwa0zqL!7ZZdBd6e^(;>el61Di=PN2#wdO>{Uk0i4naa$Fr zD#I{#_Op*Kd&NHDTsRdEQDrIZ5=+{f=6xs+WM$$mDS96mfT1`O4tRmL{xEuFmhgJ?%!=B} z6Uz3?lk<-jIwrQ8jFeuaCR}bZzVX=C@PdK~o7t)O!@!kI*+KbTpx*&#V?{su|Dlbo z6s&4vozdXwhOcc<^fCt+KRtv_=ilQ4dEu&qGbOHwPsjzVQNM!j62YPAap5ukbejTG zX8zIzpoSoz;#iELc-|!l?^4rW*oo8>SghNM0pvmkB zTMZac8IaReYEMDL3sb!T4JoR=}}UGl_eP;;H_{Q!fjf* z_8!V`6_^itAY><3cDWtVJ8BTFO0y9gB}nNs%O}vSVErk>zpMH_j;^6)C@PbGo8^&q ztZHKoTt%WtQeoW}V^XZ>=ijsBTe9W9E3y7xOq<^gJpcKU5Knno1OedLSZbot5cBa6 zGlc`(UBA|e=$UJ_09}XY@B#tD&bBJKr^28Y^?651B@}1Ha=;^E51e8P`c;*#N9MI` zD)g{y0-4tuuE>XlS2SM3lGL!}BXmpfHeJ*m*T6(83jGX{ib3$rT7WXomr{>PHBsLP+&7XH3j(iUq-@XoM|Nd~@L`P;<^}w66 zsuK`p4oq@Ft*FPWH4&Ev<_%rZd?X>#+Hwq~yvLqi$u z*qjl**9jER8cHW&P)mKA-4;x23KWfTD$mK+({<}V*QYhf=(m`9hm#h+RnUgxRKL+p zM^$T#1U5hZ$*%k_bTI*u+3a@Ur!UgRh6`L+EvGhL-F_A(S0&dr93Cz@_B+oFO8kt1 z{n&pTlYO`A9bqzJC?%~nrwLSEOSkh!OaONj4Mh1*~>8EwLv};xucxqUjO4g=r z!`ZIfoiNX;us^D*Xb&;B^Id?}<=}ZzX{B7Ii3j43x0*9qljAe7vR#`d?O0O#sQ$(Y zi#e&`8)>ov|E=VmEE&0@bDiJJ^;F0@2Uj=fz(m!FAA3PTi^nc%2;5c~&ek`pN)O;oWyPdW{yW(&D6UBhb zcCA*k&C#&swn&#NqJ)55+5-mSmr3O5#kAmgL15k|vaSE0?@;gT_8t${uf;{3XgUTi z)02y(uS5A2-BdEkjLn^FCOM~MAP|jjNGUZxY$F`1c$mB1h5O_$2^JbU8JD_s&G<-p z-Jw6y*<6klKDp4#$r9>dXxQkAak(=k*saIix7Q**Z5#5+h=~gmq+~-dTd&WidEKT)F zYZM7?kFho(H-C{*DKJA>nI3IWd@EEvDDlQ{t&190E+_{c( zMInK#@<-82JYu>J8phSl)051*$+6@oK?9Fn8;73_*faGa->W|=|L=rg)xk*ulWcB@ z7#CysFLP|{|7nh$6q#fDLfSijnPWMsPc~5`9fiGI0=`(lm~2zT|e2u&PPzS%*QtQ8= zx}tdxIG~f2I@2J1&l7l>f^1zjqZTKgs9fUw1)A<Fcybl?qhUv<-y&BD%^=bP_)$@mwZ!fJ0;JvAfY-d}B>;?g^mp1>xU*0%q6sIwFHq3#MqVv_PRa!E4- zLw9zuRIMDN*U2smHFzMVL=XJ|x1JHLmhDKOk%scK%8d4Ci+G)~3U0bwh0G{wtsEU8sn)%?K?3mBTq zIjLZ8w-kGqBqgi~lx~^2(f80AH0cP5NFgEgpfFm^veB#Y@%id+e_7S75Vnc%S+~$u z5k8wA`j%*s&wcIp{)f>~HQE!bkL-@4U+fWY_&Xk^Dx-lN0mgc~;@Po^&;E#VMqhtJ zUJCyExgS0I-ECJ8ivE8$$2R?Ij=dx@$HGPCSRWX=1~9=$4OfRz9lP;qIg`2NBipjO zxr=hC-JFPKxr#Anb#GjAl#`qCZ z-Qm2ThSvLoQoLyGR6y)~)hIT#*tt_nwf}y$vVKNW`|D(XF4yzohtDrnF4bzl5cF)q z81pobjns6BM9}UxewDY?1&Tcx%K5y-A_et_S1c>aDO@VC6}8Y#<||!oMBi~UUmH&=$2@|triCH>ETVz=rFF6eO|ag zAIM&dkNgJ}`jl8sO_)AiF7m?xQzNE99<50280|Pmbh$%;;NVhjDZDCOjum+?n7nYo z?ohWcxki<-EtqbBJ^vn<@T9 zJRMp+HkM*!!c~pk0sq7(jziTnxCKiU*f(maZm#EOqTI@gZezC(UPLErmEY5=m8C4z z&PDF)3+R)>s+vBpTaKGj1G(djH^2B=>5O7nlkP_%Ca^>5;g4`WJF3&n_`Z#I^7lh9 zbO#<6K_kybhd0G2z~Gz^=e^B63w;lla&a|WhS6IVIh?hX|JEF}Ey3qPh5|CKE_b9V zEG(v7b-vzF})v`J$ua-S!?A?V&0b(LPHSf`!6pzVB!Zjow?m`~fRS zY%c9rgH~o%RrofXFKx(8(Q%r6qGgKZN%p;ov`5XyN)>4KERMl1_h^J!B!@#`Z_rOy zS~3N>dg=ER@1x@BowmPk?+0mCBM7Di$b7Few8B^g!*?@%l-yK;>79ZPAm*l)DMH;) z%2>YQA~Q1DZjX_nQVZBdk`gvw_)PbBZq3Ec#+YV%+_8Nc%f!A3`zl!Yk|Qul;v|Np zG5zJb#))j>CtC=>T*XHVeOJ<^60THGl?S3t(nadnltbHl=7~?;YR9)6oP(a)kb|e= z3WnN+PRcr!{&hQ7I~4OG|AyRF3pAa1wE9&51EM z8bCAP_b%x!^JedrU72*7205Y^inH(m{E69p2=wv?9~YM!uP#V!i`KN6b|_rjn_#a1 z7bkva?03>AZ74i+KjtR_`MGQA=eS2M=@^!LRfbcfZg%#NvAMA@SQRMAP%OMHK-+MG zjJD+4CVQf3>xwG&z!BWbl*p`f0D0jwCft}x<>l*F4 zM!T-ju4}aG8tuA9yROl$YqaYc?Yc(0uFiLU^bYCemp=bB?I+}uM9-Izx7E~nk@)y1otA=w0j_11zh%2ol_sLnT+Z)< ze}99gT!L$HE!#7(Mo_KZs%uuEr+WF*sjro~`XLvc0*^G_D%pw5r86+vT21E7V+7*2 z$m}jR%^FC=V2g$R<}r`f6s3KSQ=FXiUuuP3Z1zdzS!LD2auRu}n{iisVZTF97S!tv zRo)6h1k?^i;UvAkwODW^30A17>xU>}6)|9VN)2iYwH z80|OKf)kf^c*PX^Od4ILIz9`3cDq-MuiH}27W3wDnNH<&x0g7GSu+st&5P8#`PR9`@d89(Rv5pPRj~d5+wF0Z$12 za&%yXpgJQLp?Ps!9X~ySUq0Qob*{rg1E2n$xX>--+Hu2rb0#i73ogTDmHm9&XbqMe zYdVzoGYvT!OHN&w>d|O+6EC>Yu4K)5Ba6j(rot5$-thP83H*J*#^Kt{5|g{2{5_?Q zc6#0W_JJgY9#sQTsH#}IP+MUnHfMj!BIh_D@95Y7z?8aI5L7L5SoC3bg3ah8AWM9nGvJ~ML`E76cuR+ zNS6|d5|9#vUihjC`_Z|^zRdG~epK8KHf!*#8!^{nUl{qOt9*Pn)@Xw7xV zsK3H3VpHckMx!xzBCG z==z&}0J>$lS`A)#c_QnaclT)*X}s6!1XRgA&CToqDLgmmQ|(M<5VSvnnF#M$c`rWu zV(%!6J~~~Qa(5fV(8v4`7`-?kOd8&uLccrVE?qomc z48TVxzmd+7Ef$wznI$lC7IrTA|7^; zZt7lZc&-n<`2C?_{Ullu<81r%O4LV+cLH|Pz(JZ3gi?C!D*u+nKnoOznOFbC5%v`@ zKARWZ__{XsJlYh-W!S?;N}J5;ZL^7eew6?U2EHC4UbQ$4 z3AHXrb^d)S;`lqQiyqdQ((Ijw=s8n}ifgx**He`b^nk|?Ow5qtA27m8Crq>JZm+T6y5ec4XSDMi&H9MMnx9f7T6HTXaYzjrH32v z>_44z^0wzXxNDB>?xl?CcUKOjm9g7qB<@6zmw$dzj8sd_C<@O2}jVm%gQ;F#QM5qco=;cGBo4;HQ;Y3gl}8L zWFGvlC6TXEgx%prUn=NrwLBt46SVjM){d(dH}#UMiAKljg$>I};gwukM<&0A}>GJ}IKwhFR2iDLopX7W=P9Bq!>PEbH2<-CAbQ?SKhfpPb>s8dJxMeEOIA069y`RCVKdKu3$*brzm?+vLf|^7rr8KvoeQ{b>%5 zzEtRIsO(a1T&PLTB4_{hDSj^Fm;I)#e^X6VbWA&L799#);+rn?KbB4D?&&Uv>F+Ly zG4lwzn;ONH4Q1boI(^A;#m2XcCOTYQL5ZFn|`s zEAdK2myHabu*XnJ(PU={%$!mas~-D1sK`6n*wX09(yi^?9Rm!|k)3GH0~jF)Z}~8gWGU;^4!JvTek{4s?>!j5mQ6&?rKg);kD3?qqzR z7}{z%F+7l6R)*81o+jnQ*i|<6?qkbTv>tXEv_L+8uCia59~aaPPhGvc_FCWRZQDlz zi0_aPrrcWYe3AVn}>1M36-l?r>R_1*f5IB=r3FvGoyvGU?~d}lhDI&+q-JPe$)fs#vVY1K#8nP|0zyj z*8M>QJp`U@}5~a`gY;SZw;Tl8y4}CxVR`E8Xf|W0{Pi5+bS<`OIc}BtDh*H zgQd}VX#%&Tf~4ar(rH=l0PW^z1g}FDv>+RY&=qbdPHQEuQLl9+!^-@&<$=zpuShF9 zuCv;jx=*KGe?o3U>z%Gm{m`}ht5kp2hG&nIQZC_VdziMWZ`ix0Iik4Es1HYSsBq5o zQdI)-ZS?4X^G97qy*jL|gk<`Jp%RGn0Kl>79T+Egxkh{_yAl03&)u-A<;%seC8ov6MON#2d3F1qfaCkJ>cCH*xJZV{Qw5H?3 z7vNSigiJWnp(wB^!T7KUe%K-M_jvv~B60>!?34nC#}wf!R3M*13K1YS)|W=z3EFlI z&RlGX+3nxVnL8;R=B?Mr{e_m3V1Q*BMin@%G#9TOen}^Y)=> z(TIB&F{)~yd`!p+_fp;Yxda$*eSsv10$^?iG`fua`?6bo;otd(80lR%88aD9Iv7{Y zskqbdQJC}l%v_b(ks%Dqm-|(2815st%G*6IZWD1FB)K~1tT@3s1}^sbhY&TowqdEg z&aM`{4i-hO+P6t2_Y_>~DeP|t=vr6f7a6mSjsh5bZ%V-Fasj)+>3j0GlB*Ux{v+&H z6nmwig)4=6{qRp&i-fgL+Hi$RhFHFG!M%{Ti_C4}I4jOtOV;Xh`yBiNYjqksFrc3l z5O8yinW_4<==jQE_)+NPt0@vg`@1(X2;(ZUWiP!?gJLwmthSUAxNDfzBg?$SL*uYR zJh|`0mSxWF@P%LCNcMw#JNN5b#~$3#L4e0seFp43&mHp?le;EsFm2cjUEjBJ9IPQ2 zpqWcXO{@SkxVw90<-n4>?XmvZAjOXk=smBVXW8?AfZ%@+BmtNx4l(%jObbS^YH;n{ zN91>YgY82NgKWV{RtlH$;R}KrdON@-)|*Na`>*3AwA}s9$duU z74~pg!7osa{IJO{knZ`0L9$S#TNs~{gPE0M4M*N|z*<&{mC`dvyW2URcFmBuFRymd!?&v-SI4T zE69ClgVigM&wW?T-;vd-)pLdNrordMFYkOjZ>gM&xSuw+2iH0?gf?;EY&`3_?bT6K zIvCS@)Ne$Ejzr_N451|0>Ds~0jE z;Q-ddthQyK`0d+=bdlc47&TX32*YM|2irfv&fEYKJ!?q@?VACg)w6Gh-Ids>{9C*t zL2N4Sg7hxEB+2~c3BCLk|M$!5i=BX2CL_IAzmKwOuno-EW{!==rFX-_&$}L1x7jti zEj}Zd1-UXKtQm!QFIS40MGRKaSg>9N#iib0pxR70c>GWRC#yOv$S$`<_^ z3l(dSA=`!GIMdi)Iu?G9V@vLemKF;wA&ir`YIhF!WO4MiE2xV) zVyd#kVZ$E8ZH-pTN*_s>P+M_)brF9l>_@D!ADiMJgub04W+Tt5bE3@I&8j@JsXyFh z3!sw$P&aYeil=&Yf(*>LJ;2pesqc!o>xZ8?u=IaHB#vABCRb}?yU`SZs23SfHuYyNdkc2&n9j*W zQtvVw?9=5oJ24yo>42qFz7tW+k5?>-#3$cW24C}7-9(^~#qX{bAeaKaFt3djTr&FX zI*uXT_aLg`=c;0-66A}EfF*A3=^Ne@V9-3pn5&oOTab$HgU#o>nm&C`Tc1n+va)yy zO5TQ}TdjoIIwLCSG{ZK)z`>cb623t}>7A`*aGs~yAwfPI@fLIEcDz%xcUWsz{NULm zqmb`L^TGMjJaG0vc->hL2K_xXz#nmMg2MD&#b2 zVbIW}*$eLU30QpWhLg@wBM;drp$J}za{P(aXVIYIrYsfC&Mx2Q(0oR5$2xmA!>WwjM;>8RlK_?DeLkw;y?hM#B$-?xMP>mBsn>2r6Ds(JAE|7)~k6Pq}+a(ex zmrK1HC)PHu+W*IGwf;Erw{P0ha&D6v;OK(@C_`>#u=?uu&4tC|1@!gq8cNDj5)LKA zhTq`#8fiV8&zk@J_D36W-t}ysz|~v39V-<CSM9aT-J@=41M+lw%_ zx0BzUX_k_7_llOlfvhTrL5E`usgI15>Tt(-U$0;=)6QaFoqtfo=iRl83=?-hd;!6q zE@Wp(p`xJbC~|^u*BHnDD3V5-ELh(5Hju?zGphZA8DECz2Y9|EaXgZ@uLJztTOrXI zj^ZmQg1@RvQnFCJ^YrZ`GXe7M%fj2mPkT%233irc6o+L5mpgz8y<-@1u^T*}wfged z5fxyDc+8rZ>NaGODpDJ)3&#HD@JIVz-}LjaSH6mb8|+JRkwQq^90Zle{Sxzb-U?XY zWBSC|(B8iA^mSe>g;uNBw{g!^!*qnxF$@+ou4UB(%uEQc8*F*Pz(`%ygJf zjJsXf;KTHvS}&$P49dxZ{iuIT2@^R}#Y3v^JJE-Ek6_hZDHK^}cauZiR96e#;G+IE zrN+Bn(4)F2a>jhC33ka2w?yt5GUJP0QUH>B^R-`=`t4vqGB`t`qkfITub~OAnjFOE zI;qK)oAvbm9RJoJ+Nx3^S0Q?H0OpveAdv#WnN| z>a3sUMkFe{Zgtnfvc?YViCLxJ{_!sJCK`j6#2}H(JMeM<2dh^Ty((9{jnAV}wB0Pt zKIuyW8a3{)u|`qJ)%|*q>|lnNJ9MU*#e2s6OuCnjM$ym8s!7n$j=!u*DW_9)Tf+08 zZSzkw#oOjHKfJt5lDqTF28pu^kvk0g^5=TEhF8#LUwi!6a*;K9%#Vh5QHkU~{uBAH zTk@?VI&FmA2IrQEbf@9v5?L+Fcx?5(E3=X{H$KIu7%RsKL}iu;7|$4I65~SwCMRCV zV-JI0sYVM0jlmZIDY7xFSE5Am)o=;6sjN@RvbTr zQ{kMHbiYQyrRkCmbr9V}HCsjp&GJu!y{$NH3g@hfa|$aTX{k5PmyOO=*XlTP+HA69 z>s&|4Qo`!R` zns4%kh&C;k@60ZCZilj)Q^0C_G3ed>X*-q& zN6Q*%tV;ORT6`dCeEkaMFK|!37GF*I^!#8e&pRV-U!%tB4)RALdZODj9J=*@;X_?52#zXk%2 ztnS8#Yhb|HwJ}@o5(+yKy&)YuYvd@sv9z$yAyfg>N_4>3NqAqX7tRf~5F9uy=A4kD zf+JyL1~who)mBLd9f1{+vE97TvY$Gnt%r=sETUC*GCm!FkIhkREhD2exUN0Z%^G?5 zY16y53+s=Y)7JdD9%_FlZfWffT7+glw99g1P@iNf1(NQmuUM@ow-k0YjLmA{SI-^4 z=PVd?8_Z&H+6U@uhd|D%3Z?IlDWTf1=q$kma>TDJn!)@NL%b7)kjA84Lh(2YSY#rH zJ`trqfc`vV!(jQ&#xxTZ5i))CH6<_N-G4p$mXbmu5pFT*=CSarV?!2DtrvR`O&#C0 zGb+*GDhMNj@IH1vDRM-C(SYh;Q^`^NW}Hu1E5%HpxSu-< zU|+8TyE88VOtDV_ntYomUNpCf8oQt`99S#C=R`%v2^vtsw2esN(rer+w_aJNz`Mq! z7fxLrjx_bAA(%m+$H*FEI)c2p% zyPh(;f-~IAS>z2|v_^fHoxb4t&G;%Qz=_8U=h)Pu_spYYh7RAeo}(y&Cw|X(!mk)i zF)iEQtx&J|C$v7=GxI}%9WvRhOjfI&V}MUcg{qFnA68GXhQXree8RkoZtwkoKVe;Grt=t(R9uP=ijo2Yo<$;k8jgn<|8mhv(3cd@L96O2H zJ_I3+Kzpcps5oRpUe`OML$Rv3dQwK{#)Gp4{4~^`OOXP~=aA9--I9PPY7!N$_RZY8 zIU0zxQiGqstGXRmyU`c?ibU@LLpe7iLv5#svl?t-DBaQ(9i z;^mcD-c?+mX~qM5NS%BhV_Oec)qxi_o14dXOTw&D6Uc$uzAYMR*;oVRxe}%W9Azv) zJFJ1&_)J`X3H1$3vpA79ivao44C#OH|?j zv+TxrKwp9c z?vTeyz5e>_URVzZ9LN}K!Rn=8;XQ##Hv>QFv|-g_vPxP|uN5~gwSB>}q9&%NZ*d|9 zroZkdwZzUpf!&JBaM*#CiAjHYf7$ZZ8%@0!%esfxFFc%iTu~2E@<@cAgJth(VVoO} zKguRZ0hPwkzr}3WF_#q;Y%KA`p|){ zq(#8!D@}vNmq&%!z*76m{lW=>7|5qbx-; zSjwB(%k!6W1AMUf$7taFYD75Ida&vr-#j2h^>rBs7|@olMaO_QXbs^tc~6si%MbO2 z8$5Juqd#2t8rBfF%lcj~3Ye}cgaDsdQISg#HC)*U-|>Rd8h%HXXzF73Rc+G!+DiSk z>$lZS=2QJ|nvMLFf?nSCyQGiui}OA1;$6($;&q5?qonvMhtuih-$TjA@PRWI{d(LR zye4mU|4FLnsSmNLo3p^e*$ZW!Y6aP!P~B#vzz;7KD-vDo)2=wGEvJNDwL{xb~*#5GSNrCJWr1*RKSrJnfa^jka zZAr$^?o!LP;GRIhV>6`ZhE@LorUJE&=|t<9DIu8;_h4Q7g>z`9&t%}?*d2j1JmYo+ z?^&>i(8yJ6?rt?bP<(=rZszhZF=-TE(SU4;yf(164W<8R`?tElLTVfqgzd2V1c{u$ z#)`)Yzm2wZB+$d=p}SnFkA)m3QLyYw@zcWZ8Mz#SY*!-rn}@O12LQEALHTk?3JN*YGmH9u4B(9N|Ag~JMVr_pMH3A7^T zaz=jL)A3O<48mY^dv|6Avk$aLF+TmoY%XDmfnGh=#xa-@oy#$D;(ZS6dx?@hZO?Mi zJ|SVNS{XAA*;w;~*|H{=#rK$YKD1Gi_)RK^==WHJM;vfUX;lMMt{+x^@ z_N5}IL3GCcN6)n@8mfKwKet_6RlbVKfg$gKV_^i6vm1clCbj|M6ZkX1>hi=`xX`Yd zi|T6?2IVL}(faM(`{fE5eVoPKkIo5^TGdw*B}a#7#)l`CB50ATY;m?$O~7_`x=a=g zQXKo!6t-dI6wE!WPQ%6Q1DqEbgcuj@kVi<$q z{D*j{spA5>wKHeM8q|NOTxqj`ku~$xkQvLAKo$R^CIber%d)qC_X3&N`rF5J%w#|h z=3QD^1Hv;tp}1&(=rDPyO%9BIx}JgQZ|l+o`dh*{V6vh@#z1-3pjgr>Mylw=ko^X)?yJnAb($LL)~q#W9xmL_4WZ6)8uLDDf)MAoG(XAT&v<~YJ=kG-r3-#0tcwa?klx#I@`bl$B6aP zsFgFo!W0UN0GaQ$J5K4!4M_1XMLXvFyJ)8-Ji-2hH&;^n^vtfv-bPFMaB%VyttlcG zaQ{Zjs`3veI(T@*b9)fOiKU#fhC8cD)Da zfR029qyBfa*yC+=Ox@*Q<8YG8ZJ&;fgIrXEmy_$G-F@fI+pYW~KJtb{TiGTqi+KE_ z6xvz}c>>jQ+k;83`m^GsDr;YW$i4S}DKm>&;uGujNxkOuQlJ*-=#btb>kQ-alBFPKk6^v`HP!roXTuT(Oz4rm-PtG^VG&}2!j zw!LGnjV6ZaBV)5^P9Ycrx{RUjV0 z*=~DCDQ_9_*uPGLOBh{od5{HrTc{ZL;R%b}*1Iub1L!5$eS7h&Ht*dl-NmYN2RiC0 zDHsrp?!)W<#2UnYxrLY}%}gvU*9qxs&Uk)ru9<{@+RzeLc2Z>_poq|$`RCm9K#b4M zP>z9GnNeTM?tcE)_Z+KE{xV?j*!F>-5eyF{qPO*d+|t~#7!dcW z5c9=1y!%;bKm=VctrTx;lU-)}69l@FNkhCB!*TEREg$N&!L3#63Luki?udpsBvq~` zn*|d)3zHzLj-zZfM!~x;olh*x5*i?Z%n_BlqhD9Djzyg##rI#Un%lv?^(H|V96kGz z)XMx7V^11x7wqQAJ(P~fcFr09 zqMY3U9ZFhQ_{ck7bPEP*cj4m|f9!a&GK*1iTyv+hRj*(TVxrCKvW(s3_`6MTVEW%X z7vh}ehSI61kzcuN8pQ`v0pFa||F!|Deta9SX^)^>22?!2ENk}ypk#`V`6?VEC^X2w zE2X@YxZd>h*L4X->GSE5ELGZNUU`mo4hh$ruT#Iuq*|Rhtv_L*>FwBTk3nVVM&5qi35(I|qq4<@k-C9}h*us&$p$fWp$ ztY?WspWx<~cV~`@8O7I)?ujX6ty-CL<|^_=oW5`GNK6r$%aF*6$rx#p)nt?f!hE{0 z`h)^ZP?4@m3OMs&KRA%RPeBSiC0_d_D-$O<0s-b5sMjkFVD;hWhVKqZ!ShuQyO%Z| z_h&9|Gre#2LaDTRtE!NT2LY`OZd!9K~+8=((Fd;1%8YS4^gdbxG zL&eor3nwmt1e2&`1=-CqiwHOhVZ%xBg3I!KZ$gH<1JZzN>n3{j(kP!;d$unED68t= zn?BhIR9rL*wLzjh23#nQfrA&a;eh5&qt<|3ieHrmdOtF>U?7f%e=I3i=c=Q8+4J-1 z6Zs&g7Y7q>Sa7`mh^ET0pAGebF^elF6woLu{U+@oz#>zsu%7ehbms%%uJseh>0EaP zb-N{!Azrm|q5hdHNDp`XlL_;IkjKbe%CNzQ0zK#=>hifJ2DzzZN zGc56XRmwJsmO9M(=vzep8GFgW!vYFW^p`7S>ehiJVY3-JB)!yn6mPX!3;VrW>S`c$CH?_4MNp)It5Y5&*I ze$SBR=aiaxeqx~%>Ngx_Vt}3W^#lfnj8WfH7JnjG$3$T4QaofI_8(J2z|=#`{K7Vv zpwLFo^dP=zWwz3;TWQy=wCh&dbt~<sIo0EBU&WeBDaEZY5v0lCN9I*RA9$YAgA=m3-YwzHTL7x00`0$=9vq>sIo0EBU&W zeBDaEZY5v0lCN9I*RAC1R`PW#`MQ;S-AcZ0C12k#!tSWfAI_c>1&%AZ=#I0oZo8I$ zs1N}(mIMo1$=9vq>sIo0EBU&WeBDaEZgF0>IImlr*DcQL7Uy+(HWR8mzC_LB>vT3d z9Ns;tu`AZ$g-7yh2};c~R$r~4$pGOeWa!4;>SJhL7CA17b8(ym)+ z*R8bcR@!wd?YfnA{Vz?s3jJuygSuwvEw0s}o@a;8{T}2XF(uY>VsQNh?-%oD2txaB zsqK&N>ry4-r+Y7xK7Ue?&WJs9LLpr&?354BZ~3pXo{`c3yx1L>)Z8_R#lXkpoX- zXqLkLLIo)=UOmJ_FC1xiJ@*LH1h9=s3&Av4cS|{}Ua(0vUOHTmoB9oJT5ZtdIEYlW z>|Fj6Ky0(U3Gg_yX+p7$uxYtm4ePSA%fn%~Wwc`&mO0DQij@Pa543#f`>z*aML9h66d-oWOy#mhGl5BM$rp z&cF|M0bl1c&V8?JG|G`y*HG&Of)FcU%NEZumQp&mRWxoJN{CYX({MRr!60Q z=6JeZZqZRb+wX0#y(j;FIx(wO1EPdd6 zR21Dt+r_L>{1Uuz<>n76p#GO%?tkak4Fwxa?S2M_AN1Q7_+=a-lNwSKg{e z2vJwK>ywYap*6#^Nxv}ZE<3@RzuMVf)~!0Vo_{gBPfEq)bi}h1@6AQ zGb#?uv$Xs4{#hlnshUd^^yT*B*HS}FoD|GhDFceb#-1#)D)~EsWq*$I{a^qRvrre> z8!_7RW)oyoFBlKH7nBYdI~H1ddPP+JdM)ct zEzIDb3f9)U0h@$QDL{k}LLLdPZqZ`@PtszinZ&iTnT~X)^MYQZJ8pM^b{l*aKL=|P z-&MQ!>KlkrkEGiJ1z*D5RB&v<@tem|eQ#=aVkHk}ws z>eh-kB*XEQO%Z@zX4+3m0p`m40b&hR_Q;g!(Q-Efu}^fek{+gHGSHsZw&&(cRctx(h5vg z!J+r%povEH^^knnxn^$GLtc>kwP}nNf4X;%H{I-9mEv)%+GCP$zW)1)_qpvdMxEw? z@r2dEI_hMa`XIyni#pC!aBlb?!bZ5$5VLZDwxm=Eh-7lI3Go8=jm~cSnVdhq9jf|K zZQ*151LfSW^OM8FB6R`4F|3XTaE2QsqB1png9MOfm+^!*Nf>N#L_wdlmTQ0z%Unx*f9w`^=8FQR7tKBl1kp4!7#aruhi+x5^;gp2uEr2qp=ZTu=g*fDa>h z@p7-3yvzwkB!-jK$}-AcetHSM{z=vIXq~?)T!$BTjxnfi(L(D+y|SSv`lmC57C0_}HgWpaWnMi# zt}Kuv8ROl8A2V{Q{X+q<0g!VVC#*bWv721o+XXLpbQeMph*jE5e0$e4Wi_|8PJ z8ca^&`o(r6{bgH`slKpo*U=X6=*G-C=f;R!jBcxnFq3W6=o=zJ5`?Q+2Gxh7m-tc3 zz#&?Gjm~xrxLH zhUr0yEqp<-L;Uc4o%p2=YCm*P2(4BKQf;!qpw5ul2zEfoEduIG6)@7Y9|(R|p%j8Oep z9LKAQPXp?KHIfG+J2)Bx7Z{he>_$*nT&3dMyK<6Eu**qiS!1<1sjV`Hh7`SNtDsQ z#M=t+eGRTz9mW;}v(HRQ0iNP@oU}je*0{$4z}{ooF6al7kY)-*z=R~cxdn^;KLU$g z{}&c(N)uiKV6plC#jw~j|G$96!jS^R0@_Iipm0vs{Dp$p^*V$%A3j~WM%6YbWo|=j zN3>DmDpkzy{H{+4O^XLKp6YXcQdo@N$R2@Xj5v`tbQrHI8~J2gl$ z26v`B*3EIRn)8G#Q8O|D#yRuD9}6mzJEXshZ+2NuUopN{%eE16pg$~$@x5+d+i56N zB)k8j|J{1oRw|^Ln6L3oLKgY9{>$B!;mKa6Ri0YMwsenCDDayo{<3}j=kkS~l zjYgw1#YC$$Vyl*@Y8ctyB%xE@J7(A;EZ=F%2bA1=3n9hJ%yEU|jfK?^MC835?WZDL z6uP7B8yaf#^0I)*`9xU8$KUWFfWwU!*#Y)V=EL2gkM$@hkt`z_C~U0mmYk|FgldFr47}u1QBL)^bY}q052c{;U8WPPaVo zx}q4Xj;TKX*~9+N3t_mEA(9rY9qtV|JG*$N*W@}0_pqDwYd8P>wQ4Lco}rnLId2 zUHTqG|D*ZHor?zcksT2aOM<&n2qm0D?g&6JP%87{5c2K0#4Z|cB|LI8C~lk|H%fbSfnmjQ}mYOcLx^wub&-X-+mv z)~sXh7|wY|X3U-a>&%&SKfuS~lOT;WqGHhKbw}#H1jA5 zz4~!=tf-jy+VS`gmQV%T}0Z>yEe+F z)S46!J6A=NGoUpC92@MOcM#`bE?S?0c8bmEv1n)_M$&Z7rzLh}Kyy)MbR`ML{T{AIZHhW1c}_9~6o7c-9Ft7S9wo`?zM%&0r0EWT>zsui^}tQSoap$VyRRRw_$iY>wfSr=aLH4 z!mAEQfvQoSG5otrgHLsnh3+~M%M_T-v4n>gKdu zm9O7a2#x?}hWGY-dyM_tF$}DkGN_~g$W9uYOIqRaXG!+WaqA?ebg%?XXleJV&#vV3 zy`Zu5@~`(PDpLtTMo5#8oA!}~A3xdNx(qi`f<&^SU|w?p){*ncVSbsy)z%Ju0C0$# z&D;ZSbx!G#!c2=>zJ65BY9}aY)Kh-la~w9iUq(4Y9`LI^Z0;JsSf#@}ar1w8*pK*2 z8;on%{sfI`yOldWmt4P?a`hqIx}jb;tyRzcpoj8NF4Px5G%wdL3^ByFd(L>mXJqqH zD~K|JTZu3!xyxqP=^W|b(LWXz9mFf#Oo}f& zL+sKwuO|oEeFs&}pmLoeWc4E%NtRY5&``k1k&Hy{?@y?VBt7Ukc&eUWEH#6fn{U{! z1*+oD8m!nB$i(a7yI9)|T*CKFs;!hx@rfoMNb#mLy1I0;`_vzB%>BzUgU5f{U(uZt z>^hky%UBCdzDc<b#mkTJw#~P z&wQeAf{TrU<8p6KDd1UO(KI1ZXQ%MS|8#IHr_?lj7jON)BRCd|eQa^c`DRNpwqnVp zjqab_^ZXa#BpUl}p+k(4RNh|R%~IEQIj**TSjT1Rs(7>p31+>^Ww8n9MT%V8$X^Lg$5be>X}IHntD5 z8ozyRuecj8VwDD+GjfTz&1<^c^a#|j@-cXt{lcLnIAG?Mk9-L=#R1D&ToDi0P-QjA zW`g--|ArNE4P)@I9uEWu{H<~}&>n5O3??G^C3x!olL_yqRC#b3G5h0* zBDO}iO{hntvN>Sk+I|Nnv0b^}twt=6c5C^5#gLYtur6f$fRb1abRzJs<#|M`hFW~Y zCHp|_?`CG2+fZsr!C{eYguB5Sw0bqDT4?|1lN2!Ol1)18&4Jkmptrn?ltd8y);PWU z3|xFsoklN!U1l#OCEdKXNAE+kGte<5Ue}lT+`x^e8y=st&V;Z8hZ$?qrL>Nv@4lj- zO`!~f+St3{RPy?fRo7qlc+BJyL_h!WJp$CYl@!F^bT|>ef#J6OzG;$J3mm1O*E}(J zr#s=gd21_|_XC9EiTw~KfYM$5@R*uNiJY~`=iMNws|!f{jTql$ws$cwmLc$mW^gP# zpT}Mfj&I@i0zyPIfH=mMY`deUkaE{4`|ZGaN}~MrE|0Nvf#N~;Isil*!R*kg=k>SE zfctmTlT~1l_4zxEzR!<`k@2_r85mZvGonrm4d*44HGI^gwkD?N+rQ~WkYOmEj|F)k z*p;Ip^siHPXG);<9uk;oD9L#CEw4s6G#S)d8;`anFlEsg4W%p4xdU3_R5@XI*jssG zO4r^AP$DMmmq)=0?GrF0XEf9Kp5E!$Y3K2F@65h@O>wrK9zMY?(nlk;cw+-F^%kuQ z<2PXc?}B3~SXj*Su8r^$eWnfC(e)7du+s3)t^V?8&o@mh{|ua<@nE;UMV*2A z>h+CcF1gTg6wM>I{`#YzSac3N>HTWpYXzQ@Sh>XMtO zUXyFN-wV3Y_PFFL*15VE##(pd|0X`0eS3qQ_y`Q`F>Szvob8wGKd-+*2|vo}9Q!W@ z$1(x&F)lvtFIO7&_6DuEh`wi;^w|mD67}KK*i?)9qI`n(rI~~Hg(>{{uf0Dm_giV< z^Z)9if0FX-zh=9q5L@{KF2mV)H=o*O3znR2KUO}Ui}(V}vFLL|tqyPTs%w49w(RG! z7_9%l@ma?Z@bP%v4vDY(p?uAn`x*ha2TKW3s4x3KWQsb*KGrT!oUC9pIuHUp`q24M z)c-wjY@PrZzkmqaRH;66-v(ESYj}m%Prm*%Bt>hkLq`1-ZV{V0-!U4Exg!rDP5HL9 z7+N$?EjiLFheV1Fk@KwjeBQ-P96uPOl68{Un)n8oZpAc+M5vawz?k4OVB7%25TUz( zhwEnl`tO7Q8b}C;%+-!U&R0HIcvVJUNO--gFJ!Gbxh}r`@?W2R){eGd^b?SsB{FVD z({xp?8uO9|qPRZM#*wopk%Sv{7b)oub!@AlUJ%l-dpGEhqRT!rEq*B-ddiZkt^IV? zl*0)HRHry6kfn{Shk!?A*sEM~ttzb$I>qYN)NRVUGo9#@?%X!VvK#$@^wlEINP0f0 z>ES~6E!ZV>>rm!PtULyXG~q;83%XXi)1gX8BqP2$r@+!`eU3MCt?<3s<96Ca0oXEI z$ZH!S(181q1Q^EBqoTQ|*Eg7?wM*o{@k1BT2a}T2=eaL$;~5{)Jj0MaNmi9eGXyxz z`RLv(d=V5Zj<~V8lihZ%v#up}AU-#vhL_Lqn; zfhG^D(GC8@c9E2edi{9rkt}gV;2$-D$~BDe*c!G5jx;lU92E_NUwf+V{KFMBg6_^z zx6=#6@t3Pz{i||!w<%}b;!RiM_wsjFH!FbiQ`I%PVW`=sk)8UFPh%i3fKu+mZln~b zx!L8f1UWB<2$C$D&@8rmrh1%_naX+S9Ad8pp2fTBV5-rrHz}(??utJ3oqbYb+y#lf zMxz;+gzea!eNwrab3ud`*6(@Ec7qVXghEW4Z$#t?^|+(5IyTVcoeEl9VkYt3l)qqL z6cjU!Ur%u$u+p6OFqXZ4PV{N(G{qS*e(h=R-U|YL@c5kf++29{^RB}cZ1UBr#(qRW z?~m>M0`Lm2;Coa91m6~~qq*krFS!YW z^oxthKNgQII01Kf^OYp^{K9CjSuHbn4)Mg?hc3mg>x-S9RrB~0>W3uFa_6%-T_Y)1 z8W4jviS>~9D%kEYy5oo2ruS}7${xx7=|(eK_b`q+bj%77EBWzvX|}4R(iGu9e{;7~ z*@KIUUuC5S(=@vur9(3a6Syv|qM{KU$sP&>z2fU|TG(LA9njKG9~m9A5sw6ftOJ1` z>=0p=P0&%f2GpAEdm;PFl`8GIqUrhgiR6H!ov^8&C>Iazk3MWE9ksZsb`)fEyIIir z=#Mjc^9JZN9IR@4|HW}rTuj`#58h`9tE_DH=gs^O-o>!Yl#+G*U;hbI{gK}>L-dDc zz`v|iFN__v&rg|NG#2#+uyO6Kivn&ac9HEz0PF9*YcbPwvjphPiu9fU!QWC_kjkWt z0gd;9BPawg=xie=kIaW(PriQlk)m{3$7`=+Q1`Z}dKp~ZAvF^(vS~f>=z4N36cm=3vE-K2 zu=8h9`16j_0cHLfcJYkFu4E({ozEdUtO|x9Pe=g&oeo91%Qu?&4ZY z60Q7KI^7`l;|oGDg?so=eCV#vzh9`|wVMbN8&Er83U#^Lf=dWIE6roY*8wk* zLpXyMd0E2yo${g2y2bEY>`64*bTYl~f3f#oK~09;+b@Vxqy$Cj1Q7+1D!oLa6hRSC zQKTbHK!MO}ASg}gMM0!V5s==LPJqxukMt6HfY3t?B-!!(zu!0C%s$yCd-lv8PB;m} zGf!Bv?zOJo*joUU=H_gJ_xo^9*cIv^kUDsc?lBD`inFIkbhfcT(Zk z;|~^xE*+2D+jc?5h@jn(UsD0!xc}xQF#0GD*CKZUC~hB7wM6l0K7ONtNd@fRPmYI3 zt|xiB;9fBhDVr9YSTZwW_%hfcC>Pnl_o40zZ;iQYxaao6pnLvS#%JMu?iJmDbO9Y- zYdhzGFh>^)#-+tAE`RY)wkh|yn*RBG6AN45$N%7sozq@sw?K;oXMDC>Kp`em<5)s5 z*8ri)G6}p>2Ib}<{fOVm=RH|mJU(t4F|FIRmGvZ+Vi6%O>&YeIjYQ>I`$M9i$<_aX zV{ZKK{7fbc{+fGLL@T_T+Yg8|^>2ygqjky#GtaP`$4p>QIxW?ba`F7E_SR;eoH(KU5y6{_D1DT^%?ALipaA8mScG?=qqDdXTcyc*#DHwTF0Pm?^gt_a z(<~mS2$hsSR%eDAJ(3 z9njeF6OpC;%2o@3F#5=V`_1v%xey7)@PMG(^sBZJNj(1QGgsl*T|Fq?pM?|NvO=?x zcf90%W`D4Jd6+E;efq6??K;2lCCo&Y!6`onJla5pi6$tdUJ$ zNrQg?24C;3f za=lkwFXx%h;sZe$?eZT_V#PC@EBqoY&dJwv^7Vfu&~x(joP6!fE}Yq{7@*;v?z{?b zSX&Y#`^YV*BTlaBx|~Lz^wXRvLJr+`+ViLy=t1B<7DJb{O4Lp>+LSzSVcg#C$cC7h z=dSbfV$g`jmJ|szF9*vrtM`~Ua+geAMZ%;$xze&qn$u2(7yIj+xW479R{}Y zrW8*0nWQ@>U(d^`!Lw zXUk&GY1ebw^_+G+r(Mr!*K^wSoOV5@UC(LPaW2w#b+^55@q)??{|4G7>{NrZu%pxe z-q^qy0Q))12hfJRWQZ`Gbxdrdyzu{|G}AEFVMX`JhVYzrJ*QpIY1ebw^_+G+`k%!(6UtjeRQgFBE7K(5C>{KtO%Aox z%3fWw|AVmXozt%8wCg$T`u|hfwM!~T^?&UGI457v$=7r8^_+Y?CtuIW*K_jqoP0gs z`Fg(d^?c_mn!W=+a(NMbx^$EXFreD_d$E#*URN*TnmIwj=bKqm7_?{if$!^W{8RY& z+GpL4ybgU9bKpWHACi@^Ldy((e9{ImLmeIWT}nHxsU%!XY7^`=#{6!u&eyE5w)nuM z=KeWqm7%F^5fvkAh(F5d{%CnlzMk)VJ>U6yzVr2b=j-{-*YlmP3DIC{A2V&&;rQsA zZLcEZoxUf5uZl}?WOy!CoCN^+RQoepp~rRSJ74+5?tg>qQkW?(wj7`3oKB)YMaRH) zp0My-+K$oF+^6A;UK2&Qr7E|tX9`fYuP5~UGD2Sq$M{}u9; zG%)K!@$R_^1h(2YYrG+P;qk`pfGcIMKgry^a|jgv(-uAM#};?<(>TTTYuZD%ay!RA zJ^p*=a-xCN>&c_Dw}(F4(@FF=@PHq>}Pf4qOhei5jRa=i&w}xwT-KlXEDYyLN|dIZ;+zYOH+HZIlav zE~_f=wK*D^8z^7eOuiiM4i=0Gup!uF(1_K3m2r@&q!3BRq&Q{RXPfM#m2}+~E4U?j z#mjKMoO?(6BmH0N+*tjEC$W$6Pq^cCr+coaW%6|$+4!=hwkiV57FH=grKHQxG5fdK zJ1>+-%ZnY`y-b?e&-u*aI#K4JyvNX`#w5SUx|H6&xFBlVFU3x5B1 z)=&*SlSF#e+I)G-w^(7gM=ljaA(!p$FpDCbZ7i7)<@Hr6+egk(2(nH#LG7~xL1Vs(0n;zE@hoR5LM@_e}PK= z%iq@`rIGaSjgE_W6&L!mE0nJk+g-$2aZ^u!Q^;605ObH7f0K%YG<})+ks*Ch25~|u zRk?7R%7PNYKv*x%)HSz&Oe@nC4v1l*9^?+qz$GBiopEg_+t1iiH-;De<9__B>MTV= z4j$;|OrcLr)i!^l#h$cr0RnVURJLs=LrTexR(E^8ym->g+uEf@8x2+mi(Ywcowgye z$*ZL05RV7{B;AAd91G)OOw_)fR2P9o*lY-*r!f_z;n9i>Fsd-4g0wQO=|g-5xiety zd!Zy<$>&&PAY=KYew??!r5WW>4)1k5MR_eDQVwkY=EogxZWSZ*emmlBwT(aRYA>?R z7IksfNqLmd3FM^Uw6+4M0ljf7u5NUWPvw}Jd~0*GOYOcyZ8C$P)JaGln#OU_7FAm# zl__Ai+q7iddx;GD=7fyAA)0RkHZp0upYIYvcyA1xB~D!PzjeqfB|r0$HtOp$x?xs^ z^ct>U(89C`ibL>aZ>7lbbp9a1HdU4LdVse`r(#IBZ!bog&y{lThoJOQg#<90$`?tg zG41n(5h&KYN83$x2a+C|w09xbh0`?JILW1}{Qb2gx&REq)@PM#cromFr{iZgs{F5P zO1sL7i2To=B)Gd1L*HJWP?NiGd-3z;r0ETSn3!k9m&FnxZwmIY4U zd~#X{8QioC<9mTO=YXx#*bs$q5JOlG-uRGrR_15f2E2!;hvZlKSz~|q6e6SQL)08F zTB{AW{j+!0etc&jWA`>YPThx?t9t91-?dZKaYJD!2l9#P2rzIsu8k7_FJ}rFIyE{TVd(b^N zF=H|Ip#sGor90IihgCsAnJ-&dodt&Ifd!_^c_c@;HJ5}$bKXj z3%8`mK&HK;Gc|zuX3U`cetl7w0536>S|K-#+F7|l_ASeWTt2l#)ddQB6vO6_DK&(H zxdVK^Y4lj2H|j6G|Ka9`o6B4e!^?Z>Jvm(*nTzw{B1`K2R_hUJ$evFA*01zkb>a!|bi?jaU#fRV&{5bO)4bni?^ z^`Q?@>@ds{_W4kNL2Hcz4~M|k{~C&E=fM7Ueb-{)`nkK-rwXEAlKQ4?Aqqict+J>OhCY z)$03_19FUeJQ^A$NZ(ipL818IBUNf>qP(vtq9UYV=nCXwZTusSS0ADDuBk=bVU}WY zsko@1M3vg-seou|=enw={&DtmsfL#@fD*;siu)x6ut(7$z3US-Kx%w?$+ zAbJc!+xNsHvx+)Sa$_N8$9D={!aML+;xTp1u6*>#ZE2@~!|C3&m@N~7YYp%7at6pjIdwp0~X0diRhUEYDUKGyDbGZp1u8UIt(HE;vy)nKWdj`jE={eKeuMV|3!0T z8f_$R=xdpLP{*+M?b~-2OMAgKL{Th2@1ciJ`lnElO$Kjyajf`ef>G}OEy~wsE&y1_ zc^d>v!fe-`oXxn1ay0xVjnY9FW*glt3ath$_-}1FD!EL7T3jx02adYztngK(u_!mI zcbZ*(gLO*T1$pb)dKz}rm4+QX(&TX|% zBLdcAL;@QcxJMt_DTo1l$^SS*!K%c0kP3zca*=hK)-cJLQuHEF?Db%#@R|yHj69al zeNoYAQS59~o&N((By!mpj&n6!sRZrSP^=DRU~lz*MX4efFL1x$J@)5Is98>c7|x}Z z&?^-uFyc7-Dklr@6mJffURzWqC6Zt>o_GmNw2p zxm0VCc&X8)KaABm9jSRTw4G+Gx4-itjJmdMXj`6-Vs=ikHhs|95U!d;g-=DhTH0NT ziZyHv8MuC9{5Z0T^(VyxfAu0{MeKaa#-lJmLrazRZe3P?P^XK^l5;Iz^T`Y8!~sUD z>_5A?g@Cv)v#}^>Qc|q+18z>S)yGO`4|PF&%T#``U3SgEw@$wORn8oiS;x=H2m5;X zl-d2xkSoP?S()GEH4tt0Op|wo(N9#zBEz&QUPZ2jYnZg|a^;)ic(HWO#^PKFJ2b zcBPX8e`kVViI{Cmn5JK_{9ShLwdWP%=5~qlhR4mzuWe!Lw~_<`O};~m-oQ-9x5`BE zS<-D$rCTpItv&CjX<7lj?a~0VF35{vCaVs&1ht#Qy(xAS#yc*HjfIFXOa&sti$FT* z%ZdZbHyC?G)RTAH@z%^zGrNGSV4@*GyuP<_l zQAnHglPf(H4d?8HGLwZBH{}LtTJHr4pB#njo1q%j2g00`zD@#8YIA(NU0jj!?p^#& zgy6w!L>j#!DmKOh_nc<6TkczR6mz0hll>1&g$ag_{>H5V#}7^1B5XlkO0qqRoyf52 zJI_WbhR%$H@1Q;iS@z1jN&3l>q)=HID`VPG=N)crEhFd5nDuV`t=e^h{asItyo_r-}{EKo8nS|VuW_HSdhb6f{!IBP%g>Iew-)U6X@4NmD`+k*aIK+SG zP*dHCJ0)i`K6SVwnubS@&U@8y>9^^yH*R9(vp+M(AYZ5Z61ib1v2{QSGV<)#h=1sp zeYzLhekt~mMzkO!c&@@2zSgBtvi2hcplDY!_j98*ZPaJb=Us?cr!mt>+l+p$+r(pI zxV>nYbMBjVDgGPi3!hSe?bo_|f^+-m7v-x0Pf`}tbE6u%g4oKKyiKUFf@oh+rKI_q z1Enel+{fwwEcpWy@&|UQ05NfKZ{%F45Xsf^<7vE<5vk0!|MqT z3%pAB+xkg((;Uysqx#@khq_R<_37-U7V-INJ-Yeud{LkPVQTL zh~d~A-ijWatq-wEJIhFDM#d7{;%&IW%cz@eWK;FTH+s=K-GGwB^!KTWNI{E$em?6qi;f#d#89Uz8O&9J${d4K^eJ&fs#iv@Yn zq4*H4B2$udl&vPAiz^Xoc&mw=zW0RMCJ-9mvb-!6)HLz~ z9rmk3fV2aItwOMg4@WE|Q(70_CUjxWL}#h4Y0yA?zIn^l{-ev1eXVpi->XO)-q9!S zzVAx9eo&N#Jgykv=Jt*a(qt+#eA|^;H!MvjOsz!;fo6-O@xB4mYPIpj$m5(M6Bs(7WNcoLn zn`l_gK}x4jiTIvqr}XIKNeU(&lUkjHK|`>Ma|z4gv(C7O={5!cKB!4s)a$By4|aS4 zRqlR48BsRWW;NW{i6hs$zKC+J&zG6QfJV4GoGtiFs;8>oYgBtKmNK@^wOlcRH3F>@ z02v1C0Z&qO473vrY*xXNfp@Yj9}5*E z*onw;_{Ou|eYTHE|4GmySxM}`IUkUJpP}foc?a)e2(=JSHyMVSd@;(q5>`Q!6mDx` z#vr9Npfjg2uk;ONq#;9~hU3-u#lmQ6zAjbOCdC)8T6GU+cG_ zIT9tH);)RaL{&}Yudaw?pF}HeSBCx|HjY7gbd&`r7IK%@jB6~;!fc_5W6p$H-D4kySGeTN{Kd%F25`P3Y{V5}ERiqi?oS-lGU>%dA(x@32mwJHWpfnU_8q z__pT>wWd5@eyt#6UbC8TH@E8p-@~lM;yM`f%XxK4?a}UIRk!xVPH}~Dp}-0SaG?lZ z&uU1-z*XxsiTJw1JQ>#1f`cFvi(6IbMcG-+yytf&Y%@ZwnqsR5gNBcz-RL@I4FthXfP=AcZYtdzi()gpw7F$i5uN3BZRSdEfL_OY1x}w z2X!9Utf>B^Dbm53o8`Duy(8ks!ys}T2Nina$(tv+l{}x?jg_d5S06Ra|DX#eK=9DnJF396jiQYKaKwp?oI0N6|?~x!4yW z;*b+Oml|WX5Zv!(l7DB6??md7a5~2aoSV&DQRJZ91rD(sM#SJs!wMA*V=V3l@_O!2 z7u8c;n^+5l!S5PFw1bumvZ7t7vy301NdQh{g_-pYdNY;9$MqXx!hGHoMzFtEL5j33 zES#~rK(+_p>zFTy@w$pqfh4=ALc8X8z;-A5D8+fxAiIx=Dh1!$I^lO)+;c_-uL&*7 zNk#-&CKSjS?Y<0&xk~F8*rags=^JHuK;wlwo9Mxz7vjSIbKXNYagY>!$5tk#EoRvX z>&2b4ZKzz8!_W&H)QJ8YUa(Q}-WjnP4zTKoq!WMRZf_Ycj)NJJRu1v7!G|hQ)Hiv_#6) z*zc)OLkLq1#?`sG)L-2Wk6=S{jhmhpb8{aoy5{(PMdRj(l{Q*4c{b3Dw{YUY>GnNI z?`jBIY@=Rxd#7USq@jjnX8-d#!p!f0p|GT`V$ym-!ejmKPEXF``4db!pnB%s&4!&b z`d7bE-x1n*;E~=6^F5+?-NN5`J}$kt5@C@ zJ72$>HX{({cwb%7lq=)-jh2aE&Af_=b%gxwf+}GSx^Ut!@h9o)Zl~H6+bBsAlx4-7 zVOlWV+tR>u!Un}%a*Bu~&BA8sH?8gLXX?Jb=-!v`nEdOEZafMh%FVJXpB-mQlE~>h zda2ZsVD1ufU6quA4@(p^4ql7~^PL@(cP{ALn9aZ<>tQB#{6WS8>5bMq>DM~P*?35O z`@-cZc=R=WL;GcCWLf5XE~OmIW)ob03eMQkf2dOJWLkJ2x=DkvCV4H;`L}vbLD;AP zoY$z=g1x>+4W9)?`^*#FB$je1sg~AleoE{oW?D2iQ|{8e(K$pnSUZe0`Hz=+ZA*|- z5l)R@IB&ROoX-=D-;F`&%yitl{DENohBc zmrcg$8>f)6y_EBcD@lB_R92Kwx(^o^%~0Th@hBmGem*2+Yeb#BYM;DklP4J zmW0IE(JU7RGlS^4C1X3)r}5XL9&iH5-J}9ovbWGq+sQwCp08M0>TT>VB8J5fkgmUNk28*v$~UpVOzx zY1F*eU1@UsLlDrg{1Ia<AW=VtOI0obqiPuk2@phg=qi!UXl$VWeQ8ONit_`I-1!I)!-#K z%5Uc7{ff!@@P2k02D*`L#?=T~A92e#j`;l7%-&X}{ZPk%p;M2hS+}*v#AX&YpIb&B!2}Q2SpH1tP;a-m+TYBUyMXykzHpTxK@$FB{M5qHEeGs{TqQBsD-(vM9k_r__3oZhK3z0eL5rWp=2!!#pRy zN@x)6-OClcaQ0d{J%OS${;$qGHKt!5;=m50>Qapg3})V_SaTNrRRgF?8(Q&B3r)K4QA%gRL3CAfqgS3wsEJgbanIHA8 zkPap5xZU>4Es&yrX!Y`R=`aUM;Ij=3cuZag@onB@g;eTEFn-tl6Y&u@z&q=G8ntt1 zyj{?ptbr*aC@3`U-7Qq(7+A9kLg(yOcdWk;<|=_JKaIl%&F-0kT!z)&aVU*9)REYa zD5xQ6|3()`@j~UOG5GBROZyL(R$_SHL$Q6;!=F$$>Ol(8N|=HqwHOD%wW>?ZeMw`O9A%3s$3I_{5?U1J@2mZOZ$k1}CT^D@m@Kjx zJu*UPIMYu$(Wp&*M^OJ;ud^r)H;5fNv$3Nkz@jxmyie+MTV~Wi&+2&60F6Fdk(-Z{ z>L0Ar_ourvMdI=K8)uP}=9S47hG0^XJ~MSZcm;w9MKvP4Ucizxk1S~yr8cx)mZcy;=kI@k;*kCrQ zH-0Ytk#Y9ckD!h>{;L(-m>{Y99#qZGHB`)Z;&e6BH{s!r%9!^0bgAtzEiq=;%BQQJ zsT9EbOMR>c%|)M{Z#^-vH@hK>V1K{d<&hc7c;8+6g7<2EEZ5T^cEMYK2f!!_MtS6o zrJDfGq|fqij5>#G&FnO(c9zdp?>z`A=imwM>P61GB6NZKLrI=r1<<~Oj%MUX?8H$Q z4Y+ul$nGZqm;%v0lHQ~;#$;V(!Zn}A_A-m}rBh(Th{>DkFM7=htIuHVeZkC8lR|wr z*(h5ARg@*EVuZO)7W(7#1f}0Dd=|+S#cQ3)xwHGe2>z@0ge3e=R3=58RNI!O&j%6! zgVNyp``c(R1AJ4qJN?lT+xcD#N#M7M3%Tw0*!@hRQ4N66y+)}}UvcBMNw@8} zX}zN(rajGs-X|Pgk+j}!!1d1~0LrxWn{|H2O9?THM^Dx>z&jqwPjSp}VBLHj7C~Ff zeNvDPu5+9aO+8FNwTAKfvwP0iy#D%mJL>0dCz||1N3TZUAkyx10atorwD&fWAWi^_ zw%eQ~oj?vVz)EY`U!U^xb3whQzB%yA9x6D5k29=UnzT7)RF!jp}ICsX?GavFO zii|-Ie0Hb?<1{#DeGR)VZG%=txQuWt8cd##lCGqlT#Ir!&Ma465aX|k7Uo>TGLF|0 z*o?4(OtG>6d8}YB?haR=_FqL&{mI#*C%f?{nfd7SJTf_D=wS_>ZHDgu3NmI!1OcM ziMY?e;eIb;+UqW(@BI@Ms{D?C#VPi$VEDD&U#yz>-|p7Cne69v|CllPG=4lH7D!%( zO>v3(-rkSL=^WWPPdFoEKZ&KS>mx`polZAS=50qi156ofY#ml%W(SfAl!FnK}1NI(&_6)Nk+t_gS)dxgT)W=b$x!1@MZ0KHLpwl&hN1R*AZMvSdO6icp$|UOQ%<_jYf$etNQgCX zA?(?veMOOqv4FtN8f@qdM~?6gYUd!b*oqorZZmy^GXi8HAK3Y-zxUR0$VPO$wd=J~ zn5!AIQr!DQ<>NE=+e}5QS<-c)?HBm0OS1H2o)7W~>RtVcy#x7^t^;F4_we!?cmB32 zyLWk&-9_JS782VqVzlj_eVC}^1gTu?RNmf-IT^{g!@nkkx2jw&)|)ghevUWi;3IwXw-a0PQ8%RVQup$}eG*iDHIRyAd&mp@R_bB16JWp4CO?9~ zk%aQnO&WVwd1v1A3ZIs?vzgzFWWV>ZKrP722*D|8b8i4Q!NM91T);w%P` zY(9M<-C-&_EJiQgR<2ZMcHrILg4JJ0QRc3h}F8N*fWx-d7< z71tgA*2n_+Ga{t#XbpcsU(B2~AjheSbtg1_pFM`%KbdatH zljLuq?&R4uno#sV^StcZ-S^*Ma9rAUFmk#6CA^#NwYi5)joZ?U`Px}b#^iF6xw1&* zhUA_x=w5>ey8YNDJ>e8xV1q2fuNQ{3vzkhuouWxh;*Uo)cmuu^YcpcCje$vC1LjKbg79q>8X-k`k-=Wwh z_FV0t56HnPB9!<(_t4NO*#=SFbWps5$Cie%nR!2Sm0!I1SbMd4ihg=`4!14qcsM)(U(<9PQaSPnx!x+NCC*}&2y=wK&`s;n zzql4^h|Mr0flrna5VDf%fJD;Dhal?Fks+Ie^g2T4ULBioNsWp(wz#@gY5;^<4X7bT zh&Oo~*e`#zBKg_3M$F5kDW?IEo054Fi6EK34%pHsiFEHwNHog`t{^X69q+<{kuh-k z>{vwDYRMzP2HO!Lw|ssnOb@Trb%b+8in6hqyMEqTfum`~*Hry^1NNU6!5WE0b5i^8 zOKfI$itfU;9Ve^kO5um(sW+VXb*n1;!^Tv0OMNoKtf}O^DD3tDycW*{mo(IIYxUy| zU`~e}*6t8bx5tk0tJz;ucYyNGc#F9ukKLwVaqX;(!o@X~c2j@SdJdr82P3bA4Yjel z)vtWa5ocO0MKI4!^tXH6bB*SZTIsl!6r(;lG}K~bL_dPJ()z4X^0PwkK*g&AlxZa0 z5$x(Hxc&e#k!54xcremx86nC#>w`(#`M5<0;|-8ECWzak%&$)#!G#E_p$wnh=A!n> z??aDwIPm66r3Kfw3-I7Y_G*a??PPA^&m=1d*$wzreYms0fw|4dD}*)ya+w!)W-)G& zm)2S(1S*iBcCT`p5rE>8O-c%ywbwGzcIC*AFKXoM{+0PZ8qGb}%b>PJcqI6@T6Xyr zV}X<>oWmJ%q_&nxF71`ZxmMgJXCeRgH)Oi?t!J3jKdb^Ac-yYL9NF_Jw|;$uD!AQ2J}k5 z$6BcuO8af3;0EU{&1V;AcKL)K@0#1F2S$dvd|=Us@#R|w3X?0{Bw`Y^I@EaJ2L*e= zKe#Y&o!Wfl%x|Y9EcpJ>WDpaZulqKTh@15*KkeHjRv%8j4+~;aB**5WN@1diIh_DZ z)=Y&(RFWXvWEbOK1I7op3lBr{VV~`*1#t2UzDgD^nFeKZG2<#!(-}#KoyQ zq7yfC$8oE08Z?LxBW6eAUB=%8F}9vbD&C9#FrZA32FV0KYo6HHJ1hN&l>V!ipECwl zUiJJNr_mK#HeyD&Jbuj7&Cx+4GF8<224uD&Boe7-Q~K`s zNr&42QHtBM?Mk`Mmpp0@yxgqaqVu7G?Joo0<;=R@gIX8g>|Lv+?p?`1=_=hnn+L#k zqeM8$IdWi|9yO&joqJVIBL(`T?hJoc;t5%!cr-I6=wbf;SswbJ)F`VX;|QKv%|wqB zt9<%TJZUxOCB1jx#OB?Q>*5)BB3zuqCi^<%)S3ab(@d590h+1KsxSNHVMl58!Sg!d z)>7cfE0MD^TpzEF;#y8ww*VT@cP#r@{p1gW_kKng?}<$|UQhvrU=#jgK|vw(>9N|w zmtyr>SD8k>`7FJLU-lnR5bP-+s%dLp81&upA+-8pOW4F3_lL<(1E@g*NGQ5(*~~HJ z`v^6ThGbG{?V(X4)bN#dsozwC&Dpc%Yg>ip>6#L}*Y2wv$#T^G#7qZR5DvxwN#>r0 z?0zJ|a{#`Pl!cZ$l$~)$mF=j|=efRw<#pA_z1yF$=!(sp4?04>uOQ5jrhdQYVgju; z4=&TBgsAVw3mMH>;biF{4ZDxn$zd_iRGV&S9jBhvk}^B4?Igna(36zR!t~s@q+-1% z^CzAut1DNWbTRkspKzM*K!ZTsjTwd-YkL2aV&mHcQq|_#VM5#LjN5tT_E0F#3v8sU2)I&2~ z==%+wCWa&6?kCG&(isj>hb_u>Ikld1ubZEC8;Ckulbp#rT~@sOEn!#gu!&q$H=Txh z&H8Kbdj91eEjB)*C^+SH8yEeKa2lbJ-0e0G5?BXU62=M&i&#rWOmO|MSw_E&rm)C$ z*X#=O?Xo_7<1nW0SSZPZYe6f-Z@X4-I-ry1H=FwwOlC&yttyzXpX%1n>Qd>v%154p zgGpDm^{n;%Vt@*Fs~~9QXk3zD6ZbyZJ8H_QzI(j!<+T`2Cu9mI4(`AI{2-ePL9@pN z%%mgq8A;P;YoN1F>Q&|U%Mh(-QVAgZEfygDOssJ!zPZz&bTlljvnQ&z%@F7y^{&97q{Ra;W5YjK zNNVv6RjZdLPh1+l2%l^$;Ip%mIBXwxxO~r(OP4l1cDDPHD4#0(4aV3%++4kV8cjB> zTGRXERHF2zJMjY14J&m&yiQD*RBiy~rS7|$>aV71aQjfmPw~e=(sDhT4iHxUZKeWY zxn8x8sg{g$J=z!undAn|-K<1)l{)Z^CxxPzaG#Isd|Rd)e@*kXjt4dly&*u(;Y2E! zKX*V$>g(?Oh(QY8y0|ct;jYSng|4|@sqz$QQN1~CMs~e1CP^dmn3MrLSu0FIy->z} zkQ0xwZ&7mcT~ehNf9=_NYJZz$4&_(p`GQ$hE%SLg@iI~@BC_UJ{;>7y=ct=uw)ciF zU+d7og!XBwv`*0e?{UKZGqNHEAvUUXG;Xh3U+DN?>NTP6mHoXNGkk{D$rAx6ot2SQ zB&Agfol5VkI|>{s<~}xAI^V^_t;Py=sT}lv_fJdty4Mi#T&;N->j(=Ed}+f%!Jy%C z!(O;B;z*7VU|>7rfv9(F+{*(K_@u`^Bfjbz2^AHw1Qe-28h7=_HNekF2E6KptUqfG z=bDx=V3JSd(VAPsv~?;sD=KVApkc>ST1UKMr&V&ggf(%H?v*md(dssk5lraT{d;Tu z=NFp%tehqiL7U2z)xbG3@I#Vs<4!BweF3^_kl3DR0D>NN=Sf-JfOCd&rRAOYd@R3Rxu|1+e!kZG$+R1GsdTa0`Kc zBYzyR2C)4+y)}D+|KWr!;$9~Zl}{Yiwj*GX&tNNSd7TIFkjXsL`on^S{hc8iUKu0O zfHF39rxQ#p*C!qBTG9Nf;|F8r zrKgiS4}GzuhFy4mWS-ZoN7$rSxcer%@+&`A;o+G-W|g)a!6AfO$`X7+E+@9gX#0AZCU-YX)9U^WwX3jK%}TCiq9urhd3;o;eYr!z`oql z05|nMyv}fgbgWTIxclKz{~-)pQfcOXRQ6?(Ms-iPwBagI2;t|pX0C4a){s#5VV6)8 znZRb|9H(66qt~E2Q|Err7v7H1RXRvR0Kn1?a6rm-pdYb z{!P*UU5$a`*ojiw{!q`Rsm<=@Fc79jp$&Aip%Ix~NsYa#wzNQ8kzf0%Q+3 ztw)c#E2-2kpT`eVaV%qd}(36-Jn6&YAXtlu|A9XW%4~0I^69-G;}X-Ule~x%w=$k{jDew~dAg%U!X^EF(3B}~n{ggB^Y9QKF=6eL*?(!nuqg1`$RFd~J?W);d zaf9?Ruj8;Mfw^W_-_;FZi_g`du_iSP3T`=^ha)! z6nr^$3EHxBV_nTKOd9l-UP#Fn3E;JLB>?(&C@zUj;*{6>!K zhij5be_M}|)=$BP_L^UboglI(P&}4z{$=;bBMKfZ>5U?0KZ<&rJ!Q;>yvuf|rt+4G z>mx_&++)8J86Il;4d0cp(2=f_uI|MZIp9QFu@vAlRhNdC>koBhACtMRY6j5VOBDvrBW7_T*O@Ti`;V4U3#8UX%v(0HI1h zn`Fc6x_nZir(;#S!$rO{;m9pHxGa6r7RB$Rz?7CT*3NT@^UV&x@2rdm;G#?B2KiXo zodVU0FSmWrjI%VdFf_OsK8z~3E=~!q(TQTdbUR%$s|xs00{8<=^P=YobLC9|etXTz zd!qOep!8#V(lF`Yy^sNu@31f?o&r=QG8BHcJRoUzkc`D`3+1gN{EQuV1a#Ai^uACb z9P!_H#1t1cN)+cVXTKgW%d{P6ybj?wt|gK+ks?>=bdq@8>IDwK7y#0U(>HLRSI>SQ zF%^my;NQ0WePD|dl})0|*98^#=`PSPHu!`d*iHwz@(&ewc;kwz5ob8B!N;v`*4KQi zask=L7GXeE&lyn;QjF5p_|CYMZf_Z}sHtOpcb{L(C}4Mof1Z;AG3$F;Y;-Dx8P%mR~uxLM*~Y)|M`tko-NKR30@ohNJ;?In2CfJic1UkHE(q{sizyKusMfkBp@oueL4sNlLihor$eEIHE6tYaw~Mixsu|exXIHr&Y4z z<8w#RdO9PWlFLq31(D`dOYasuXU2Y^#zSv6Yqyi-$46c~qA9-_j@DHD)|zsmW8hp( z>m#LXTI}k@6Y@8etG6c}Oz_%U!S@^!kPl;M;d=wye@v1H%I)B6VEA0jbnCZ_OrF` z9QmysfB)3EgDyJF@}t*d!IFH~OxR^7-w>S38D^mj%zGb{sTU-JS(tPnls`;d9 z>zyq(%Zz-0oKTIZ3T(`2=IuBstw6zozP2|xm-z8Yie6WnDXe1-02@~o^ajMw*Zhne zD@8W8S8xs}&if~-s3-!gD}+WAFI4*PStD=BmYkw3scWY8;2w+rg3w(XQewU zDUj8wovpiCs)Sk+S>MRlDMka8hax_DI!=b5v13d%sV;;@(u`eplnVF&{APf6^NQJP zKR;3mSHt#lc9aBF{&2m!5^{h9zWsdFd383(+j?%K>W6d zu!;eP#&fn!j;wi|3TCZY{2tLCTU+I7)!>D3>XO9y&>M?DPPUS!y?0SD?v|4W=m+AS zI*KPb-g_C!e=^Q2VMT0Al~csOylm3FS9r$O*_BWB7mrmK5kAVqRZJ^Be9W}63_XG z2tzQAh5T`x49(;WqrwC7Wxis!PcyK2Bv>4NELir7M0*b|=KFKUZteG$#FU9M<4O2G z0WF-+jxEK!RmqLV9~>e3;TzzB4PXZbZf={`vBU8^dxF;d>_rsRfiAzWH4xFO%PCf_#NzOYw@U zMW?&T5N(%qKR%K_4g28(2%{7Xe;oKmKk&j0wg=N+KcGV{=w5X?M}CnR3)h85^8|8d&X=*nr})(90!&I1559|3z1$ovhe~f(6TJK_2MHX;4sNQRPC^z{|dcgXx@b-}qhew~HZtA47El%0|z44iW zl8bJZf0Q};y;Wk?J@a9+_a_>Pk)4-K}G^T7))Bzb=enS`~s(x9a>Wi z*aM{A$Ud-=Y$i+1wS@k!Ev^Y&ioW}rX|7E#zI?fsKdEv6-a1}vjaJ%V7ig4x9NLyH zRRp%$ciTTq1+ikutRIi=x&Q|wEY24>*CJUVD*k`*bms9;w&B~iB&kqIl4UAAB%x&A zrjn#W_Ux5}?E5-~Bu@*IER%IeNS4XI8&bxWow3dkV;hWZ%x3QUo#*#^-}jICZ$6)y zx$n8p>%5NR_@0*@@oY9Ng;UpKGfh4to)ma0JGnljH=)DQ+Cg5xPh|+uA~$-d?`%o^ zJSOCLgtwbEJBPEqdz-$xbm{6{ljF1O1ZTw6LyTPtI{gg!Pow9VS-(r{E!_f?5ti1@ zlx_$^f(MwQsTeZ+&hMMuEmji3Sg66z0>)HI% zmPK_^=?%I4D^;6-(Fmq~kkO==s=?Szx){PjkL3xvgb?^&h0PkcYk>%S6{u zQMeXwMh%WWs1khdaQq8{;dEX{tZNST_V_e4fh`*PKc`^P+a73)W^9z)BJRZ5%aDlm z3g3fmEY_3=;OsXg%Uc;4TN^d4Wg@BwtjK-yqK9XUESE1|`mM3wMw@=hlz3@WYlAEQ zVi8pXPCs_8M|CP4VkfS?MCG+-4W6|JeO5)z<9Y|X&;ln;^5f4T!&r)#gPpBea+C>I zVf=+ypW?{o_v$6^a_G@_Dqs8f+v+&HKQbkrunXQ1#Wm!)Fpyxg`7lv)=i7gYD9!X% zug^XJ&lgi&MtPxcmqil<);HwOKPIKkJgA!g7%Skd4BDT!mLd84$eVGtFBK8GvETAv zxeG!}*N}5JmCG_ZB#T!~^bIM?Y#3N5=0}F%i6)cm> zGm89#_I^Y)_!T-nZvgF}gs`?b1e%dPhAF1AZP~%$#;`G($;M{X#2^sX$5MpAE1EuC zVCN=(08RSZ;MZWY2zWbPvD*;-fLTHxea(hqC%#u?{K2>!sOSKit0J) z93~FF+sHMZte6!-%2Z$O<)$~Zf3Eh5>s)r<+3i(2(!fFc!IvTEFjxOW{|khfw=2O= zkb+!m)y?)FaYFuX{1YFw^RYYbs=}VRz+Q)5P8i!~4QL%vK)Ae88^s2&ypOr7 zuH06>{o*YnQsnTdqw7CUeVIu0o#8RJDs4XIt-Y5x^7!lS?PS*<-V3?J9(tdT=<7Gl z3Y|?egO3ySR)$<)i9)t#7`CfDde7|+KZP~S#~;>aT$(V=iv?%I`x3mp^zMra-+A%- z#?&_{;g%Ka%v3gDg1Bz_pU?JprfamAzJpN)|1&iY=u9-6a!-Au@5Tratgs5vv}i>l z9c=HuMfHB3RU7j-vkR^&oe!qp63JeI85ZSGy{dsdEws->=z+qWPLD>-f)iYPV?EmBf0 zhhKFlBy122o!Ox!^ilGfUXo7mnu67~f;K73>E z{p(C0$rC1WdJ{FI7lw{1R-(sxueMkyTkNOKHx=&>P(sM9=3WQ<;*Vzqzgwg1VPIF&+DC zXC(aft_2V;$qs&oc{T8|NfBW!qSHu#@3}a6L65-$rI^kOQ&)d3Q!M^*l6frxJGUd6O(+4N!i&;&^prJ?r|8w1B$ zllMwev5*LR!clccQ6k;-#Rjy5Nw8q5?IjhG!9Ir5kW&su#X;E?4)p%E)F63mgeuBqEPBV6bL;b)6X|pIFZ5jx-5B_seCDw zI|ZMsmIhuB4_Wt93f(w+x9eu`Y!J>sw8jN}#_)?_&WLrZlu;L8A!mD(gvLTq``QdYx z?vg$akR|n;693NW@EkludGm+@Qj6JKilpyKSN_vlB>b>yq&kIn=II*68Lt>8Oor8WhwSv&s z?M*fI8GCEO(kEEKOZdxCXw` z)R?vMzBKjb_Zho~MT2zVj=dkmCA-(MLoN5dPhR)mt{gGeigW4}QC_%kJ3GoZj1@9G z@mu9MSwfXOUZV<}NrEpmZGNgSC4n)#;-_I_GBMx!8E!9!M=RGZg{=Kz{oEnyhJLiq zSa}_S2S*;nQ95QBXE!YUeTE->ywp(4h&ULdVx$r^FRnN4Dr`$t(C&p~|20r2*Gn}k z-TUa+y02vr%fN~t{*xFbu-FJ;c(1r~8;*9XR2wv=UvZNlB*HF273P|^FWa7~5T z`>&jzKe-%?Eu|@eZd;Km`-<#H(w+RfiGN>HfyQf_Toe4R!IS5Wbp6`Y#d_N{Pznk5 z3T(*fLo6Ze_3_i?&D!_J7oXe+q_+uSbyxk*bBiC$8D(PQ5;fN-w`09I*yJm=)@pcM zKYh?(Me{L+9r$E)@wB3X+?(SK z`m{nEDy?!!hc*}M?=W<6y@u*IuOeD{y;=VwP@!~YemPxmPv`A>^u);v=Ra-oQNYb9 z0zccF3=7pe9B_PDWsrfzp4963&E4uOW0dvl%NZQzg)Mk?l0qV!^C%UaMIIc8DAjhk zs_#N%o)&xDUd%t=K$O+M}Lrkjxz6@=fcJ|~TKn=guJ zi#9v&j$VQM4EG=Mn~!TmE4}lPbHXL-lNePjx0fs*DMFpI11=vSfN-U%s75s3N|+{4 zmVc=#J`B}3>3~OwVI;uv?J@sHlVbBT?Ivb3=&#p?DLSvtAorL z5t}t3>T|i=KL-NCsoD)T{{~u$trsHROG+;gqy#}Tb`xYcu?FC9AQyeBbF3>)DH4mY z`u>g%EXVlm%+DT%;B|<@cUbqL6&Mf-cCMx7IG#mOa-R6{^g85$0Sh3#I!3&rx4>^L zdX_u$JNQz`(Yu0p=4qJifQ3vUk2aZ;6aC>PA83Zxx* za-p8zwgW2cVZNs@j^O$S=oAFHA+eaYiuK>#9W^&G&@tM;jED!@(5NI(AmUm)%$Vh# zKOwXi&qTC0VUFXI#~`(YC@t8E1uyQ!0m!)!0Y~_-%LhRT1u9_8ft9wpWwZADd1^IM^snbMxr!3ZEgG4{#Qer z*oWSPzlqD*gUg{Gg1chg)CZj~lPr=)RmWc-2G%`N=BjMt>{mm(4R58(l>5gdUfKHTE;PAvprv!2HtP?#Km5ITNL8z zaZLGfdbHSej49sT(zd(Gu0RKr_M?WFkYgY3XR!61W~ES{hSYa@ zMu#kKR>#{v6o>Uy%m+0H(uX9W85`Rn%MKx=Rt0f|R%KC_q%n>gwU}jaqjuW36~lZD z1-23X#lD~JYc2p%4a)S^4-?j}O{pJpR)K}HEsHA^0U@G@`1ni))#s7Z7-0iL&52lz zeajmk9|b(wlgq-vLmHGd9_mg)q8>xaQcBVSd%r6U8Bfv{?l3e-o(aP z-oU>tvMd#QOHe>UbLG%(%e{|edU?%uT>wII9*Y$(Xw9)7xZK2b*|ina*!fqgL!oK? z6hB_?u;B1UwBvbLvxS`#bbC3C%2lZAylPJibTK*{Htp6AfWmS_Bjy zA3fWF(BA3VQj<7$3kqPvlCZKQrxlmu^~VBVMa1%}9qFLV4~V&(MdRRkk)b|6Oo<*X ze7GCi`KhQIfE$VVH{{3^ukK&Q7yG`^It-PNy?3%qjuO+YhMy~#MZ8#nSNLz6jBH@0 z)=GL>dK2cytcTI|=gU?vwzJN7@LSJ<`B9M;6E=!mv=<$GFyqo$uo(=fWFBu2m>Vcf9E3U>GoX zb^S+2upeu|`D;;5WY1N~G7DYIP%D7sGy~&VKMSYXQc|6j^;y?pKp)cUYmN)u_qT&Rg7a$8xx=EopM=v7mNgm86?1-?cwSOWR(}UY_H;viT~e>TfgG zS&s(8{yJkf2e+MnwGt#3ZB^YDA4B~(8qUVFH$8lJSGVWzoY^mip`D=LqPf5#G1Rw9 z3Uc$m@dCfP^%Qop(Qb!A+b>ilDD?bQS`N}btjvDPKlumtMf5xanPyfKb!CY2*NEr1 zWg|`e*hOx@1#Vd?s+QNhhEf6#xnEY9B(&2B_k)`a!XkOAB<(A$5MIDa}6`HSAXj z9b=g}KF>+l^e!K1s5hgL77)0->A63}9v?EQY~hl_SPr|MxfWzpC&=Cis+5}A!qqva z9S@W7OiCK`FW=aTbIZ#aaC~jzdgHxN^CGDb&{R`Gl&9FVymdcguwub>-nPLhY%4GR zMFcDJ`^YA_g&JiKpI&_}y=k+B3jLrPNL>^%`7^|bs66QRZYi+OIDYoTn`c|VDH8e9 zPMNm7w^iZVo#iwB?!%)jC%8_-$~WUpA1TOc*04*NiJWds{T@X8#gk`eE&j`ggl4eL ziuR%gv4V2aM44|saP@|$EtXNoBy4~W4q^!%|Jj{M+j}l%C)^p?y{jO(SEbLz-{TAN zLJ-4T_Vz(;uI`+~Z0#P-KsTU^LS`c|^(u4t9JJuGFX-=&CfHGnpHFw@S>I-CvZPV# zX$~citUyvZM!~lcW!^Ok5e)+ohkcrq*`N($8(wJ~>XRQajY=jpDw?LB9>;;VMf24L zu_qMgo&ROzK6QlKN0k;u>~~`!aat6m)%|Jm5y&^er47V`WG!N4?4Ol1J5NdMRm$H+ zM_8m0D}&SeV%CqtHfYpRF`oqsXOWF=+SeR15}a)ee(#^#em1i8!_PjRgN)}#18(z# zF@@@)mQYd4D0aSEOrI4?xzK6P7PI~oufC^TrLIflD8U`hbwtxPd&z#QHJC=Ck{__greo z>FDe5XnSQH_01UCU#{63BVZUM-qg}E`t>N%F!tc$hSQ!JjNSi~$Q1}!QGR?6_vCk0yX4jT>bfIn|`t=08{<65(`M(ns&-!3V`Y+C(FMk>6 z4)bRgrTCl+JXHrv8X^A5_G#$Sli8c#f7=wvZbv?zQ~FK!kQns4poKHk)#O}kyxL`u zMl|L9J8`WH;`p4aQ0g`A=9CM!$&7NR9h9iVuf7r~t0{E==iuM~!S%tKN^PLlio}YLfeg9NRQ0~hb{fd`z((31PZ*y_I<4Qd8s`gvo(JRRhmH560 z8h(l9+OHWCK*MSo=S_PrCv)4LJdsX@frP1LcqZP`CZ#k(R%TGU7> zm(^<*PnHkeO*!~np4xaitM>`x^hwE~IBoUf-P)%*!>L-L|Fq~V)^GXDGX{HzmP zS(J^Z%r$6t>K}Dj=j@ukdqOjVmA*Vm43c>0q#s@`C>uEKy?c=wRM~gOzdSzdYs%`u zWR)xWXru4E%EYOgR;dOli9x>;zjj!bp4{&2v_Eb}%!^lWmv8>m)@gBY((@U@Eb+eC z%4fGRs}jx}po+D6-U0LP*N!TXNb9A$#{I#-w?)ub;>G>{U0O`?|H+3%qG4X`WOkXd ziI`P_1I?d7Dq9uyXHnETHS+{H7b3Umpv^#Jum)w+{Ob*?7XulVo2^Xm?uySJQl%2r zE1PNmC@P>>eXhN)cy^KXfIYoTuJ?*unHiojUYCYC*xUCb4Y(j3ti~TZ|50-7-(*WI z-syor`gP~K8r#2wdL=>*Dw~P&S_bJYKnt~n_b$D>dF{LZVv@mKy5t{5$UL&uBByq! z^X0Ay`@6D8v6bIidm90NLOt9yiyr4c&$DbThVW+TGY2&2u%Ki^f9UjHv$<(;lZ z{^SO>;I|X~JNVVE)&K)h`>NMUjp!VsdB{h2cM-gGuWDOT{=H%V3zGbgQxghu;!K zFf^C2-F}}mLgU@gf{zy{2`1lt4vHC_+b-<~Xro3@ot^1@w}1Ql07SjT`7JzwIE^+xOyAXKjK&c9650|oj^8>%cRWg$_k z+&+q~rl;^LUm&0OP7Zywq+F?{nYG~~S2r6q{fr9E#R`tYLX9+b`)>5G`S7!j(%-@B zSaAnO+83xS7S5>mU&SesNSKY<0RYu7;23yF2V(?ZLDya5uk9kg| zH+{_-b1sSZynn77C!A`g0v+0cQ{;FqgGFX2|smr8@u>V-hg=YA1alst^sbW4mTc ze^5?Vw(kE>ifvq$0&?sUb(X&EIDwRsl_F=&_TywYLW8lg^JT-)LYK9=&|84~jtbr| zfw_&lh{CJcti6NnxV>{iB{oZg$PQm5?tlIU{`q{pB`b7zSvlB(&HVCdz>c^r7a%b1 zBZa9WCQ$QAXCixQi8Xx)4t!&W7EX`P)d85mA!N^8F>i}RC_vi@8mnUSp6N;j;=vOJ zz58n-qoBo~V@~uQq(@S-NJ`B=f8ga{F$#>N?;s1b7U5rZvGLHzdto(8)jq6^x@YpD zxQuF>F(PJ`W)xB9vMCR5=&T0((f;pxwCA@ zzY_HR!Nb+`CSGKK!vxXQ$T1#x12gj2WHCzb>~W&LOCwK$;WL zz=^^+l&6&wPHP5V=A}Q4xX8oul-L8DpXBepN!_v{h7 zWq*+u{V5*u1|erpZ{eHl3lxnL zN9)f&@@Yr5?iCP|QMBju-->+ywl<{c&z$*~b3GdfFsoNLzBTE?u0~%HF`#wi?z_sh zQA^>isE7tut({0FC};{}^ATon(6z zDy=>aeQ-N!v3XJ2jWH3m+2_gU!G_I4{?04cC1pZc{_nox#dBm2^ss=*oqWH zUEjV4yYBaDQ^?7e|7e}|0=e=5#&rB~07c1FflW3jDM@+;H!|kluEk>N7XG6{oq(MkwU>h4B*%yiOYi#a&Q|$CH*YQ4 zM?{MC#@6>A0Xv2=$oH6Vzi&+}J23eVv>a573NuL8avktz?>%bu-7;0S_-k~Be5^)V zSnJEiS9h2H2!dsEt3|L@&lbv!UIR)&e@H6}0RsiUih_P4Z#oI;%VYjdu7vkjsvC1~s;?C96uG_Ej|jDFMHl<9KS#PfvR*IGGc-=h6E zcyAs8&XKvV_wKkX@tQ=|F~~~e!>*|_%8UG6-1}tz+j{+eR;00uXrJkahS?TZwa zn2yoCP=8ZMNxxdi`jz(GvgOmd_1VYxo4tY%5Z+y#MOG_L2Z)J`=H7#Xa=uiz@z4jW zsM=EbZlhjyfkQ4RE~A9i*rB^oO0R|!?Y50`Sxrx@;Ec6y$X~Y3`2@{@8O)v3plrfvxA8SLATf)Pbm-5q8r?4F4HH3DxvR z`1k&)do3|uJx>pr4*kh|&htJB&-4Df!Sk^1yD8?z@^(Hq$_@x{rnd&$J9xHD#@yS# zD3dCm(;B96-()T)puZvRJj!Mi{{D{|ZluXIE!EmlgUft(Z;y0`q-dgbYLJD5)0dSr z-@V}JIfx16qN00#Bkj$Mb(4w$f7b~S(_C4wwQy1@+CI{+6pEfUHF*XuIi{bZ?K-^A zC9?@I${%$A1G2!+fh;gt#7l%y^oSR7Fu&siGSE*?mYlBo`FDfR4;E$l-=CM=&OaU5 zy3U8m?7gNwU>1QgB~VUs_UWzGn@+#7qB=#B8SrVl5P5PauSqDpL_BEm zWD9f+{NUuaPd|sX#d_Q?T}Ouq%P3!G6zTtLz8>}3l^&BZ#L z2>Z*#Y)faJ;Y#u-Z+Jl~;Uw>JEpvld38pMhGs-EEHCoi8rtB2wtXApYI|9xEDD?xM zo?b`5mH1Q9!2vL^dC=2q3v~th%iCMW(lv?p~f?8W~`Q zFd20KU#L%!qO@*-qI7GyqV(k#akij~1e}7l2>qFR#$i> z_VRWztTDDBWp1rn74|!04>Ws)2ypg!6P%-FO#ltE^RA?)0xRhtY5FMq3q7PDNtU=} z5^3)-gj#c_L9ik=g1UQ;9tSbe4NJBzF~E0s7oJ7ejlDPiR5bZCWPlrtOsd*!B&DF( zMH1%sh6GK5;|Q_-VN)22Q+6W8V-CYeoXqVCGdt# z-xvtKs+ctRkBZ=AqkGBqTMLB|q*wvvp0_$}!4AQ0T^tIE^~9tqrNPsd5Q*;=yY6vssx3z2s)SDG&Ofhz=H+7lxc7@I*cFp$ z;KFy>oAY9~W>826NfcvnkI1nhI11?_1_=H>y>(FS{?G*UrT;C{Fx)P>jKdCXv{^d zOGw>WGtxSvC~8>2UQD&%4j=72|37AKkze7q7p)dO;Wc`JX>On95$o)W5rJ!cKN=sBVwO&(B$Jt@TfAMNO9zi;jk3|BjSFkq+OjGfEro zrr&Ta=Q^)uDI-)0KlJ{H5`IWWLPHze+FK|-8ZJ}{;MrTu#3A$M|B|;BRgHkrSjiQD z#xo$tD|eH&D1(-0r@;1S>$H7A?uBt^P6muQ9gI+IxO2-R=Ue2~Ey)wbH*bC_T6SWs z;Zn#^)Fz@-yyO=d-!S5xGBA@p1iP}2DvtN#bfOOq61ofGiMVM6Fs(a*~wuP2$^`=h(?F%AA*{gKU#mrgT8y3BZOsr z&PH|$-Y+?WlZ`7%M~o+TJ=pbudojvGT1uMff3)N#Ut_5P=r}N)TXN=qgi09dFcRFamRbuiwr;sJiFjLYHZJ2_vSrZbPC{RG?T*RUDYxj- zxSo$$TEAt&r%k-k#!rISBTril7f7>2=@y1Fx&@!7^r&j6vN9)FhPDR41Dl7RH~If8 zf)?CdBYrBT5VqXKQr@4gF4(Dt##k{DS?D@^Fiil)_5V$2 zi~@FxemfZ*tU%$969*qRJD{Ibzz@9Yhemqhh1X$t2o!Uonc$iHr@Ba7Zdz_mA_2W0 zz=AR=5NX!Ue^a-AX_%nl#9pxE@IP*gC&XmY(|*{U@{rc56K)5S15sA&eMrKB>}){4 zPG%E<0CyDGeHB{J%`Ur&n1}z+XQ?Q5!X~zJGLLwYXJ3?nB%yD!(cAiZa1;E1DK0Ti zP$U$7o3;8h<3qt+uM)lnyBD4VTAYv3-9u^o)mI!%reSw40WMz@@nD+E!O4e?dQMY+ zCiOUdTGHO`hkza=C~T>gc!{T(Jolg}n=o95A%k}S*|MkX0S$@t753Bv1nz_mrPw6F zIwcYq9l#=GHdtW(vMySDKS{5LVKSRLlV|;HUBke{kx*nU5=0@Gnyg_!ZpgpdXzg?n z6B|WGI5W5>tHWt9^k4`m2fga>wyNw^%b%ix`!%y;&UhXGs!fG<_^%iU$RE`7O9?{F z_MvmpI~|aNA7pkf^uV!H@df4g8Lx);slc;r{@I*G87?Lon%F*oxA?wsln8oC_-}@5 zY@84U+KC~KaR-0theOX2=yJbIR z4V8%3bSnk~p6ol^7^h(7)pjxNZhXk#8S#wWxiZN>!4tloLV~{}14+qB9iKEmd!GyM z2=2CXbfd`xACb_B?Tx#teQ>HSu;J>1wFxQhh1$2}oRe0PnvtZBSjZC{h$@c!gyBGK{M#d$UQTW29%(*nxA?BPqA_R$+jKiQ|rWE!wflS%WFbn4vbRbHo! zT~-icEakgK(6mfUW?moMZVCBhrsa7m?(3O(zB{K|Po>45Ebx5R8B@8P;CCYRZ3yah zs@n%mN~JjGthD`7=ZWi=Q2?nzcG?LR>n$R2_!8485lV^8f=kxX+3u>9`CK5R1-VZ- zhYa#w4iZTCqz83hvMrT_3; zaw*jMx15m`o3-B`-wDXs@*an9;XT&)W@d%AS}n<#Y)>FPkGh@x4cdTsVyZ1s{IlfQ z27~%Z1T>`2#S6TX0VRjcW7TGSTUy2IZ=nxQe(TH9&_kCzmS6N~rWg7T#_L)*!IY|j z?eB>&LW56Ohq0D0mn-$MTkrx!?FwyYq4I6cS>nJYzISY8)Q6Ju*SR+Yn4hi~Zv?b$ z;Ei1UD|la45Rq*HnTCzaXL?rpO}Y|7#&zK4@DyY<5cRPA-m4TroxPj%CJe~SQ@bfQ z5I$b@S9YPKHOSHlj*o4{ysALcdodOrA5z)l8cOVonBke5q>&&e`t2uWGG!7w$hFxX z?SDR$70?Ca^0o&^nxS62aE%|knR~yynt$F@%WncH5_rWSA^f3cipvoRqr{6x@)-;O z5_+EOxST32k}`6-IuS1)Wyx_;UoBM4(Yo41hNeo`+Yh;24A}iTLhi($*bzw2v z`4HB%S1yqi+oyQ&^iQv>3;QDbA;LMnP)fBq``4o_#Eh6u1&Se7Hu@%^WMH51{bL@5 zENbU1OijC~%vxLXC|6)3p~*(7vdlGnBM@uta$>91)1Jk?t*FZPIgg8sq9`R!sbqja zPGd$z_)H#%+NHU!7H_0deh^ni--)?Bm`tBb zv-6h6IYpE`vy}2ftBvR^yZiQZlir7t)i=QVlz-~r%F$~Bv8J%usACrx(^m&5_+TVz&1eDsWCfu`?rXCAX; ze%!L%DVCBfID2&yik6zPcA^bE>XKi=+^u%2zmosvE~v+*wS*X8eGbR6qF`%y zceDR+w~Rt9IAIvD%Xu`7JCgnjnKC3QZ3CYHyjXhai0(B(XSaiVs6Zn_DjgU*I|-~E zzWy$sdK>|+!(-`15CaWBItLyAn2HQNeij3ng73pzWp~Ma>}$M|`kp0c^jtQ2?g#hC z3Gu4uSJWhIR_vq0e(i|YtD@pKbq-@<*9L#YNQzW0=Gh^%H5V&9P`4u-LW9giyKYs% zNSX!W9FZIZj>tB^UUj+?TB(pv|Jubd_e-UMCqWz8>pe}Y6;O4s%4^B#v_}wOK z^I_=Z8@lR?j??`-Z|=tMmmex78dW)vzBp_6TF(HvldZ&$PjT<~d!9nRwhsD)c{vMA zS2;}kwTWupe5YeJvPG_ZCZ@|MJ05%$ar}vHqri(~uCxok)69LNn_XJJ>EXX0U(`P) zLP_vx4^A2-KkN(*;p_-p-%5HxAHAE(W0h%s6dUVjYIDK4g5DPG^>2re>HU|FI9W8C z2kvhkBL!4fR|#Ir`+m+>{``MoKpE5}Hw?%}$UWX)_d*r;iB!SV0A&$(W0{ZJH+UK` zVMJl#Go3uT7|+Xe@;{?x7Z#R5k(CQ;q`Y1!r*FmxZT;3d<8?_R5UKM@-y@}=xx)^v zobJggAwRKdV~S`?tl~J?;z3zi^Z@%mR@A)sTXCH9WV}?cq#J^U)o)|fQhnsyB8T*y zthP2U&@&=g9fT;xe6`me4@bMln6~ZwEuI_^$EwRYr&`&npv*d`)e;pvX<~8W=JV&O)g_+VXA4!J&XM}V%jy4RwlE%S6=S}5Q-ryx41Qub{rN9 zvA1Mam7K-Ho2hNoG#oqE=lHFtdLTDOrWtHn<0FU0*EzcTFPa*3oh=ZKx z++-IUFQIXGT5ISO*@2v>sIyX%f6lr2ooji{or1@K8w-i$&>5OL>)u=ea@A7Qh!s}Q z(I4JOm2X-v#V9|PSuCb@FkZb;{9$Yw0nEiiuPm>zCNjNR^~0!9Oj)p_6|{7&0X$X} zrS^vqBCYE#igKjysMqj{Zyo;xvTlDt|!^y-eauk#&h;6E)&bpG1 zw4%Q}31dxjdW{P=AHW$Ud^uMzn+%WMcy_Lt3y)4v$|)M@URdHG?EFCroj8I zR~9S!gyJ;G1-w6O9#}EK$`8;$`b9s4&T8 zfHIG>8`kEM^{=>5Z5yYDn*}N{*2L0=skMbosMB$UL1u3Q$ToB=>h)tFeeVHwn z_`l2PZ)N5*{S=Frjb?E6$vTZ9CWb-Usl78bt|U}u!~9{f)B)IL6;YP)pfH)Dm%e-Y ztj{v4dkP*3*x>gOW_NiDs~470d+0N!Rlev-mdd-GgR=QA0`2gick^`Dux0q&nYObH z;_&O%=-gc_9J`Oo!+b0NSJf`=JvT@%>AmF+Jg>4U9)A3$`LxE9t7ctwvPw&KIkE$R zo~Nc?ztGh7<#6~LedxDy_oJhjnz+{97meoY^#X%ed1w7>Ru(r#8ZX8{o~6-3v@3~r zZz@Hx2BhAoA3k7NDeE?OmcbcuOzqR@ixmI4h1?*e#37ft>5qPo<@vGp7Jb5Re9o!I z`R5@$LQI2DMN(a6rHHlRrX!~g1B01 z+q#=lP@`{Sv}+XO)Mk}jn2{cOJPAyK z{s+W^-TFR^_7Jss8Hz5&0Omn+PIWVI0*knO)O+STR0eDpjLMBKt#bXrmXCKH}#=MM#crT+niKYa~bkp zEW5B&+3?%p0jy%6kP*|VwWoYQIm)5iJi0w#K0AO!6bh_djz{`fFhijlJ2 zs+--PbYZXESD+0n8Db%X@OX1MRh5-7`*?F4p7RnP`Ch(<4cC`4!<)GLpyMz~hfMZ? z5(DMNlDgcyY_F4wma$##%N9ag^OYbLfLPqNXRb_6SYtZ%A>qq)zXg6ZW$rw8nLz^^ zuxMpWY9L&dTDyXG)B^Ad&a5z%uC#%P`*7Hgr}WiXBZD5YQI7-)Ig6=y{gFTCA>b5%6*@oI;P-Y;g6RhMNE~O(1gB5C|>k z&C-a&9UY2Khu3AOmU)(He8%nDqcOGfK^6;7UTtGN3fc6E2+O5!jM&DFXIp+K_{3{; zK?sZxK%F%$#cwJlVm_kUzoH zN&x3psUW`thmEJ74TQ-N_WX~OV4{Evm%T12+Y1J`&k9GJ&k3Qh!(Bj6vJ!XjCznm*a z5;O6wYvJp%MV=1Z`@x48O;t7dnj>HwTl2(WJ*G}|iw({(%gSLNzZkrOv!4~)0pc&H zavP9Um*WyfIRcb%Lv9M@Mt1#-=bhbnmeWgQWDg*$l)86cQ*$+nzC8+B6S;o>taDun zC(j`X3qFg}sz`|%A^wJmdnL~gVM%JGmPg&2w|sKn&hDW$P%L!fb$(ucq&PfiGgn?4 zyLhl*lV+&4Ot6O^F8LO5_iG;njKvWs<96ss8x#KB^5;3NM0Y&&E2GM}XB)Lkc$Wnh z{?=*^E9joxeoYlB0QsXrL;L66t{Yqj%P@HJo-juH_?WemP89E)9f2{e-n0lvQJosV zQY|vW&|{IY%N`*(qZR<(_*|58WV>i}`pR4x4VkkgJ;w@m__bE=@asr>gNyxKV%R4t zV*k9yjK8tO@*TlwffI^6|1w467Bmny$EIaC4borg5`UQqUI&|bR5 z`%uQ%U2NhPl!HI3w~|%_OmNNB5Pt}oP5ZIO9}BcqnLPLE&^Fs`$Hwp@qy${-Z;IWD z?-dSQyWe=C(78YA-fVrR#Ed?n)$P(sw0jwhsfMm`(V33L@|;J2<1*^ja){$z8A6FE9u7X6aYh6h_X{xPDx0p$!{U@)>3_+$%FPIzOq>% zSLoMSUUR2gqS1m6_A756X`M^@#C6|!_!j%9z~;+(AMFW}nk(7=rFf({VJM}%2mc%6 zk@@fT__H=tMR~R_hPOQkVa`z(E}!nF9nS5HWS5DD{SkR@F># z(MA{|$a6U#qtnU+duc<)JjKiF-9mUZ=o<6CGg(q`YnB=~V7Vp^(n;i1is)jwZn8(n zrZWd-;7dT&G+e=pwGa{!de4#5$Lrw&pU<<`rJs!@CS1~EUNnkGF7w^&HCy?@E$|o; z#?>*{E}|=hG+Nwxs#n zInDHPIo)l+*;`(D3%<;XMDxY%pv0W5CEV{Gm1F23SJ-eyjHn|~gKKQa?D?HDH=2+vM_4rgcWIv499gf_zam}$&sGoZ^k@+Dj<%Txoauq=! zg5*`m##br#leORyCZSN%eGs{pD(z8T!Pb}!OhQSi(ufxaCL;*joy1VQFl94@Tm;Es zvF{NPxIra^0bMkMPPnAy!F$MO-o5)m`1zJ1g=ZnZ&cG_}#b)BmMp?;|9sZ~IB?F)T ziT9pS&3h`M@vQLc;ym*ZA6m?RzemYoaV0&&H@iYdg;>K84v*A^5)ce2g- zYHT!ujGCItXoBybsxj=SvnidV6=<;!;`wn_sp+hsZ5??~mfw<_PFayA4q>2E2PTs! zVGIJj-P2cu=9?fR3}8LzGxCnX3xwKeP5hTr0ZV3a$^tAC)?*)qi0}ZsK(Bq>tPPVu z*j#0k6;tKSrf1vIIzP@y_N&xi2>t@Px?3UT7`Rh?BecLpBUCxmVK2q+eog zk=w=1=A)+j`GpMn7bQrIeBYgMy%YsbxnNZMF$)L0M4pNH5ex%PMe1nI#Z?!p&5^RB z9a6Gz9Ky&TlTte&F>^$1sirQ^is7i_k~NbpDst;a;=mSk)oS8BrYfji^N9o4lw)J@lMl=GC0<5 z^KOPlFi)4*D($v1l-^VTxn?1}+Bf&lO!KycMo7Xj2sN`>Jb1#s3XQknuLE$OcbfF;MIb3UrrUnM3t!1hiQuj3aTX* ztrmOgfk!jF!Flsf?Y0s|(bE+19sRyNs>VLmI%}6$j7HE0GJxCzOXYx874>#W{kKXz zKx)i&{fwI$Um{UI%r+*7iGTlmi(xtS!2PxdjdTx!>Wj>oj_jw_sG}%BOLL7&R3%EX z10_xA>$CUQkNP^t7Q6Z&Ik12W_KYf=Zt3iNH&1)E$-65zTjmKGku;N-RHbaEC&9By z6{iB=q?RlsBQv!SikOa6diibhm7|g?F&0S@5z`nMx$O3pwLb!xSXFdXMKNnQ(ssc+ za2=Ew%twK=Zqn{@IyPR&E=g1>H@*~{zN`}FW|^ZpE>Bao19GD#2~Lb?w8ex)H~RtK zyZJ}pRQ&aE<~ZiLg!O?D0?j6Gx-K8JeOUczrFQ4fBoGf_EfTgdi`Dj4DqY+cvTe+D z=<>`=Nu=dw#nZhRd;RfARh)tU+@5f+6^hce`J|0shSHyP{(=9Y(`?tmX{y;} z&!#k*swq?}Z4FJO&#ei}LhO63s`Nbq0Tln)ro4Gzbk?+Yqp~CT44+pL(%64q(ONIl z3tUO>rb1pjdZk?1ohc&5fd^nk_&BN;v~XbB zn_ym}ocn`N0uok1uNj93*opw-+|FO3iA9tRp60fuwu6!cSyo=jZ6Sz9Vy{ajL- zd(9gao=1%5WTCM zNp^J;j8mjXuavi3Wm?a8Ykf;_VVO=^*ziCa;P4NwjCswoNo~2@Uy6`< zGy!^+V}oVqf*aswa5=hn!!)r}y*N`~5CC)Bw4xaWDpc{=oGHBHsYW6+2 z$}y?{R)J$tmHIfxW$mi^?MW3@B!5y%BbG!Ul-`PJ0lSidN|~~4RsAu>9@7o1t7}O_ zmUEVcnsL51oN3_wV87I8M*euRoI&H%qq}{_Hy}=~PkEnC zX@VKdUl%?aV!-b_DDL@-?4+Z;k2HA4rV|{>h5lraVh? zBE1^84LI>9{a5Ac76Z4N*8MA~Gy8p=fH?lLB<%oDHUx3~jl+bwVg%Z2x99i`k>jvC zyf9dJ_B8s}Yms*&=?f>^A@#$bPPhA}C+hPiV{y5ywE7T;gh9jCt}m8b@fX4vZWpj- z6-s*S-d?|%9#599#SEN_c&svb;k%x>?t$o)Ua#CX$p|<_45Bei2DM!W4HQO6KFZA{ zbm62FKcWCGz3%p;!AU>F8_ZsztfQaqZ=PUgj{aa9J9EoLO>G88-;$Y=1CDDncw;VC zBJ}ue!ALY)ny`BSZ-`A7OnZo|?W#z^M`diST zeruhq4j@)A&l5u+>G_x^huJgV!k&Jsi%6lJj{kIjbN%C)Xq!S&$U_!8$&RrRg-Xpfi7GUN-|P4EI1B&gbqP~Y?hJbqKw|H=zUcwRyH11|USAKnA* zZZ1HeXZB=!C%Dil*3Rv_cw1I7FQ0A4AMc}eLkx3x+k+D>9F+?T$Tsk$^KaYVgRB7zUK1gd1p!uv65OffmmbO_sG zAR5|yJWywnyi5`scQrD;78b7;TMs6a+cloRdLA@A`?LW(f?&<}IVdnTpm&4}&W=cdAQS?TDy z@8R%CwY~(eqmPT8$3Mfoc2*6w6KEkCHxEy<@XhRr_hz9eJ-ga%R(x^016yyNzK{H6 z#WdUdOd}#$)kleZ>o-7d)&|w4zEwW=8>1k~H(e-Io~(I}kE3>;^*(mR+UK)7pPbcv z&8;<3nb;!0pIjZ3Z%U|u&F?IDX@V_uA0-s=`}pMKIHa>{K>00zxIh)|alpZ?!3SHa zu_#oNFAy)UQn3*6SGBe_ZHm3NJQ_a6SgEZUzN{r|vUuYiIHumyXzQAJt@vX#R3}E& zsMDszigdo$p4y&R1x49`ND&To^MWiawaZ#_9nRAiA=ZIF$Ja)$=mCvmsw-6U%T9PS zv2#n(EuoYmwF|-d2%V zT>SY9eopE2Qo5Hm)|wK8FQ3AI*Jwy#u|XMIE-#=yhuE|TUYg#W(z!BLl~y-#YhLCOg?)u9DCXvCFjt1EOadW74{WUK zN)-KgWP+|UPkSaIviQiL+QSnj6c1N{mb3jo4L`^6c_Gl9C*A?-2ua@zrjG>-? z0|5)%4YO{Q1KI)c!*J3aX%T8c%f0dm5Qtge^rR#kvFT-~=gJMDlevJ3@HLk?qHj(~ z48rR!tFqVKc4m?CVg!QbnH;SQ0qEeEGQllGI*5b|Z>Dd8Aj_T1`x7xNEL(%4fP>~LU*Jy=gjtALo<0`xhb<8d+3uON<0|@LsO@hq)Ab#$h{@X65;_{rs_7-Gx-S z)CiV}2bJiZMqZ%0rnvvQS&@$RqI7SI4o$d~Mt6rM-FRO^&6f6}ULoGr$$$P;L^AQ9 zSNXAH)F}Fi?S)=Ip>y8ijE=@A8*LoEp6f-RXZMUV!6n?Nr1#-_4vkY%!y%cd|s6?1>4P~ z+Ub4vp^sH_g5SkO9|hM%w{vrFZ?u4xaB!8q z4ip9-I?G!UySb}S?K=2fBw(H4X&r%C%Z%*EEnnWYpCz9VPOvz-U+Sgx-EizS1N3_d z7jZ$Iq<+B9Bf+2tyGU2*b?C(RLf*#9ux|QLHbv1XnPx`xb+n3Ltm+dr#kY1pY>N z`zl%A`ptP!Q9HUG+=U$XaV$G0bEA#Er4QR{PihZg`y))B?mkl*$44{ad1D|$2;6JW zn{-y3MooEF^t-wo2H|;qPG9>RW<~Mw;?NA%fdu#rYo(ee`91i!7MrS=@#P4|s9>fl z&Ub?3)-a6gXj>_0{9Ieu6I;dA5K=L67_tMJr+Wfic8k<@oG|@x+2^2&*T*BduXacK zw@kd*Lq~(TNaUdkF*@4U6~fICBmrUJb;M(fj$V3!D*Hwl+`+#FE7X*UYQRmw5A~f) zb04I7>@MGAG{n5+5!`qg>Ar2UW$kw(=j3%cj}%uH#**mk;p!hkxqdaTs(ouyG?r92 z`h2DA$c371dlixRFyY93G`nMc$T#x%@s2rr{{Qq!vlNwHeiX1s+99)1mJ+|7tjK#x z?fxC08H)B?UCaDTyS63U)R%#gz94vkg>^@>ZIb^{ z@2s+OEqOIpA#*f^zl$jJ+52U(b7P8fn9WG}_+JQ0-<2^6GOgaeBud|B5)6-RE)={FBkn z#MkgMYGnHSD#Iv?&&S`xvEDMOw9J1!wHnG(OGkNV>2SwUgjp`hh>?%|ju3peToD||Iy7l;{%=&?U2 zWI0UJyTPXf-(0fFRilYzZnDp7wi2emV^il-O(aUZ^6GP44zPn)~1F4 zbkwC7{=y}f@LY@r$s~HMDa4ZNjP--j3m(D)BA)G^?jH`nVRqtfqYvlDXgFX4{+X?M z0111l72B9{K83S3GXJI*#YuGB?PT{}mHgGJPC5LIJ6=Z%sW{sgazK$@`=Q%$q_?8( z1vLIFB4NkgV`2g;;5Z|w4u`^1>Ud8|x{|G~YcW6*jDH4A>2?DGF}Dv+$ZH%f+51;fnAt(otk0 zI9rJ?GVq|hU~eZb7AVZOZcDCuB|^xgyg)i_{#P7nxw92&SNUjY@wDxp!%m+ExFLEy zF=Sd}PVj5b%N!^>0G-=!QQWsEEGnCf`hnqVD2=e(03c=$SJt}>ka+L-Hv!^N(c7hq zWvP!FwwKUEzS=^GnJ@f4qz#jEwVrreep8>CRMC2lOXk5(%wnCi^f(1i#%%73T}o7q zX8h!XBEpwrRP?Xq@(o-y4Xw>L0gMqVavscy8ln_X{QE%V(((ovMAu*gK zB!sJs&~dP9t3=!1x?K==s?KJ!6!2^n#s-1|E5#HsflH4ds{AdJ+E|thMDiYi#!)iX zU`Whwh0zxyVf}2abXB>@`%OadZ3J6MED0MR&Z7lm1}6HH#gxPEPn3I#=_b*^tC=Rl zJ^3s><}!W}V_ux1zu=Bhm#|f-)O?}N&B*IvoA_iV#}vX_g7m=un()g8%OT1Lfx`@9 z5AaVi%(zH86FxaMBso_y9<@u(3ns-HZ<1=O-wA-z>jsuG?$6a7ggpf|$e)as*T^fT zRb)MLcHnVZjBor!)xwd5mup7U5k{L2zeAsI?8}l87zb|#nAe)CxucceP~@v9#XQd(P$g)L z0yGDWYastwl`B$oBP?`Dbc!@)U^t`LKAatOiOeG`w+k2Wg0p^HsGLI}thB&OQPD>x zy=r}P3l4`W@i7LAAu8(Wk6I{_dMC@v;Emv)YfbAXi0Wb(OBy8)BiDG^9&;$4V)Bf{ zRK3X&+vHqN>Xm1|pPxVX&|5$M*KeUp#jEc+UOrrqWXX_7(xeZFI;-yNq{Xg%3t4dK zlh2FuS3fZ`z|@WeB7Z3SJDbYI%Ezlj_1g>`5&7>y6QxSf z$6*m5ilvFyzMxY$|CMFOvRFNpKUtV^#kO{Qve4-sfN>Pc{pr`~id$eOe?;O`Q8Opl zE}!PxMK-0>+lJ*;p>~(;d2%gip0?5zMo2kYvgII)f0 zGWDt4$}sg167mI-Bmjde0CQeAbs3sf+A3HT8{$BRPZjRiWC{?Nzzt~E&Y^zQemcX? zH89Zz(()+r;Bn?)Q^sf+7YvF|Gxr zD9YQwjl=iy?VArW8&lXe4!2dZ8h?xH3z79TP_b~@I=b37m}b+acAjhyo!6UJk;}n} zZ^0`9Qeyk_O)XF_n%coXb_RT=2Rak-VLSH0;jn4Yf$Uh&^+<8$I7=Thbf<3SkC{@0 z+Qr7rA||o2omJ&GZmLEHPn@Zbwlz@IG(HmAFZ3PZUkKluJEOcWeeX2G>9aET(supX;FMys3tQfMpk{T1qb}=-OXH?x6T)1TF!Ha_%A%6AV3}>dYr85oq51YZ z`5S)=ac}d7`KmEhBbytm6rBcOQaSoAY%s69tdGKBZKj-Gtcou;TL>(;%3-Zv|K z^~RBUy(ukw_z(pI-|U= zJR>miYgX??@OzMMf;ZNjZ{#w}^isGs#J4$vL%GN%n*@D2Ps&27tTJGs@!vLMLUh5< z1FRc${?=n0rF7EEI_+t81aop&{Y(L*mlC#94AVR(um(gJs3yOroC-~kWFD?VlfecC zz~*(dL5%6sa8F&lPghXOe2c$SN}fjvtE;Sj?W2KV?JuzuSg=n`7Hx!RJ1XL&rrY%d z<~!l}_yP3aW=>jii;eCYk`2AU@P1XaIqaW@`M=%;kWVIk2U>_dEZ97=apUmK+-kJC z-J#B0>skI|myMKy237!|8%3s+YKggC>#Yi`dJo^zy{viu^R)W3S62c%Um4k=51{K{##(8e^|~20_+ME@I6)f6Y@to-D}?jE=OYyBq5ga_+R{11oN!jF9k=55QTXD z$~b1nwY7!%qbPQ3s^l1@FN1Z-RqL^KE358^u6ItCOGcB+LR+Es3rU6f%lzhaL6%&* z7@pFvhAqLqcJa7~<{eUbg?n8g6y$tZwPR*AxXw0R#ItoD=lfm)&f(<3kD4CAH;{wD z^PJgeO#}a8&F9vqSJ(WOB~FWp)XkpZ28oVhXu2(@vMpPPFqrf}`~beuSwq)nUDv)c zh$l}#ip_JMe<)K0KpwM7ZIL^SQH|5H+ zomAFy0H?XT(OY;aHP|6m@18#GCGvBRg`Z>6&vkyUS|E%EbeQoBCnVdNP-6-e>P^AbX6c8 zu*)VH3(obu@%ia=-<9~PQ)q1hTF>YILYWhOMK9Z#KawZ*x1eDr7=2n2iPN95zAd>{aFYQwoCWRQj=H9t zPI(Q)iTo3>Gl%cw+y9p&O3|`)MU0DGWZV1qn|ItM=Ra=ykIjal$Qc*Q*-+jzT2lf? zUIDzAqR2-nsCViITP85G0FkL_%6YS0Xzo=Xk|!^U9m8iXYzNwv=D8TAiy031h3!%C zhq931$ppd|b=Pc2imtOpuY7j1HlM1;W*EcR%olYZ5PtYvZNmox@dyM8K17l`sDdvT zHMfbfZ82lqapa=&)jS!UQ$Of=;D}}`g%CnK_OVCsb>!!5_h&`*GsvOJ?7D)%W~qSA z$J}0Yd7x=zTs_kC9JjsKxLUR?_yFO{+@u|gSKif$Whd=|vxoDXatWoj!#2+zg~fb9 zy+6T4J8paO{05jgXXMr8*n!gp=km_57R0{2`lI%A>jkg1DW?$DtJM*L3k^cMw*Zkg zOy!h~7QQgH*0G*nBRI$3y`@B*-A`O}Ur{IC_T?$v{ndL=aNMOC2L`XiAFMt-XY)ah z;QDz)GU@!kk<-jxREKP@)$(-8T<^rup%RwAkR2G&&&vPwWC)OJQBb|hsmEkbSL+^4 zk~lD;PqGHgOtN>*B7532$dS0-@4$s;<7qu7CPSuCwB~MDb648R0TIjjjqI+8MJ$jl zh}y}om`q7RarGcnldrE*j^Lc)=WW*k&nKJj-(KV?O$`o0#{ zYGWHEl*>#87hVcuI+DJ|bFGRk_x+jmZ2}MCjqJG5e!is3O|OBne}WJEUc?-iH)Z>` z@q;1@^eA5qMMnEypa&?&Z0%i}dX|?q|GJZa46f|*HQM@-vYssea{C}sy*pjaSayXI zFeDsnb=X+l$f*?0-G{n zEesg=&Ebj%SwKDT!VZlDOSfHeq0}xR@*Z?CzDn{iXNa~wGGK&XjQnF~X~Oq|QFs1X z?tUXfj-K0hFyV=lFDhPp+DJxa9tlI-_+D?b^=W|%3_LhJY%8Bu+SaxAkugs2#_dZ_ z$XST(wYnO~)gR5C0ZMD9Sf1^yBINK@`$Bq_Id9y|D`j~vM)c6bU;!Bl&vpuaHl2f; z$*u7{8Y`U7EQsa^xNal#{E55x2UzjN1UJO4>L;)RAz-V>hSVOWuk@ZSAU^zzn4DU_ zy5wo`vdpEfow%Me`Z9+JM{$#h$7%Ohp-ab@n+e?Os2i{v8p|sH3+L#!=${FM{L49( z?QjHofo?QIMJZtRZ(ujy2FhQIZai$5GU)A7sW(N>_GaOp)y>Us42%Hq;2BqunMe1% z{u%2_I{h(U7%YHA{t6~y-2#o=;2*IIc{vKM$@Mc~;mAi3gg)77ixtJ)3vMT1O8A$` zJB+>6$VWrgs(6iviP?3CNw0lH`og_WL2p@_zBC|jpXdKZDGAwRd*4nx@mjzgpx?#> z)|zTelVtUC$;0QKy4{`blkFCZd7-9UX`2PW*o#UAFDz;JHgdxU&o$cy05%Arsr#Ml zya%XK?<7lhJ(AC|lgXqF6~I*`HBd73;9d2t`Lwvq<;m6hVU=~LJ21a>`NndIDf>&a zP*GMx|MTX2y06M2`5>KbY$VOQB9t9O!ByKIs~wCunlZtv|IYQf5aIt{bAA8%?xSe` zp}PbBlnA`A%6p>R48^=VelG6m;HSAuJ+3GU5Ph(H9n#J{>{{+!Rz*0n3Q!d=BS!maqqwNw-nro`qyR|-VNDuj$V*^%&+jVGH z@u7U$ZHLstc52t&I=wQB{jp=tEq@V0!{4NU;k8D?(~$3?3h<69FytbX!6$KpA!W?3j&+C%4@txu>;L(K5yFz?_TLu;(KrZZ~5b*OgU1Uh=QO5L&2 zUCC}FyF4&{Un@%{bx2-B&Xt&Hj8`U~f(d-*`{=a$#I%%||L8u0N|GMKWq=?4avg+^ ze}orP)EJksN>{xJEZJc_Cu#9Rp@E(xP!Tkjt$ycj!-;7VwJU~Y&39kD{I<@jdG~&M zidDVyS;c+bE40&wQ?+N`$gF6EBs}k=K6&c>9Fl#S!TVwt$aZstooiFF z_mzXPd}N%KER0VP1NYPj`BiFf^uGxJYp|tb5_Y9p!e?X0$udDJBIN=F7U#N`)ZE}1 zP~NZvIoO%#9FdZ1LfJL1yYN&>8c9Lapk|^|oR$m?%v=#a`#rj5!euAq?8IL2d=L1` z|7$>M1HEi{Ipt%*U3l0I27}!W$b}7Mfu={H6;8RtD$9TH|E;7|guN5e@cux6G1;6$ zwbMD3@PS_pF%7pRNR}qtgG`v|K~^vW!9JXQ_;w~otC0hZ1_$aln;Bz;{ zwl=8z<%^~1H!^c6^klwez>{Z@8DG((IU#ybv zQ(#f622W}oY?uzo;kXLp)DK+kE$=T?9uA6bS3!L`BLb7ZH(Wi*tp=m|zCrT9k~;ua z8Iv?CQ$_jwgDy+{GU&6Yptg+|jkN<=(NnO4#CO)iK5**9N~HqGbn&H79H0DTLT&$S z98QL1Z$3>2{_`)lR^#_XTFD?0Nn4?pAeYr9i@NN}U9+ZsT z5M<)#^QnqL5iHKFZSM8mkVhdVRULc8F5Mm5kL0`%T}t|CO;{^B^XXfKt$c6#HJvRh zlR zcb@-9I(CH{y#QwTKThVjq(@5o=95go8#+2bpbaMOgWQ)Jw?h>`t5u6a_i@?6x{NDG zm1^5ef-L8^CvOAM@Q$3Fa!h00~;c=c&^f8@p@{r4lTmIff6D zafo@$LaPuGoVE+e4)!)ZNBzNXPE%jWyQAr>0%r+o0{QPm79dmfoYi&}OC~*AbE26X zh37qLLT+1L=lJH+HO%snXQ&!mH&5b-p@Us6tZ=8!R#X-^JX@=#nO>jRr<-%0Ntk2+ z-Tuh3-%xVG?O+Ybl)Blnkw+43cJ-i99k|~2U0rMjJIgfey$xOc=>H2gF0sF_e{fmo zVMTbA4J-1N`o6S|6wPA3PBJGl#NEHVs9(`Xc&d)|;VZ#w@A5_K7moFtPa>wl;0@vZ z-+7jQ*kK^&NbD;+lzqD*&oudeNi4CRgrz*F46cFfRmNmGF3HCD{W zBMw^kFXls+Ua-pzaFt><>9V;x{spreMZUj-4c})uCPi4XEZM9{Z5g%og$BPOX?85& zB&~6|%>?=`Z!R%)%2)5SYkaEn?baN;Q~(s32hxrI!(>;oeS}2|%X4uw_+o4Zc>4I> z(=>VLEa59lCexO5^;l|~%h(ob-_GXPrn9S9xG_35gzD~%UWPiSxz$XvKil;kBiGgE zPJ=w`s^dl78x~&}9BMzgV?M7q8dNaFjta z>=Yfz)d(!V^%CZV+kED<{f0gFs*`8RrSL;YN61j~_;F-UYOsL$|!5_!Re&udibE8~)yU)IGOs}Au$R%qfu@tXk$XTFQ}&GmbKoNo}#Io5S>!T{9vKOEZlgwHf= z+Sj7rXHjYPdH^d=yA953Et2`skZk30q8=3W&?+R|Hf62kJAFJ(@1|&+8o7+rI77A_ z@@jt@!7F1iZ?q$S+l9|7(=5Sdp%TnLinLcs&Zs{!AN0E>O0SZ6i>84YW6pji26i!CmiBKW^{_ z^jW0!ruRSZ3I5?PHTz*{QuVq0=zp@}yYhne{Y>@E!-bTqRYtWgSJegm->k?k{)HlMESJ;d`70hKJiMU%HxF1yn97GHz z0gLo)vIrdD&?LGwX+qFV4I5E!$NamrN~9+z$7;2n)gx)_mcgSGN$rM;;AkEuF6?r= z7Z>3>gIscAJr5sGkMLA}MGk0INihaN0f62u*N9i2CBgF9lWZ!}-H?b`uSY}MI&DGM zdouybm6g}@!-LfFJK}9+aRAwznfedeZ1dwU+58%-F01?MPspNiZT+|0FYIOacv7XO z#dFba9)JDIqk@D@7B*K|?Ln06-x-^KT95yJ&!XNC>Hr%8Fnj_9|4HX~rwn8rZpZCd z{a<)lL?&Fyy4Ln1LDE63TzT(jinyZRkz5sO@Jl_?D?2nI-JZnGrwk<~;MAY#M*_VTs3e&Usi*)9-mD3a6CZwd3b@u;RiH|7?T>`pwz5Qmp}|bI(W7Kcs)z zU-)Cyck`{17u6JZ^PjqW;C_yU0uU#IT?q6Cu8qT=t68<4>%hGT={1rDz}5iR_~tGE z=KF%^YUd>^$aHzbj;wRS7w#~{y+THyqtB$;hwW6`BU#eshoNPJ5*7gm%;Uy9b7+5|toG1e1GUEAs%D~bFKL%$Bk&(xXZv( zi7fyKM1h-^iDj(jCZy1wpA4y-M?w=GOp$UD?QuzPD-U~@%f9D>gD&uOXcD)t{TIYeNXjAVv z+4!h-xld5#m?8!c;unB)NRbwPYq9Cl^vuAX5dmH{Cbh0+dw0@1U=2FItY1NREV1eE+=ms3THz?()d+-GzhOrv>kUW(}42eY# zo#5W+0r(K8HLU8*;;#+UHXm0m(eH3EjAYSu(9C;HbI<7-VDhBYMtQ@{LV*sU5I>WS zW7tVQ$y|~#s4kP_-BKGuq#q@=U0>!mPtuM<>;M#Kue}Og_Bws}#&m*o6F6Hiju}#c z=pfHU@1M)*A3p?gpf~YVwI7b9sAM22)!52!mo7kSM8H!W}XAYZCq2 z*jTvSR&*k5`y`f$TfPKG??%-Ex4*-xCV&2k3-=A%@r%II6+-}tMm+s7gH*!P?02!f z#L|(@#nQX;bwR2bD8gB4s*FBOf^Ksz*IYjh_S}w~NJ^bjXan`g;wO|3QV=^saJqsrS#P|C? z%rfJXV~zcx{^uqFS>9L&>dUX5&DV~gY^4?W6>U)@nG_> z+K$D!M-jv@To_`XSQ<+p54)NBEehgw(#w8&4_`-GInwy8x!3Jpg$8=;&eOnIs*xjA z%UZb1?Sv~$UoxEnokdk`7@L)3I31bnaf(+A<`o5+Zh}b+%5K^B`7b9gKpy1arbH}j>Ba6FTLqAd3)vK{GXsh8 zKEFem4}1dq!WiaHteT#zk7Eb6@POpiO5gSmUd<{s4G~DEYE3=UnlBqv{|@8!!V2-z zEuNQ^r>B3|m%|PXxOOAIsrcl6Xcj=Jxllihg$7-1BmkL4_`O*5r`khO$6fM}fpnYl z%S8h@?dZ7w4oZ~`1DSHBI#F-#7}(xceEl~Gwg29l_4pP#wx_^0DB_Prj0VI#ay^(W z%Qi&B;6`+8elznLY%M$-T8fz0;F%V22mWKo8S}sZuhU+hFAA)xgyfn)?lSFywk7HT z!?Ak=2`i2qGm+nny&O;1u1_ja#O0dQ$nT~UMNpdrT=CJc$Oc*Ca~z`Ho|ebt<>emB z6Dmk1I|n+aW!^eCdu4)N>`CCrPS!Ms?!1nGSjXvVFr*^my_&tPIn&4(`m3Wro`14ma)i73ZY6w!O!M@ZB#4d0hog51G+W)qP0#W_ zUM_y<&s_hzJgR!5!7ao^^Zau5+o$&;Ik8QNANqxR1!bGA-06&SHMCPa%k*eIeopT` zjfdXofco;_l^a93eTaY$U;p~>1JTU^Y*wFU{tn#MQ2e6oT}8_8Ug|!A!~oPpv)?6U zouw;IZ${CB(%QhdR2`2viqf%(v;JmnNB1M)<#9iKY#?Wui6>1SDru{mb$pU>UxT_s z5@D?(YI?U4QUr}paVW~&g}H`9yPL`P8I(N@?Fh{g%VzE=5o#D-#Kt_7^bPK_8UF=o zSI80z`xOlrmRmf*%o}L8#4>7sb+DQc&kwb(TDP)W=I0e~hdJ&5H|t#F(YWTeb@F?-k)xTtOB-qLlONgPSNg z;t}!G(m#s=;+W52-$B`F&6Ox}EIMhIYd%GIsw#A)EYkYdv*Qm>)RQl=V@C@!}&mm&N?)rhy^y1sQ3$c4w0l+F9Qhgp=L zw8NBwD~))H?ab@@@XrPHWwCn7nVx*k7}pglr2FLo6+xZelj=oN$9fuN9ipEBB}#vh z?jtA(Dz9*B8}M@S0__k-Y&S#aQZD+y@!AT^>6}^M$ri6i|A$fr#v=i&4F^Xwsl|gt z!xx@1<0H4J!zwHqbuXNc3{IZ79)C$lz|#55)vS=S+b87dzJXgA&SNky&fF0IG0_@b zy{^IfdYt{NKC9S`)1`I>D_Psn%C~NY&^zn z+_kiXhVc=Lew-h1Ui)<$q;wBkn)JnjR&XLp#17c9FrfA6&cN*l2NjgD9_NG4z{U=B zZl1+m^SLZ#>fknn?GZ%c^I|b-bN0Qc@6YwdSgKU$o_o#A^zK8qn#02%Tbs3%!o>+? z%Fp%Hu*(#CcjGB_v$nQIXB*>kI!Ec%2F5;clkHeAf#0#+hhBX727AAc7LUldsfNR#Tt9nTSja?J z*kjB@8Ce3Ne%sQaep)+jxn(tjK(;hl6ucU@46MjhgXedMTL&$@t&))S*>!CxQ%sk1 z;I1dq7vRd?BX_TB3)5Nf;ak9C^1Kjq5%2gr_BK6n^9xwxrmG~jOx$yNCAL<~gW401 zv_v$aykt-u?~Ln}T#2H_ySMV_E>RPn`(i%qxEu}bB&*Ord;XlBAnHQ>JY_I&>h~_G z3vPes_^8`xg^OiU^AaKqjtUp!=2rJzC<7xukERoqORs`QF^j#2Oy3+_4x_j~?ff)< zbYa~7$Z#>sszfbu*?ld(*@@`Y@~b-W!#0Ry^^id=ac6NeIrZ5WLeaKWmipqRXold^ zkUE{r#Kp}yAysrNOjhK#fnKUd(N1QqNyrFSG`jER-Sn|Gwh+;2U61CQ&k-8j0!UTA z6mw{;uh7lW!(DJ8lX?3~kyy3E&@~lw4@B@zc>5dvuRY=cd8hUGX?iF?;mt$oR|VR+ z##L`l6ApV6oM>u&M|4@YA`ags63Y9-2}q2M4UHO{N7DYrOzWig1;rM-HVvDlt}uSS z{y}Vj123w`=zd3uj-v*YG_Nh?v^A{e=|jFN0&Q{-m0ftr!H0i0gu2q>gC7pcSF^kM zaKk~RJ!wx`${*Jq7v!HXbIH%Y_l^wM!EDD-1Ir~M6SIE!z=T1Caq_NXe|*{pR3BTf z#GCW5L(c0FX+*Bz;I3#NrcXy^)QY2@6x`Y!T$VCra1S?dKG9ybV{oskNIj`}dnh3G zGRg~%^B&rE$e=!q-&A*a%ED6_@WQ*{C&TZ<2XpG`#zT9JMd(jdov$`x=G54vmNe1* zg#jtFmiGScV-p8QT-LSrsUldj&y%%W)x$KF2)Q8DHH)=7JbCZ(qs_;6X9eHdvnk6h z8q00H<4`3K+?5rVl4bI+;DP~9*VTy=_Ll%`qVwe0+Cml>(TiKzbLzQyob~{|tU9L& zY*B)*w$yF^n)<}w!J_AKKTUt35G%yu{P*d@*f_P|w|9Ts6~5V|7v^;#RLDl6P_9n+ zTj_XS#r)5pANLBW_oLdkPotfrYJz|4JUFm|p?~ntpYc5`+%(8Qt6ph6WjMrtvv;4# z;SZYuB1iws2JtPw(p_U(>C;qDC@iKMrFzkgRj8v zt!}kXomXtB>(vu?`dvT-Y4z`lt7H(#H2wj>wq63|5*ve>jM+?=8wa4W70aR(4Wof0 z`-eU!8aK%ukv=DGziaVpkK1IDLafYG>M-)lE#5DG{UkXuo=H7#>IH)d#GfP^TfVFX z$$qm!D7U^yZMw{AO>^kK&VE?;vvb9IYv<)L=vSVFg59=v%*3#13=AB#|O-Mn&l40 zt}*$IqeeXj@5;J;tvK!JX|u>==+vJpY;T`4sUvF$VmY&JctTi+N2p93vAd;bRj()a zfYX2eB4fD7RdXxMO_yfp#zC~3LOGWLPesfK#re2C^$CtD0Tn8m?NgdE^~doGk@;k? zxW;>CDYMroW&N|tk8LYUYQvpDDz@V1v%Q(*)t{%G4~mzmVf~b6R}MuCNoXYXrtJa0 zteJzqi|IRI{l}lhRzF9DLA$xEhvc0Ce0fpdXc<{pw*EiNz4c0Tfv)4fL6)yUg z2)E!PkE`?>Xy;V!8wn5}4o^|5YwkT_M|qzn5h zP;P)2P8WRA{ZsMoyXOLJ?l7a=%Z-XInv~cF7P);!dWw_P?nIBz9*H#|T|EnaT)L}o zQI`Z|vRtc+y_n;TYE2){^!UxmWY~GQcE3W&!d{03|6`&-u?ZyPzVpZS7qwyUD03(N(mb&>q`=tUGxN79*rb*}r@ zl?YeB^PkOweI9gj;8PXD}^d!aKgkMBmbnF;dK)VM=kvn|)haJ;uh~@QvZ^ zl)AW0Of?ZL9s&RlDSkyLM0<1z*RbOY;#{&Yi1+~&0Z z$=7m^K>(ZVkmc&p&0ctpwJ7zcOek)3HCocVx7{;aWTw4m@wcF&QtYW42EWYCaVHqCEllzf+G1lS z4MIl3MdozXLu8JP6wO;LPu+M3|6F(5r>eB~$G+{9Edl98i5gO(jc(U`kzA)FOoaiF zUF9I2WGHEFXpNMy#+Men$uKefooqRg=|#1iKwFQ~B_mJh??vg` z=RKR#`wd4QzCoKxrpG33{&s(I z!Vp{C&F8;?L(qy*2n*#d4ZTAy4C|VLi+|YVCp=kav;{^fbL!i~``0+J-|zl~>%V!# z>5IP!@|&t~DX@M%$EfSjd~fbsi^-cgXK*rYZ&F)5jT-?>LmixNj8o2B%KFp%wb%|i z$L!XqVZsJ^rq$8<*~D!{SZw3VL^T#%479A~xcYbW>60klRuPHB{@X^#7gh>_+M$ny z0^&Z3CKqqOFK|HXe{)B)f%q|Itv#|Ouk`MI`7f^dPfTAw?Bg8H5MQV0d6`Lh`25Tz+bHjG`&DkQK>BoJxD5*`7ZFK+|AClJ69>T6*${`HPTSyoSAop7}=7F*?%Qv6c}$)+K``>h*4v z`fG!X<}dtm)J5^c78Fm4b zY^+mRf?VH)1=1eRGNgnwk4YI!?3-HCWwQ4Nz6{wd=ua<=6hN{QYt2V=3Fr>fcM1QQ z8hm^$d+7ZgCM87LuMEbPR1*=NCm7Kn1hQ9r4R>9prphl(>x=bNlPs*g3HFa9k zue&K*@iV|=ReBIpVH3#_xBtR7vL@>9Cf!W4+G2J2BaJ-S(ILj=0HuEdt>~ixQ;(jApY6+|1%p&b89<6J5h69X~*2 z#)69JSlZL{+wq)L^s()NShN@I`+qKp6J8!e$S4359;c3N>3-K6b2pJync&-wRQY6D z0jp;EQq$i-iSZ)MFW{X*fMGaHSj=VozQipnWqC*udn7bSD3eMsJmy+DE~n4 zu4^ETY@Uhkj209_ZI2cww6ezEbu?YRc~ zLyZ?m@`>PYm7v`hd_k0mj&#WGO{S;Dm!a%v%xoe6^GV(yD+)u26w zu)iY2;O*SHpIfTgM`vSH5mP$c@SW#s4j2?pH(Z9ya9AwK!-XLkd9G5_OFIDoBr4>K zmmATo>9x;r36P6~hb^w1ClC{N-^6J@{VqDgnDxm1cK;XSmvSCp|p&9tc-1T!2@}9c$r?tfJ40e#fEK zv;LoLN&j#1>$m%4STUCI_pTS!d;;mn>P0PR&I-!@aZWwV&UnY}xix)!Wq?evo}lj^ zvBHLjw<(H`p()ogjnM&Qk(d5&<&Lkj2i`j;8}x$rB&g*NhYs%Q2(fKt@a%$8He=l@ z_p_H5+k^{vv_*dBRirh0cPlGqj+5`H zIeeCE<-2QH>J{Q+BO7YHI;jNGek{&F8HZx)e{;lYsyPeK4TS`GTQd#L;mSF^=RK3l zSc5A}aBQtPkpXd=qf!s&25<&^r&Sx@EE+5_!6lw9UK1;5-Axc*Vt{$sUu+y_mb^3{ zD(1=;%Dc>uaAS44v>smtgc94S%z7rO!Of9CNBYR*|I)1j4BCrYW>k#M_@ZGBohmEZ zm*%+CbWw>8Z(Fjhvc)5#iqI?$$WRupJAEjTdtG#On*0MCa!SuElU_)-`?C*;na}zB zc5S4fqR?O7`jAq)dO|g4dq2Lj_4ix077m@in3dr_Tp++##P`0020za1o?&LVO`DtHCnDjCYI@Tj{Bn^&6Z>m0lcf~EaViI8y@cvpKA z#RMvYrk#@7)D6Yy#u|EM^qZ!rN+gN)C5FDzk@9a5+^W^v$Z03VKvghKEvmb!9r-V# z+F>a;-Kxd;5Ks&tCGY;!*e?8*NpYfu!-gwYuYb?k$dIYRE!6K&wa!w+XjxYV= zxzcg((r@y=Qw{9IR3KI3)__?%H2NDJT~CXNFE2sj$u%YPq>Po!vYf7UwLI3y8XsSr zNe)BUOklBts!uCpXM!?B!TTJa$LG6JyCF4VyBudJVfonuCNBKZvBItsObT;9!?j!d zr#QBLGxZ-`14{%{<171^iYu8#sfSlJ0HvY8PWNYqem^BJVnHr+By1dZOhhoBk-4hs zsr*(`H5$QRBonRZWV85sHvC#ln?F=3Ab80g#8hHLOso*YhoerhMu!Ugv@+Q@c>v1n zcMgj5j)_iCSx)>S#fGSw7BkU zKc;v2`>peV5*VA&w=%JpAHCw-6dmCQCzt+rp@G$=AFUy=_hG&j&d%gLc-oYfO_Gn()XJTA z70GcQzPFiJF3hDVqs(N1t}B|Wo#1!c#6+o%y4w!0diQRx^^49y`g$tOdcB-5?`UcVXf*SfFUj$ zBnZYk$qS!P_;g-|mp4N8Px&>2=QF5Kd!~gCqEqn?&ttUNW$y{D_Pgdi@80%Z4*n&+ zKNe(DJxVs0238y-@$Da1`9Br`PqzE>6xpAmF;$5EvP`z6m$jV1pSDCk20&uc>tkUx zL(ta6aT=Zsocwii4hj9zi8{0^a+KK_(f-D)zA-SDy;+@M<)`RKE}>#Ed)C*t)sr!Q zzOMp@MLfRKeNRDSEcNq)ZV3)~^;XMRC57A}r_}ei|9TKrL14ZtDZ}ymTpD+wKJDNN?}SND$uB!A2vkl_^Xv z)P2&&W{6AFZ*}=53P)tfmvn+DOFR?PMW|f>#VHT`!g(jQTV|{$E553}Ivbsr@N_o$ zwOXa(G~4~!@}+O0xvzWf-dUdP;0b?}+r^5sJo(-`HzHKiFwJ`Y42zDW8KK7Z^eDNM zFd+ZQgYE`9|LETVU;jV6aMy4ZE#<~tkgM_Q4WmLl`Uz=#-?b#7o;Fc0cfhH2!7*9I zvBMxEEroP%0(r#vpD=>frjG(Mkq&kTzLcpC-_je~gBMF0Z+u!da%H*BAkrr;AHH!- zxtMeQ`ZUFeyEBK6epwZl4dCEk-0vP}T6v$!PO6XdnThs!Cx#H`zy!<@l9)}g%CgcA zyXPu8nyK*@r!`l7M1=EXr*5JNNsZMUAU7eKg~=)qp8v-$C@@d?wm)ymNrbeA$o;7H zYe~`=1a9u)gOW2Nt@obiX(}-Y603V+%Iqdpua*=U?OC!k?(@kneSW<(rco3lc?-RN z8Y;g-d@H|Zl8|&?0AM0jnCoB0OO|$C5n7TATQ2AE$mU4zFg70r*pA49V#Qt4R%_;? zG`6y55jy#-*%2~IW4R3AnjkIdBBBJ7CzGtGY}EM|mv)sQ`tY^e-<_ihu;ziI3&)*B3SqveB~Twe}YoU0U`8#TpS;vkJoynzY2 z-DfwTeAi~>Y}3W2$~#B0Oc|8yS-&#b>=Tj3$H;UT{&uHdIhU?nR)^X^9u=_Cm7YaN zRGAUuEEE_f&$&mdCgc{QPSpNv-d6SLOJyj1$vzJSr4O=MJB)-m&PP3Xe(?!^V8>n2 zNh$ed37J-9wrt)PnQ=`I714Ppr%coRwoAVoF|kR_f+joS3ej2LT0-tiUm zMH)rJpF^#2pOPm!quO{d8eSS(5{-&et$F{UHZUXi4E} z)$-wK-CNX?d=jS&+*0{S(Z!&J+PXUI*oto~KVmcY&5 zb0zEAOhzjpTz~xO*~f)RK5F5ADkcC!)_zOJ$>{o5cKqRkuG#+)kuRo4-xOKZ1262# z@9+PRN->@u?n{FQRsxY`om}w0kHnPyfypwv1?W=`-+?iI=eKeJVZPlW*fQydbJ1OP zEUGa~SkumK9#$D{H0n-S4VOlq2xXP22&`_S!4QO(1o3!Cm}5IK+0JpJym)*kqBxVohT7s-@&^g$FUl=b6j!>eeB#x1Pz4tocvO;l&I-8_fIfwOi6)!WN>&Y?)_B(D11 zy9PqyAZ`Ilt}$RDiV7rpJ4$1v0n45{8>AXD0W^O#aWSj+>MSOwreo5?PCtIBCNg&K z!G*Bpf`V%f4bC8O-H*GLv70T-Ed0av^1CPNheU6#GCM{3RG~&P)rTO3w$PkF6q0q)a{|(dKwV* z|My{CPcgMa%fqU|==((Y9MwYb*nt)6_q zp%MEXy@PN~hUSyUPk^=!07u1JlcC@usJmM2B!+7UCw>8|KNAg8k}Dfd!2P>l-aGdJWM*| zT*|6q=kZQO*n$%5=h7#|bjsy4;UH%u!G!O+PdS#p{_pJCgcdZgw8PVp>lDig@Sk`} zfF-gDLyR3WDV6)nkpR=CEng&f-k_^N#{mBq9(ku4%_|ALp1S5Z-k!1e44&%*H|c>E>IOKfnre3$t}7H3C7}5Mtl>vU zQkwA~`7MBNu?DPO2O|PPSF4=yQe0q)i0z5Yz%PS?fTF$gc9c|%=3L`c^HEmLL;&$T zD_GO2`{Ti|sgqE^qCjwIhb1>+p+tIDZ7bJ#wsBl^+MT>HryVz@Bh|5!-@9pkWJ`U4~%&y1PkuuMkx>dP}UqB_l<$dvU z5vdVkzIB88SOL`*_0}YkVco}rMt6;^a*DVX^Ry7m_wFgDk1nLYmxpwdKe-c?>MrQO zC4a=_T^GVKxN=WCmtcu!Mxh%ii!d#b$2TCi-Ny=jw1L(s3>js8+p~wSC8A&6rWccPY~XoK z>)-5X|NhYI@L&2R)08u~fwmI*tAXM8OQLu*arVa37ezyve_>=WGNb3H6bsWTTO7}< zqBTs=-^EKFrz10aNT_%+rD_q2{Kx$`(k-jWvy(&p@t2NrKEJtv(pR$@3-`YTWN;efCJMZK>bYVedM1o(f1M5`z%6~LlO3DKSKqu zdJ)j2D}hH`#!J;<5$~Be(VUBK<_Hm#Hr!#6QVwL9S?IU89u1E+(KNlFf?L~U3 z^4cwUq9yn2`ZN93xzXjzeByWA<*F7wa@iW1DYzy^43tHD%fha(OaMr;lmtOtn18+m zSIvrr)Y;y26SkM)>~BdfHY44XoyPk}u$%UI%{HJdjp2Fgr$XF=!#0QRN4q00&W)gFC|S zY=T@x{*qSaITlaU=4pOm?3_wEH4~5@s>c#6Z<<4x{+n-sp^W#0o#4{mO_Wfw-|0y3 z>rr`T-BBE=irBgjO@hnGtL}ZQwwb!%%n->{GMvBk8Z780$44{k8e;5Me;vtFXL78& zAEBVvbcJw+<%(I46O-HLh~8*%sF39<}=t=>*pk!ago zD=#*vKop?|#gJq}U4jFWJm%(GLGFFLHG#PBQ|i947u~gsm@M{mxjr&8rmN2DZOoXmw)HSK1cab%dQA5NzarO|l6xB+W0aN%cXzSH%mcuH8uD;~Q z2WOy@;$I}Bp5-u%Y43lpcUb>6jvNU-@31gx?2P=uB>NUPwfS9{d?uO_o4`=^{8jIR z5t^Nm_3v$;W_3P!*>=Ot#~(Cl508JeKc#QKwd{w-F9T;i@jcC_yF>4MX2K=o$KTvv zFz(7jQ(E|)B@T~(veiAmd)I%&vU$GUt|>u!zOh(5imZus1nx2InUS;KopE}1ykz1x z>P2gsBeJI&4OHrBNsEUyN;T**%b)FU;xNPvK!|ZL%=~jO+pzB4)b;306nmG6lWu+> zAkPoly^4JwTEj`MjZ-ukYRLu%&oW@VV^qL9ha7>w-xK1XdsEL#9ahD|BKt`5%q`gh zjf_Hm%&4u?VmLNuum;KbY2>~o*k7j5f!NN0c}C4`^$hV0mS37`M`6S*~Y zc4v_Au9|E2`7FlSt@}$sv>sE@l=l#axSg6qu-*bOT^Q#3f#9R)I;6+C@wU5ZVfQS% z6jX*+F$UfCE7>6ACQAsX1yh6nj%kghZ`to8pG2*`ZQJU}eXbU@FPT-3kL&8c@oWA8 z=Cc8M9{J8l&635bf8i z=_s>yCqc^8k!9mcXF~~4?OItfX`=V_QcHISDirClqw$v*0S;Ol=~$eYnE~+6`;f)N zmPz1J)$#Kaj#mC0K-_cL-zZnMPk~%r&c<3DtJOtWd5iHaa42P{J_{ONdYQ6+o>g8# zb>Z+-nZ^2f(6og2Hs8YE+x%`%I$JGJFWJlPEf0~{jTOP!xMe;5<3%QM*FlCZc1E1+ z2f2XUusNeHId|O=5rM0F>R~hgd4lqjI$Qpn%XU4fo_0qgVqW&8EGtMX>(k974x_xA zOutQ^4?fo-KD|A};OowkDq!EUb?PR1mlfspr$iLn{dL557}Kz8$R-v%0j@fU;?hmJ zImEE1hdW{LfM2)eNUzi@7%HGNr>oY83r$pf z>qA1@-8~5cwY1b5PTsSf+11;>i;?`LlrfrO6|HC=t%^g|kW@T6y6b898#3iTd+-Tl zibW>6kS=i$zIu9$zSFn^i4j!1G_E#M(f$T}(M^+Ssl=J$Gbgz8PO*j8!;ZjE-7b{2 zc9HwgM3iK4+J7*t%U|nTbKbZXFum7W{~8)t%%JyVrSeCg4S)!-V*TL zXfT?a^AS>4wP)z7#aQtJrpL~lK6l-{(|wU21vkjyHRDAH+?R8Z!Ht;H zZsLrO=n4R67P zb3zYi8jQa_@qbqZWpY)mj;bis*lW3H9P;26ppGdbJrexywE?Il&gkooBnU0z+irv4 zXVW2&>+Rw398)B&6j7dhY%7dRy{^gP;qhf9^dINyjO@=j;HadRwWn@7eDwB}cc8)| zeXQwY`>xjX6}21crb+ws%cAf$qtt9|1MyVTIQ= zw~tlK!mV4)gsml#OU`Xo2Q1(|Wv&#gq_FDQZ0Lu0@^~n52BUe?i4g$Yuip)J7EgYD zre&Y|KwdSiN=`{(&OpQDoyhYjpH?F&W3fS~fi`EgQ+jUQYjDtTq6C-xGwNWGfZAbp zNR16~qbLFuz>p~ALY=E+(7 zvTQ1M$pg#i8ED}{q{aJ}ca zP7_0Z6`2vTD@gNr&oaE?O>vIc{F#|4R!Cj(06^Sqk%Id8Ilu7u3CV$Fa?Ut%mJInM zX}sqOXk}h#3Vox&2H?QnG2zko)IAn{$=hfZ*Z2Ndn}>>-AnC`m!)a<{W>4r;Zl^=? zHmlH2&QHiY(e!&&qqa~{h&h#BR|)axxO}!k8#(r$Vi1*E$nT5d&gk~rbM(Yl^pP(^ zId&f%y?wXxPSR90%C>Q37sNY!)>PrPe;p6Ac_X>IuIY#bvpkXaU7R*ziw7hp3;C_A zIu${CYVwDmA&wXhKu>BXs2}>O>E(vmT`1S9y4ia}mmF?G2>E(vn6Y|c*)|wI$ zisyfU({6ku2u3qN;vcdxt6vTe&4w{j!%NUyTC8MC!pf<_eQ^JeYDm55h`b~HO)Cl_ zC4$tYyzkU#+;uZNzT7pdS??$==thb0{>(aKHsT12?&lCe4uWi-d%#cN7Fd+fqWHJD+fmhQo_#Y znfrnHT`*r$GwzCAelXab;wd9$z_*ZNr&7yUFFG?9cMs2@Hk_A`TDi|x^SZ~j*Dm31 zO#Rt5Jnr!suAl9xCn>~p0Np%pr>?sDK$$`0<%PX)5rnP-iGEe+ned=2cSt21=z>Bj z;tN{Pxxx*p3_l@#?wue`E-WTdu>5*jrE;td?9?<6I4=fAqE6JcorzJEP+|ytctUfo zC^U{EMYMhO0_e+xyF+4lq>@gMq2I>2xz<0?T)K$FBe&-GNET#T-gIvE6sTI31LDr0 zHXKY)i;dom2wa_GSTs&(f0H!N{Z@ut!;K`wPDpd zCaV+S0gE4H^m@v4A~@mN3Jg34?{lyPGbx7fA4)$WAwNq0E6^<9l@tpYy=jw$8;Fuh z%NlBeYBUx&K3qjo`g7#%WXfK-nWyhVXokW#WlrnPOqn|3zAa(Ju;^djR{oa`N>{!9 z__7H6bPLb$0NIsPr1n9JCbLdnNftpyfJ8rn$dfnM2K6Ax5ul-u^%mcT+9eHJ0WsW{ z!t@#2WAeoC==TRB4|X#GZg+`_a!cp}Rn(DJUy(mdJL{8U z)#u0sW5v7+cRSJKc6=x;&UaqTUcY1%G2uyIcAg&i-c|Z_@LZDw^w-6mVlkwAx?_9 zukhM*o#mpLuzIi2!zV~lOu4d57!vzkAwMQ!6gJ=MWHu#~*cQwYEFmD4cV?KSk28A& z(f5`qO|b82Y^5K2Oyun6dBYq17>BY-`}rH`hCg5TFioGm)%aUFpxdpksDrUjH6}20 z_mu@gmzDcjL1UT^;zeZTS_wz?30OllEL{K?KV17fRB0Pf-6$rV;EFNZjXuqBc;xYo zlmGlxw8dZCB!=~xxcE&G)Bf{c15<^Z+1k!GHx>#9NDi-ZECKRRjxjTQreU}7kN-iV zK#JBKpm0v>jK4H6c-SZ2amc4vK^8|3!^e<_-i;^7>Q4H9AKbezx`zEi_H}pDlu^}2 zyLqXHN&8@+ZbtjvA+qW!^K=DB9hE2pByt7hIQ4b8dy4=1_qDT@h;K8c~TQ+W$@dTxgSm?cfcCNmc2#I4CZ)VuPf5Xj58V2+qO3n$%S-* zAJnq|*VVsTcNG~(%L-jyFBt&;B5$b)Apy8eaJ5)Nsy14%tQsV!)fe(1{yaBw0AF^G z@E!KPmITMOUe|A9`h;|C1bm5T7##nGSXit(=rzUgQH74e=0bZlf+)e z4HA#B9fsrPm|Lb$7FaJ@mW4_qMjChH8rZs zTw#iuiDhDLR+HDkN((y4V0-7JIF6sO_f@usC0s1}Btthjydn;EPK_7=5N4s_vtHbZ zlh*9<{HAzpu$fkLt})n&g3!{aFi|$+2|fsy@7G z%qDHKVXIk5ULsfTV19y+I*4zR^vNm&kU+xmNi8m~EQaBa3BB`cxrJ zgTVceE?wGq|8EUcEKrI2&JTm9w>+U|_iX5#BTd%uyw3|Wn9S0p?A7!GbShQFwZZu- z4T;#l0moQThpX-$+nQ06mIjpTCm;mZFzvXmdP3&a37w^ZJi;_xN~|sZ(iLMsy3Pe+ zDyA=RZpD%^cN6Kuasp$`_)II=?x5!F{%KvFP-X-c+;qgh7HMwtIfCn8CO%_tBy;8y z=5XD7q!`_#kHbJL59k-=Ewq}9q3Hpeo=~TNG50ekI^P}uFYDT4QLod%A$i{@m1VTf zSq$mm^(cJ-JB!x?8})Gs=Qq=Ck(X7_$@mQP-FwuE_6GAK$*sDfPFrleTgR2j3LE-Z z^VNoNh;wl@WK8#;$`j~YEvk_}AvnXQq_d(j<5%1H{I`SQm&mQgjgYQBa6r@`8za$b znblRqJs_YvrzXMl8-I-NcfPD#O;@p?5g~z;j9D>55$Q@Y;zwLngEh_{E>wgzGNV`}jR`n0_Q<_>L-bj21`^ zCESgrVf#sEWA{A=Vz)cfyQyY9-z?9YH7*pdEV;{xKAYPl$3nKl5=Dbf z7R@ed=1^Umye5oSGTzuc4LX`%Yd;QDrP6?+$vrs*)1c35q{AeX;~#&#dBH*89Mjqi zy`ezHzr$1T0hvexo4na-@=<@(Adfzt-r}!pUP4mwvvH&;*V)Qe7UA5bL`%8;%vs4U zy4F1B(flKG$9((6i_i~`X~osptAvKxAb5qbim~MFj)Sa`91jmFDbaG+eBjWrex>;h zEO0rP8UH+EnCU3~tz^VT+&q zbk}vUo?6gIKcG`-h;Auvf+PAfxYufwF8xq!b0|O6B`pyw5&2;i)yqzvnx!fCdb&Qy zNDO>r2_)49pykpu(&xSR<}RN*@nX|{E7ngOKch!zEcoI~(kzl*`Q5v>Wc%Zdw+F3} zV3VXmIk~#Uk9!?_1RR&A;IGs1n~&~8nWb3+gTXEkfRqPax|H{{CCEp-b&#t58?oQ?P(*YOH_}c2 zD~ib!kff7`lbSzaRH=LCARfc4sL-zzU_KFU77iU9r2eO`MrI+c+^`C8z{v2wcf%~6Yieu zs^iTDXhMp@%l9HPrRTYhs$6K25ML{_Xd3zRpjY-OE?W!!^5E37zlShI{xTS2SjCTJazk z5|$PgUF)~whmCA5z{oGP8EaOR3waH~mP}Tc+AaiKbPt;)D>VsCxv2e6HL%ZeBpxc3Yw?b1+l zgL%uEmaUg`*Y>E_eE5l&@5v2fpqa+OgbghH7G%+QEZM`~)}!ZQbFmty%UK)JzhAr4 z1z-D7SYp@(MmAnH);~*_-Jp&kJ)NGu2Exd+_q43>sM=rdAKKnxH3|0W<4BI5NH&ee z&ou!NDv6elM&3^aP0h>Re^A8M|EHMN`iru%U2w%(5K)QNzk)=Pq&6x{)k%|fmV(o} zdT;XaNDsYH6Z;^BW9ikb_>x@0@8ckpRo}0I@DO(25t`+h0dG0tC151?XGSJI59Vj%)C{5G{h}m zZuJY~s@5nxXVfaDW!A#Um)z+~la}EY=2^)8dPmRY>$1M-A*aF}prcCNc>6UL1;t_6 z|KqX%x9f=_`88=7zHN7|dz%cEI7ciq$Dl2N$Cty0R+DMf~!gQNz?rfoTEtr1T)!u22_J37> z3leBMNs4UOvN>b0#T`Us5_NZbm7;|&`$8WdvS@~idVNaEuv-)fRPfHOP*lJ4WE-~! zgOLM7kvqTSgYL!lgRhq8ze}qGA9q8CU3vvP2{%~-tqxXH-rqG4#C=JUz3rMYGHU(c z#;xz~TCdVyslT0{-tsqphEc`sA=YY|WgorxbZUzG#df6s8=P>BaaW%j_tetWfn@da z`Ry)P_+a0-jg;uV;AiNE!#dO7@l0=YRr8#|f}B~fN#fE-*WTNCi1(k1_N};YzyJ!3 z1}scvgIORAyaUX;9T-l=o~6U6Cm7SWf(}4yKijp>9vqc#A?1z7?xu|QL53Rs9FTG1 z(-Q}TZ5z>;9fUeAT5ZIdHE>+jI2Bq$UeYoADiy< z?p6Gy13$PT29KcL6<4cLo{LN&ikn8Y zFVb!U4olGW4a4xr=#R=eTZ?64c<~Ogv$sUtUM6_|ACqkVhd?|dx7jxF?ZN+Tk}VSO z!=2@t?#yPgG|`iC5pl=6JNR4htDNx-=I|D*>0_I*{sr2K?i0K%q*MRsBR=SDEy*|D+~IDNi*^5hhazcNZ_u_7inEQ7qM3RUV2eeI8QW7 zAd2Qi2;z3?=Nej-`#Z6iD_CrepEW61dlKjU{4Cy;_W3j>NgLV_H!*0@HevI|nM_%M zWPXt3`dx4D7T3&ao|viooW4=~5cCIwM#c)9nF(wD7l2OmA@B^q0+j&#q=V=Ju7F(HR`Fcgcmh)GBnVfvft z(}Yi-4?rF?%%*1qJ$0^`B1;O$W9g?n5Z1*g=JEvEM#X^1N;)zqb7z;at+e+$SXrA2 zPwxw`>+lS}CrJ=12mayp+Rsc2`aRbO!+_A4pgNo@f)qX;@jA%@tK0n$I%1+xY){gDge`nk!!cKwWZmdlnXkJRx*>6v8zk)NKtPCI;8+(Iv|ql6MSr24MCg$ zvDVWYHuEKoC+Deyq41S-ZKE&;Aydlz=c&%skG1`E z2aHvyRt@9(oCC5O!?eDm$fWo9k{TPKoJhK{${$r~rj7mdPO9aws1S$mADGTrXO-Yv zmsQS>j9b90W1>UWl_c%QnaLV!yuzWzJ`+Qxn9UM&XeaD44E-(5<8eP@KbZbISzyAHxJV! zbaBN4a0kFT^i%e9wVm43t&Hh`$*$|K>tB`)JX%P<9Z5(<@m%B1-bDp1%)PVY`x&Uq z(8LhXQ5?$Sh7DM~fO$#%=PCcGM}C{`Bc@^nwagdX<`p%QlY1Q~aY|lU^!sHFuF_vR zceEQ!vlzMV@!gHRDk1}l_Y4m)e`^g}j=2_gObNLQJ^ClT_iV^6UPUTdGXJY>9_R`q zO*HSsDsV-M+%2CYWe%&L_xmeJPo467dY`MpNNImj{Ld+(Um1OY7BNFz9AHpaSKA)? zo}{_KimhAF)7?C${0C?c$F}(XC(RI`e?^23gmlz0`LtIWV;l=19@58aC~wqvzV&## zh#r*tc;w#LQPQw^6}s^rJ0F;WA&vvmh5ot0-w**?g!@xu=>ABJe3Mdo{`9o!C*aiO zT#3~t?@AoS`ZP-Rr~E2eR-Oz}qsNT8OgkYqPJzY-){Iv0u7^=4=T2ftC~{?5)mDIc zz1MQ_S`KT_g=I*P4f1{3Y|i5ENnGI8#8LBsl7fT?a*}%7${lo#x@L+r1dp1`hNsg_ z)RxYqk2J?^Pd)YU@u=pPHk2ymT_q6rI{jvjH!56-%O|c} zePRsi?UP4qQa63j9~Ao=svs)Y4;wy1qN~SkUkv*Xkl^&flKkeP-60$sc*(0~+Is++ zqA4DEpei!s{N&s*AGg}W6M&Tf=DSjE@Z+VeO7;`FEanhL5(v*C8Vg7!amXQEkJG7; zS@AO@me_>(aM30D@-G3r{uFQB>CETH4TNf^Xh>zc$((B1fM_6sJo9pv;6r^A8pQbX zyUjxYmnu&gVb&({AM810j6Du?Z^(GqXhCM!NK(=!el;njbeQyb=$AC^TrIX0{>dBR zPW;&py34vcaY}V0$NOy)6hoxn&7}P<7~z_j<@rM>rOoav*W@Rl5gt$P25L$>Ozhz* z#87tMFoUIP*h#aAl>rQ{GtX{+Ar>`Ty@_nU0quGact^Q8TcPQwe=7fjSEg0I_py`N zDXSOFe8gIjd088n*%uR?S9dBQJ0b0F?qH?3$7mlL0IAeJ@sI1;2GZ^}DrQX|n)3TG zfYe#o`jUNh$ColqKb56jP$&G<>SYgcyPGh0l61np(K@ zkxr#Y*>s;Dy5sZenM6BAMk2zRttglc|ybsgy2eTIjmnY#2y;*i?lVlIBQ(gWs)fJZ53Aj z5qS06IC?$nU%lxZ-}<5A+~J#H0n>NeK871YkI_SOH`A-S#z}__`9UcItfI)>)YjeT Fa`)L&e@E8c7kuu4tO4yVML~uzhbwOxRs=W*P9x}T_)%1fxTc@rK zHTA?r<=e%t{8xdRN9K`{e}RaU$U&>gGUZ;6m?*dmZI7H-Z1)(>h0o_XH7Z$q|9QDq zgFc$wyC-@lB%$PboVM5DJUmVNn-5C+h2O%RF8nu?pobhyeEzbdMx$0uWgk#Auzfe3 z3?UDpyu`Lvgd0isy-S*h<*=1jcWXU%6ov{zb7-o#w=en===X36J zzCYYQeE$H>amHNNYk58%FH_&Rqk}t>SfvI=YkrpPV2*A39KLP@m~%TpDwqykFOf!~ zgB_H>(PHB*=$m?ghf#K`;m8153gH7gWS<-_E8c~`N9`}pKhA>=AI&gdMr{BH&nIox zPY8VN4V<-6tcc#*_sCNP&nr_~%m4*jRo2c|lzv@R#dSjrFo~+G#I}eU`99I{p7E@U zd_AsHJ3$9b@%3j4^P^&TCSKz;-ORH1cLEn$w=RLfSQ5oDRp~2z*puy8m9>w(Q8u=K zv1a34S`H4X6bBYs3>3unYEZkg_p`o%zok~Wu&lRhz-kTpn5Mu#iX{VkA-F&7&qjxt zlR8lM`zN#lYLuDp|M^8<)`1oV_!m=TTf%j1V}=O(@#{|Q40!MO0kM(F|3}m-#UHJ4hnTFZ{-cDfl zR$UZvKoT-n0qz)7UXBbMwiZ&o=JONn=*A0`*qH>5we#}U>>pZWt@I@ z{yD$Ms^irX2XE03;Fn+xH?OyMVwD_wU+Fzy_nS1O0gl8{A zA`~r#1hFM*+2lU6-#Zib=Q{P7vkf=73lAy~;C2clNK1cAduf$KPToO4@T&F(tmU&3 z?XU|!)zYvOOYcE_)qm~RXzsu?5dVZ-#(l_IdGlm*R~zt~=RRE*8cX+1fNJ# zbXP~q3;n4O6<5WeL%y&3!etnIuP=%A*!nn1_}YvR>VvdJuLiBQO)8#3-_GfexNmFt zPgfj{TyEc^lI&%?HyL%?)avSt+q+6~-%hmB7pP*>lABEbzFu1&R!}JW(1~}UY~d@f zPKG4&MeeHZ>x~t@y`oXww|r@-dm*6u&pqG8H1=;9>4C_WsAMM*+ery^z7&JxWUqb# zyu|$G!h?6RlYGb*)9*bH#YZgz7-3L|5}}QNg42DCL|-`JBxiz-#P9g72E{}!oZn$@qFH_Ca0qoNsXT+;Xo0|*mt9$~ z4tXEi@bB>}0Hn~r-Bn%)z1XBoeOB22WY5|=_I~Li2_%-W1oNN9tUFithq=ABIIfWd z1kzJ^LwV&#pFKa7>^U+%Hx)hyF0SrrmxE?lJC|1g9RnEpwMbbMM?JF(S8Ycs(=n<0 z#0Rw48;MSh%w@*=6`qjvA=WRwJeBJov^~kjfK|A6mxI{9f{yO5nGM60=goAObLHIM zfNX?$+928(=rgS^-1~eXqH;PaFmfMrsb?Y?-{b_REG+{Zob?c|mG!jQ6we~}dogrL zwhRs{su{NkG%4L#@chFOBot|NK#1Yg{4y1O(c*hr$Ykk< zBq|ENq__IiwBa!F6`Wk}4th_x34LNWSuNb~aPs}**?|Ci^&G^twM!dK+iFv-zk$6! zrVkg&N_1k`!e0%D!4IFqq#Z+``isE}){5A%xlg{7bsnZCs`##9elLOmoirIB;dWeo z25<52>f}45vZ6&3ZD^hR7<3KYOv3NPKLPT0BK(J@Rw&O#*r-X&;6*#Y$of1Xbw_RV z#O8IuMXe{>h3I9#`W2^nuIIW&pvn5?jE-bejqt4MI{CLYD0*vBLv%GK7)1AVEvYFt zsV(ZuzGlo`pk}_-6V=ith-$cI8xRB_vtNXqXRa!G*#B_TD%mG`D#&c#NK0@#*hw3% zobr%#z%N}%DPKrFwe$b-78RX2@aVx!lyBB(-K#WX(YWAxl5y2wUr)Zx-}IV{riX8n zcbY<4v?$!w(m)S2=t`wDJV|2vJI<}o0o6ZJD!aK$Z3ZIu4q75JKU)Guy9tTPUfuSl zq^M`TN$H_h{&M?*jRi^_R9>;f7lQw7N-7Wd=$I+^o1AUE`Dl6kR1EU_S*pgOUgT}3 zpu^x}5n~c67Bb^v ze_8U>dG8hmD_O_S=x9!5*H=zrWX@)A#-A)km6b5ndA2zQalEcSXlrITv3p5-v3lxd zxHnN_6qBu|$b1u!>q3h!NSVor(k`l-VXe~PTJvRYHoT{ZMC$I)tlxlV74BXgmW2m@ zXjK-i6V@pEUn6@Bc`*6m`B%4@MkcPU+aC)n?-l!Vi5VQV)6Vr$T-wXNhCg$(8BMRzURMaa-=5d{Tm|2QUU8%hp_q6uRQ_jNSPB|Ye^=z% zB#ewDg5CCLTnqc_d0=K@8ci_wUOaG1`|*=IIV%f4i~GecT6d^>4i6g<8DY3pt1gAX z2U>S71ktRK4f4s1)|de#G_V{`@h-!rQQR-KASxnKBu+tn0QMjkVCWQOK2JMvuNa&G z4c({%GOw6jS0tD{gi1yqdq{nAolGL_$KFR$V-EO*vU6*ifd zo;(P{GnQ7h;n{D7a*t-M&C>VM zRq8}dZ#&{`Kp5TN<5JsI3lTDRNTOvm+b`W&Wmue3iCH-%u6<5=M))}}=W_7Nhh84u zHzYHkXjr_Hnk5CX0;Hr#t)yZ)7e~Y$x+#A-h-~aa|%s*6^uKmiS;1@>gUg(J9+l@=Gn<}GXkiG7= zdYo8%t39fK$?6V^-I|X*GtC&3vgF+H!g6;8CFw?0YpJfukQtD{iipF8DkW+~C#TfJ zxdGU$%=81MD?aBU&Hr(oOM3b7YUcjaQJKJuKUs4XGKtmH%tPm=zFV`iGvJT3p|o^0 z$DJ=cZd~j8*34fm5|+>B$}*a}3XyX#z!mDR-KMurQz5_ONDFSILlbL)HO9+y51Y z2|z2&RW`FebzSgKKrLnti6R4*tW5jf3v?WBO3jDN$Qn2HzJ5y@NRYkxL}fV3=3@2b z#}}XX^xhOU=hy#WqBa2MC?a;BQB-MstbM%8`c9)AvTC=H&ATD%LQF+02i0?C;<+QH zCa$megbnT5z-(sc53Rekpfkgb1L6&$r@SJug<)xIcq;2ovLQtD3%qUr@n7cF(um&~N#*f@bcAhQ zFHYo8f>K&eXEe_l*s)W`E9zRWYQNVl9G1@i^92il2_h_;3!Q(NFAap-$;lGHL>&8_ zSHi}aTR|%)q`j~dy1%S-TN~`CDHrnBbYnREof=19KIAkAKnNvOy(pfG67W7Vy)2)y zm-NF*=+&No;9tNUBaZ-=>wkG&ng45!{`-E+);CuAuRsq*Vy$|2(`5?mZ0rGjw{tV9)`jV;GxaU`bqj5VF3>%kuIO$l`uhnL2NtX8z|% zU$~18o||(XFGB8*_^4)Drvtma6DfN78?l&HV>nS0Wyxt)Yw=I=SfsVT3p}^dkq{VX zuoWTN`=0y^SWgo~+ERXcrNnNi0Gs?B1L$9{0}oevd4!Ka{0#?VmqayaS-PJ-Y|2mX zZrA{V*NZcwKF$PCiyiL3ge`JVVH}hJ5U~?30?AO?w9byR*v{y{^ZVJpcW*e@&;`hF zZ!Qsgn3O0@-gk?ipFU(}&E^!0u3mKP-N;UhN3#dEe;LY5RB&R-1z2ezT4J;&;X{$a zuIvQ~HEF9?YK&P!n@@nnBCIVng9l4R*Ptc0*IrCN#iD1`qWQ*=RD0_-=Jwu5ygk{2 zL>r}<0`(4yS)xtFQIY)-@drW%%5Cux&SGDdjqd8?;+FVL--i|e2q&zjbem|`DV(=B zFK!Dq@%a96VQ0LcT-{WEYbmbkG@OV5Q&|C?+^YLUz);dI6HCai?DPtkpG0mk9Yy@q z3c+Zs!*&?-T~3(pK@Al%tw5Ie+6Vt@nnOH28I|X+)%B(MaIKd@?!XkG_g#*K2>f5M zp6~x3v0g?_`Rxg~Bd-3mAk3C1H*;5~cj?iPLgE)!-j^$>q$b44lgfv_$QwOL;NRpE zRFz3O7%$jl3?5paR+;n6P8ah&k+@RfG_Z1N_xk@=tQYjM)*-c=bVvuuypH++3bt4H zSfsIY`qC%-`kiYt_&b8N2`=V~t-gv~A4Po9;(X3(V{8X0o0j6^W!qxkAD#peJ5`)n zX{5kIKL3Bq`QPuS{FRrM&`if8~XKlkYrx%~X+jm;FTyS;B!yBm2=zUc<8XhhYKeP_wtrPfI2M+ti~ zYvS5J5pC%}>6Yg96D{c%YNh};$4hIRs>Vpptfj+$fnUGp?M>^KtjS<7`Ang@ccI3y zB`o7>L`ZycrG0UO*W#+-#0@|)aQkrk*{fzn7zxouQy#bQAxdqX-q+iY<J01%3&TNGAdfwY`DRjJn4`JHD0k)*MVp^A9iNkO|NgM zY|Io`V;)o)yN)PNHNeyoosvIuUzj+D(B?m}n0edw+ph?VFwEULQv%HdqyPP+5Veur z22(8RgTbmzhXj|f&k()|3Zlr2@ww^OonXJ@-m79Y?T*u2usLuzChB{viyv?k_K@-7 z+^fyab~;cEla8OEe5+E{`LTZHQ4tV$?o(8hhg)~+hT8+J-02N)mLRMDAmE)eF};pC z>Bwy_z5^#ECOh!=QD3RWW998ecgPe=>{Atm?wLQjOkS1GM@pjRC)FKm9*=IDb#y8A zm}_yv&R0t&%lfYtti`FXX0j<6zHB|I>Nq*|<$7ysF9ld^lcEW~{hSG}nnc$vXJTJH zeOVM!)Z^+Syz@lM`GJ<{{s;>7%A>Zkoft6V5~t-kmSaLsl|W>*_{V(qY@@9kU+~4V z2&2cK1JUYDa@&F7U5$Wd?W4ueOfMUtJpOZ*<;>%W?sFjtN%mTRzUzSqOhuD$(zG{T z)8ncPey4qMU~f{x;ThI7({|tO4o@k7RR?t6kkyHN4_Q&Gm!R=rt2^P`hn>j4=-)6q zrn}X>dqCYVQkM?A*!z|vN5^ag;@S8@fX$21abP-E@$mEi0a$}7rUy@-Fc|b(V`0*0 z7>}!K`bL-qRFUp+I{@zFQg&joMGeM|02C;uHcH<Sb=t#a_XekeT?bsFYuH%F*!g=;XV!O|zobxijP%7*;JNPp_tNe;$_2(P>;q$yt z#|_^ED7}{@lzXNLom^ZF68a?96B^jQucsL7ODFgE>Bfk5-Ec>Pr19&1p(ba@TN{^3 z>mS+#&_h2HX$QK7OuZA1)jmB(^;mFMzb|{nP{KC6DhVI5-3+QJMfeI&m)U(7{?vVY zVGiq1LPpszLCs|U;=~sQ4Jed;Uty}PVLL`%O1&(5xxK_5~ z(77Xwu7`XHY~KUmq%|?ZM+LzLY(TAo3Rl2E~9=?-G~OJ z8J;1Mi=)Igau%dFI=RLRzz_SCmW24yh)NK$0BM7poJ{2fQs zShAPWpo0%dphW=`4uIcnM4@?Y10i(~r>5yh`&j6a^v@EW$rfHEAb}dncY6nFk7`tM zIkAZSds{;NqueLFj&-A!Vq%be1%|D*r;~+u>$>FWY@iD>an0J!)e2_rQ-4gZHKmp8 zrQ&TMp<6XLNb<6aSh_fsJq`V=-Nq+VA*2 zd*UnefpY&-^2E@=XYelQs~eI@COSX%*3c~$w2K@tLsE`z@4TADaZum-3-iW?MU(Uf zXHn99uFov}VO=e$5_zHV1$%k~3X~ERT~lBbX<~ElV!+=!{@mtbVUd^^E;#x`LJE~m z^;Uba!G0RzS?pvfGE3 z<=`>unAfpxZ`deAjHqs;LEZZA2#ZFSi~3H$keKJ~MyiN&Z_I`{u#FX7+`O|K0-eYo z270yV>*WbvE2;TWeJTDk>gJ=UI^yw9A)+bg!|B>APeGj@e5~A+-O@Aczx@}XoIasY z%PTr5expEokL16Ai{iEIsZK;J<9a&5*EO?i38U2m;JLk4@R4QD&cumqtv#J;11P4u z-cj`zvlKG85?MXckh{C6kKsA{7W%MYnwNprPOsSc8*b!1P<%Ky-*8Q!F3Fe7#x!_6 zY!`8U2<~W2)%(dSCV;cwpj3qb$247lX=o?s6L!N-y$WP=u@Q@0I-uD=d0PBPWnyQV zCy#^{X)E1vaapVTiooYBQjqvJzRS19|u}wIAzPxr}3DJ z-NDxLj8Cxf&q3}fAOmII`>-V;tqXnsChEw85KOn)Y>=<|1EtP`Y4=-%Q?*rfbM_tV zxE7@~P{gDH;!m(x%;t@#=`+oH z-G$-RA=kvOUD1U?_r5QX_%z(Omi-^|{y&nsE=EL4;uR%K`EOuLLQaB^w^6+iSvpvF z{MA|idwvyOICIalBIE_?`l+WmYngGtPM%SAaf<63)^Zkp%>-DVL4Xk9tK&eQ5b})m z7HVLekQApf^&(SC=hlldkb9pGSijo4`HWZAr5FVeQZnnEzEVGy`MhkyDtP?-cR>Nb z?DPseD9-3+6SCz_j+LCwAe!g~r+y@r5l`z1=i<>H_n%1{dnWks`tzpWkDlaN2`bFy zz1Iugm^jvj{s@UX^ZeQBh1NU!PQ6=119&9@W~K&&fZfD(mwdmv6B2TIyAjrJda1n# z9k66;VRNXRW=FCvVAQG@T(X=E{+7#D;{L1ih1a)mB5y2`RIDhm%iU$$zwbj}zg4I> zY6@VMeAeHgekjJ>ci(+;-=(tC%Q6?)uyTq;z@qmfpkod|6kZ^-iEnX(JEo-%WIxWEl?BLF8|go?d=3E?d;QOAjgo96^DO+LCmF|F;5nXOd$f^Q3HAkNKdc6@wXAl`^3-v zmBb|_bQh~NO4qfSK3%N^Gzsds5j|xfD`~DrPhswtIYCCPI6>7r#bS&Rvh3)L$^T(q zs5(m}gk}{0k!l=WDe?f11sfJ2@6rUaWHP=vO*2shB95``dJhq~jZV#I$i-;yAhiHVKS@_j-X~9>@GcM$bybV6qEc%tfHx78 z`roxihLU3GV;P>JWc1GOrb6ymzXZ03SPe z5W+B9fw!LX1#i}BWE!_o{_ZKg{qcYrpUC$x7zaFWYs05P3O^$GsPiRUO=73-?9$DV z$_`oQ>oP9p<_0z$>b-WFlOCqE1s#*f>aN`zzcVZmeL}&)%3tI&lB*9dUa`~6*=#16 zt>lIUk-I30YN6LaER(}G`%OqFXtnL0LCu-2S)byJ+D_QaZVv{Z9 z{So6ZhFu*y=X3D;8_66-xuTlevZTbXL7hEX8Wtw%ae0R~!{+wCm3Y5ou{Zu+Y^bfV zG}hnb7#2^f&lG`mkdCxGNeK!Ui{dEqBNU_9Vf9`^i@;<~k17!gOp) z^LM~(_(zG?1DRxZJX=LV@p&JIHF_aGQtxeBbq?1@fU9Hm7XWdq0_rz%=1KPI#GL+R z>qUDIJ5yZ0>wGKD|3NHW|Eg+_$uFNA}XKJu^U35 zBrac0F5?iSfPz<@Uz5+Pegi1u!-2-un#8G@_O<&26leYG@@F{wMIWQR^or~2kC6s* z9l>!5=b01T*j7K=(QMxY5L&(?XqnKCp_>ltAX1#41dhDs`2KBy_CsuMO78Qaj{?dK z9<;k~QHC`VFs2%oM%2ZoVY$eB$S=`puSvC!bJ}o=EV-vulAgzz%t0O)Q|Rx%3`}Vl z>LhHs29SuT2$b$c6k3PgU(FqNZRk?0Q&yc0aHkSc7Akpw=8HsjyD@Ryi`^fE&V6-2 z{y5O%v+t}*??C(!#Cn>nLL-;7{5>;D46{i9jzX5)iv1lWVF?-$sM{-e;S?ZvEFCb0 zs5XmT^#oG$$_7D~x$%1PoW25W?Z2mwh;wpc6wc`U7<%}q(P~%x-2wKU0Nbq;dVLP_ z2S>yNvn9D{%rS<&Ny-eWn#5oP>qOx$7A?^ybn>+<19|JQIU+hT&Ep&S8yG#0uqx;M z_o9lUuQhjtp#Y7C3&XoeO)0rBlk?Rxg1=m6jvHGPBMnS0`O6AQ8HUv1Ro zdB}_tPmf7ahxu)f^{GXU)MSV(PBCA;%wuj(ZL%pPaj*$4}-f`tzT$T)9A z?jNrVGl1)S%nG>NUbxaYzs@5Av+VRX=46@m#!1D%S3M(0>{H`;-I&C&xx&==;sK2O zo4ujM2l0RnV5{`zuUd%;jl65zX;Hs~$K)j7Fiei=n{U@30EOo))Ob*t*OQ`dD!Xyn zy~5iE|!mNLgzPcGVj!3Al?eFoJ{GH6ZUPHQ}BLr9zm#hYx<_p)0 z0;?U7`%~UOUu-v!u|2@|d`n6EX`)r`$SCLyKV`hPMJdERA$MZ+g2TOi7|yAKXCK*c z?gHhvG@{?I^C1~!w_>(|f4q1)UelMO&SQwbD$r!cie6@kNMlex(^~t1fcr^A_7%bT zPX630O@A5wA9tA<&fMj9ZWuc3FM}~e>ca{H2E>mRXjCyrG2Bs}DcGXe{^^J4dGrz^ zj=VpmyYsAJs`%3qY13j4lcL(@pLk&bu!76duk9bp0Bfl_JE5I^_}96|V#?BFj{98v zF=hI&p29fIXNG{2x&}yl#_swKo2X#MMLzJQH4DWBAN-E7pu@eEHzqlAqF86%7Qn$@ z`vEYFF-gdLJMLyU(#EHs@OAQAB^9+#tgS^y`ugO`-YDCiO3`T*i(Ic&n4;sP!#0QR zl&qxx<=gcu{0k>EcwDw1%0Z^2M_~JFmGBQy8#(q0)4Lq7dB@OLRC;ug&cQPE^Ki&- zR1eH%2=wpxa+PPDo1XkSHsI`)YC!W5EKP$jg?kqvu!BfrP9McWhIwQ)3Zw@_eMijP zdn(|yw@D%go?~3h4q^|hfn-iO`*FK^?$kmJkb@h`@CAenoV;FFea`EMhSn>8t+-cX zyBL*MMI*HO;xIG9CMUL=A8;Ng&n@G%sLr*9T8CAzj8>S6Xh2`c4;&}a2Fm+V9Wn`Y zN2QFfr@4m$3thEz59r*Nc&a)k|Q9}{h06v$6 zOR2D=&P4^Ny|ze)`4%-&K5hbAh5^5QKcSagzoFmG1yvt+8)tL82geuJeE@1IFw{M6 zPc8y*iHNEM@7cGm9AOo>%|kb4M5ds;8p_}4bl#xSU{WV0ZDWt zBy0RQU;!8;sg>3+*!a=!TYb5_vJ~3I&->!NQvp@jT0=R-HOk+?oq9<%-_HU=Ujw?W zk(o>lerH!C-I%ngwO+F0ZUdI;fgV5aGP9a9LL)4@3)rcX$+1DII@kJ_od>!uVRPe6 zYq{8BH>Vt>`c(_V0k&)rq1$`TliOm80`ifVd%P|ba1ZMDUl>_AM zR#`eo3E&6T(~`+fz%Uc4%o{5n++vUg*G39>6@cV^AJO0~HjV&m%e=OV@nnnI`P+>1 z4xm0=VselpEW`qI%9lR1Wvv6z*WnUy*cS<5p9DO_y7x?c(0UZyvsm-}sPSID*}kNz z0~&+T{9l??wyv+=sM3;GFnc64s87uh@DB=nE_34QUy-?VYnPfYq2Z|cZ++2a7k^ns zRa*Vv-aXUg_bvSW{p5BiAH>D@lC|I5H|&bQW`T2J$fEWbreKznc0>}9et6OGI9$zx zPeu*;ZRx(ayia9liquix?fdTcGBctgNn<&>bM1b;F|Q0~BXudSAF>fLJGb4VgWK8k-kD*8iFxMg>8zddqoF^K z&F#B&r1Et~%a=#T`em<=kClquvYM~*etGtUK;6ob!r=BFP%&*VSLY*_`Q!2=l8u_W z>mvNWBPy|M$8hdM%|?M^E-Q8;zjJ5 zx#HF}wrZVJq*R}JsQuh#aQ%%1K!bE|k;TMeil}k;+_LA;EWUQ}?E+oGrLz}oCAn1t zU3if`r-#cCxD>iNB-%A_{oL8-EetxYU1qf2g^-*$s<0WbdQA-HU`a`tVDz;ddkXB!h)KPw17ycoWJx4a9|0B{}> zhNH42Zts%lMfKIA2pPpg5&Lc5mM&wt%NzK5R+^Ejo--gY30kz@+{$R8H}JO*LY&h1^x@t*Ourk)Zk-vacKP3v9KgF{V#B)2tN*6?40o+u0@X8B8{ z#gfSJ8eYxjAK`_F6O9j8pL#iMKe%EuyZxhI!Z6lty|s48%`u$m-vG@}|uM z*j~e`aGeX-&QDV@-ay5*F*{=64{`tz(IX&Jt^b5EAAud^#GoBrr#(kM=VD&x(O{|5 zS6I8EP%o0Q>B26(y#0ayZUWBdC<@=9s-oz=kT}~DZL3Pioh>KMXIwo^RLhWj)Q9dr zbN1gUCfBkorfpr#u*wl*ku7QM)3swsGYB?4J^R^X)%~#e0aaXId@R8il$9Qs>o_}g zvMO%ZO#CGaXY04!&Z27Yth?meoY!w^L{as$DH9&heir}$Md)}XcX8Gx>{q{#YiBt9owtg zVK)I3jUu@^LiiV4*d%fiCGdI&TVVq9Mh4Lzl%;w9{9tl5XtqRP@Q`%b6H9N8*Xi#3 z%VJ&bvl9X5?yRqdk%HIyO5Vyy{9a5qjnaTGmfEM@M40<@jO_vAS@>E5c_BXNbtdvuaNb)6BpQ}uZCb*3|O5sPEv%4;o54zXPN`@o%n?*nT^sNt9bw$c6 zFa5Evn7nAUQr;>+sFTC zv{{)`S1=Y9r4`WiqFwE35OW3oU4Q@cup_1h&HR*a>fU7a{XX_t9bk{U=Xr_6&lOFj z>EPd+`X}2d`l1(hA1}Z6)5YP{htBhstA zw`1g=TYSsg6}Io@4$|Z-8SB5nXxXsS0z_@%RaC(op_u=*W1BaTaFM~NfeMOD1mDT{$ z)lX#HH7M(3JFH{lLK`4tJ8Hl0ld{-4cd1x0ruZt)z4tOKHR`!3;1s&R;h zpIcRA9x4q!qtpCD$;URU^Y8O3=|30$mzm86C=SYU*osYkEOcvb=*XtY1Sb zvL#5whl5|eYiMVnMS4;}{1On5mQW0ta*4R|Gu*S1)H|V%c3@~cK)7P4lYnGA2E!}D zY)vW~4(ly+>fH3v{bw$(Q1Lu5aMP%`EISLSdlWj#%Q?T& zTD0O1g6tjW*yI697!t!{UpNGs*BTTpj?{D&!5p5Q=ZhK~W?~9G)Oz=X>nJc7j)DQD zrtJ2^;7gS~3f^`hH?}*$D;GM{GTG4WfzG%oo2Oiq`)0E%?xLxme;J;it%@Cm?O`E- z9IdB>PRwlJ9H|H1#gyA0iOdU}TNG`?xJpBnIsnxnZ>DDu>YV8)rt|0BT4%$@F2L49 ziQrKq3(u!d9Evq}92oN-{p#-#NGRX4+cPZth)b1y+N12VI_l7vUp|HG04 z$Uzd+#S`L!sz7gqwduaMLAoT0GVR>d3F!&)#q!n=BX zI~k)`-lblU;2&*-yKoWus6H1ci8?PKE7MfBXC*2NrrbkCZPqU*x%Ym?z5e(0>_NgS zSYNb(EGu;)61Ne^S_<<o$BKofcPr{umC#CHjjh7fE%@NZDDPEyC;v!d@6#C zY?6l+YpfTBdlCWm6nkc3t}v+Td&IU`Nq!_v(w@uQse%+`-k&-0+j)S1ZbS#pu~Vm~ z@yz8anqW`t`4%Fc5w@%+tQb2Cb`4x_GTWihTRdq{gLNg!R%Fn?y$#buv*y*z{t;w3 z1wn#8FMk)k1Jt>PrqJ?vRpG2PaD+Qz?{Q$Hr)uW#?+r{mXWhC-0Lo}8=>lU}8Sd<9 zo+ki9YZp+9-$<2#)to1n17>|BAIfzOvM>LmX<_y#S0NpjSl~0T5opuoc?Qa9X-*ew3rvYuri^x8G9zV61RAqM{5uqC|-66gDDl^dTSa=b-(<4D2@ov>4Q z4~N6h&^K@m7e4d(pxxb;oe%b>f1F zE0IwX@eA0oD!^m}ozCAYD;$ZMEOCs6t8a=uKu9**C~Z1+s1^JOvs6_5!puIUmp*lV zSv#}Y4!kA{?<2*C?lC6ZwXLqbQtAv@sT8#!DonhPTQ_bdAH zr+<$m_n&|tzT%UlRwun>~BgDoS z$~$aGq&0-g|t3`JE1j1#pL(o5+j8)uae%12G4(mg{>)=y`fwFJL|xaiy5jpA|Qm!GmpIn+jAWQ#uLt|}Ou8s<`eeq+Sc=`+)L z{^!4*8bXq|PK=p1*K_M?>rsXBfE6k@9y1_awy1V_Id--Qlh>H*GcTSp=JKTDr8D9_ zVzbrWGc_%fFA@~QE%WGgAO;37E4*@{1+a_HWjlYI7^adF@!RJhSW4872qTsH>sumT zf>Cowc*MnZaBU_wmVHt##pP@7BO{ml;MstbfuziMPbYSXqb28}%5f5=or0)9 zzc5k~{9_^<2ZTFg0|TP3C(w;H<1>x#TxT<};F8QiV^e-zmoDHQlr;okD34R^&M6!U*rF>s zY30WkM+T1|Y1Y=vqwy%2+J}eU32h_27NNf~k>A#`Vi7<~?^j7_u8$1MJC|Rak_R)C0nt-cBQw{~4T9{6NJ1Jq zNfteYh`JPL_LNCQ@iG=Z?5uHc$yHddQJGtoHiXSW*MNu9;HyR2_Vh1V(3bD0tvq4p zt$Sq>67{$Oqw5tYBzObGjrhcK3ZfC5COiQi9g{ZhmtSc9Y1xlNS=K#`j=qUsjz70M zg+65ugNV72i+HNPocr5hpr7ke@eY}7;D;$AD_G3*H?o1oNzSGYa=_ZdcN?FhwPf25 zw4@ib)=a`x@~}LKz_RJNOL|dH`Iz5KyL_gu`A5XY-*EeRmp#y_ElM2uk9)Crb{Dyn z6_;d*e8z^N|4t@i=5@u#eai-@*yp{QA}y=~_zdb4KAW$R`?wfK996APeW@@F#i4h~ zq#AV2TRi#@oe%1C>C56l1-koeGY^3p0>b((cDDTHPQa)2ORjS zAdY~x$#C?I|9eRlKQ&>qNUdK^SU+rZqo{G`$8wC{TO|aQ8P}GhtYSuQC)TmTqd%7b zJ!7v-jDSaXxYK-G%pAkKALuIA!!4*a2d7n*wp^qOPyYX)ph#oXg z3w*KHf23XOx{PsvF;p7Txw|@G`>1d8 z?tO7gr4@dq`u@(1PQfAN_?jKm&pn)qxBLZ>?+%1!@dYKnUHBV%#@YW#QyfhQXvm-NH-{)shx$kLD50?`Kdx)<@>nq=4Fq@Sq;)IaA-%p0z(w}UanE^*zU>)a6 zH1_)Vdea%g;Pc~K(mtl8vEn2_HB%fVOIw)y)3&IOYp^%i`5M=k?{I6M<+_vob^aUv zPj?-)Iv>WJt;l#AF_r9cxb8wmry0LLYrM^Nq{ucN z$wNLMz{7N>F8 zBif>$lXE)Ohlg_>2JU=F{?@9q^ovkrb@XQaZjY+z3|P;wu2zUd6~eZQ zKph3${@6q+E)`W_`hA19o%giFdA0gbWZFrI>umXjT6w7^$w{5HvB=4zo6CEXo&&m( zS|%5-^*kS)EsfZ4%_jP@{WPc1*`Mho@el;Q`!F6508ioWN17r)6yUkljG9Sd&t?zA* z<3#9vZf&OG`Rhj>q-GpP#wo6dZ&#zX3J7f8;SM2j%yiH76uuW;8RLLuBa;pnKV{z6o4a%H@LObMjn|h%-Nmue7Bub^uiLw$vT;A=m1S z0;|H?mYps5DlGT??-o-YGjtbLBuHZEDf}+>f*;XTboil(b6?jZozeW~@+truiyf>t zK;VI$s>CJBMV9kN3y*+;nH$YTUX5oizJPUB(87DgZiMHPrvnD{v!pL zzQYS#E=&2vUf3^ID&&xagRXCGI0HN!KJ~NdxkqB{wSWfT&zb&C#EpFgX9qs3zj(33 zijDvdhn;G5O3*C>2wda~t|<;n^y4JfgzTF6QCZ%S7(~za5X)ciI(uiYfzi?~@9r24 zL=*q(&!)Y<7Lr!@`}pUx_{6haeLCiZY6D~DLt?vLXwH9(g+L~&q=I zGgq-EmVBZ>1>6X0)4cI-lx%U;SO|V?d zquT67PSH={m+Ep3Zpm>oD@+yHu?Dt zeu=UgOZGXjHywq4P`Q-sNx5bR7e39wyZx<5`K6F$;c-La0rD@OS8_tCnn?3-vDrsz zsMPcxP}BJ(MNMqr-UU-8aeJc(#15(JqyE3%_3$hkgC13JuQ-KG8F|^e8|S z{XSBexeLJ`F55)S??OxFbt9nz5j$Q(IKYB(IF7a_ZrEK{bN44#z}wnK;RPcU_PeD{ z)nbT>D_?y~6Kt|SB0X)2tV*3QUS0~t4_-N(6uRN=i;(&Xf5Jb%H@9;`#(l@ei6zV* zH@ECUdVRKOf*(D60J6OV2KCr7ul#xTr!V`K1e^P>b-epveqASjXsJs!hzhPImA!(( z^~Z^+7-Yr*@(u0>M8{LQFqxR2f|2igxBNwW<}m4#ekY&`!8LKZdZ)x_`*Mb%oT^mh zP%ciUu8O3|pkn^YRz^+tc2EcOBb9#UYS5ojw7LC{ z7Ce~a?TH(`1&H!H=op84STId90EjC??6%Q1i>E-pBj4?)7w`0&i2WyiPW3-#Z9d{d zIFS)4Vk49{`Uj`TG_LR1R)FukZgtZ8(iLt5}vwIvhM14Hv7 z!X$oKPzLqxOam_;qhYnWu)?8UC(7=6=Q$%0feEa%EyXwiI^eYB7FIP1G|1}bL1q;9 z{#y6t_$CH#JCDF5_y(vrAmjVt6;psJ^L}B5X7HJWSkpTpV;nU1rluDQEX|`-P(a&g zqLN3zh#QxcWe-1;koOiA9EsSeelxOQeJw_A!XO%?jO}Sl16xTkaL{i`?m0mg=`U4? z+188N1>d7@6*!`lBB{fx=H*kMeowih1gar@p!47&*0G#%pTjK1v2uV)K?;@Jmb#81 z@r{3uySe8R*0Kl7r5d)OM)WyWJL|@!yhlxm&c6t2r|)!x6NcWJM+d)wizzkv{vYPv zGpOnAZ5IUsL}?L0>4YL80zry&2t|r0qF|v4(vjY~2_PWSMQJKUnuU&pPC#1dL68<{ z(hZ?^NV0!C&;Nb*{;>ClJ?G4sGs6rY7+_{)t$W?;y01coC4C>F1Q#bNhdo=FO)c5G z#T1;6g3QDk_1Fcwf@3S|8>}5H3Ys?X^RZi>OHZ7hSZd1rhnPXDqW_&w@Nx2az zR5#t=qn@uBnpF#?oQ^;KPV%c0ADOw>{t7JE`1f_##Sdj;1(IU+jfH+&B!6U3Wn!>eN+|k5s#X>IFUiv9gth1T2%ggKq!H z**Y+pZ0)SL01VI$tQitLL$Qb7C^M$o$E{rKF^Or9|JKISqrc}UtcD6ll3k&duA126 z%o)pX6vt4zRX0xZ;@j-nGOXWsz&epl#0NPfuI=kI@&pizM>vXidO z7SuI?&-iTGjEUK4j|blS-}f$|nwFS3ShPWra}_(OZ_vw`p&$tu! zpY69NOUNq$4+x8Cmdsro;$siABRUZb?kmT@5OYB!C9llu9`VuSD(OzsT`vWjQqr&a z!M~G;%BR1N{SoBPOB;5}fTG|1#SVU^oy}eHDwZ!?orvfe5g95yMDL9X^$Wop@{eMh z+0Bf|z-`X)5b@Ns?j9VW3L@q)f{%*I3duwGvK8l}({If~1Kl#Otgu8K=qGorpKy{L z*{ETGSfh{tKNWyrlds-+*Eg)SmN5QFVx87wScQ(|747k2PHRL$@sWnoZ&@IJTfw?8 ze_`%K1B!eaVN;BKZaMBT(c)UvS)xfd^FrL_7?}L^wt-zD-Ubx)(z=mnk-esPD@grf zG9J9pMa>WgKKI=k6R$VT7|Y1k5-E#j`l~0_a*5xjVRq$>9Mpo7T2Y=NQP~Xin{v~Y ztN}_|ZnKT0QQQoxZ*56#A3!rEjBrN&;5`pIMeJU7T{Jgkt> z>A(-5Oy%9br@R_!{Z?cVmI(KIP!Mr?qA9LSDn!^vxFGfz{I`Me*w+^hGAG#^s3CC; z9QO_XEWd!kSgZABMK`s z)i?wpEMyk1vi49Vuz0A>gm2&d(4%jj>z~%2vQxrPLdhEvY_z==& z3CBUo`>4LJOXv%3U9bhQOVm~LK6l0 z+z^F&S|3~P1sY*m$ND|)otM#!3*|NnhX7;Fc?M;`tFWNZOs&v$WA0fjJzrvC=K6Mv z{{&&iYrG5gg;Hf9X-*@pa?I0oCn>Ly!t3Ug-)uxfiP&;wN)4iSl4&*Fs>|klOAVz* z?|eE{hR*Ye`Wv0eG{taTw)afi))0#pRjen+8nl@>>F3&3OH=~#JT+<%Cz@>K7Cz>* zwtdl$)7a`=H^bgX^VrsvYfZDsw8-X;k)Ai1?xzF~PB=^^eZtaLzrRM|{u2gbwAZ6- zF@2oNKb-o8I&Z1VEvEd!r!DZrGZbF;>#1wOUioXX27%)?x!{sh<|2@f{`odabL~FGtvtv56`%Y>uJ?c^6>`Z`0WN71W*Rl!GCpG2v1*R_yvsN z(Z{6V*o1@};cbn(ZN~G1u505PX5@|oHdk?M4WdXrrEQWtr9dt~jIwaK5ibnikNNyfV=8{j zWqsk=UKzFLN*J%)Wgu*OP`M~oJ-c^*(}7E)4N(Gu1X?HLZz>C!Fma)5aH!jKNu#oH zW)d%VyHMR`Vy>hU?8+{-n4;ut-~ zh%638;?Q=OF(4|{hTo=~#}EdpA4e{Ez433eX$!P%G~?p5%8D4q%tIAUbO!x&>;6hv zfjCtwG^ay69AUzK7M8YaX}c-j0K(tO{PeSt<`?!h*w>QP?UA3a`6(?xDUUz1ywu?T z+;5P9{M1qR;YR^|T{UZ^7FTA){aCp1wX%fUWQ%WhC&R6i_cS0P#H%Nk(};tGt>pm1 zW+CZAThso$`^|yB1KWqeldDC488(DFCc1^243xUZCWvz5jxM0f9XM3uu}++o_ZMC-sRakBp6 zL0$y&te-N3lTED%2}xf!zV6eT0qN&Cui&v3Bv%tSTGi-!@qSqJ2Rl3~ucFYVp=||Z z{BkV;Sa9Dy@6d`wi|y13gKb*J!`ZK)rh}xRuq8!i$jt=C0Ms*h{>t77o70sM8qV(3 zMGxJ`=O#*OU;Q4kQLAik4sAfV87B`9zNNLHOY%qEnnezzwAgb$O~H|xnu14b<;Eui^=R0)KM zLR&EQG#HahU~+H5R`DeLxz?bLhbPDkeY6-2=Sv1Y*6*4!cX3x3{Qkzpt<{mliFWZ_ zNj50Q(RWO zyJ|j5U6`>Fvy-gosNeH_Bkh5JyGbq&)0E=)yvCqRu6mm)vXL^AnCYgl8^d;-e(5AP zZrs1+spB}GR#Y!3nI`8MTRkPOUF5yBiyXtc1SmYgbux;8?Q9dt~?tt@&n^g7bHG?*ThW4K+oGR4<{OR5idF2)qfvtf;aWn!fPouNW;u%%b z4l@h+a+SHA=0VV$XymP=+_hHNUE-y9wkHCQ%~|^t9Dnf(Y3T`w?)k8q{+M4BW=?PA zQF>UAOv)>%B>rMhzU}bu!3+sB%b8QaRgr52eV1Ka^bNqr?Ak}aSjygok1l5u1~o_PpORfTiS9Vp8dns~t-*ek zP;(QGURbWU%kiBQ+g}ds}S`t-}D< z=2T%z%cTie5ax{rNci!q!O6?=Aw`Em_jEnDELxo6HLG~=Z~o-L@`x#!4hn|zshVu$ zx1b!CO^W$^bAEvX@tXdj*pb%ww@1CX- z0b>+ygmyd{xH2j6MiX<4aqNh9&>NklZl?tOK)aAcw6ia{fDF7%7IiVCn!kI4g(2jM zwqRrDc7N``h38|4JE^~AD{XGAubY#*XHDY}{xip-02q_F{^uJPnRXA&G3>B#EHQ=v zvJQ7)$3_R$Yp?dQr9gm3aUt0gy1awt1o&^RMZivLMQIvy5v3+HBIS06$E~AT(y|6P zFfA;EkS3o;G|6IZDRUa>-O_ha??U6L83UK+G&RBH3AjFA&m%D#MO0jhbsB5S<*{_+ z_TQXR`E7Gqm#*;}Jb`khTvSa2vxuONmYDii(&-#m6naq;=!UcLOgZ3vN)z%S&M`qPfvxuG8#pK0_nWH~`*8c(p7u}3Q(4U2an(^Tf zp*3*vEJ8N0IpC&zUD-D|5cUIrb8XOy=?yZ~z~;1N8fYLt0iyUBKlSUkOG2dLY(L-2 z#=S^CDa?;~4K^NLe2x;k1^zv_pDhT+a$4`w6J_BD`{tShp7P7V74_0EswKo4Ur`3t zW3kfr=*FQha&i+@U>+xIoNBy0Yppuq%)M@)H__RUU}yfSxY)s{*F{dtRhz*Kx*RMUN@4xPEGm` zPo`N|H%Hlnd%A_4`7F@$?n*w<WV|=2ci;U9N2qgL<&SIlWZyaxW*<65iuTHn zA@O*&&q?x@d?mV@O|EYaoV6z2M0C#{Id0XgJ@ZC3dizK^8+~(5+QBjES?Wf%&FI)^ zHt^rOhJn=a4;&xAPt7%DOSR8)w_i<&<}kEQ>+C-H^o<_^;Z~q(qmaL#_278}cF12& zNDHh;YVFr#LOPs`dz-xCv1a3C+g`EhQq+iWXz-mVi56q?>@gj*6Rr-;r5tZX6aKI$ z?6%J3fohd!QBE@`dY<4>ol%OxphDj-AAMe`QZHkya$s+H=0}us1(6gIj4oU&wPDXg z-7Z0$OhpTWLdN=W>{))~ny~PCi531)R zaT>cH%ZB*v z=(F~8_A1!$ZRr?3FQKZ%$E&;!1YlD%!2U>7*{^^09Vj2%%=#7y zB!;&iwmkCS%@SDB(Thu%nx#Et3eePyHsA3kC{3kw_;pkO(%h_uJtADJvvAWZ#A@Y**mvgSvQ=W2Kom-}H-r7Hb^k5ZZ1|L%3I5&X zo@Mu?lG3(wB1s2O0uYsu83(W0{i(P9l|INJKq-BVPj*Ye`gJ?QsG0?sN`x@dB0cE^>Nr@VHuCzK4ToAIXIKI&&Pl@ofUyxZJkI`f$*wCoh>ct-pT!C4{HN zAhd36yd4s_Gj&;jrvC+DPVUdr&d_1tmT7E(Pq-OrKg)>36 z=qXUp(1=_N2zTfxA2HQrX6}AxF%`*iJ?oKa#^XF`kP^@fob`=~{6D^7xe-BUO=FgE z=L~x;M|)m@qc|nV{e7JGsn)kg=WUH6JkER6a8JbSj~NeQXX42pA0HPL(Al0en8o>% zil!>b9UmKRPa_uPQ&1;m)~9m}?xWdz?2(r>d-RCsQ^!yBJVFP_z?nzb{6&}nQ^52` zxD%l}p)Nq|QYH z`+ZGYt0jh>a-ufg2Gj_Pqu=QCn5L<*#8pDpK-lx^_52uI6t=YL{RcZHQ%Se`E- zdc=;ex)GZ&kl=c%G#(e{>jLIvdm#pfaDVQNC?&q}qC`Ew(UyV!j8>~Ej;oph0l!9* zV!-`Po!xLzgEePG`&FZ@^%IdQzP`sI5BXzgnWX(HV{V9Xyui{)w@1v7&T|Rg{q=jd zY!tIEL5xUX#+w9b?W39H^rsQ7X|>Ub@WvJ|>hJRsHj*2<>+_?~nPUk6Is5TytB4a$8xNm4 zmR{(wx`e0@r122*8r-7kRWw5sBC6E@U8HL$KoAO8K2GB;dapc2_EEaoN!v*Nc_u4G z8#@=foo1^zw{uK;7u-tXRC|Y%^k)$XM0UY!PY<=kn6qp?Ve7;oQ!*abAxtk1dSiZV zwK%^Y7rb|_e=$bMA~0ZI=e0!uGBo`j!|>kUG)>-tctb0c4UD_#7R4wJlnSK z#AkG<@xAJKLE1pBfITv|+&)+1}M?irE7 z1^c)2yXX`2uMrl95h(Nt$CUU<_ImtTH`2W&x19X}@$IIjdM{^Q&C8V%$;n4Fu_@+= z-ID$we96~KAd75#8P3hw(li4PuMVxN8*?~G8_YsCk&;NiI0^E1Dl3ZNMebkH9-|ij zhPn}ipU_SEC%zZ9Pe6pa4&yfp#DkC4$bVt3aM39}*OWo%(P{D^bSku>aDJnBqRQqp z1I-6Orzxrx@@^8=2&NaBAPh@(go6S&u|%^uRXstSfd}RR#Dl{OyFhYHP4oQm*ysVf zlWNH6dmTMq1=!A-Wj>4|fw9FdzmayV`xr|AW%_Q;8D9%Ik#mE>VsCvi&mX5usvz*K zK$LxG!{eE3UpuOP;fXkSf{nbHsQk{eAj#iujw1=EiFkg4`(rd^i{&X701Z-oPF@V_x)l37!E!xXNLa4)}~{u@{uM3O52*;P$32$V zYo=fRY`-JgkjXD%mD^=7VJ0>n$T!@ zVaDGennfeC#p9~A*{4tDEq60_q5gxjdpamMn$Osh=w9y^0A4sYuzA@TWlp{&UHpv{ zJrzQ_p7L{ctIVg(h3x11NVtx~TS3ZFaegf34ghq^&(V5pcW!_qVkA%{Y^`p?w{uf| zGS?*uX+ilQNi{s+z7p_^><~?j@|GIz2V4C@YlY5-3xR2ai+nVHSyg&%#_Y5Pls(oc zvD}I6&7r2FAtyRrq!x>-MXCOE-Jng^Vb$>{O%~LMau6-Z<5+5PB ztnCpd5*OAZpB}3$1)L<}3+~WT(dJD~4^6(Ms$ezx=KMvrC{ zle`sfHnjsyPy;&#*yf&8G8&dMHe2;UH9SR2W4@j`>a>Tu zs=*u57HxMX<}4fwS{y-+{*NfY=0eX*LnPI}F+YdDmcY(0H>GNy)BI#?7U-wb{sYy8 z2YT(v>o_!?xj^NQ1hK#;=|9}wlQ1)Z|19&!1?gL*aM|^}v7csXsD^XF!@+&){=P(E z!4H4#t0ErPs+>EyZ;bfc|JIJp1_~#p(Z)oHijR(IB=dL^A7#qn;8}?EEK(Q8bQ45q z4E?<$ooJwJdaa8bAACBvjQEiwiTU{vWc|JA+fJgG9eE~Tot)trb?`au@%Do%Yp`xN zOW7L4S`(DCMH4TqYKZ^j&XrGrqUcrH`0f$xX^0b@DsmV!NW(NR2z`IDjj~Y{kzI@4 zu5H{bpL^PnFh0kQZ^6M>>_qjaO zb%*?OF-DY#8yXQCR07LX$(e4!18qA(GA+%R@x;9~mQX+V{7jfjh$-9eBN8hYaJd`i zr1~E5e2xMq7_^XXQ?5~A!cwdwSUsk_HUUnK1IKd5U%!`#pn(rfMNGG?hkitsy#5wD z?)XYOMTlor2vQ=Js!n5fSbFXOgXF}!3%10JoR8B2?`R{Kpdfy1p)nVu?&`HKz>CE4 zm@%|-N;_2W1ln8lRXuK*IJVDH4W!p7kd{tUcHH~e`k-~B@%#9)f*SGuGZH(V?5Rw? zusN`t9YX3|o(Ulh9@59kX={$U>#5Oj;djWz8H#OYi$LSl_t~UBeg4yn75XbtFB<9rv=6*qY;)$J9LTB`*DeC};EQCPM0(CmfM+46)X3H=pi~-reXHWxM;$3@eYeN7 zkW1`zUz588r0Dnpa$<}Kk*eJy}o5mmh4$P!^rlI{R4iywD0`Bsz6>m%?5(6 z$&1JCEN0|)g8Blp`f5iM7Sw(USuY=n$y3SzLj#I1^UGRdZ(492hHO_Zi+Jn~wPp>@ zUFNJGjRp@y789-6vLZTR^fIUXkaTy&K-=3fqKb(YKF<+7+CZQ@K0>vYkmOb8f|-PS zQH0Lu4Rlzz8! zR_U$fb}Ki9svI`EL?gd@E^J9(<8vijgZYNtt7atjf79;YdCnPi&Xy|)?DGD5X@sZC z?)=KHW6XyVp^hbf; z-F~{dC|TBlN&>KZ&p;^vvGh6>H`2Mwsz83|ZHt5LJJR~r%pE) zn@Bc(Di-%9rs2`%WJcgipZj^C!N<#%FK-Mi9zr!gMxQ!D9Apc&3=Do9oxUF=E0CS0 zDiyl2&jm>9_W#qk3>z=bN_w_cz`&t%5uic^W2XL)LYg%%j%aXtRC8dyvZ}|g#RsS= z%|7g61k=5cpNlQDGP}8Es7@^=DDg#ds~qwvBWm7QH1Oop-9zuV;l&!2ZQrT5gCY!< zIn(w{w-@>B#ynQ63UalJxqHLO1=jLD_t}02<_dDs))R7~n~4*s9k&}R6e7xq`&h@8 z7YHl?`mthd94>3l@5hXCvPpi|Uyv>)T5vbrY%O|2W^Ng)P|9 zKTyj6*4m&9bEaTnpr4|kG@QKErkwzfduN9coA>$7^pYFlP3k_98-vDWz3)7Bo~TsH zRN5G+VzHU59m}?R*TTNCXu}W|IuBJwQ^YO0laHl+T=;;upnE&f{b&B|{sj@E0GFOU z$iejk6l|v1Q{rHX9GNgeS>L)O()vEf0BO` z%GQ^SXfVZ7SnMjp{6awMG1PDBUj1T*FL?DOv+`EXnxjBdR;E0xa!>Jmmcu48)?f~g z6Fy&ticzq?T+WB}%Nn3^8pazlc2#1eEt;nN7X(!Wqwp;gcvP$L(A%kFG z;8hc=no2D5No*wRDXqB6jjH8ZeCqvfWB6aSylj-C?=w)#7A$t^}eIMVv)=3)bRlZm!M*MFMLDVtXHy5ZV*gl*z;xyh*vHRIbm< z&FhD+s(Ht##>V4v@0XT|`BHu9xEk$K{U@?(W2yi`raGkJJTM*XPWcR&w6J(51hQ(- ztkqe3c`g+YZlnO?nc|VF(47)yYe3_ar8*uuUzk6(9FN3xze@k7*Y^bizNyao{FHh3 z0k{GH{n>b%AxcI*ZR{5`)_Og{!zH5RMwYWly=}TEa#S68_kw(=;@0)4t4F6D(t^NP z>nl${`qFbQp=|UoZr5O+ibzMk$=j?%iM1aD+gp8ynoa_8X{KU)+3=0yo#kQ^>Ad-B zolNfhC_6o&LxMb?h^H#7UZ_Id<4+Ki`Fk*wo3BJ0iOF+Dx^sktD>WOVbAHN-#TqQc za0RiU0uQ6XJ~j8dX{Wr#sh2Aac3UXdGVc*9?1D!qKd=`P^J4W|yz*B#F%2%*R&kqp zq7kfDO>-a(J7l$-r=UV7W$s5CtsK?mWvv+LIUkm{+~{fr=38tFV@ki5MNjU$EiNJB zakwAGv;DR$Xw#e*7@EQMDHdD>&x!Yw`n>;c*B2Km-DiaI`rt};1pIv~`}h>b+LR4@ ze1Q3#=%GsfnM%N)!uF8@>S;|!LVm|1?x(gKfSF~*HKy3|O7_CqRI&ZpO&h}rTiL?5 zqBmdC{rYyp%&eL=0Dy0cBEAy^-drw1*qz}}znl`_&w;1cf6CYU^|Ru&s5tu4ffE_1 zI)Le>2?@fG<2UIBohnlKn7rj9Q;0bqrXX2D*XOHkg`bpY+ zdVcfa{p!OQtqU?O^m$T;iG6~xAB;XZqn_34QjR;ZJxPv+4#^j+uvp1vALi^ZWwo`T zdWB?m*C1Rgl!eKh*eXWH%_JSj?~q&|I(!Wv)_9>JOC|mq_3|5J(Zgx+e`f0QztM0( z?_i-6AxgCVLakFPe(T|TY+18qTmX+Jhr`^;5cidc%Mx`D#8r#0z`prz(nGTg`E{%~ z)u#6`xKz8`2UnK~AVt~o!BS@mUN7^}Rtc|CX%dAa%866NXYD@IHgW$J-LbI3&zB68 z8_#Gi2C5r>ek>H%<+O5oMO%o^m`5w-v#-#rI}5X2HDCB&d4NNI@|&gy+3NrEpz=}j zfQmS|XE%~%WEcLIO<#4k=_mYZW||)w@dkIN@5*9N(|{8q_k$!CI{9#FCy2H0NMafN zfh^l_Bry;D-m=6)&gi%!O0%;(=nN@+i}NO_C0g(svmVg`#1 z8;mS9a(M&JdDg{D(`%eH&WF-XrUbW84sS*xdUGL+ErrA+0Zl!HyWr&?y!H9!n90k5 z3yc_0>9^kVj0#;QB@XZ1?xbA`JOTS>v{*d$aRDEzd4$nQX?+L#jV-&A4NVWph?=uhB z_%NOTuRZEA%3-m2*6dLlodIA}>Y-awBfqeNWmk7(h3f z2m&{8())p9=OeGCMz5o7_95-*ZUyr4DPquqd^by3=nO?0gbdY@`uE&R$va05!$G7B z6>n6QQPlZ>;ApuynN-F6=}>W*@P_|5BZ1>?*Zsw2Eau=67PaUC4R^|y`Q(Px#ebsL2;#Jbfar-;#0;=bM4+%us_cS;cAr= z9eX}2EB#i$7-={6e>FxbeHr+0ROwSPsMx@R-NQzsCW|l*^OBLb;;cmO>ABfv1s%G$ z^(y&#a9c7dx3y&vl_34w)y@wfkBHDL#OYeH#=OCCkFMGH;g@(9Vi%|SsNDFm^x420 zP1aApk((jwTb~7xtFs5;zZD|*v&q{>64?m3^<^@TZ$x$Fnc>20XSsXd`? zJSUs7{3psEdzm|PCzbh2UNBOP7S|4{08bs~Q;+HL+?8W&deN`|)X!5ErI!g=t&19$ zd0)hsY3K}8<|nB9kal~&!ddLVv9gI*CQ;z)ic_VVbl?3S&0T7_sCob2Gj}<3WKBCC zx-(Rza{969KoxLAOuicXX@pnyQ__fla@eaMsV;%+hCOm||G2yG0PZepDdiXA!=|=N zu22y))B6|&t?#Q6)5`5o=wsR`*hw~LSQO@r{=D~J6?*jIQ`uXY_(c5|#A>gOo}~o4 z8aYv!zWAqrfj>TF+G^essPL8uqWh=j;`dT^&!wMP|32^a;jHNgo=$D?0MloYShIgH zvvw{3a+5wtC-cHL&^ach8~W3dcNFj|7>#ABKEc%Gmg=M8H|1UJb2&i`UUVux$sJdH z@X0#S%6G!1?xFgD4 z!S-*?_ugB7=|g)QpH8J?%bx|`6UQT^eUKx*HyFt(jh15?2XRMSDor;U!DV~3ZEBSwM-Z4cBQ9bQcmd|RSMNP1mxO(@caMgQSrOgV&v zqT?1{5m4j33Cs1k4zgm_B{xZ&uLQ=}NAv|=h(mh;pyB_o_R$@9sS@_smIG%hTryNU zrHbCY%e~y4wQg-;{5aZ!*daVCzVP11$-4`EZYnfGZGckg7(PZ8Dr_NM zco6QG#C^uFI_x5woLQ;X|2?Iz7u4r|yL5NsXThDE%p2*N&zRVU=i-&L3OkeeGwl^+ zV-hu_d3fcKFi*AcKg^Xz{~u`JJHwt0JO1x9@Xh~M8u+KR>FnR*Q2O^@2n#W9U$JI- z7A0V;tza@-)}^JTa3P=GM^-VOt|H0KjvuHP{-LqW3(bY9Z-@qj#n z-o)Hzo;$|C?HT?i=Rogo3VyIsZD4Ou#hNIc&*#6kW>0vJpJ@aZw|6V?GG+^r!b^4l zB$di_e;M2pWHP?Rrt{Hr|B0JzU(^l6L^G{NTX<0LvdyYV9-AYNPTUECX znYko2Mv5IlqGfL&ezFc($7H)aY_=(x??Qe^YnMpeIs4t#`27|6{PL!EfRm8An_s{|rgu2qBaImW?ep^{UrW@><}8FBMmmStXDKAVUSYY{ zQ!}DP=hV1aRut3r4`h%SEQ~yf#(iu05|a4t~?*AW}!PJ zvpXg5Vec6-*1Zf}pF;whon+)N{x%!ou%3gg8O;XFGFwg_)xY{B8OS0?eNf5sThhRB zjRKr>6W|f%CwPAXw}4-zQMDh(wP`Y`tW@)aBrQuBC)Nts>2&RjM=I(N!W9RB`1a(DtofrL@SF%GIv|s&d-AK?3>=7Q<_4%RM>Qz1L-5 zMfzjD0k| z-quFe1#*T;@MD*sPg+j=rrN!InFU8a{w`ozd(A4d6O&Fkz=GVzAQPhR-~~5q47pv~ z3`&Yz#s#ZG4{s5GX9$FwZ}AiNnXU-AiUH`kz0XxEk%2Hl(&h$cjxTUGM=$~~h~@IH z%i%H?9%JEvo%sLt;CQ;xoD5gucB1HW<#2;9+#(Yr3Np~Kao{7|M6H--e1yD zT|H8{LsUxL%~j{3U#{Zp*=nDy@)#2bgM#GJjay0G|26OUrIv(G3?4a-eG*t^T=&T& zSI(5lTLk)EaD8B}$c54A$As06`|->gE?e-X4sA?b~(9iA|Idphys)+N;lnj3=j96IflUn7-L>lE3SO%%NDX= z4thcACff#Kd2y1k;SIDCXP{;OQIRrc@$?&I zSa+V>yBoKtqxr~CsnF6Fnj)`=#5qU1|S6K zViTcfM)e$S0fBmasU>!qr|Hic<|- zNLoI;xWL`^GFlwqld3*f4BVwmn<9yWp$(~;m;ZmD1j!0#>*SdJ`Q!cf-Uudp#WyCA zQFqPsF2X~rbVZYhm*Th zt;}XoAUE=;t7y(HT4h{0)Nr@9MW0Ra;ss+M zB$Vz~r61Cb@ELY4XkjjI1}g6-_<+)5A-OsMOL3yZRL&6SQS|n_1^8vIreHPs1sw2k z%OaYAaTJTCdqAOwdf>xw=v4t4sAAWfT5ePr%x`uctVqF=;{rg6+vXHO1diz-r^O#y zC8*fkk*5OU99#kc`fHJ3*Wv@ezH0_nbanxArkbzyjQ!F}SnDxDryxz z(ot{$lxvjsCuy)`V%cx&KytOsy(-ZOc9%+k&^18=|>FRA$4 z#j&Wb(s6LlUk*`kv3;beQcx@vi0oU2EDfJ|rIgi*Pbz8h2xP-$d;mhc9OC<+WtG2G z^g+_VW-~JF@p=)x)u)1r+LrTot8@hibo6pA^NO^UT56x~uLLxLm8fX_T^F#4<2X1; zTCK`*SUg&FO9NVE4S&mg!Zc3L^Nb6S{ai*yS**|oz}PD8*xnVaMx4r{oVZZ#!Q&OB z*d+fZ31d1?Ll4ZpBE0g5Tr&>d%!5pLJRB){m=oh6Et( z)({t<7T_@gi-iY*ecY3yugX|b37^MCh`1^ib}A1&dqCu+mE%N;K8?o zK7qj-=8`u%IES-@TKD(d$px()6C& z+OB42AF_|mlKF{n63a|^ck7Hj^xqU2DQTY+rvY@uoBP2FKryxiD(_|z-rW>f&+Q}8 zYYXE{GhG4y;dj!!0k>17pXvu#d_Fh8`jXPN5`W!DpCD1 z0b)3&?ntpe=SjKngw6p6Da9%hASDlKc{;jDD`41WE~`#=322|+5eDFTE01!r_S z2VrnKpW=mn-qQqkYkEbJg|H(=2?FI*MEd@=FO3C??{J0P2i68)_Fvmc{q_miwoP5V&&e3$0Y*HXHJgVGmvA-0#e_*^8-TvpRMQ9- zkezJzdsB2eDImxwWm)bKl&h^6K;6Xg`6}@xatDH2T9d=p6#=96gNKWIKYO$+Xu`i; zWa!r8xN!6|Nu7e_v8$8#mk@uw!l2!xmGaBek`>|3U^!FcbJaN_!%G(37yg^9lJn|; z;Mv0Bx}#uoszYzQNFqC)1L!)ERlaR}N47cQtZA6x!b#`_`GwOGrE5by@T^=$9$gP7pL+_GVSsMGGs<<(<#9X8IO z&fAm=o2@jAT;uapH3)zP2@IrrAK`7<>NS)ah<4#)ltA<5ckB7G?3#8t58Y39HqKVl zC!9Qv3-KwRbWDdWBzL-vXxEYrnIedjR|8=uI$4dr7(x1RRb`wOBrpK$%BHCFEjf=H zx!39n zfq2NXOZ?!Ls?fDMv38~k`b7G`-3l9?+}5h8`n6Hb)L41D5sScgIC0sNe;ikq#=u^&|HbHK5_%wm0sx^(1&c&%!dRA=7A4j6T2Bs#Wz$ zuZZmHPU%*YCohM9-?x?s%k0h#wY+8K+Q0oAKDyzqJQh15zu#H{;Eo5tU*+B_YCdeS zv=H`aQ3fpJRz}Wq?XMnxqG!Z10bZw#kel327b#^))>;MPF{DoG^Wh#O`uL6R++Nd~ z*lRKiv|6MK#VLK8)U5KKG)1@%liuD#TC(o4y#T;F31XfP%P})iCkKpc z&X%7j`YBzO}CY=~y@x9m^I&{nK<5=k5Gco97??r{%y4lVqHi5`ye`_5nJm zFIX|)P8{UJAvZ`S(9qgvjaIJ3zlDoav3)xSp<;9;BJ7iqLKj$y~e*ZdcSwkV5>xJHQG$qB(GL)EB5!ZNW1v9 zDwxy)WsecQVQY?Gvz!B(KVIBB=amP69Le8l=x?imhM2Jh0?+PkB#}d>%dQO`;z)74 zBr@AH_%J;UW_qqn-c_*l!~4?0TYaYj{82ZqhUJrLz=wA zF`BhtVw&65kQ$t;@lTt7#&2Y%qvVb!^#P<44(3FvF=iP>h|Q|-tEM=_g7vQA)^>*@ z=ZD>;GDmDL<>@Rs-I1%ijoB~NoTkp*sQYP?ck{6frm*=?z0R&zSV8r|@^sHf1JB(Q zIkq;%#y^)OvdO2vo>-ELH|H9hS(TOJcyIo#T0MF}r)T*gTsC*4^v91qh?-9q zHr^n0u3UnTi;lAiU-LR`A^qX6(3K=zLAiD=#4@4`&Lt+-<(qfSg+P?UV>4J{d;5Az z;S%&kfeKb`QAj`H)bikOVF#X!JJ#7~Z?iShe1*KZqpCmorg!;?L5hcpp+C9lWMc}k zK{{FE+CTNoN(v@T0^>CmglGWnVZW$8$qtq^bMKoK!xNBJL&vV@jhU0Jtxnt!$L?*( z4?K0L?)8qoaP|>2erJ#==}A!>v{3VLLYc3Q5As9&VfkTznx#eM3*~wWwBnMA+fnl3 zd$+nbJCrFA$3B((gF1@-9Mh1Tg%^CalGGyS*H%94gf$BrZR=|jFG{#Izix%MJo)V^ zu)8C zVla!PC}N6g?4uNwGPcM%Bq7UK(vW2=qp{AI8O&mq-$$qK_x?Wa$NdM~_v7|2yyyM7 z-q-cIUh{ml_$Er@rL)8j?CS%36A>lpc1HZhzK^GI@(K)o@nO9;(Wqf`9#e+pTjtfo zg?!f-C8-J%ncpApQzVh)4FJZATmjsaUKyboaT}cHkzii~F(BR*XlAv<6+dMfJ3ozBb z3Z`c84I!+i5MF;P$AUKAh!X665{%vnE>>WioV)VG2F)7$1jW=Z_l@K2D`>f>-aS_I z_`@UhB0m@3W2IF4#?{(0Q>doZ@vp}(bwO`hkE;&r!@A&tEcoBMuz%QZoj=co$+n1h z*LhA(otMKt)M)E#dCWF^lSJZBZ&gqTW*$tEEB42ggkdA~hK&@x%F0%8=?`0;%wEMU zUrx^&!Pb4tWQaLuTREp9(s3hL@XsYh!NpV7RJ%IgBBRwLj+wYZCg^vx9kZh_LLI&vP$!aFE34mSzr?ENddo49v=`k z2)7f|aqzeGE|!7`b|mDeN!=CC!m%vZBh?czLeEH?ErK8~o1_zIN^8FRNfLhmDOn!l zSnCq@>-Df$-&{Ed^lh15zX*HM?TRJdLz-Xp$31Quq?0`&std-@Vwiu9&tIXEl2zb% z=fzFWidTsv*lH!kd2ujVa!E2EAd|+0e8$31SzV4(29mf!wF}<#YUi8!fnQISn8EIY zFJX>V>qq8-mpBfM=4NbE>B$13W*W3)U^b8Mpz|DonF8K`Yj_xG>I`&O20Y5iB1Li~ zKeLwS3l!XfKmjnuwQ`*A?@0sm*>XBHEjw4Xoa33Cu-Ba)`OZ+cC7#~z-nL2B!2l1_ z5DAO1wq+DXMW02^UQR-acwqF_l#_Y| z7uDO0vm;=uecufouZ5rGZe*4VjklOyJ(Hp=6sQ+9=ZtOtM-x2(O4ox^!S>kh%TTLy ztc#Pu_ba8sO-4TsG*aTM87dlF4kN%l7#X7g!-(QN+r=Mmnxhye}z5TS#rw3{-4x7rI5(l)^YM#UVi837{plBb&Woai@9Z#asYI`s z?%cMo0gK4NT+8~NnFIm^b$McDg2I;a2@ChAo}=N>!reF~5_R_h777do*~1_ z(7~JMphq@Gh-DbjdrY%H(h)Pd_x*+GV24r;i9#L4)`;f?kvTh7g@be^10E`Qw`xCR zrS@@4(Fg~{`1dpgw9&x$tW^&(0h-usxW`F?a?|}Kh)lhN9T2n+gZ=LjUXoDZqvN7j z_{Fx*_cR&=vyX|11IQ>l1^YjYFRk#Sq!3yn!MKg!FP%>6EmQ=HGChrNdiSncz(1|X zIj_!t1lpj@i6vLl{VV zV;S@ST6!9El=cv>Rktl>l1_v<`?X3p_a3kdZT4giktdv5m5*Ku5mC}`69u5y8h^gi z%Y9afatUB*jFiQ(4v_q8fpy&1UYi2(-5lyK5|I-EEowiW#~L3Bfb3Jie*=%7{f5kN zim<;OuSaf`A~l<0za05=+T(UvNp))@;{K=NBDp3Vx|a1KJ^E|y8Pp_Gh@d3-!F0)!M=WM48A-P0I?E4}-RM1daQ5YF9bx-EPop_;}{#T;o zPRXbasS?$odbwaMBn+4#1mCAJ04AsN(L6G8D3G~3yuj=&5nGI;E*1O?{` z?+31IK{HtgvzSre5}-Fd+>*VZ^L{VPebkgVrEPWcgZ7p!!&=X5eE;xT)Yc?m%G-KL zI=0H&%`{yX{PAem*cj{yZ^~8&?k>2p1FG7EM)G?R1Zz`=6FlC-_L61~VHFQ9trFa_$U6M--DpXtrE)53cYkW<>}zS#+WW)>&yqxa>tB6**-9#UX|r zkbhwQV92GY9?i=FDa~`O@AeliJaspkPN>z7H1ZU7OZ%1ulu!yTxvcQj+38y};Y*gR z2^AGbr#ED1W@PP54$K8Mlek+VNRr9FB>c1;ZuXuxK7pH-WA|*x47m(reGYGh{Qe34 z$R+DOR({L2V=o2zIZ_SW=c?OX6ctQIYFtgHdTx&_3_hf=^RzT<5n1FN&lBMj(jjiE zC=ER6d+z%{^W^QN(gH2&B3ix&RhvIJvM?ib-#kisL<{4bQIeR?s03Ww8B2CgX>JH# zXcZdGp?;0qF?uXC*Yd0TTx34}t1Z`m=|M6@j=NaL@+u7#a|J`I0Te=6Mh?yu8$iB` z7Q0YBq8J=*wY6KQD&_gl0*k8B%^70o+#EUX#I2|Rssfi9DNbt+=2B}U^ zJ)sh`-u>0QrK!_q&t_2ml2>DIy;sCIy4om7&9>P!*PrL{Hs+X#>c_$h$#|EG!W%uF zTAHh##Y^uZVSQ-9`J;#6sB(d4_+oU6CVa%qVqR(TmW$~X>CmuN`*)6_D{ZH1Z)8mo z;G)%mX9y30W%x98h6V~=EQoT5utf@xM1F|E*@lGbX@M2yhyjo9-cpa`7g2AIOQ*eo zY|oKHX@E&QUrdKRi@zUSpA@SBnR-TW3-xS4|X*)qF5J_EU{YV|!+@@r?4^ z6wVRD9Y@t%lFA52EwF+1>PL0;az^THz3XEqc%jzCF*W(?{(pO|FyOTZ9{HS>2?mKP9B-&tyOa!m zLvS)gVu({W6ygy?)9c(wNZ!$}GVOsShWM@=FwP zqOJE`6HS2UPOzB5i89fl?ek?H)Kd4@F;X4>YGYWoGKAB3NA-rJb) zmy|oVOqZH}VPjjuB>cLe{pS*~+%Vi@TdG!oFE1?f(?L8thAE!utEs&5@TpYh1_|W5 z+Ni|&-k2G4(Ldz6ddHMUb)313j{DZJ6^G#N`p*Mk*gNFX_bG&v+@tTp~u$zX@ut+wJX#_RGn< z!pZXb_1gxfrB(8;7-%-wCp+5i0fn%>2zga=y-Hx>`z3xarCM$=0gpZMz|W}pw{}R5 z@kLmn;A#PZJn_QpnGymnnWhAVCi%3|KYz+M_U+YG93gBv1(%U&y_p&VmaqM|xETeB zy7CtC7yC-@;p<02&^LLVl`wcSaYG03H+_tWLijvQw)U^*JVCQ12MQK5Q0C%RDanqC z7qj=m3570zcO(ly1-Eky<)(>eGBB1Y*5dKs11L9IquqB^mwW zGWEeik-USYjP1!xr!Yb$@&cJK%wOT=NhUUXjJ}fi1*v0L+{AVxtraY$r3Z*fCxaxSzv*qb^P>mfW@)|eKp}P?k&?r$C;9=M%tuoM-8PS zla9{c(G~j06D2ASu5)3o5$<7OFyPDHV0LLwb(HXpY%FVgT52KqD-mh;DJ&egX9+DJ zv#nsofhlR+eVADYP$WpggcjxJcxZ*;WYt^`g`yf(JK?oOa=Mj|JFp_H1=X*%e3ls! zt5W{aO^3(>cwOO3i!s~cIJa;Fk}Ls(;oLzK4c@iUt3)ns&zBMjXXv`F<|h46Sr`NW zvKwmU6LPXfo#)n=dfUM52jJt6SAw;!_zSZob>iWpj66%+kQbBWtQIOte~h6}fhbi@ z7#C9EfJ++SHzQWxtXcio;dbFo%M^In1FG zuwv94&QY-zD;cePE%DFDAbgK;xbHaE=XBYTF0JV_oj~SZIj*S|l;oFYkB(}w$JK}Q zI;qjNhr*Xc!w0vf}U8T%0EFaUC7IXq6Jdu?hEZoIJaA0=h=fUPjp2S zdF^tpMZWA4n~G+vky}49e}Zjx9!dD<%7P zBUQ~(FLuq$<+;E85ESYuMG%fP;}jFg)~rd+TcpCo3nie{Jyz%0(-iToZ?_IGtI{7I z0OBF!RJRIZ%7!(je6|L2aN=e3Z{MT@&9lARu80j<>mImm{pJxgJJ-UP$}}NFeB*s* zXPkzYubu8%_u9hU6((Ak3AU(O;rF5DIh4&mrqdqAOy6})bhJ@V!~WJm34TxC$ktGLybM z#=EdPs{GROCY>U##Of$xwMa-QjdPmQOEWuENVRP}+zT|`jmJd4C62acjoAaV-Zj?c ztz8I~TGNYLs~uyX1gV~FJ8nzmXc0l7kh5+1?M1w$?l$>~fIq{LX= zKJ|~fl6k!u8x(qSdSrMeUN<@MpYinjqzOukjl>^5f7G#-$Nx;8``x5Ij(qA393@(I zBK?l$F>3JB)(fmWB&v*EJLV$~1JOr@9KOJa`*#g-nwd;`LpV~Sj##=dqd`#mTNXCv zv1yV&z`HhK{*a!TZ6={#F>zoEJc#g0^4hf3q5Ev@d&jjj|L57d2#70!elmlE_VXk| zf(_^SK6VYb;DRQ44xB5jTaIr*kA>7Npp?=h?f>7M#I#}<=d@_^Dwko3{3Ik4Oc^8Bj+15yMt`BfpZhfup`lrh`QXGVx=W~SHIwDHw0V*G5 zjzZRE*;t~2D3XF0&5q$_B2XOm8KrloxyCN;7fBf}tiw^&Jk>w*pE!-1R%z#C@BaJm zmdV)cQ%(@L8QMr7R1R(}I6Ro1(Kyq{CvkWWKw6+H(h<4HsV4yyA?*ghKN@oT4f!AX zD4#8;SG=0MsucOLHc&&Y(MTj(1(@or$ z7YscEv~(qSkJ44o3D!eWVD*kHmQ)8s-Ch_pm6;`SjVCP4MA3Y8uQh3Dq!IO1rwce_ z1lCZ7c|Z%r9j~F&3Xssh$W#-g=6=0!c?%rbdB2~2!I=Xlh~JE3H6}cuZk@M1F?kW2 zXGjvbdb-~gYt+EGpk(8VH1=c*Yv|9y3JlK-kNBcc`t>E{#+Tvsx|VgCS!`xR0l z4w|*yY(v>4fFiIFtNw1+kFcl`7SI7C^p4IfYy~eqYCL%7AAP&fmXMT!fVM<(fndKI z>d3Lng^DltV=B(ZwlV7m@Rx-8a8z-#4VYAYs2*cbrt!7peA#wV1kE)^QPOi|*keb$ zWP*AtF%dM|cQP>(hXT*NiWhHUSi*hea(1JV@;oVefo5=*9XRmXOsfQ zKy>+_e9O_B+%_6qO(@J`uJob5e>?tWvQbD^>4ZjB^TNW>Rm12uLpS(#w(nq@;phV| zl)ke^v|&B(4;@Hp7?OOvmL#%Mh{%HFk44yjd^v5k2i26cy*GUnnTfTqaQPIUi*D>| z>6qoW#2}o)m&BmiwMQ`&6w0 zVWqSDkF~$r_DYk*H@MV%FUC{)#a=g$3pJ9g>w_YCl~E3*b!qM3fl(JI8~l#<7ES@H zI4B+G7?IIoR$JFgtL*!-$-?)`uAbST;*-jd5$RtPT92K3npP*9LRXOu;rEu3Ry_&# z)m?X^TD>rXp9;Iu>X6N~b5C?hVSI~xmRBqkE^dEup~=+TpiuH8xPI`FgTZBm;qWOG z4tpK_{V0g=tA%sOUR|kk`sG^MuLy8y?_$x|jxZ*CQ}y77r9swd+2hlmO%d##ee;Tg z?D+cCtq8rDhOqszXJr$?KBy;7;R)2VL0V*Mforv!#cvoRR1Et8#5L%M@VoXdx2jx8 z8{}mSnW zy3%~)G*4@E1j|YtL0`qgk0^AjNHmq+jx5jcq@s&i#YEP z$TeNqA$YCo2$c-%Iu4`&563i_S`N266&kLzU?|U=6!zet-(@b7ua?|*)~&ynwlEev zo!@6a{zrQ9Z=I;fXSVcDRDM{xI?~O-KodzM{Z9e#OJ$)P<^Qja02sN9I@W}&f|h4q zv>Xz#`qNiPQ6jK&!9E09*02Dw=(r41VyGk;x_;w!&bjf;HNe`9$GC6~A@wc0TazsR$*9^JbU`q5*co$cW9pvn-X7d

      %_t@b8(B{5bVSZQ9$<#-e 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

      $%uG$i3`8K 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%0An_ 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


      FJU3l}6 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 pg0 zgQ&mrud)E2-#WRwpnN_)+$rS_B>Xy;7gkrqviTjX+*Z$(@;}ENP3j*S!!m3`k~fd3 ze;S0pWD`9j&g(WlFSr=bt6ieur6X$N*U8u{NL#nRlw`W~<9Bkj<8ChREv|+-={##D z+3>~1xxhSfC9ZbnTU7&0HB>I-sn?$H(&;v0g+cIHJs_W;3+ou39Qw0D7Oe?(emtrV z3QUH<7o|y0RLLmgE>Kn3pnH;PuaB3Jpgq2Gg*Wgpjj!5OQI})~c{^QR1&R-LGpc58 z_sdx>1$xigD~3vLC$zl1Eun+6j;NW?9hpTfYd>piq_B>J1SwD3ssOB%ef-K`3B-l8 zV8?|TADe4V_Pe`WuVpbYbB^O;=9j#$rJutj*ah{|?^vazaHQo|2)l4-l$H2;!d!f4 zrY44arrQe+q2O=6**?_Qp7Q$r_5Dk`xw^tB*jds4T5fwx-euF+zWAME zvreX17^O&NdV!~=uM>T@YFyq0IV>eSR_ne|f4ab~vI}=4$I>i4TW1Mx&Ea?6NFbDi z+X0X$YU)U^$INSs10dl>VoEs5d?{WHENfSXDcrQpH01Q6`+|=3-f9EYeo3y}Ts$Z( z_SFDilv7M538F>bLfKxrfqL|-{PsMWY~8&mT06XHT$Kp}`v17I*Y-aFz*ljg-(TWeZ0r&Z&#-Qz|L2ZlB%D+P7^`O02~uy)1$=+Uhi0xIqb_Zko( zqx3 zcNG}&C03t1fe{l_rbHNrKbrpejh7B-dUR|P12xi`q=Uc~V*p<=bb`OMga||MTApFL zutNFZU==9UWjXe??zUqQ(w7R!s#yjX7pvSanNR253UVQ_J0LAV*rQR>@#W?5SE^Kd z_;LXYF*T`)7Dc;r)(C} zYSWysOhCCj{z>dG%vVQ2Y05gNWKkLa$6ieQYQwY5^TMD5EJy<0PRonkB85QT$ETK6 z!EG5NwYw0TP%{#8mRd3HY2%yTON*)*pjO%COL6AsguX7^6{~a+ENkD*z$r($iMHj! zFxL6D9hAmFHll;K1oL&VWPtV?tJt0}1eKB6xCeQ}&bCvP$7Qfz*H#FczC>llF&lp= zwn9$H&s&P|f&zADV1|Z$QsWT`JKS#MqG>K-k;EPyo?*c6O-rR3ss8Cq8#*3=$|jDq zODomG6jsr*ATtFIf)@DWF-A7E)60?Ee6y_^>`fx4^eguXKh}&SpqJ%0+-d3CDWhw2 z!XvSiJ{H<5P5g&n!=*=06zdpnnt1qAXXRY&moGl-c40n2(dIr7zWF?E{fETcEOLcP zrkfa|Q~&wgJ4J)Hbj!WZn91gxcSPtWr~pLJ(84yPb|2qyjM)>*S2=jeDz+m2Zj5VB zVZLf`qja5bguR)Vxt(_2el?EGJmAD{ANc(Q=HrB?fI2yXbE+3>nF5aNR5-_Pd9R2s z$~A`n$pScf32ck}Fe3>Sm7`{o33Xy*?L5)AIQ*5@{?}ZuV4e`0_sd(K6y%|kD0fMDc zzui)65aIT}p=5nqBdYw0ZVmg}uSEvZHHsS5ytMLR5byHPm>_?o1a2k{RnqPg{Eqrh zWGF{3x9+5O%z&cz(nzE`w<%Z8+{~=Bly@?Vr$4ghAljUS<6xHb{Vck

      GtV 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 - - - - - - js-libp2p WebTransport - - - -

      - - - - \ No newline at end of file diff --git a/examples/libp2p-in-the-browser/webtransport/fetch-file-from-kubo/package.json b/examples/libp2p-in-the-browser/webtransport/fetch-file-from-kubo/package.json deleted file mode 100644 index 139ddfa1c3..0000000000 --- a/examples/libp2p-in-the-browser/webtransport/fetch-file-from-kubo/package.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "name": "fetch-file-from-kubo", - "private": true, - "version": "0.0.0", - "type": "module", - "scripts": { - "start": "vite", - "build": "tsc && vite build", - "preview": "vite preview", - "test": "npm run build && test-browser-example tests" - }, - "dependencies": { - "@chainsafe/libp2p-noise": "^13.0.1", - "@libp2p/webtransport": "../..", - "@multiformats/multiaddr": "^12.1.2", - "blockstore-core": "^4.1.0", - "ipfs-bitswap": "^18.0.1", - "libp2p": "^0.46.0", - "multiformats": "^12.0.1" - }, - "devDependencies": { - "test-ipfs-example": "^1.0.0", - "typescript": "^4.6.4", - "vite": "^3.1.0" - } -} diff --git a/examples/libp2p-in-the-browser/webtransport/fetch-file-from-kubo/src/libp2p.ts b/examples/libp2p-in-the-browser/webtransport/fetch-file-from-kubo/src/libp2p.ts deleted file mode 100644 index 3d97d38243..0000000000 --- a/examples/libp2p-in-the-browser/webtransport/fetch-file-from-kubo/src/libp2p.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { webTransport } from '@libp2p/webtransport' -import { noise } from '@chainsafe/libp2p-noise' -import { createLibp2p, Libp2p } from 'libp2p' -import { createBitswap } from 'ipfs-bitswap' -import { MemoryBlockstore } from 'blockstore-core/memory' - -type Bitswap = ReturnType - -export async function setup (): Promise<{ libp2p: Libp2p, bitswap: Bitswap }> { - const store = new MemoryBlockstore() - - const node = await createLibp2p({ - transports: [webTransport()], - connectionEncryption: [noise()], - // this is only necessary when dialing local addresses - connectionGater: { - denyDialMultiaddr: async () => false - } - }) - - await node.start() - - const bitswap = createBitswap(node, store) - await bitswap.start() - - return { libp2p: node, bitswap } -} diff --git a/examples/libp2p-in-the-browser/webtransport/fetch-file-from-kubo/src/main.ts b/examples/libp2p-in-the-browser/webtransport/fetch-file-from-kubo/src/main.ts deleted file mode 100644 index e2279bdf4c..0000000000 --- a/examples/libp2p-in-the-browser/webtransport/fetch-file-from-kubo/src/main.ts +++ /dev/null @@ -1,64 +0,0 @@ -import './style.css' -import { multiaddr } from '@multiformats/multiaddr' -import { setup as libp2pSetup } from './libp2p' -import { CID } from 'multiformats/cid' - -localStorage.debug = '*' - -declare global { - interface Window { - fetchBtn: HTMLButtonElement - connectBtn: HTMLButtonElement - peerInput: HTMLInputElement - cidInput: HTMLInputElement - statusEl: HTMLParagraphElement - downloadEl: HTMLAnchorElement - downloadCidWrapperEl: HTMLDivElement - connlistWrapperEl: HTMLDivElement - connlistEl: HTMLUListElement - } -} - -(async function () { - const { libp2p, bitswap } = await libp2pSetup() - window.connectBtn.onclick = async () => { - const ma = multiaddr(window.peerInput.value) - await libp2p.dial(ma) - } - - libp2p.addEventListener('peer:connect', (_connection) => { - updateConnList() - }) - libp2p.addEventListener('peer:disconnect', (_connection) => { - updateConnList() - }) - - function updateConnList () { - const addrs = libp2p.getConnections().map(c => c.remoteAddr.toString()) - if (addrs.length > 0) { - window.downloadCidWrapperEl.hidden = false - window.connlistWrapperEl.hidden = false - window.connlistEl.innerHTML = '' - addrs.forEach(a => { - const li = document.createElement('li') - li.innerText = a - window.connlistEl.appendChild(li) - }) - } else { - window.downloadCidWrapperEl.hidden = true - window.connlistWrapperEl.hidden = true - window.connlistEl.innerHTML = '' - } - } - - window.fetchBtn.onclick = async () => { - const c = CID.parse(window.cidInput.value) - window.statusEl.hidden = false - const val = await bitswap.want(c) - window.statusEl.hidden = true - - window.downloadEl.href = window.URL.createObjectURL(new Blob([val], { type: 'bytes' })) - window.downloadEl.hidden = false - } -// eslint-disable-next-line no-console -})().catch(err => console.error(err)) diff --git a/examples/libp2p-in-the-browser/webtransport/fetch-file-from-kubo/src/style.css b/examples/libp2p-in-the-browser/webtransport/fetch-file-from-kubo/src/style.css deleted file mode 100644 index 072f654118..0000000000 --- a/examples/libp2p-in-the-browser/webtransport/fetch-file-from-kubo/src/style.css +++ /dev/null @@ -1,109 +0,0 @@ -:root { - font-family: Inter, Avenir, Helvetica, Arial, sans-serif; - font-size: 16px; - line-height: 24px; - font-weight: 400; - - color-scheme: light dark; - color: rgba(255, 255, 255, 0.87); - background-color: #242424; - - font-synthesis: none; - text-rendering: optimizeLegibility; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - -webkit-text-size-adjust: 100%; -} - -a { - font-weight: 500; - color: #646cff; - text-decoration: inherit; -} - -a:hover { - color: #535bf2; -} - -body { - margin: 0; - display: flex; - place-items: center; - min-width: 320px; - min-height: 100vh; -} - -h1 { - font-size: 3.2em; - line-height: 1.1; -} - -#app { - max-width: 1280px; - margin: 0 auto; - padding: 2rem; - text-align: center; -} - -.logo { - height: 6em; - padding: 1.5em; - will-change: filter; -} - -.logo:hover { - filter: drop-shadow(0 0 2em #646cffaa); -} - -.logo.vanilla:hover { - filter: drop-shadow(0 0 2em #3178c6aa); -} - -.card { - padding: 2em; -} - -.read-the-docs { - color: #888; -} - -button { - border-radius: 8px; - border: 1px solid transparent; - padding: 0.6em 1.2em; - font-size: 1em; - font-weight: 500; - font-family: inherit; - background-color: #1a1a1a; - cursor: pointer; - transition: border-color 0.25s; -} - -button:hover { - border-color: #646cff; -} - -button:focus, -button:focus-visible { - outline: 4px auto -webkit-focus-ring-color; -} - -@media (prefers-color-scheme: light) { - :root { - color: #213547; - background-color: #ffffff; - } - - a:hover { - color: #747bff; - } - - button { - background-color: #f9f9f9; - } -} - -#connlistWrapperEl ul { - max-width: 400px; - overflow-x: auto; -} \ No newline at end of file diff --git a/examples/libp2p-in-the-browser/webtransport/fetch-file-from-kubo/src/vite-env.d.ts b/examples/libp2p-in-the-browser/webtransport/fetch-file-from-kubo/src/vite-env.d.ts deleted file mode 100644 index 11f02fe2a0..0000000000 --- a/examples/libp2p-in-the-browser/webtransport/fetch-file-from-kubo/src/vite-env.d.ts +++ /dev/null @@ -1 +0,0 @@ -/// diff --git a/examples/libp2p-in-the-browser/webtransport/fetch-file-from-kubo/tests/test.spec.js b/examples/libp2p-in-the-browser/webtransport/fetch-file-from-kubo/tests/test.spec.js deleted file mode 100644 index edebee8011..0000000000 --- a/examples/libp2p-in-the-browser/webtransport/fetch-file-from-kubo/tests/test.spec.js +++ /dev/null @@ -1,76 +0,0 @@ -/* eslint-disable no-console */ -import { setup, expect } from 'test-ipfs-example/browser' -import { spawn, exec } from 'child_process' -import { existsSync } from 'fs' - -// Setup -const test = setup() - -async function spinUpGoLibp2p() { - if (!existsSync('../../go-libp2p-webtransport-server/main')) { - await new Promise((resolve, reject) => { - exec('go build -o main main.go', - { cwd: '../../go-libp2p-webtransport-server' }, - (error, stdout, stderr) => { - if (error) { - reject(error) - console.error(`exec error: ${error}`) - return - } - resolve() - }) - }) - } - - const server = spawn('./main', [], { cwd: '../../go-libp2p-webtransport-server', killSignal: 'SIGINT' }) - server.stderr.on('data', (data) => { - console.log(`stderr: ${data}`, typeof data) - }) - const serverAddr = await (new Promise(resolve => { - server.stdout.on('data', (data) => { - console.log(`stdout: ${data}`, typeof data) - if (data.includes('addr=')) { - // Parse the addr out - resolve((String(data)).match(/addr=([^\s]*)/)[1]) - } - }) - })) - return { server, serverAddr } -} - -test.describe('bundle ipfs with parceljs:', () => { - // DOM - const connectBtn = '#connectBtn' - const connectAddr = '#peerInput' - const connList = '#connlistEl' - - let server - let serverAddr - - // eslint-disable-next-line no-empty-pattern - test.beforeAll(async ({ }, testInfo) => { - testInfo.setTimeout(5 * 60_000) - const s = await spinUpGoLibp2p() - server = s.server - serverAddr = s.serverAddr - console.log('Server addr:', serverAddr) - }, {}) - - test.afterAll(() => { - server.kill('SIGINT') - }) - - test.beforeEach(async ({ servers, page }) => { - await page.goto(servers[0].url) - }) - - test('should connect to a go-libp2p node over webtransport', async ({ page }) => { - await page.fill(connectAddr, serverAddr) - await page.click(connectBtn) - - await page.waitForSelector('#connlistEl:has(li)') - - const connections = await page.textContent(connList) - expect(connections).toContain(serverAddr) - }) -}) diff --git a/examples/libp2p-in-the-browser/webtransport/fetch-file-from-kubo/tsconfig.json b/examples/libp2p-in-the-browser/webtransport/fetch-file-from-kubo/tsconfig.json deleted file mode 100644 index fbd022532d..0000000000 --- a/examples/libp2p-in-the-browser/webtransport/fetch-file-from-kubo/tsconfig.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "compilerOptions": { - "target": "ESNext", - "useDefineForClassFields": true, - "module": "ESNext", - "lib": ["ESNext", "DOM"], - "moduleResolution": "Node", - "strict": true, - "sourceMap": true, - "resolveJsonModule": true, - "isolatedModules": true, - "esModuleInterop": true, - "noEmit": true, - "noUnusedLocals": true, - "noUnusedParameters": true, - "noImplicitReturns": true, - "skipLibCheck": true - }, - "include": ["src"] -} diff --git a/examples/libp2p-in-the-browser/webtransport/fetch-file-from-kubo/vite.config.js b/examples/libp2p-in-the-browser/webtransport/fetch-file-from-kubo/vite.config.js deleted file mode 100644 index bcbaff69d7..0000000000 --- a/examples/libp2p-in-the-browser/webtransport/fetch-file-from-kubo/vite.config.js +++ /dev/null @@ -1,8 +0,0 @@ -export default { - build: { - target: 'es2020' - }, - optimizeDeps: { - esbuildOptions: { target: 'es2020', supported: { bigint: true } } - } -} diff --git a/examples/peer-and-content-routing/1.js b/examples/peer-and-content-routing/1.js deleted file mode 100644 index 6edd96b356..0000000000 --- a/examples/peer-and-content-routing/1.js +++ /dev/null @@ -1,59 +0,0 @@ -/* eslint-disable no-console */ - -import { noise } from '@chainsafe/libp2p-noise' -import { yamux } from '@chainsafe/libp2p-yamux' -import { kadDHT } from '@libp2p/kad-dht' -import { mplex } from '@libp2p/mplex' -import { tcp } from '@libp2p/tcp' -import delay from 'delay' -import { createLibp2p } from 'libp2p' -import { identifyService } from 'libp2p/identify' - -const createNode = async () => { - const node = await createLibp2p({ - addresses: { - listen: ['/ip4/0.0.0.0/tcp/0'] - }, - transports: [tcp()], - streamMuxers: [yamux(), mplex()], - connectionEncryption: [noise()], - services: { - dht: kadDHT({ - // this is necessary because this node is not connected to the public network - // it can be removed if, for example bootstrappers are configured - allowQueryWithZeroPeers: true - }), - identify: identifyService() - } - }) - - return node -} - -;(async () => { - const [node1, node2, node3] = await Promise.all([ - createNode(), - createNode(), - createNode() - ]) - - await node1.peerStore.patch(node2.peerId, { - multiaddrs: node2.getMultiaddrs() - }) - await node2.peerStore.patch(node3.peerId, { - multiaddrs: node3.getMultiaddrs() - }) - - await Promise.all([ - node1.dial(node2.peerId), - node2.dial(node3.peerId) - ]) - - // The DHT routing tables need a moment to populate - await delay(1000) - - const peer = await node1.peerRouting.findPeer(node3.peerId) - - console.log('Found it, multiaddrs are:') - peer.multiaddrs.forEach((ma) => console.log(ma.toString())) -})() diff --git a/examples/peer-and-content-routing/2.js b/examples/peer-and-content-routing/2.js deleted file mode 100644 index 7c7c2ab643..0000000000 --- a/examples/peer-and-content-routing/2.js +++ /dev/null @@ -1,68 +0,0 @@ -/* eslint-disable no-console */ - -import { noise } from '@chainsafe/libp2p-noise' -import { yamux } from '@chainsafe/libp2p-yamux' -import { kadDHT } from '@libp2p/kad-dht' -import { mplex } from '@libp2p/mplex' -import { tcp } from '@libp2p/tcp' -import delay from 'delay' -import all from 'it-all' -import { createLibp2p } from 'libp2p' -import { identifyService } from 'libp2p/identify' -import { CID } from 'multiformats/cid' - -const createNode = async () => { - const node = await createLibp2p({ - addresses: { - listen: ['/ip4/0.0.0.0/tcp/0'] - }, - transports: [tcp()], - streamMuxers: [yamux(), mplex()], - connectionEncryption: [noise()], - services: { - dht: kadDHT({ - // this is necessary because this node is not connected to the public network - // it can be removed if, for example bootstrappers are configured - allowQueryWithZeroPeers: true - }), - identify: identifyService() - } - }) - - return node -} - -;(async () => { - const [node1, node2, node3] = await Promise.all([ - createNode(), - createNode(), - createNode() - ]) - - await node1.peerStore.patch(node2.peerId, { - multiaddrs: node2.getMultiaddrs() - }) - await node2.peerStore.patch(node3.peerId, { - multiaddrs: node3.getMultiaddrs() - }) - - await Promise.all([ - node1.dial(node2.peerId), - node2.dial(node3.peerId) - ]) - - // Wait for onConnect handlers in the DHT - await delay(1000) - - const cid = CID.parse('QmTp9VkYvnHyrqKQuFPiuZkiX9gPcqj6x5LJ1rmWuSySnL') - await node1.contentRouting.provide(cid) - - console.log('Node %s is providing %s', node1.peerId.toString(), cid.toString()) - - // wait for propagation - await delay(300) - - const providers = await all(node3.contentRouting.findProviders(cid, { timeout: 3000 })) - - console.log('Found provider:', providers[0].id.toString()) -})() diff --git a/examples/peer-and-content-routing/LICENSE b/examples/peer-and-content-routing/LICENSE deleted file mode 100644 index 20ce483c86..0000000000 --- a/examples/peer-and-content-routing/LICENSE +++ /dev/null @@ -1,4 +0,0 @@ -This project is dual licensed under MIT and Apache-2.0. - -MIT: https://www.opensource.org/licenses/mit -Apache-2.0: https://www.apache.org/licenses/license-2.0 diff --git a/examples/peer-and-content-routing/LICENSE-APACHE b/examples/peer-and-content-routing/LICENSE-APACHE deleted file mode 100644 index 14478a3b60..0000000000 --- a/examples/peer-and-content-routing/LICENSE-APACHE +++ /dev/null @@ -1,5 +0,0 @@ -Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at - -http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. diff --git a/examples/peer-and-content-routing/LICENSE-MIT b/examples/peer-and-content-routing/LICENSE-MIT deleted file mode 100644 index 72dc60d84b..0000000000 --- a/examples/peer-and-content-routing/LICENSE-MIT +++ /dev/null @@ -1,19 +0,0 @@ -The MIT License (MIT) - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/examples/peer-and-content-routing/README.md b/examples/peer-and-content-routing/README.md deleted file mode 100644 index ce482db5bf..0000000000 --- a/examples/peer-and-content-routing/README.md +++ /dev/null @@ -1,143 +0,0 @@ -# @libp2p/example-peer-and-content-routing - -[![libp2p.io](https://img.shields.io/badge/project-libp2p-yellow.svg?style=flat-square)](http://libp2p.io/) -[![Discuss](https://img.shields.io/discourse/https/discuss.libp2p.io/posts.svg?style=flat-square)](https://discuss.libp2p.io) -[![codecov](https://img.shields.io/codecov/c/github/libp2p/js-libp2p.svg?style=flat-square)](https://codecov.io/gh/libp2p/js-libp2p) -[![CI](https://img.shields.io/github/actions/workflow/status/libp2p/js-libp2p/main.yml?branch=master\&style=flat-square)](https://github.com/libp2p/js-libp2p/actions/workflows/main.yml?query=branch%3Amaster) - -> How to use peer and content routing - -## Table of contents - -- [1. Using Peer Routing to find other peers](#1-using-peer-routing-to-find-other-peers) -- [2. Using Content Routing to find providers of content](#2-using-content-routing-to-find-providers-of-content) -- [3. Future Work](#3-future-work) -- [License](#license) -- [Contribution](#contribution) - -Peer Routing is the category of modules that offer a way to find other peers in the network by intentionally issuing queries, iterative or recursive, until a Peer is found or the closest Peers, given the Peer Routing algorithm strategy are found. - -Content Routing is the category of modules that offer a way to find where content lives in the network, it works in two steps: 1) Peers provide (announce) to the network that they are holders of specific content (multihashes) and 2) Peers issue queries to find where that content lives. A Content Routing mechanism could be as complex as a Kademlia DHT or a simple registry somewhere in the network. - -## 1. Using Peer Routing to find other peers - -This example builds on top of the [Protocol and Stream Muxing](../protocol-and-stream-muxing). We need to install `@libp2p/kad-dht`, go ahead and `npm install @libp2p/kad-dht`. If you want to see the final version, open [1.js](./1.js). - -First, let's update our config to support Peer Routing and Content Routing. - -```JavaScript -import { createLibp2p } from 'libp2p' -import { kadDHT } from '@libp2p/kad-dht' -import { tcp } from '@libp2p/tcp' -import { mplex } from '@libp2p/mplex' -import { yamux } from '@chainsafe/libp2p-yamux' -import { noise } from '@chainsafe/libp2p-noise' - -const createNode = async () => { - const node = await createLibp2p({ - addresses: { - listen: ['/ip4/0.0.0.0/tcp/0'] - }, - transports: [tcp()], - streamMuxers: [yamux(), mplex()], - connectionEncryption: [noise()], - services: { - dht: kadDHT() - } - }) - - return node -} -``` - -Once that is done, we can use the createNode function we developed in the previous example to create 3 nodes. Connect node 1 to node 2 and node 2 to node 3. We will use node 2 as a way to find the whereabouts of node 3 - -```JavaScript -const [node1, node2, node3] = await Promise.all([ - createNode(), - createNode(), - createNode() -]) - -await node1.peerStore.patch(node2.peerId, { - multiaddrs: node2.getMultiaddrs() -}) -await node2.peerStore.patch(node3.peerId, { - mulitaddrs: node3.getMultiaddrs() -}) - -await Promise.all([ - node1.dial(node2.peerId), - node2.dial(node3.peerId) -]) - -// Set up of the cons might take time -await new Promise(resolve => setTimeout(resolve, 100)) - -const peer = await node1.peerRouting.findPeer(node3.peerId) - -console.log('Found it, multiaddrs are:') -peer.multiaddrs.forEach((ma) => console.log(ma.toString())) -``` - -You should see the output being something like: - -```Bash -> node 1.js -Found it, multiaddrs are: -/ip4/127.0.0.1/tcp/63617 -/ip4/192.168.86.41/tcp/63617 -``` - -You have successfully used Peer Routing to find a peer that you were not directly connected. Now all you have to do is to dial to the multiaddrs you discovered. - -## 2. Using Content Routing to find providers of content - -With Content Routing, you can create records that are stored in multiple points in the network, these records can be resolved by you or other peers and they act as memos or rendezvous points. A great usage of this feature is to support discovery of content, where one node holds a file and instead of using a centralized tracker to inform other nodes that it holds that file, it simply puts a record in the network that can be resolved by other peers. Peer Routing and Content Routing are commonly known as Distributed Hash Tables, DHT. - -You can find this example completed in [2.js](./2.js), however as you will see it is very simple to update the previous example. - -Instead of calling `peerRouting.findPeer`, we will use `contentRouting.provide` and `contentRouting.findProviders`. - -```JavaScript -import { CID } from 'multiformats/cid' -import all from 'it-all' - -const cid = CID.parse('QmTp9VkYvnHyrqKQuFPiuZkiX9gPcqj6x5LJ1rmWuSySnL') -await node1.contentRouting.provide(cid) - -console.log('Node %s is providing %s', node1.peerId.toString(), cid.toString()) - -const providers = await all(node3.contentRouting.findProviders(cid, { timeout: 5000 })) - -console.log('Found provider:', providers[0].id.toString()) -``` - -The output of your program should look like: - -```bash -> node 2.js -Node QmSsmVPoTy3WpzwiNPnsKmonBaZjK2HitFs2nWUvwK31Pz is providing QmTp9VkYvnHyrqKQuFPiuZkiX9gPcqj6x5LJ1rmWuSySnL -Found provider: QmSsmVPoTy3WpzwiNPnsKmonBaZjK2HitFs2nWUvwK31Pz -``` - -That's it, now you know how to find peers that have pieces of information that interest you! - -## 3. Future Work - -Currently, the only mechanisms for Peer and Content Routing come from the DHT, however we do have the intention to support: - -- Multiple Peer Routing Mechanisms, including ones that do recursive searches (i.e [webrtc-explorer](http://daviddias.me/blog/webrtc-explorer-2-0-0-alpha-release/) like packet switching or [CJDNS](https://github.com/cjdelisle/cjdns) path finder) -- Content Routing via PubSub -- Content Routing via centralized index (i.e a tracker) - -## License - -Licensed under either of - -- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) -- MIT ([LICENSE-MIT](LICENSE-MIT) / ) - -## Contribution - -Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/examples/peer-and-content-routing/package.json b/examples/peer-and-content-routing/package.json deleted file mode 100644 index 0218be3139..0000000000 --- a/examples/peer-and-content-routing/package.json +++ /dev/null @@ -1,48 +0,0 @@ -{ - "name": "@libp2p/example-peer-and-content-routing", - "version": "0.0.0", - "description": "How to use peer and content routing", - "license": "Apache-2.0 OR MIT", - "homepage": "https://github.com/libp2p/js-libp2p/tree/master/examples/peer-and-content-routing#readme", - "repository": { - "type": "git", - "url": "git+https://github.com/libp2p/js-libp2p.git" - }, - "bugs": { - "url": "https://github.com/libp2p/js-libp2p/issues" - }, - "type": "module", - "files": [ - "src", - "dist", - "!dist/test", - "!**/*.tsbuildinfo" - ], - "eslintConfig": { - "extends": "ipfs", - "parserOptions": { - "project": true, - "sourceType": "module" - } - }, - "scripts": { - "lint": "aegir lint", - "test:example": "node test.js" - }, - "dependencies": { - "@chainsafe/libp2p-noise": "^13.0.0", - "@chainsafe/libp2p-yamux": "^5.0.0", - "@libp2p/kad-dht": "^10.0.0", - "@libp2p/mplex": "^9.0.0", - "@libp2p/tcp": "^8.0.0", - "delay": "^6.0.0", - "it-all": "^3.0.2", - "libp2p": "^0.46.0", - "multiformats": "^12.0.1" - }, - "devDependencies": { - "aegir": "^41.0.2", - "test-ipfs-example": "^1.0.0" - }, - "private": true -} diff --git a/examples/peer-and-content-routing/test-1.js b/examples/peer-and-content-routing/test-1.js deleted file mode 100644 index 3d9fd4e220..0000000000 --- a/examples/peer-and-content-routing/test-1.js +++ /dev/null @@ -1,13 +0,0 @@ -import path from 'path' -import { fileURLToPath } from 'url' -import { waitForOutput } from 'test-ipfs-example/node' - -const __dirname = path.dirname(fileURLToPath(import.meta.url)) - -export async function test () { - process.stdout.write('1.js\n') - - await waitForOutput('Found it, multiaddrs are:', 'node', [path.join(__dirname, '1.js')], { - cwd: __dirname - }) -} diff --git a/examples/peer-and-content-routing/test-2.js b/examples/peer-and-content-routing/test-2.js deleted file mode 100644 index 1c73889e6f..0000000000 --- a/examples/peer-and-content-routing/test-2.js +++ /dev/null @@ -1,13 +0,0 @@ -import path from 'path' -import { fileURLToPath } from 'url' -import { waitForOutput } from 'test-ipfs-example/node' - -const __dirname = path.dirname(fileURLToPath(import.meta.url)) - -export async function test () { - process.stdout.write('2.js\n') - - await waitForOutput('Found provider:', 'node', [path.join(__dirname, '2.js')], { - cwd: __dirname - }) -} diff --git a/examples/peer-and-content-routing/test.js b/examples/peer-and-content-routing/test.js deleted file mode 100644 index 07acb00823..0000000000 --- a/examples/peer-and-content-routing/test.js +++ /dev/null @@ -1,5 +0,0 @@ -import { test as test1 } from './test-1.js' -import { test as test2 } from './test-2.js' - -await test1() -await test2() diff --git a/examples/pnet/LICENSE b/examples/pnet/LICENSE deleted file mode 100644 index 20ce483c86..0000000000 --- a/examples/pnet/LICENSE +++ /dev/null @@ -1,4 +0,0 @@ -This project is dual licensed under MIT and Apache-2.0. - -MIT: https://www.opensource.org/licenses/mit -Apache-2.0: https://www.apache.org/licenses/license-2.0 diff --git a/examples/pnet/LICENSE-APACHE b/examples/pnet/LICENSE-APACHE deleted file mode 100644 index 14478a3b60..0000000000 --- a/examples/pnet/LICENSE-APACHE +++ /dev/null @@ -1,5 +0,0 @@ -Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at - -http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. diff --git a/examples/pnet/LICENSE-MIT b/examples/pnet/LICENSE-MIT deleted file mode 100644 index 72dc60d84b..0000000000 --- a/examples/pnet/LICENSE-MIT +++ /dev/null @@ -1,19 +0,0 @@ -The MIT License (MIT) - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/examples/pnet/README.md b/examples/pnet/README.md deleted file mode 100644 index 2e3104fef9..0000000000 --- a/examples/pnet/README.md +++ /dev/null @@ -1,53 +0,0 @@ -# @libp2p/example-pnet - -[![libp2p.io](https://img.shields.io/badge/project-libp2p-yellow.svg?style=flat-square)](http://libp2p.io/) -[![Discuss](https://img.shields.io/discourse/https/discuss.libp2p.io/posts.svg?style=flat-square)](https://discuss.libp2p.io) -[![codecov](https://img.shields.io/codecov/c/github/libp2p/js-libp2p.svg?style=flat-square)](https://codecov.io/gh/libp2p/js-libp2p) -[![CI](https://img.shields.io/github/actions/workflow/status/libp2p/js-libp2p/main.yml?branch=master\&style=flat-square)](https://github.com/libp2p/js-libp2p/actions/workflows/main.yml?query=branch%3Amaster) - -> How to configure a libp2p private network - -## Table of contents - -- [Setup](#setup) -- [Run](#run) - - [Using different keys](#using-different-keys) - - [Exploring the repos](#exploring-the-repos) -- [License](#license) -- [Contribution](#contribution) - -## Setup - -1. Install the modules in the libp2p root directory, `npm install` and `npm run build`. - -## Run - -Running the example will cause two nodes with the same swarm key to be started and exchange basic information. - - node index.js - -### Using different keys - -This example includes `TASK` comments that can be used to try the example with different swarm keys. This will -allow you to see how nodes will fail to connect if they are on different private networks and try to connect to -one another. - -To change the swarm key of one of the nodes, look through `index.js` for comments starting with `TASK` to indicate -where lines are that pertain to changing the swarm key of node 2. - -### Exploring the repos - -Once you've run the example you can take a look at the repos in the `./tmp` directory to see how they differ, including -the swarm keys. You should see a `swarm.key` file in each of the repos and when the nodes are on the same private network -this contents of the `swarm.key` files should be the same. - -## License - -Licensed under either of - -- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) -- MIT ([LICENSE-MIT](LICENSE-MIT) / ) - -## Contribution - -Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/examples/pnet/index.js b/examples/pnet/index.js deleted file mode 100644 index 115d7f1792..0000000000 --- a/examples/pnet/index.js +++ /dev/null @@ -1,49 +0,0 @@ -/* eslint no-console: ["off"] */ - -import { pipe } from 'it-pipe' -import { generateKey } from 'libp2p/pnet' -import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string' -import { toString as uint8ArrayToString } from 'uint8arrays/to-string' -import { privateLibp2pNode } from './libp2p-node.js' - -// Create a Uint8Array and write the swarm key to it -const swarmKey = new Uint8Array(95) -generateKey(swarmKey) - -// This key is for testing a different key not working -const otherSwarmKey = new Uint8Array(95) -generateKey(otherSwarmKey) - -;(async () => { - const node1 = await privateLibp2pNode(swarmKey) - - // TASK: switch the commented out line below so we're using a different key, to see the nodes fail to connect - const node2 = await privateLibp2pNode(swarmKey) - // const node2 = await privateLibp2pNode(otherSwarmKey) - - console.log('nodes started...') - - // Add node 2 data to node1's PeerStore - await node1.peerStore.patch(node2.peerId, { - multiaddrs: node2.getMultiaddrs() - }) - await node1.dial(node2.peerId) - - node2.handle('/private', ({ stream }) => { - pipe( - stream, - async function (source) { - for await (const msg of source) { - console.log(uint8ArrayToString(msg.subarray())) - } - } - ) - }) - - const stream = await node1.dialProtocol(node2.peerId, '/private') - - await pipe( - [uint8ArrayFromString('This message is sent on a private network')], - stream - ) -})() diff --git a/examples/pnet/libp2p-node.js b/examples/pnet/libp2p-node.js deleted file mode 100644 index 8b6b5e817f..0000000000 --- a/examples/pnet/libp2p-node.js +++ /dev/null @@ -1,34 +0,0 @@ -import { noise } from '@chainsafe/libp2p-noise' -import { yamux } from '@chainsafe/libp2p-yamux' -import { mplex } from '@libp2p/mplex' -import { tcp } from '@libp2p/tcp' -import { createLibp2p } from 'libp2p' -import { preSharedKey } from 'libp2p/pnet' - -/** - * privateLibp2pNode returns a libp2p node function that will use the swarm - * key with the given `swarmKey` to create the Protector - * - * @param {any} swarmKey - */ -export async function privateLibp2pNode (swarmKey) { - const node = await createLibp2p({ - addresses: { - listen: ['/ip4/0.0.0.0/tcp/0'] - }, - transports: [tcp()], // We're only using the TCP transport for this example - streamMuxers: [yamux(), mplex()], // We're only using mplex muxing - // Let's make sure to use identifying crypto in our pnet since the protector doesn't - // care about node identity, and only the presence of private keys - connectionEncryption: [noise()], - // Leave peer discovery empty, we don't want to find peers. We could omit the property, but it's - // being left in for explicit readability. - // We should explicitly dial pnet peers, or use a custom discovery service for finding nodes in our pnet - peerDiscovery: [], - connectionProtector: preSharedKey({ - psk: swarmKey - }) - }) - - return node -} diff --git a/examples/pnet/package.json b/examples/pnet/package.json deleted file mode 100644 index e619f3fe9a..0000000000 --- a/examples/pnet/package.json +++ /dev/null @@ -1,46 +0,0 @@ -{ - "name": "@libp2p/example-pnet", - "version": "0.0.0", - "description": "How to configure a libp2p private network", - "license": "Apache-2.0 OR MIT", - "homepage": "https://github.com/libp2p/js-libp2p/tree/master/examples/pnet#readme", - "repository": { - "type": "git", - "url": "git+https://github.com/libp2p/js-libp2p.git" - }, - "bugs": { - "url": "https://github.com/libp2p/js-libp2p/issues" - }, - "type": "module", - "files": [ - "src", - "dist", - "!dist/test", - "!**/*.tsbuildinfo" - ], - "eslintConfig": { - "extends": "ipfs", - "parserOptions": { - "project": true, - "sourceType": "module" - } - }, - "scripts": { - "lint": "aegir lint", - "test:example": "node test.js" - }, - "dependencies": { - "@chainsafe/libp2p-noise": "^13.0.0", - "@chainsafe/libp2p-yamux": "^5.0.0", - "@libp2p/mplex": "^9.0.0", - "@libp2p/tcp": "^8.0.0", - "it-pipe": "^3.0.1", - "libp2p": "^0.46.0", - "uint8arrays": "^4.0.6" - }, - "devDependencies": { - "aegir": "^41.0.2", - "test-ipfs-example": "^1.0.0" - }, - "private": true -} diff --git a/examples/pnet/test.js b/examples/pnet/test.js deleted file mode 100644 index eb78f5a6f9..0000000000 --- a/examples/pnet/test.js +++ /dev/null @@ -1,9 +0,0 @@ -import path from 'path' -import { fileURLToPath } from 'url' -import { waitForOutput } from 'test-ipfs-example/node' - -const __dirname = path.dirname(fileURLToPath(import.meta.url)) - -await waitForOutput('This message is sent on a private network', 'node', [path.join(__dirname, 'index.js')], { - cwd: __dirname -}) diff --git a/examples/protocol-and-stream-muxing/1.js b/examples/protocol-and-stream-muxing/1.js deleted file mode 100644 index 0b3bf5b1e7..0000000000 --- a/examples/protocol-and-stream-muxing/1.js +++ /dev/null @@ -1,80 +0,0 @@ -/* eslint-disable no-console */ - -import { noise } from '@chainsafe/libp2p-noise' -import { yamux } from '@chainsafe/libp2p-yamux' -import { mplex } from '@libp2p/mplex' -import { tcp } from '@libp2p/tcp' -import { pipe } from 'it-pipe' -import { createLibp2p } from 'libp2p' -import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string' -import { toString as uint8ArrayToString } from 'uint8arrays/to-string' - -const createNode = async () => { - const node = await createLibp2p({ - addresses: { - listen: ['/ip4/0.0.0.0/tcp/0'] - }, - transports: [tcp()], - streamMuxers: [yamux(), mplex()], - connectionEncryption: [noise()] - }) - - return node -} - -;(async () => { - const [node1, node2] = await Promise.all([ - createNode(), - createNode() - ]) - - // Add node's 2 data to the PeerStore - await node1.peerStore.patch(node2.peerId, { - multiaddrs: node2.getMultiaddrs() - }) - - // exact matching - node2.handle('/your-protocol', ({ stream }) => { - pipe( - stream, - async function (source) { - for await (const msg of source) { - console.log(uint8ArrayToString(msg.subarray())) - } - } - ) - }) - - // multiple protocols - /* - node2.handle(['/another-protocol/1.0.0', '/another-protocol/2.0.0'], ({ protocol, stream }) => { - if (protocol === '/another-protocol/2.0.0') { - // handle backwards compatibility - } - - pipe( - stream, - async function (source) { - for await (const msg of source) { - console.log(uint8ArrayToString(msg)) - } - } - ) - }) - */ - - const stream = await node1.dialProtocol(node2.peerId, ['/your-protocol']) - await pipe( - [uint8ArrayFromString('my own protocol, wow!')], - stream - ) - - /* - const stream = node1.dialProtocol(node2.peerId, ['/another-protocol/1.0.0']) - - await pipe( - ['my own protocol, wow!'], - stream - ) - */ -})() diff --git a/examples/protocol-and-stream-muxing/2.js b/examples/protocol-and-stream-muxing/2.js deleted file mode 100644 index 57e86294d4..0000000000 --- a/examples/protocol-and-stream-muxing/2.js +++ /dev/null @@ -1,67 +0,0 @@ -/* eslint-disable no-console */ - -import { noise } from '@chainsafe/libp2p-noise' -import { yamux } from '@chainsafe/libp2p-yamux' -import { mplex } from '@libp2p/mplex' -import { tcp } from '@libp2p/tcp' -import { pipe } from 'it-pipe' -import { createLibp2p } from 'libp2p' -import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string' -import { toString as uint8ArrayToString } from 'uint8arrays/to-string' - -const createNode = async () => { - const node = await createLibp2p({ - addresses: { - listen: ['/ip4/0.0.0.0/tcp/0'] - }, - transports: [tcp()], - streamMuxers: [yamux(), mplex()], - connectionEncryption: [noise()] - }) - - return node -} - -;(async () => { - const [node1, node2] = await Promise.all([ - createNode(), - createNode() - ]) - - // Add node's 2 data to the PeerStore - await node1.peerStore.patch(node2.peerId, { - multiaddrs: node2.getMultiaddrs() - }) - - node2.handle(['/a', '/b'], ({ protocol, stream }) => { - pipe( - stream, - async function (source) { - for await (const msg of source) { - console.log(`from: ${protocol}, msg: ${uint8ArrayToString(msg.subarray())}`) - } - } - ).finally(() => { - // clean up resources - stream.close() - }) - }) - - const stream1 = await node1.dialProtocol(node2.peerId, ['/a']) - await pipe( - [uint8ArrayFromString('protocol (a)')], - stream1 - ) - - const stream2 = await node1.dialProtocol(node2.peerId, ['/b']) - await pipe( - [uint8ArrayFromString('protocol (b)')], - stream2 - ) - - const stream3 = await node1.dialProtocol(node2.peerId, ['/b']) - await pipe( - [uint8ArrayFromString('another stream on protocol (b)')], - stream3 - ) -})() diff --git a/examples/protocol-and-stream-muxing/3.js b/examples/protocol-and-stream-muxing/3.js deleted file mode 100644 index eb88137a42..0000000000 --- a/examples/protocol-and-stream-muxing/3.js +++ /dev/null @@ -1,69 +0,0 @@ -/* eslint-disable no-console */ - -import { noise } from '@chainsafe/libp2p-noise' -import { yamux } from '@chainsafe/libp2p-yamux' -import { mplex } from '@libp2p/mplex' -import { tcp } from '@libp2p/tcp' -import { pipe } from 'it-pipe' -import { createLibp2p } from 'libp2p' -import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string' -import { toString as uint8ArrayToString } from 'uint8arrays/to-string' - -const createNode = async () => { - const node = await createLibp2p({ - addresses: { - listen: ['/ip4/0.0.0.0/tcp/0'] - }, - transports: [tcp()], - streamMuxers: [yamux(), mplex()], - connectionEncryption: [noise()] - }) - - return node -} - -;(async () => { - const [node1, node2] = await Promise.all([ - createNode(), - createNode() - ]) - - // Add node's 2 data to the PeerStore - await node1.peerStore.patch(node2.peerId, { - multiaddrs: node2.getMultiaddrs() - }) - - node1.handle('/node-1', ({ stream }) => { - pipe( - stream, - async function (source) { - for await (const msg of source) { - console.log(uint8ArrayToString(msg.subarray())) - } - } - ) - }) - - node2.handle('/node-2', ({ stream }) => { - pipe( - stream, - async function (source) { - for await (const msg of source) { - console.log(uint8ArrayToString(msg.subarray())) - } - } - ) - }) - - const stream1 = await node1.dialProtocol(node2.peerId, ['/node-2']) - await pipe( - [uint8ArrayFromString('from 1 to 2')], - stream1 - ) - - const stream2 = await node2.dialProtocol(node1.peerId, ['/node-1']) - await pipe( - [uint8ArrayFromString('from 2 to 1')], - stream2 - ) -})() diff --git a/examples/protocol-and-stream-muxing/LICENSE b/examples/protocol-and-stream-muxing/LICENSE deleted file mode 100644 index 20ce483c86..0000000000 --- a/examples/protocol-and-stream-muxing/LICENSE +++ /dev/null @@ -1,4 +0,0 @@ -This project is dual licensed under MIT and Apache-2.0. - -MIT: https://www.opensource.org/licenses/mit -Apache-2.0: https://www.apache.org/licenses/license-2.0 diff --git a/examples/protocol-and-stream-muxing/LICENSE-APACHE b/examples/protocol-and-stream-muxing/LICENSE-APACHE deleted file mode 100644 index 14478a3b60..0000000000 --- a/examples/protocol-and-stream-muxing/LICENSE-APACHE +++ /dev/null @@ -1,5 +0,0 @@ -Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at - -http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. diff --git a/examples/protocol-and-stream-muxing/LICENSE-MIT b/examples/protocol-and-stream-muxing/LICENSE-MIT deleted file mode 100644 index 72dc60d84b..0000000000 --- a/examples/protocol-and-stream-muxing/LICENSE-MIT +++ /dev/null @@ -1,19 +0,0 @@ -The MIT License (MIT) - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/examples/protocol-and-stream-muxing/README.md b/examples/protocol-and-stream-muxing/README.md deleted file mode 100644 index beda3b2b37..0000000000 --- a/examples/protocol-and-stream-muxing/README.md +++ /dev/null @@ -1,305 +0,0 @@ -# @libp2p/example-protocol-and-stream-muxing - -[![libp2p.io](https://img.shields.io/badge/project-libp2p-yellow.svg?style=flat-square)](http://libp2p.io/) -[![Discuss](https://img.shields.io/discourse/https/discuss.libp2p.io/posts.svg?style=flat-square)](https://discuss.libp2p.io) -[![codecov](https://img.shields.io/codecov/c/github/libp2p/js-libp2p.svg?style=flat-square)](https://codecov.io/gh/libp2p/js-libp2p) -[![CI](https://img.shields.io/github/actions/workflow/status/libp2p/js-libp2p/main.yml?branch=master\&style=flat-square)](https://github.com/libp2p/js-libp2p/actions/workflows/main.yml?query=branch%3Amaster) - -> How to use multiplex protocols streams - -## Table of contents - -- [1. Handle multiple protocols](#1-handle-multiple-protocols) -- [2. Reuse existing connection](#2-reuse-existing-connection) -- [3. Bidirectional connections](#3-bidirectional-connections) -- [License](#license) -- [Contribution](#contribution) - -The feature of agreeing on a protocol over an established connection is what we call *protocol multiplexing* and it is possible through [multistream-select](https://github.com/multiformats/multistream), another protocol that lets you agree per connection (or stream) which protocol is going to be talked over that connection (select), it also enables you to request the other end to tell you which protocols it supports (ls). You can learn more about multistream-select at its [specification repo](https://github.com/multiformats/multistream). - -## 1. Handle multiple protocols - -Let's see *protocol multiplexing* in action! You will need the following modules for this example: `libp2p`, `@libp2p/tcp`, `@libp2p/peer-id`, `it-pipe`, `it-buffer` and `streaming-iterables`. This example reuses the base left by the [Transports](../transports) example. You can see the complete solution at [1.js](./1.js). - -After creating the nodes, we need to tell libp2p which protocols to handle. - -```JavaScript -import { pipe } from 'it-pipe' -import { map } from 'streaming-iterables' -import { toBuffer } from 'it-buffer' -import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string' -import { toString as uint8ArrayToString } from 'uint8arrays/to-string' - -// ... -const [node1, node2] = await Promise.all([ - createNode(), - createNode() -]) - -// Add node's 2 data to the PeerStore -await node1.peerStore.patch(node2.peerId, { - multiaddrs: node2.getMultiaddrs() -}) - -// Here we are telling libp2p that if someone dials this node to talk with the `/your-protocol` -// multicodec, the protocol identifier, please call this handler and give it the stream -// so that incomming data can be handled -node2.handle('/your-protocol', ({ stream }) => { - pipe( - stream, - source => (async function () { - for await (const msg of source) { - console.log(uint8ArrayToString(msg.subarray())) - } - })() - ) -}) -``` - -After the protocol is *handled*, now we can dial to it. - -```JavaScript -const stream = await node1.dialProtocol(node2.peerId, ['/your-protocol']) - -await pipe( - [uint8ArrayFromString('my own protocol, wow!')], - stream -) -``` - -You might have seen this in the [Transports](../transports) examples. However, what it was not explained is that you can do more than exact string matching, for example, you can use semver. - -```JavaScript -node2.handle('/another-protocol/1.0.1', ({ stream }) => { - pipe( - stream, - async function (source) { - for await (const msg of source) { - console.log(uint8ArrayToString(msg.subarray())) - } - } - ) -}) -// ... -const stream = await node1.dialProtocol(node2.peerId, ['/another-protocol/1.0.0']) - -await pipe( - [uint8ArrayFromString('my own protocol, wow!')], - stream -) -``` - -This feature is super power for network protocols. It works in the same way as versioning your RPC/REST API, but for anything that goes in the wire. We had to use this feature to upgrade protocols within the IPFS Stack (i.e Bitswap) and we successfully managed to do so without any network splits. - -There is still one last feature, you can provide multiple protocols for the same handler. If you have a backwards incompatible change, but it only requires minor changes to the code, you may prefer to do protocol checking instead of having multiple handlers - -```JavaScript -node2.handle(['/another-protocol/1.0.0', '/another-protocol/2.0.0'], ({ stream }) => { - if (stream.protocol === '/another-protocol/2.0.0') { - // handle backwards compatibility - } - - pipe( - stream, - async function (source) { - for await (const msg of source) { - console.log(uint8ArrayToString(msg.subarray())) - } - } - ) -}) -``` - -Try all of this out by executing [1.js](./1.js). - -## 2. Reuse existing connection - -The examples above would require a node to create a whole new connection for every time it dials in one of the protocols, this is a waste of resources and also it might be simply not possible (e.g lack of file descriptors, not enough ports being open, etc). What we really want is to dial a connection once and then multiplex several virtual connections (stream) over a single connection, this is where *stream multiplexing* comes into play. - -Stream multiplexing is an old concept, in fact it happens in many of the layers of the [OSI System](https://en.wikipedia.org/wiki/OSI_model). In libp2p, we make this feature to our avail by letting the user pick which module for stream multiplexing to use. - -Currently, we have [libp2p-mplex](https://github.com/libp2p/js-libp2p-mplex) and pluging it in is as easy as adding a transport. Let's revisit our libp2p configuration. - -```JavaScript -import { createLibp2p } from 'libp2p' -import { tcp } from '@libp2p/tcp' -import { mplex } from '@libp2p/mplex' -import { yamux } from '@chainsafe/libp2p-yamux' - -//... - -createLibp2p({ - //... - transports: [ - tcp() - ], - streamMuxers: [ - yamux(), - mplex() - ] -}) - -``` - -With this, we can dial as many times as we want to a peer and always reuse the same established underlying connection. - -```JavaScript -node2.handle(['/a', '/b'], ({ stream }) => { - pipe( - stream, - async function (source) { - for await (const msg of source) { - console.log(`from: ${stream.protocol}, msg: ${uint8ArrayToString(msg.subarray())}`) - } - } - ) -}) - -const stream = await node1.dialProtocol(node2.peerId, ['/a']) -await pipe( - [uint8ArrayFromString('protocol (a)')], - stream -) - -const stream2 = await node1.dialProtocol(node2.peerId, ['/b']) -await pipe( - [uint8ArrayFromString('protocol (b)')], - stream2 -) - -const stream3 = await node1.dialProtocol(node2.peerId, ['/b']) -await pipe( - [uint8ArrayFromString('another stream on protocol (b)')], - stream3 -) -``` - -By running [2.js](./2.js) you should see the following result: - - > node 2.js - from: /a, msg: protocol (a) - from: /b, msg: protocol (b) - from: /b, msg: another stream on protocol (b) - -## 3. Bidirectional connections - -There is one last trick on *protocol and stream multiplexing* that libp2p uses to make everyone's life easier and that is *bidirectional connection*. - -With the aid of both mechanisms, we can reuse an incomming connection to dial streams out too, this is specially useful when you are behind tricky NAT, firewalls or if you are running in a browser, where you can't have listening addrs, but you can dial out. By dialing out, you enable other peers to talk with you in Protocols that they want, simply by opening a new multiplexed stream. - -You can see this working on example [3.js](./3.js). - -As we've seen earlier, we can create our node with this createNode function. - -```js -const createNode = async () => { - const node = await createLibp2p({ - addresses: { - listen: ['/ip4/0.0.0.0/tcp/0'] - }, - transports: [tcp()], - streamMuxers: [yamux(), mplex()], - connectionEncryption: [noise()], - }) - - return node -} -``` - -We can now create our two nodes for this example. - -```js -const [node1, node2] = await Promise.all([ - createNode(), - createNode() -]) -``` - -Since, we want to connect these nodes `node1` & `node2`, we add our `node2` multiaddr in key-value pair in `node1` peer store. - -```js -await node1.peerStore.patch(node2.peerId, { - multiaddrs: node2.getMultiaddrs() -}) -``` - -You may notice that we are only adding `node2` to `node1` peer store. This is because we want to dial up a bidirectional connection between these two nodes. - -Finally, let's create protocols for `node1` & `node2` and dial those protocols. - -```js -node1.handle('/node-1', ({ stream }) => { - pipe( - stream, - async function (source) { - for await (const msg of source) { - console.log(uint8ArrayToString(msg.subarray())) - } - } - ) -}) - -node2.handle('/node-2', ({ stream }) => { - pipe( - stream, - async function (source) { - for await (const msg of source) { - console.log(uint8ArrayToString(msg.subarray())) - } - } - ) -}) - -// Dialing node2 from node1 -const stream1 = await node1.dialProtocol(node2.peerId, ['/node-2']) -await pipe( - [uint8ArrayFromString('from 1 to 2')], - stream1 -) - -// Dialing node1 from node2 -const stream2 = await node2.dialProtocol(node1.peerId, ['/node-1']) -await pipe( - [uint8ArrayFromString('from 2 to 1')], - stream2 -) -``` - -If we run this code, the result should look like the following: - -```Bash -> node 3.js -from 1 to 2 -from 2 to 1 -``` - -So, we have successfully set up a bidirectional connection with protocol muxing. But you should be aware that we were able to dial from `node2` to `node1` even we haven't added the `node1` peerId to node2 address book is because we dialed node2 from node1 first. Then, we just dialed back our stream out from `node2` to `node1`. So, if we dial from `node2` to `node1` before dialing from `node1` to `node2` we will get an error. - -The code below will result into an error as `the dial address is not valid`. - -```js -// Dialing from node2 to node1 -const stream2 = await node2.dialProtocol(node1.peerId, ['/node-1']) -await pipe( - [uint8ArrayFromString('from 2 to 1')], - stream2 -) - -// Dialing from node1 to node2 -const stream1 = await node1.dialProtocol(node2.peerId, ['/node-2']) -await pipe( - [uint8ArrayFromString('from 1 to 2')], - stream1 -) -``` - -## License - -Licensed under either of - -- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) -- MIT ([LICENSE-MIT](LICENSE-MIT) / ) - -## Contribution - -Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/examples/protocol-and-stream-muxing/package.json b/examples/protocol-and-stream-muxing/package.json deleted file mode 100644 index d8d8086336..0000000000 --- a/examples/protocol-and-stream-muxing/package.json +++ /dev/null @@ -1,46 +0,0 @@ -{ - "name": "@libp2p/example-protocol-and-stream-muxing", - "version": "0.0.0", - "description": "How to use multiplex protocols streams", - "license": "Apache-2.0 OR MIT", - "homepage": "https://github.com/libp2p/js-libp2p/tree/master/examples/protocol-and-stream-muxing#readme", - "repository": { - "type": "git", - "url": "git+https://github.com/libp2p/js-libp2p.git" - }, - "bugs": { - "url": "https://github.com/libp2p/js-libp2p/issues" - }, - "type": "module", - "files": [ - "src", - "dist", - "!dist/test", - "!**/*.tsbuildinfo" - ], - "eslintConfig": { - "extends": "ipfs", - "parserOptions": { - "project": true, - "sourceType": "module" - } - }, - "scripts": { - "lint": "aegir lint", - "test:example": "node test.js" - }, - "dependencies": { - "@chainsafe/libp2p-noise": "^13.0.0", - "@chainsafe/libp2p-yamux": "^5.0.0", - "@libp2p/mplex": "^9.0.0", - "@libp2p/tcp": "^8.0.0", - "it-pipe": "^3.0.1", - "libp2p": "^0.46.0", - "uint8arrays": "^4.0.6" - }, - "devDependencies": { - "aegir": "^41.0.2", - "test-ipfs-example": "^1.0.0" - }, - "private": true -} diff --git a/examples/protocol-and-stream-muxing/test-1.js b/examples/protocol-and-stream-muxing/test-1.js deleted file mode 100644 index 5e13eb6ed2..0000000000 --- a/examples/protocol-and-stream-muxing/test-1.js +++ /dev/null @@ -1,13 +0,0 @@ -import path from 'path' -import { fileURLToPath } from 'url' -import { waitForOutput } from 'test-ipfs-example/node' - -const __dirname = path.dirname(fileURLToPath(import.meta.url)) - -export async function test () { - process.stdout.write('1.js\n') - - await waitForOutput('my own protocol, wow!', 'node', [path.join(__dirname, '1.js')], { - cwd: __dirname - }) -} diff --git a/examples/protocol-and-stream-muxing/test-2.js b/examples/protocol-and-stream-muxing/test-2.js deleted file mode 100644 index 885d54117b..0000000000 --- a/examples/protocol-and-stream-muxing/test-2.js +++ /dev/null @@ -1,13 +0,0 @@ -import path from 'path' -import { fileURLToPath } from 'url' -import { waitForOutput } from 'test-ipfs-example/node' - -const __dirname = path.dirname(fileURLToPath(import.meta.url)) - -export async function test () { - process.stdout.write('2.js\n') - - await waitForOutput('another stream on protocol (b)', 'node', [path.join(__dirname, '2.js')], { - cwd: __dirname - }) -} diff --git a/examples/protocol-and-stream-muxing/test-3.js b/examples/protocol-and-stream-muxing/test-3.js deleted file mode 100644 index 0748b259db..0000000000 --- a/examples/protocol-and-stream-muxing/test-3.js +++ /dev/null @@ -1,13 +0,0 @@ -import path from 'path' -import { fileURLToPath } from 'url' -import { waitForOutput } from 'test-ipfs-example/node' - -const __dirname = path.dirname(fileURLToPath(import.meta.url)) - -export async function test () { - process.stdout.write('3.js\n') - - await waitForOutput('from 2 to 1', 'node', [path.join(__dirname, '3.js')], { - cwd: __dirname - }) -} diff --git a/examples/protocol-and-stream-muxing/test.js b/examples/protocol-and-stream-muxing/test.js deleted file mode 100644 index fd441b83ed..0000000000 --- a/examples/protocol-and-stream-muxing/test.js +++ /dev/null @@ -1,7 +0,0 @@ -import { test as test1 } from './test-1.js' -import { test as test2 } from './test-2.js' -import { test as test3 } from './test-3.js' - -await test1() -await test2() -await test3() diff --git a/examples/pubsub/1.js b/examples/pubsub/1.js deleted file mode 100644 index 0e15e87ddb..0000000000 --- a/examples/pubsub/1.js +++ /dev/null @@ -1,61 +0,0 @@ -/* eslint-disable no-console */ - -import { noise } from '@chainsafe/libp2p-noise' -import { yamux } from '@chainsafe/libp2p-yamux' -import { floodsub } from '@libp2p/floodsub' -import { mplex } from '@libp2p/mplex' -import { tcp } from '@libp2p/tcp' -import { createLibp2p } from 'libp2p' -import { identifyService } from 'libp2p/identify' -import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string' -import { toString as uint8ArrayToString } from 'uint8arrays/to-string' - -const createNode = async () => { - const node = await createLibp2p({ - addresses: { - listen: ['/ip4/0.0.0.0/tcp/0'] - }, - transports: [tcp()], - streamMuxers: [yamux(), mplex()], - connectionEncryption: [noise()], - services: { - pubsub: floodsub(), - identify: identifyService() - } - }) - - return node -} - -;(async () => { - const topic = 'news' - - const [node1, node2] = await Promise.all([ - createNode(), - createNode() - ]) - - // Add node's 2 data to the PeerStore - await node1.peerStore.patch(node2.peerId, { - multiaddrs: node2.getMultiaddrs() - }) - await node1.dial(node2.peerId) - - node1.services.pubsub.subscribe(topic) - node1.services.pubsub.addEventListener('message', (evt) => { - console.log(`node1 received: ${uint8ArrayToString(evt.detail.data)} on topic ${evt.detail.topic}`) - }) - - // Will not receive own published messages by default - node2.services.pubsub.subscribe(topic) - node2.services.pubsub.addEventListener('message', (evt) => { - console.log(`node2 received: ${uint8ArrayToString(evt.detail.data)} on topic ${evt.detail.topic}`) - }) - - // node2 publishes "news" every second - setInterval(() => { - node2.services.pubsub.publish(topic, uint8ArrayFromString('Bird bird bird, bird is the word!')).catch(err => { - console.error(err) - }) - }, 1000) -})() diff --git a/examples/pubsub/LICENSE b/examples/pubsub/LICENSE deleted file mode 100644 index 20ce483c86..0000000000 --- a/examples/pubsub/LICENSE +++ /dev/null @@ -1,4 +0,0 @@ -This project is dual licensed under MIT and Apache-2.0. - -MIT: https://www.opensource.org/licenses/mit -Apache-2.0: https://www.apache.org/licenses/license-2.0 diff --git a/examples/pubsub/LICENSE-APACHE b/examples/pubsub/LICENSE-APACHE deleted file mode 100644 index 14478a3b60..0000000000 --- a/examples/pubsub/LICENSE-APACHE +++ /dev/null @@ -1,5 +0,0 @@ -Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at - -http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. diff --git a/examples/pubsub/LICENSE-MIT b/examples/pubsub/LICENSE-MIT deleted file mode 100644 index 72dc60d84b..0000000000 --- a/examples/pubsub/LICENSE-MIT +++ /dev/null @@ -1,19 +0,0 @@ -The MIT License (MIT) - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/examples/pubsub/README.md b/examples/pubsub/README.md deleted file mode 100644 index 538e3c5dbd..0000000000 --- a/examples/pubsub/README.md +++ /dev/null @@ -1,140 +0,0 @@ -# @libp2p/example-pubsub - -[![libp2p.io](https://img.shields.io/badge/project-libp2p-yellow.svg?style=flat-square)](http://libp2p.io/) -[![Discuss](https://img.shields.io/discourse/https/discuss.libp2p.io/posts.svg?style=flat-square)](https://discuss.libp2p.io) -[![codecov](https://img.shields.io/codecov/c/github/libp2p/js-libp2p.svg?style=flat-square)](https://codecov.io/gh/libp2p/js-libp2p) -[![CI](https://img.shields.io/github/actions/workflow/status/libp2p/js-libp2p/main.yml?branch=master\&style=flat-square)](https://github.com/libp2p/js-libp2p/actions/workflows/main.yml?query=branch%3Amaster) - -> An example using libp2p pubsub - -## Table of contents - -- [0. Set up the example](#0-set-up-the-example) -- [1. Setting up a simple PubSub network on top of libp2p](#1-setting-up-a-simple-pubsub-network-on-top-of-libp2p) -- [2. Future work](#2-future-work) -- [License](#license) -- [Contribution](#contribution) - -We've seen many interesting use cases appear with this, here are some highlights: - -- [Collaborative Text Editing](https://www.youtube.com/watch?v=-kdx8rJd8rQ) -- [IPFS PubSub (using libp2p-floodsub) for IoT](https://www.youtube.com/watch?v=qLpM5pBDGiE). -- [Real Time distributed Applications](https://www.youtube.com/watch?v=vQrbxyDPSXg) - -## 0. Set up the example - -Before moving into the examples, you should run `npm install` and `npm run build` on the top level `js-libp2p` folder, in order to install all the dependencies needed for this example. In addition, you will need to install the example related dependencies by doing `cd examples && npm install`. Once the install finishes, you should move into the example folder with `cd pubsub`. - -## 1. Setting up a simple PubSub network on top of libp2p - -For this example, we will use MulticastDNS for automatic Peer Discovery. This example is based the previous examples found in [Discovery Mechanisms](../discovery-mechanisms). You can find the complete version at [1.js](./1.js). - -Using PubSub is super simple, you only need to provide the implementation of your choice and you are ready to go. No need for extra configuration. - -First, let's update our libp2p configuration with a pubsub implementation. - -```JavaScript -import { createLibp2p } from 'libp2p' -import { GossipSub } from '@chainsafe/libp2p-gossipsub' -import { tcp } from '@libp2p/tcp' -import { mplex } from '@libp2p/mplex' -import { yamux } from '@chainsafe/libp2p-yamux' -import { noise } from '@chainsafe/libp2p-noise' - -const createNode = async () => { - const node = await createLibp2p({ - addresses: { - listen: ['/ip4/0.0.0.0/tcp/0'] - }, - transports: [tcp()], - streamMuxers: [yamux(), mplex()], - connectionEncryption: [noise()], - services: { - // we add the Pubsub module we want - pubsub: gossipsub({ allowPublishToZeroPeers: true }) - } - }) - - return node -} -``` - -Once that is done, we only need to create a few libp2p nodes, connect them and everything is ready to start using pubsub. - -```JavaScript -import { fromString as uint8ArrayFromString } from "uint8arrays/from-string"; -import { toString as uint8ArrayToString } from "uint8arrays/to-string"; - -const topic = 'news' - -const [node1, node2] = await Promise.all([ - createNode(), - createNode() -]) - -// Add node's 2 data to the PeerStore -await node1.peerStore.patch(node2.peerId, { - multiaddrs: node2.getMultiaddrs() -}) -await node1.dial(node2.peerId) - -node1.services.pubsub.addEventListener("message", (evt) => { - console.log(`node1 received: ${uint8ArrayToString(evt.detail.data)} on topic ${evt.detail.topic}`) -}) -await node1.services.pubsub.subscribe(topic) - -// Will not receive own published messages by default -node2.services.pubsub.addEventListener("message", (evt) => { - console.log(`node2 received: ${uint8ArrayToString(evt.detail.data)} on topic ${evt.detail.topic}`) -}) -await node2.services.pubsub.subscribe(topic) - -// node2 publishes "news" every second -setInterval(() => { - node2.services.pubsub.publish(topic, uint8ArrayFromString('Bird bird bird, bird is the word!')).catch(err => { - console.error(err) - }) -}, 1000) -``` - -The output of the program should look like: - - > node 1.js - connected to QmWpvkKm6qHLhoxpWrTswY6UMNWDyn8hN265Qp9ZYvgS82 - node1 received: Bird bird bird, bird is the word! - node1 received: Bird bird bird, bird is the word! - -You can change the pubsub `emitSelf` option if you want the publishing node to receive its own messages. - -```JavaScript -gossipsub({ allowPublishToZeroPeers: true, emitSelf: true }) -``` - -The output of the program should look like: - - > node 1.js - connected to QmWpvkKm6qHLhoxpWrTswY6UMNWDyn8hN265Qp9ZYvgS82 - node1 received: Bird bird bird, bird is the word! - node2 received: Bird bird bird, bird is the word! - node1 received: Bird bird bird, bird is the word! - node2 received: Bird bird bird, bird is the word! - -## 2. Future work - -libp2p/IPFS PubSub is enabling a whole set of Distributed Real Time applications using CRDT (Conflict-Free Replicated Data Types). It is still going through heavy research (and hacking) and we invite you to join the conversation at [research-CRDT](https://github.com/ipfs/research-CRDT). Here is a list of some of the exciting examples: - -- [PubSub Room](https://github.com/ipfs-labs/ipfs-pubsub-room) -- [Live DB - A always in Sync DB using CRDT](https://github.com/ipfs-labs/ipfs-live-db) -- [IIIF Annotations over IPFS, CRDT and libp2p](https://www.youtube.com/watch?v=hmAniA6g9D0\&feature=youtu.be\&t=10m40s) -- [orbit.chat - p2p chat application, fully running in the browser with js-ipfs, js-libp2p and orbit-db](http://orbit.chat/) - -## License - -Licensed under either of - -- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) -- MIT ([LICENSE-MIT](LICENSE-MIT) / ) - -## Contribution - -Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/examples/pubsub/message-filtering/1.js b/examples/pubsub/message-filtering/1.js deleted file mode 100644 index 03f7cff285..0000000000 --- a/examples/pubsub/message-filtering/1.js +++ /dev/null @@ -1,131 +0,0 @@ -/* eslint-disable no-console */ - -import { createLibp2p } from 'libp2p' -import { identifyService } from 'libp2p/identify' -import { tcp } from '@libp2p/tcp' -import { mplex } from '@libp2p/mplex' -import { yamux } from '@chainsafe/libp2p-yamux' -import { noise } from '@chainsafe/libp2p-noise' -import { floodsub } from '@libp2p/floodsub' -import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string' -import { toString as uint8ArrayToString } from 'uint8arrays/to-string' - -const createNode = async () => { - const node = await createLibp2p({ - addresses: { - listen: ['/ip4/0.0.0.0/tcp/0'] - }, - transports: [tcp()], - streamMuxers: [yamux(), mplex()], - connectionEncryption: [noise()], - services: { - pubsub: floodsub(), - identify: identifyService() - } - }) - - return node -} - -(async () => { - const topic = 'fruit' - - const [node1, node2, node3] = await Promise.all([ - createNode(), - createNode(), - createNode() - ]) - - // node1 conect to node2 and node2 conect to node3 - await node1.peerStore.patch(node2.peerId, { - multiaddrs: node2.getMultiaddrs() - }) - await node1.dial(node2.peerId) - - await node2.peerStore.patch(node3.peerId, { - multiaddrs: node3.getMultiaddrs() - }) - await node2.dial(node3.peerId) - - // subscribe - node1.services.pubsub.addEventListener('message', (evt) => { - if (evt.detail.topic !== topic) { - return - } - - // Will not receive own published messages by default - console.log(`node1 received: ${uint8ArrayToString(evt.detail.data)}`) - }) - node1.services.pubsub.subscribe(topic) - - node2.services.pubsub.addEventListener('message', (evt) => { - if (evt.detail.topic !== topic) { - return - } - - console.log(`node2 received: ${uint8ArrayToString(evt.detail.data)}`) - }) - node2.services.pubsub.subscribe(topic) - - node3.services.pubsub.addEventListener('message', (evt) => { - if (evt.detail.topic !== topic) { - return - } - - console.log(`node3 received: ${uint8ArrayToString(evt.detail.data)}`) - }) - node3.services.pubsub.subscribe(topic) - - // wait for subscriptions to propagate - await hasSubscription(node1, node2, topic) - await hasSubscription(node2, node3, topic) - - const validateFruit = (msgTopic, msg) => { - const fruit = uint8ArrayToString(msg.data) - const validFruit = ['banana', 'apple', 'orange'] - - // car is not a fruit ! - if (!validFruit.includes(fruit)) { - throw new Error('no valid fruit received') - } - } - - // validate fruit - node1.services.pubsub.topicValidators.set(topic, validateFruit) - node2.services.pubsub.topicValidators.set(topic, validateFruit) - node3.services.pubsub.topicValidators.set(topic, validateFruit) - - // node1 publishes "fruits" - for (const fruit of ['banana', 'apple', 'car', 'orange']) { - console.log('############## fruit ' + fruit + ' ##############') - await node1.services.pubsub.publish(topic, uint8ArrayFromString(fruit)) - } - - console.log('############## all messages sent ##############') -})() - -async function delay (ms) { - await new Promise((resolve) => { - setTimeout(() => resolve(), ms) - }) -} - -/** - * Wait for node1 to see that node2 has subscribed to the topic - * - * @param node1 - * @param node2 - * @param topic - */ -async function hasSubscription (node1, node2, topic) { - while (true) { - const subs = await node1.services.pubsub.getSubscribers(topic) - - if (subs.map(peer => peer.toString()).includes(node2.peerId.toString())) { - return - } - - // wait for subscriptions to propagate - await delay(100) - } -} diff --git a/examples/pubsub/message-filtering/README.md b/examples/pubsub/message-filtering/README.md deleted file mode 100644 index 7b9dba1309..0000000000 --- a/examples/pubsub/message-filtering/README.md +++ /dev/null @@ -1,135 +0,0 @@ -# Filter Messages - -To prevent undesired data from being propagated on the network, we can apply a filter to Gossipsub. Messages that fail validation in the filter will not be re-shared. - -## 1. Setting up a PubSub network with three nodes - -First, let's update our libp2p configuration with a pubsub implementation. - -```JavaScript -import { createLibp2p } from 'libp2p' -import { gossipsub } from '@chainsafe/libp2p-gossipsub' -import { tcp } from '@libp2p/tcp' -import { mplex } from '@libp2p/mplex' -import { yamux } from '@chainsafe/libp2p-yamux' -import { noise } from '@chainsafe/libp2p-noise' - -const createNode = async () => { - const node = await createLibp2p({ - addresses: { - listen: ['/ip4/0.0.0.0/tcp/0'] - }, - transports: [tcp()], - streamMuxers: [yamux(), mplex()], - connectionEncryption: [noise()], - // we add the Pubsub module we want - services: { - pubsub: gossipsub({ allowPublishToZeroPeers: true }) - } - }) - - return node -} -``` - -Then, create three nodes and connect them together. In this example, we will connect the nodes in series. Node 1 connected with node 2 and node 2 connected with node 3. - -```JavaScript -const [node1, node2, node3] = await Promise.all([ - createNode(), - createNode(), - createNode(), -]) - -await node1.peerStore.patch(node2.peerId, { - multiaddrs: node2.getMultiaddrs() -}) -await node1.dial(node2.peerId) - -await node2.peerStore.patch(node3.peerId, { - multiaddrs: node3.getMultiaddrs() -}) -await node2.dial(node3.peerId) -``` - -Now we' can subscribe to the fruit topic and log incoming messages. - -```JavaScript -import { fromString as uint8ArrayFromString } from "uint8arrays/from-string"; -import { toString as uint8ArrayToString } from "uint8arrays/to-string"; - -const topic = 'fruit' - -node1.services.pubsub.addEventListener('message', (msg) => { - if (msg.detail.topic !== topic) { - return - } - - console.log(`node1 received: ${uint8ArrayToString(msg.data)}`) -}) -await node1.services.pubsub.subscribe(topic) - -node2.services.pubsub.addEventListener('message', (msg) => { - if (msg.detail.topic !== topic) { - return - } - - console.log(`node2 received: ${uint8ArrayToString(msg.data)}`) -}) -await node2.services.pubsub.subscribe(topic) - -node3.services.pubsub.addEventListener('message', (msg) => { - if (msg.detail.topic !== topic) { - return - } - -console.log(`node3 received: ${uint8ArrayToString(msg.data)}`) -}) -await node3.services.pubsub.subscribe(topic) -``` -Finally, let's define the additional filter in the fruit topic. - -```JavaScript -import { TopicValidatorResult } from '@libp2p/interface/pubsub' - -const validateFruit = (msgTopic, msg) => { - const fruit = uint8ArrayToString(msg.data) - const validFruit = ['banana', 'apple', 'orange'] - - // car is not a fruit ! - if (!validFruit.includes(fruit)) { - throw new Error('no valid fruit received') - } - return TopicValidatorResult.Accept -} - -node1.services.pubsub.topicValidators.set(topic, validateFruit) -node2.services.pubsub.topicValidators.set(topic, validateFruit) -node3.services.pubsub.topicValidators.set(topic, validateFruit) -``` - -In this example, node one has an outdated version of the system, or is a malicious node. When it tries to publish fruit, the messages are re-shared and all the nodes share the message. However, when it tries to publish a vehicle the message is not re-shared. - -```JavaScript -for (const fruit of ['banana', 'apple', 'car', 'orange']) { - console.log('############## fruit ' + fruit + ' ##############') - await node1.services.pubsub.publish(topic, uint8ArrayFromString(fruit)) -} -``` - -Result - -``` -> node 1.js -############## fruit banana ############## -node2 received: banana -node3 received: banana -############## fruit apple ############## -node2 received: apple -node3 received: apple -############## fruit car ############## -############## fruit orange ############## -node1 received: orange -node2 received: orange -node3 received: orange -``` diff --git a/examples/pubsub/message-filtering/test.js b/examples/pubsub/message-filtering/test.js deleted file mode 100644 index d0ddc95b7c..0000000000 --- a/examples/pubsub/message-filtering/test.js +++ /dev/null @@ -1,56 +0,0 @@ -import path from 'path' -import { execa } from 'execa' -import pDefer from 'p-defer' -import { toString as uint8ArrayToString } from 'uint8arrays/to-string' -import { fileURLToPath } from 'url' - -const __dirname = path.dirname(fileURLToPath(import.meta.url)) - -// holds messages received by peers -const messages = {} - -export async function test () { - const defer = pDefer() - - process.stdout.write('message-filtering/1.js\n') - - const proc = execa('node', [path.join(__dirname, '1.js')], { - cwd: path.resolve(__dirname), - all: true - }) - - let output = '' - - const expected = [ - 'node2 received: banana', - 'node2 received: apple', - 'node2 received: orange', - 'node3 received: banana', - 'node3 received: apple', - 'node3 received: orange' - ] - - proc.all.on('data', async (data) => { - process.stdout.write(data) - output += uint8ArrayToString(data) - - if (output.includes('received: car')) { - defer.reject(new Error('Message validation failed - peers failed to filter car messages')) - } - - let allMessagesReceived = true - - expected.forEach(message => { - if (!output.includes(message)) { - allMessagesReceived = false - } - }) - - if (allMessagesReceived) { - defer.resolve() - } - }) - - await defer.promise - proc.kill() -} diff --git a/examples/pubsub/package.json b/examples/pubsub/package.json deleted file mode 100644 index 97c909fc67..0000000000 --- a/examples/pubsub/package.json +++ /dev/null @@ -1,47 +0,0 @@ -{ - "name": "@libp2p/example-pubsub", - "version": "0.0.0", - "description": "An example using libp2p pubsub", - "license": "Apache-2.0 OR MIT", - "homepage": "https://github.com/libp2p/js-libp2p/tree/master/examples/pubsub#readme", - "repository": { - "type": "git", - "url": "git+https://github.com/libp2p/js-libp2p.git" - }, - "bugs": { - "url": "https://github.com/libp2p/js-libp2p/issues" - }, - "type": "module", - "files": [ - "src", - "dist", - "!dist/test", - "!**/*.tsbuildinfo" - ], - "eslintConfig": { - "extends": "ipfs", - "parserOptions": { - "project": true, - "sourceType": "module" - } - }, - "scripts": { - "lint": "aegir lint", - "test:example": "node test.js" - }, - "dependencies": { - "@chainsafe/libp2p-noise": "^13.0.0", - "@chainsafe/libp2p-yamux": "^5.0.0", - "@libp2p/floodsub": "^8.0.0", - "@libp2p/mplex": "^9.0.0", - "@libp2p/tcp": "^8.0.0", - "libp2p": "^0.46.0", - "uint8arrays": "^4.0.6" - }, - "devDependencies": { - "aegir": "^41.0.2", - "execa": "^8.0.1", - "p-defer": "^4.0.0" - }, - "private": true -} diff --git a/examples/pubsub/test-1.js b/examples/pubsub/test-1.js deleted file mode 100644 index 064f4aecf6..0000000000 --- a/examples/pubsub/test-1.js +++ /dev/null @@ -1,29 +0,0 @@ -import path from 'path' -import { fileURLToPath } from 'url' -import { execa } from 'execa' -import pDefer from 'p-defer' -import { toString as uint8ArrayToString } from 'uint8arrays/to-string' - -const __dirname = path.dirname(fileURLToPath(import.meta.url)) - -export async function test () { - const defer = pDefer() - process.stdout.write('1.js\n') - - const proc = execa('node', [path.join(__dirname, '1.js')], { - cwd: path.resolve(__dirname), - all: true - }) - - proc.all.on('data', async (data) => { - process.stdout.write(data) - const line = uint8ArrayToString(data) - - if (line.includes('node1 received: Bird bird bird, bird is the word!')) { - defer.resolve() - } - }) - - await defer.promise - proc.kill() -} diff --git a/examples/pubsub/test.js b/examples/pubsub/test.js deleted file mode 100644 index 1e35941f74..0000000000 --- a/examples/pubsub/test.js +++ /dev/null @@ -1,5 +0,0 @@ -import { test as testMessageFiltering } from './message-filtering/test.js' -import { test as test1 } from './test-1.js' - -await test1() -await testMessageFiltering() diff --git a/examples/transports/1.js b/examples/transports/1.js deleted file mode 100644 index 0ca98ea875..0000000000 --- a/examples/transports/1.js +++ /dev/null @@ -1,33 +0,0 @@ -/* eslint-disable no-console */ - -import { noise } from '@chainsafe/libp2p-noise' -import { tcp } from '@libp2p/tcp' -import { createLibp2p } from 'libp2p' - -const createNode = async () => { - const node = await createLibp2p({ - addresses: { - // To signal the addresses we want to be available, we use - // the multiaddr format, a self describable address - listen: [ - '/ip4/0.0.0.0/tcp/0' - ] - }, - transports: [ - tcp() - ], - connectionEncryption: [ - noise() - ] - }) - - return node -} - -;(async () => { - const node = await createNode() - - console.log('node has started (true/false):', node.isStarted()) - console.log('listening on:') - node.getMultiaddrs().forEach((ma) => console.log(ma.toString())) -})() diff --git a/examples/transports/2.js b/examples/transports/2.js deleted file mode 100644 index 9cc39cfc85..0000000000 --- a/examples/transports/2.js +++ /dev/null @@ -1,64 +0,0 @@ -/* eslint-disable no-console */ - -import { noise } from '@chainsafe/libp2p-noise' -import { yamux } from '@chainsafe/libp2p-yamux' -import { mplex } from '@libp2p/mplex' -import { tcp } from '@libp2p/tcp' -import { pipe } from 'it-pipe' -import toBuffer from 'it-to-buffer' -import { createLibp2p } from 'libp2p' -import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string' -import { toString as uint8ArrayToString } from 'uint8arrays/to-string' - -const createNode = async () => { - const node = await createLibp2p({ - addresses: { - // To signal the addresses we want to be available, we use - // the multiaddr format, a self describable address - listen: ['/ip4/0.0.0.0/tcp/0'] - }, - transports: [tcp()], - connectionEncryption: [noise()], - streamMuxers: [yamux(), mplex()] - }) - - return node -} - -function printAddrs (node, number) { - console.log('node %s is listening on:', number) - node.getMultiaddrs().forEach((ma) => console.log(ma.toString())) -} - -(async () => { - const [node1, node2] = await Promise.all([ - createNode(), - createNode() - ]) - - printAddrs(node1, '1') - printAddrs(node2, '2') - - node2.handle('/print', async ({ stream }) => { - const result = await pipe( - stream, - async function * (source) { - for await (const list of source) { - yield list.subarray() - } - }, - toBuffer - ) - console.log(uint8ArrayToString(result)) - }) - - await node1.peerStore.patch(node2.peerId, { - multiaddrs: node2.getMultiaddrs() - }) - const stream = await node1.dialProtocol(node2.peerId, '/print') - - await pipe( - ['Hello', ' ', 'p2p', ' ', 'world', '!'].map(str => uint8ArrayFromString(str)), - stream - ) -})() diff --git a/examples/transports/3.js b/examples/transports/3.js deleted file mode 100644 index 4663b5563e..0000000000 --- a/examples/transports/3.js +++ /dev/null @@ -1,91 +0,0 @@ -/* eslint-disable no-console */ - -import { noise } from '@chainsafe/libp2p-noise' -import { yamux } from '@chainsafe/libp2p-yamux' -import { mplex } from '@libp2p/mplex' -import { tcp } from '@libp2p/tcp' -import { webSockets } from '@libp2p/websockets' -import { pipe } from 'it-pipe' -import { createLibp2p } from 'libp2p' -import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string' -import { toString as uint8ArrayToString } from 'uint8arrays/to-string' - -const createNode = async (transports, addresses = []) => { - if (!Array.isArray(addresses)) { - addresses = [addresses] - } - - const node = await createLibp2p({ - addresses: { - listen: addresses - }, - transports, - connectionEncryption: [noise()], - streamMuxers: [yamux(), mplex()] - }) - - return node -} - -function printAddrs (node, number) { - console.log('node %s is listening on:', number) - node.getMultiaddrs().forEach((ma) => console.log(ma.toString())) -} - -function print ({ stream }) { - pipe( - stream, - async function (source) { - for await (const msg of source) { - console.log(uint8ArrayToString(msg.subarray())) - } - } - ) -} - -(async () => { - const [node1, node2, node3] = await Promise.all([ - createNode([tcp()], '/ip4/0.0.0.0/tcp/0'), - createNode([tcp(), webSockets()], ['/ip4/0.0.0.0/tcp/0', '/ip4/127.0.0.1/tcp/10000/ws']), - createNode([webSockets()], '/ip4/127.0.0.1/tcp/20000/ws') - ]) - - printAddrs(node1, '1') - printAddrs(node2, '2') - printAddrs(node3, '3') - - node1.handle('/print', print) - node2.handle('/print', print) - node3.handle('/print', print) - - await node1.peerStore.patch(node2.peerId, { - multiaddrs: node2.getMultiaddrs() - }) - await node2.peerStore.patch(node3.peerId, { - multiaddrs: node3.getMultiaddrs() - }) - await node3.peerStore.patch(node1.peerId, { - multiaddrs: node1.getMultiaddrs() - }) - - // node 1 (TCP) dials to node 2 (TCP+WebSockets) - const stream = await node1.dialProtocol(node2.peerId, '/print') - await pipe( - [uint8ArrayFromString('node 1 dialed to node 2 successfully')], - stream - ) - - // node 2 (TCP+WebSockets) dials to node 3 (WebSockets) - const stream2 = await node2.dialProtocol(node3.peerId, '/print') - await pipe( - [uint8ArrayFromString('node 2 dialed to node 3 successfully')], - stream2 - ) - - // node 3 (listening WebSockets) can dial node 1 (TCP) - try { - await node3.dialProtocol(node1.peerId, '/print') - } catch (err) { - console.log('node 3 failed to dial to node 1 with:', err.message) - } -})() diff --git a/examples/transports/4.js b/examples/transports/4.js deleted file mode 100644 index 6ce792e669..0000000000 --- a/examples/transports/4.js +++ /dev/null @@ -1,81 +0,0 @@ -/* eslint-disable no-console */ - -import fs from 'fs' -import https from 'https' -import { noise } from '@chainsafe/libp2p-noise' -import { yamux } from '@chainsafe/libp2p-yamux' -import { mplex } from '@libp2p/mplex' -import { tcp } from '@libp2p/tcp' -import { webSockets } from '@libp2p/websockets' -import { pipe } from 'it-pipe' -import { createLibp2p } from 'libp2p' -import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string' -import { toString as uint8ArrayToString } from 'uint8arrays/to-string' - -const httpServer = https.createServer({ - cert: fs.readFileSync('./test_certs/cert.pem'), - key: fs.readFileSync('./test_certs/key.pem') -}) - -const createNode = async (addresses = []) => { - if (!Array.isArray(addresses)) { - addresses = [addresses] - } - - const node = await createLibp2p({ - addresses: { - listen: addresses - }, - transports: [ - tcp(), - webSockets({ - server: httpServer, - websocket: { - rejectUnauthorized: false - } - }) - ], - connectionEncryption: [noise()], - streamMuxers: [mplex(), yamux()] - }) - - return node -} - -function printAddrs (node, number) { - console.log('node %s is listening on:', number) - node.getMultiaddrs().forEach((ma) => console.log(ma.toString())) -} - -function print ({ stream }) { - pipe( - stream, - async function (source) { - for await (const msg of source) { - console.log(uint8ArrayToString(msg.subarray())) - } - } - ) -} - -(async () => { - const [node1, node2] = await Promise.all([ - createNode('/ip4/127.0.0.1/tcp/10000/wss'), - createNode([]) - ]) - - printAddrs(node1, '1') - printAddrs(node2, '2') - - node1.handle('/print', print) - node2.handle('/print', print) - - const targetAddr = node1.getMultiaddrs()[0] - - // node 2 (Secure WebSockets) dials to node 1 (Secure Websockets) - const stream = await node2.dialProtocol(targetAddr, '/print') - await pipe( - [uint8ArrayFromString('node 2 dialed to node 1 successfully')], - stream - ) -})() diff --git a/examples/transports/LICENSE b/examples/transports/LICENSE deleted file mode 100644 index 20ce483c86..0000000000 --- a/examples/transports/LICENSE +++ /dev/null @@ -1,4 +0,0 @@ -This project is dual licensed under MIT and Apache-2.0. - -MIT: https://www.opensource.org/licenses/mit -Apache-2.0: https://www.apache.org/licenses/license-2.0 diff --git a/examples/transports/LICENSE-APACHE b/examples/transports/LICENSE-APACHE deleted file mode 100644 index 14478a3b60..0000000000 --- a/examples/transports/LICENSE-APACHE +++ /dev/null @@ -1,5 +0,0 @@ -Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at - -http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. diff --git a/examples/transports/LICENSE-MIT b/examples/transports/LICENSE-MIT deleted file mode 100644 index 72dc60d84b..0000000000 --- a/examples/transports/LICENSE-MIT +++ /dev/null @@ -1,19 +0,0 @@ -The MIT License (MIT) - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/examples/transports/README.md b/examples/transports/README.md deleted file mode 100644 index eac5a5009a..0000000000 --- a/examples/transports/README.md +++ /dev/null @@ -1,336 +0,0 @@ -# @libp2p/example-transports - -[![libp2p.io](https://img.shields.io/badge/project-libp2p-yellow.svg?style=flat-square)](http://libp2p.io/) -[![Discuss](https://img.shields.io/discourse/https/discuss.libp2p.io/posts.svg?style=flat-square)](https://discuss.libp2p.io) -[![codecov](https://img.shields.io/codecov/c/github/libp2p/js-libp2p.svg?style=flat-square)](https://codecov.io/gh/libp2p/js-libp2p) -[![CI](https://img.shields.io/github/actions/workflow/status/libp2p/js-libp2p/main.yml?branch=master\&style=flat-square)](https://github.com/libp2p/js-libp2p/actions/workflows/main.yml?query=branch%3Amaster) - -> An example using different types of libp2p transport - -## Table of contents - -- [1. Creating a libp2p node with TCP](#1-creating-a-libp2p-node-with-tcp) -- [2. Dialing from one node to another node](#2-dialing-from-one-node-to-another-node) -- [3. Using multiple transports](#3-using-multiple-transports) -- [4. How to create a new libp2p transport](#4-how-to-create-a-new-libp2p-transport) -- [License](#license) -- [Contribution](#contribution) - -A more complete definition of what is a transport can be found on the [interface-transport] specification. A way to recognize a candidate transport is through the badge: - -![][interface-transport badge] - -## 1. Creating a libp2p node with TCP - -When using libp2p, you need properly configure it, that is, pick your set of modules and create your network stack with the properties you need. In this example, we will create a libp2p node TCP. You can find the complete solution on the file [1.js](./1.js). - -You will need 4 dependencies total, so go ahead and install all of them with: - -```bash -> npm install libp2p @libp2p/tcp @chainsafe/libp2p-noise -``` - -Then, in your favorite text editor create a file with the `.js` extension. I've called mine `1.js`. - -First thing is to create our own libp2p node! Insert: - -```JavaScript -import { createLibp2p } from 'libp2p' -import { tcp } from '@libp2p/tcp' -import { noise } from '@chainsafe/libp2p-noise' - -const createNode = async () => { - const node = await createLibp2p({ - addresses: { - // To signal the addresses we want to be available, we use - // the multiaddr format, a self describable address - listen: ['/ip4/0.0.0.0/tcp/0'] - }, - transports: [ - tcp() - ], - connectionEncryption: [ - noise() - ] - }) - - return node -} -``` - -Now that we have a function to create our own libp2p node, let's create a node with it. - -```JavaScript -const node = await createNode() - -// At this point the node has started -console.log('node has started (true/false):', node.isStarted()) -// And we can print the now listening addresses. -// If you are familiar with TCP, you might have noticed -// that we specified the node to listen in 0.0.0.0 and port -// 0, which means "listen in any network interface and pick -// a port for me -console.log('listening on:') -node.getMultiaddrs().forEach((ma) => console.log(ma.toString())) -``` - -Running this should result in something like: - -```bash -> node 1.js -node has started (true/false): true -listening on: -/ip4/127.0.0.1/tcp/61329/p2p/QmW2cKTakTYqbQkUzBTEGXgWYFj1YEPeUndE1YWs6CBzDQ -/ip4/192.168.2.156/tcp/61329/p2p/QmW2cKTakTYqbQkUzBTEGXgWYFj1YEPeUndE1YWs6CBzDQ -``` - -That `QmW2cKTakTYqbQkUzBTEGXgWYFj1YEPeUndE1YWs6CBzDQ` is the PeerId that was created during the PeerInfo generation. - -## 2. Dialing from one node to another node - -Now that we have our `createNode` function, let's create two nodes and make them dial to each other! You can find the complete solution at [2.js](./2.js). - -For this step, we will need some more dependencies. - -```bash -> npm install it-pipe it-all @libp2p/mplex -``` - -And we also need to import the modules on our .js file: - -```js -import { pipe } from 'it-pipe' -import { mplex } from '@libp2p/mplex' -import { yamux } from '@chainsafe/libp2p-yamux' -import all from 'it-all' -``` - -We are going to reuse the `createNode` function from step 1, but this time add a stream multiplexer from `libp2p-mplex`. - -```js -const createNode = async () => { - const node = await createLibp2p({ - addresses: { - // To signal the addresses we want to be available, we use - // the multiaddr format, a self describable address - listen: ['/ip4/0.0.0.0/tcp/0'] - }, - transports: [tcp()], - connectionEncryption: [noise()], - streamMuxers: [yamux(), mplex()] // <--- Add this line - }) - - return node -} -``` - -We will also make things simpler by creating another function to print the multiaddresses to avoid duplicating code. - -```JavaScript -function printAddrs (node, number) { - console.log('node %s is listening on:', number) - node.getMultiaddrs().forEach((ma) => console.log(ma.toString())) -} -``` - -Then add, - -```js -import { fromString as uint8ArrayFromString } from "uint8arrays/from-string"; -import { toString as uint8ArrayToString } from "uint8arrays/to-string"; - -const [node1, node2] = await Promise.all([ - createNode(), - createNode() -]) - -printAddrs(node1, '1') -printAddrs(node2, '2') - -node2.handle('/print', async ({ stream }) => { - const result = await pipe( - stream, - all - ) - console.log(result.map(buf => uint8ArrayToString(buf.subarray())).join("")) -}) - -await node1.peerStore.patch(node2.peerId, { - multiaddrs: node2.getMultiaddrs() -}) -const stream = await node1.dialProtocol(node2.peerId, '/print') - -await pipe( - ['Hello', ' ', 'p2p', ' ', 'world', '!'].map(str => uint8ArrayFromString(str)), - stream -) -``` - -For more information refer to the [docs](https://github.com/libp2p/js-libp2p/blob/master/doc/API.md). - -The result should look like: - -```bash -> node 2.js -node 1 is listening on: -/ip4/127.0.0.1/tcp/62279/p2p/QmeM4wNWv1uci7UJjUXZYfvcy9uqAbw7G9icuxdqy88Mj9 -/ip4/192.168.2.156/tcp/62279/p2p/QmeM4wNWv1uci7UJjUXZYfvcy9uqAbw7G9icuxdqy88Mj9 -node 2 is listening on: -/ip4/127.0.0.1/tcp/62278/p2p/QmWp58xJgzbouNJcyiNNTpZuqQCJU8jf6ixc7TZT9xEZhV -/ip4/192.168.2.156/tcp/62278/p2p/QmWp58xJgzbouNJcyiNNTpZuqQCJU8jf6ixc7TZT9xEZhV -Hello p2p world! -``` - -## 3. Using multiple transports - -Next, we want nodes to have multiple transports available to increase their chances of having a common transport in the network to communicate over. A simple scenario is a node running in the browser only having access to HTTP, WebSockets and WebRTC since the browser doesn't let you open any other kind of transport. For this node to dial to some other node, that other node needs to share a common transport. - -What we are going to do in this step is to create 3 nodes: one with TCP, another with TCP+WebSockets and another one with just WebSockets. The full solution can be found on [3.js](./3.js). - -In this example, we will need to also install `@libp2p/websockets`: - -```bash -> npm install @libp2p/websockets -``` - -We want to create 3 nodes: one with TCP, one with TCP+WebSockets and one with just WebSockets. We need to update our `createNode` function to accept WebSocket connections as well. Moreover, let's upgrade our function to enable us to pick the addresses over which a node will start a listener: - -```JavaScript -// ... - -const createNode = async (transports, addresses = []) => { - if (!Array.isArray(addresses)) { - addresses = [addresses] - } - - const node = await createLibp2p({ - addresses: { - listen: addresses - }, - transports: transports, - connectionEncryption: [noise()], - streamMuxers: [yamux(), mplex()] - }) - - return node -} -``` - -As a rule, a libp2p node will only be capable of using a transport if: a) it has the module for it and b) it was given a multiaddr to listen on. The only exception to this rule is WebSockets in the browser, where a node can dial out, but unfortunately cannot open a socket. - -Let's update our flow to create nodes and see how they behave when dialing to each other: - -```JavaScript -import { webSockets } from '@libp2p/websockets' -import { tcp } from '@libp2p/tcp' - -const [node1, node2, node3] = await Promise.all([ - createNode([tcp()], '/ip4/0.0.0.0/tcp/0'), - createNode([tcp(), webSockets()], ['/ip4/0.0.0.0/tcp/0', '/ip4/127.0.0.1/tcp/10000/ws']), - createNode([webSockets()], '/ip4/127.0.0.1/tcp/20000/ws') -]) - -printAddrs(node1, '1') -printAddrs(node2, '2') -printAddrs(node3, '3') - -node1.handle('/print', print) -node2.handle('/print', print) -node3.handle('/print', print) - -await node1.peerStore.patch(node2.peerId, { - multiaddrs: node2.getMultiaddrs() -}) -await node2.peerStore.patch(node3.peerId, { - multiaddrs: node3.getMultiaddrs() -}) -await node3.peerStore.patch(node1.peerId, { - multiaddrs: node1.getMultiaddrs() -}) - -// node 1 (TCP) dials to node 2 (TCP+WebSockets) -const stream = await node1.dialProtocol(node2.peerId, '/print') -await pipe( - ['node 1 dialed to node 2 successfully'].map(str => uint8ArrayFromString(str)), - stream -) - -// node 2 (TCP+WebSockets) dials to node 3 (WebSockets) -const stream2 = await node2.dialProtocol(node3.peerId, '/print') -await pipe( - ['node 2 dialed to node 3 successfully'].map(str => uint8ArrayFromString(str)), - stream2 -) - -// node 3 (WebSockets) attempts to dial to node 1 (TCP) -try { - await node3.dialProtocol(node1.peerId, '/print') -} catch (err) { - console.log('node 3 failed to dial to node 1 with:', err.message) -} -``` - -`print` is a function that prints each piece of data from a stream onto a new line but factored into its own function to save lines: - -```JavaScript -function print ({ stream }) { - pipe( - stream, - async function (source) { - for await (const msg of source) { - console.log(uint8ArrayToString(msg.subarray())) - } - } - ) -} -``` - -If everything was set correctly, you now should see something similar to the following after running the script: - -```Bash -> node 3.js -node 1 is listening on: -/ip4/127.0.0.1/tcp/62620/p2p/QmWpWmcVJkF6EpmAaVDauku8g1uFGuxPsGP35XZp9GYEqs -/ip4/192.168.2.156/tcp/62620/p2p/QmWpWmcVJkF6EpmAaVDauku8g1uFGuxPsGP35XZp9GYEqs -node 2 is listening on: -/ip4/127.0.0.1/tcp/10000/ws/p2p/QmWAQtWdzWXibgfyc7WRHhhv6MdqVKzXvyfSTnN2aAvixX -/ip4/127.0.0.1/tcp/62619/p2p/QmWAQtWdzWXibgfyc7WRHhhv6MdqVKzXvyfSTnN2aAvixX -/ip4/192.168.2.156/tcp/62619/p2p/QmWAQtWdzWXibgfyc7WRHhhv6MdqVKzXvyfSTnN2aAvixX -node 3 is listening on: -/ip4/127.0.0.1/tcp/20000/ws/p2p/QmVq1PWh3VSDYdFqYMtqp4YQyXcrH27N7968tGdM1VQPj1 -node 1 dialed to node 2 successfully -node 2 dialed to node 3 successfully -node 3 failed to dial to node 1 with: - Error: No transport available for address /ip4/127.0.0.1/tcp/51482 -``` - -As expected, we created 3 nodes: node 1 with TCP, node 2 with TCP+WebSockets and node 3 with just WebSockets. node 1 -> node 2 and node 2 -> node 3 managed to dial correctly because they shared a common transport; however, node 3 -> node 1 failed because they didn't share any. - -## 4. How to create a new libp2p transport - -Today there are already several transports available and plenty to come. You can find these at [interface-transport implementations] list. - -Adding more transports is done through the same way as you added TCP and WebSockets. Some transports might offer extra functionalities, but as far as libp2p is concerned, if it follows the interface defined in the [spec][interface-transport api] it will be able to use it. - -If you decide to implement a transport yourself, please consider adding to the list so that others can use it as well. - -Hope this tutorial was useful. We are always looking to improve it, so contributions are welcome! - -## License - -Licensed under either of - -- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) -- MIT ([LICENSE-MIT](LICENSE-MIT) / ) - -## Contribution - -Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. - -[interface-transport]: https://github.com/libp2p/js-libp2p-interfaces/tree/master/packages/libp2p-interfaces/src/transport - -[interface-transport badge]: https://raw.githubusercontent.com/libp2p/js-libp2p-interfaces/master/packages/libp2p-interfaces/src/transport/img/badge.png - -[interface-transport implementations]: https://github.com/libp2p/js-libp2p-interfaces/tree/master/packages/libp2p-interfaces/src/transport#modules-that-implement-the-interface - -[interface-transport api]: https://github.com/libp2p/js-libp2p-interfaces/tree/master/packages/libp2p-interfaces/src/transport#api diff --git a/examples/transports/package.json b/examples/transports/package.json deleted file mode 100644 index c5c06b6f19..0000000000 --- a/examples/transports/package.json +++ /dev/null @@ -1,48 +0,0 @@ -{ - "name": "@libp2p/example-transports", - "version": "0.0.0", - "description": "An example using different types of libp2p transport", - "license": "Apache-2.0 OR MIT", - "homepage": "https://github.com/libp2p/js-libp2p/tree/master/examples/transports#readme", - "repository": { - "type": "git", - "url": "git+https://github.com/libp2p/js-libp2p.git" - }, - "bugs": { - "url": "https://github.com/libp2p/js-libp2p/issues" - }, - "type": "module", - "files": [ - "src", - "dist", - "!dist/test", - "!**/*.tsbuildinfo" - ], - "eslintConfig": { - "extends": "ipfs", - "parserOptions": { - "project": true, - "sourceType": "module" - } - }, - "scripts": { - "lint": "aegir lint", - "test:example": "node test.js" - }, - "dependencies": { - "@chainsafe/libp2p-noise": "^13.0.0", - "@chainsafe/libp2p-yamux": "^5.0.0", - "@libp2p/mplex": "^9.0.0", - "@libp2p/tcp": "^8.0.0", - "@libp2p/websockets": "^7.0.0", - "it-pipe": "^3.0.1", - "it-to-buffer": "^4.0.2", - "libp2p": "^0.46.0", - "uint8arrays": "^4.0.6" - }, - "devDependencies": { - "aegir": "^41.0.2", - "test-ipfs-example": "^1.0.0" - }, - "private": true -} diff --git a/examples/transports/test-1.js b/examples/transports/test-1.js deleted file mode 100644 index d94544ce17..0000000000 --- a/examples/transports/test-1.js +++ /dev/null @@ -1,13 +0,0 @@ -import path from 'path' -import { fileURLToPath } from 'url' -import { waitForOutput } from 'test-ipfs-example/node' - -const __dirname = path.dirname(fileURLToPath(import.meta.url)) - -export async function test () { - process.stdout.write('1.js\n') - - await waitForOutput('/p2p/', 'node', [path.join(__dirname, '1.js')], { - cwd: __dirname - }) -} diff --git a/examples/transports/test-2.js b/examples/transports/test-2.js deleted file mode 100644 index f254851cb9..0000000000 --- a/examples/transports/test-2.js +++ /dev/null @@ -1,13 +0,0 @@ -import path from 'path' -import { fileURLToPath } from 'url' -import { waitForOutput } from 'test-ipfs-example/node' - -const __dirname = path.dirname(fileURLToPath(import.meta.url)) - -export async function test () { - process.stdout.write('2.js\n') - - await waitForOutput('Hello p2p world!', 'node', [path.join(__dirname, '2.js')], { - cwd: __dirname - }) -} diff --git a/examples/transports/test-3.js b/examples/transports/test-3.js deleted file mode 100644 index 242af9a737..0000000000 --- a/examples/transports/test-3.js +++ /dev/null @@ -1,13 +0,0 @@ -import path from 'path' -import { fileURLToPath } from 'url' -import { waitForOutput } from 'test-ipfs-example/node' - -const __dirname = path.dirname(fileURLToPath(import.meta.url)) - -export async function test () { - process.stdout.write('3.js\n') - - await waitForOutput('node 3 failed to dial to node 1 with:', 'node', [path.join(__dirname, '3.js')], { - cwd: __dirname - }) -} diff --git a/examples/transports/test-4.js b/examples/transports/test-4.js deleted file mode 100644 index 6c4850e08b..0000000000 --- a/examples/transports/test-4.js +++ /dev/null @@ -1,13 +0,0 @@ -import path from 'path' -import { fileURLToPath } from 'url' -import { waitForOutput } from 'test-ipfs-example/node' - -const __dirname = path.dirname(fileURLToPath(import.meta.url)) - -export async function test () { - process.stdout.write('4.js\n') - - await waitForOutput('node 2 dialed to node 1 successfully', 'node', [path.join(__dirname, '4.js')], { - cwd: __dirname - }) -} diff --git a/examples/transports/test.js b/examples/transports/test.js deleted file mode 100644 index bc53a61f46..0000000000 --- a/examples/transports/test.js +++ /dev/null @@ -1,9 +0,0 @@ -import { test as test1 } from './test-1.js' -import { test as test2 } from './test-2.js' -import { test as test3 } from './test-3.js' -import { test as test4 } from './test-4.js' - -await test1() -await test2() -await test3() -await test4() diff --git a/examples/transports/test_certs/cert.pem b/examples/transports/test_certs/cert.pem deleted file mode 100644 index 0574192b2c..0000000000 --- a/examples/transports/test_certs/cert.pem +++ /dev/null @@ -1,32 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIFlzCCA3+gAwIBAgIUMYedwb9L/BtvZ7Lhu71iSKrXsa4wDQYJKoZIhvcNAQEL -BQAwajELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAlZBMREwDwYDVQQHDAhTb21lQ2l0 -eTESMBAGA1UECgwJTXlDb21wYW55MRMwEQYDVQQLDApNeURpdmlzaW9uMRIwEAYD -VQQDDAkxMjcuMC4wLjEwHhcNMjEwNDI4MDIzMjA5WhcNMjIwNDI4MDIzMjA5WjBq -MQswCQYDVQQGEwJVUzELMAkGA1UECAwCVkExETAPBgNVBAcMCFNvbWVDaXR5MRIw -EAYDVQQKDAlNeUNvbXBhbnkxEzARBgNVBAsMCk15RGl2aXNpb24xEjAQBgNVBAMM -CTEyNy4wLjAuMTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANNhXBu0 -GH1Kzl9iaQxCxEnyyAShS5FYScdKxqpYsgJT4poLWLQBZQEFLEqbdillIlTZqMss -jWqkFL2xmjqdcnOKFEZUarntVE2hxFYYQex2Fi8MYwFj+Pvt74d02xPyfzFNFgyX -a1EakoGBwClaf3I7jW7raPudjcf4HnwQ7r/NwiO8FqHFZgLcTnwI8bk+cxDoDAqu -mhqMB5nnerqvKEyR9Fb2PoL+8PwOPJOOKTDVwLMeMJu2WLR8AU2FzOj5SVI2qsu9 -Ps5azysD8KQAMcw4y9s6do36SaMQS85fbvXBV7XBqMD34HPBUbFiCoFoaCzK9Zfb -pCXyVJMUNmw5hyq9nbjUt4Kvr/58bU2gjUKSdPf6KhBxFnDZwl+2qqPdVIb/qtwz -HExtJWq3upklXNOg3HoR6vcr1O9ReJHrzLRMEb51WP1aN/qJ2/lRskcZ4A806qwr -W67BvnOg6s3ZtxHN9v3bsyfsvC66w8PEfCnCVxugC7cUW0gtW54AU75T3ukg7X+m -vECr/+qIzNEBIxxCPgefCG/JAdJhQ5SCvoARAVPStUIWDmigDeOt7go5nKbdVIJ4 -7bbBFUhHT2mTHu30fHhRqSDcHzwE7Zz6YJIJmKq29UmzUazFnKlLU67MjLJwiDPm -fC3GyOdAWkkZE5hjtkiy+3yWoEHhaJYRI1u3AgMBAAGjNTAzMAsGA1UdDwQEAwIE -MDATBgNVHSUEDDAKBggrBgEFBQcDATAPBgNVHREECDAGhwR/AAABMA0GCSqGSIb3 -DQEBCwUAA4ICAQCx/ynu4iCQAK8VId/QQe7GqgOpFgx+6Mce9GQC6ZVEjAPgapsS -Pl+l6+11cFjHKv0+Z/iN2JgkFmNXfwJcfYI0tHbMK+0U9hgKb1eFgiIwCqb4cPOz -wMwusZ95BjIbtcEbL/+pMUpNhmjPz1fOILJZtDVq++lqJCv7t8+SoAmMVYtlcLNg -muuV/UYR3uqvnAJmjgJVWs4otDGrxCYJE48M+9L2Gm05Htpi9WL1bZaQ+fJ85m85 -daedLc6R1/ZRTIH6i73sD4rYs0bx1fCJvkbcgXtKMHEkiHuG/MzR7Pa4cJAVKCx9 -lRTgrO7Gkllt2+jp4qg0YhdNq89e0DNA5cyB9H4udRgHQOcrlVRiX9OD/Kz+F5m/ -fQwMdbnqdg3ar5DSa8Q5g3bdLbNSCcI9sjCLTkNxUC/XTWGdG03RCVIt1qvBvZHk -JaG6xGpbRZ5CN0T9eindd38JBrkPAPfgl6qhwvcqh6uVFYua+7KmF9K+mKarlmMw -6RWaw2j4sMgUyRIS6fR9vDc20SrtoNvKQM1U6+0VYs1nizfkmsqqqRODmERKbKwc -ahKJFubXfr8gz+PipAKFZbxr2EPAyoiNkx+0eM6Eedo55oP2BoGHEfXEoAonyMFM -F/xTbpFtdRYE2hwsZCk86fpbcPTmdCY8txeZ7+4Bme2d9XXsTAxF64usqQ== ------END CERTIFICATE----- diff --git a/examples/transports/test_certs/key.pem b/examples/transports/test_certs/key.pem deleted file mode 100644 index dfee30176f..0000000000 --- a/examples/transports/test_certs/key.pem +++ /dev/null @@ -1,52 +0,0 @@ ------BEGIN PRIVATE KEY----- -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 -xfk6H6FDZv4ao7QSrFR4hlTIz6V9/aqQkdOhsBSQyQKCAQEAzHwz4Qr5xVduGLbY -S6HV/7vHDI6Jf+3lBvqUidWa013w5yls3sZXsSckkgshRoVMszayIbystnXJMNcx -YlEDWn3iIItzHNHMKkzdOvsCETMIlvnkt6UTmK4xY+dSq4jp7Ty0N+qi8fdaCb2q -tyrYTnHHYId6bUHMBY5QZsYAaTNvYNAO96A0UaNyl42q84iTiLkJYg9SsQPad15W -7gU84Jk6rEMYdndQDvEAHpnZ1y0yA2vtySZYsbK0wj34tgTl+0/8izn7JgF4ezNH -6iQ7Z0OuDT763IrmIxBH0ZEi9YnwSYyIsr6iUYjlQIUuPFRnQYQXEdm5Xfw1pZsL -xhYoTwKCAQB9edDe4LX+0z9i4qr0iHV8H/WoyI5UD/Pc217PKkYM3+ewR9SL9D9z -TS78Sl7HgRgEmIu+MR/u5B2ePf7jkvB/oxyPwqAzJeJ72mV3Mevm27G/Ndd8lt5W -FBCGOx7ZeP4/Cv4mvPD979ix2IalDoWMSWJnpQPN+B1jGeCrUYAXQc1k/vU99gLa -8Tuu3WfBpVAsO7hAC9mu6tuLyfKVqiMOVs2aky9xLqiqW/6uIcGu+owrr+gkDDY/ -JfBSUfxYKcjtJiHOEbFGrrRe93XsngmaTz/Hv9A/QLVCuJgWEHlt4WHSc+BtAtaV -9avp6VlyVNfe4KEKW7IekrI0cmfMdXkl ------END PRIVATE KEY----- diff --git a/package.json b/package.json index bb6e033168..4515fc2584 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ }, "private": true, "scripts": { - "reset": "aegir run clean && aegir clean interop/node_modules examples/*/node_modules packages/*/node_modules node_modules package-lock.json packages/*/package-lock.json examples/*/package-lock.json interop/*/package-lock.json", + "reset": "aegir run clean && aegir clean interop/node_modules packages/*/node_modules node_modules package-lock.json packages/*/package-lock.json interop/*/package-lock.json", "test": "aegir run test", "test:node": "aegir run test:node", "test:chrome": "aegir run test:chrome", @@ -21,10 +21,8 @@ "test:firefox": "aegir run test:firefox", "test:firefox-webworker": "aegir run test:firefox-webworker", "test:electron-main": "aegir run test:electron-main", - "test:external": "aegir run test:external", "test:cli": "aegir run test:cli", "test:interop": "aegir run test:interop", - "test:example": "aegir run test:example", "coverage": "aegir run coverage", "build": "aegir run build", "clean": "aegir run clean", @@ -33,8 +31,8 @@ "release": "run-s build docs:no-publish npm:release docs", "npm:release": "aegir exec --bail false npm -- publish", "release:rc": "aegir release-rc", - "docs": "NODE_OPTIONS=--max_old_space_size=8192 aegir docs -- --exclude interop --exclude examples/auto-relay --exclude examples/chat --exclude examples/connection-encryption --exclude examples/delegated-routing --exclude examples/discovery-mechanisms --exclude examples/echo --exclude examples/peer-and-content-routing --exclude examples/pnet --exclude examples/protocol-and-stream-muxing --exclude examples/pubsub --exclude examples/transports --exclude doc", - "docs:no-publish": "NODE_OPTIONS=--max_old_space_size=8192 aegir docs --publish false -- --exclude interop --exclude examples/auto-relay --exclude examples/chat --exclude examples/connection-encryption --exclude examples/delegated-routing --exclude examples/discovery-mechanisms --exclude examples/echo --exclude examples/peer-and-content-routing --exclude examples/pnet --exclude examples/protocol-and-stream-muxing --exclude examples/pubsub --exclude examples/transports --exclude doc" + "docs": "NODE_OPTIONS=--max_old_space_size=8192 aegir docs -- --exclude interop --exclude doc", + "docs:no-publish": "NODE_OPTIONS=--max_old_space_size=8192 aegir docs --publish false -- --exclude interop --exclude doc" }, "devDependencies": { "aegir": "^41.0.2" @@ -47,7 +45,6 @@ }, "workspaces": [ "doc", - "examples/*", "interop", "packages/*" ] diff --git a/packages/libp2p/README.md b/packages/libp2p/README.md index 4e5f48828a..28dca9a77e 100644 --- a/packages/libp2p/README.md +++ b/packages/libp2p/README.md @@ -78,7 +78,7 @@ We've come a long way, but this project is still in Alpha, lots of development i The documentation in the master branch may contain changes from a pre-release. If you are looking for the documentation of the latest release, you can view the latest release on [**npm**](https://www.npmjs.com/package/libp2p), or select the tag in github that matches the version you are looking for. -**Want to get started?** Check our [GETTING\_STARTED.md](./doc/GETTING_STARTED.md) guide and [examples folder](/examples). +**Want to get started?** Check our [GETTING\_STARTED.md](./doc/GETTING_STARTED.md) guide and [examples repo](https://github.com/libp2p/js-libp2p-examples). **Want to update libp2p in your project?** Check our [migrations folder](./doc/migrations). @@ -123,7 +123,7 @@ If you are starting your journey with `js-libp2p`, read the [GETTING\_STARTED.md ### Tutorials and Examples -You can find multiple examples on the [examples folder](./examples) that will guide you through using libp2p for several scenarios. +You can find multiple examples on the [examples repo](https://github.com/libp2p/js-libp2p-examples) that will guide you through using libp2p for several scenarios. ## Development diff --git a/packages/libp2p/src/pnet/README.md b/packages/libp2p/src/pnet/README.md index 45708eda85..94d03c0362 100644 --- a/packages/libp2p/src/pnet/README.md +++ b/packages/libp2p/src/pnet/README.md @@ -8,7 +8,6 @@ js-libp2p-pnet ## Table of Contents - [Usage](#usage) -- [Examples](#examples) - [Private Shared Keys](#private-shared-keys) - [PSK Generation](#psk-generation) - [From a module using libp2p](#from-a-module-using-libp2p) @@ -32,9 +31,6 @@ const node = await createLibp2p({ }) ``` -## Examples -[Private Networks with IPFS](../../examples/pnet-ipfs) - ## Private Shared Keys Private Shared Keys are expected to be in the following format: diff --git a/packages/transport-webrtc/README.md b/packages/transport-webrtc/README.md index 6b13043a49..2c0aa57200 100644 --- a/packages/transport-webrtc/README.md +++ b/packages/transport-webrtc/README.md @@ -12,7 +12,6 @@ - [Install](#install) - [Browser ` ``` -This repo contains the JavaScript implementation of the crypto primitives needed for libp2p. This is based on this [go implementation](https://github.com/libp2p/go-libp2p-crypto). - -## Lead Maintainer - -[Jacob Heun](https://github.com/jacobheun/) - -## Usage - -```js -const crypto = require('libp2p-crypto') - -// Now available to you: -// -// crypto.aes -// crypto.hmac -// crypto.keys -// etc. -// -// See full API details below... -``` - -### Web Crypto API - -The `libp2p-crypto` library depends on the [Web Crypto API](https://developer.mozilla.org/en-US/docs/Web/API/Web_Crypto_API) in the browser. Web Crypto is available in all modern browsers, however browsers restrict its usage to [Secure Contexts](https://developer.mozilla.org/en-US/docs/Web/Security/Secure_Contexts). - -**This means you will not be able to use some `libp2p-crypto` functions in the browser when the page is served over HTTP.** To enable the Web Crypto API and allow `libp2p-crypto` to work fully, please serve your page over HTTPS. - -## API - -### `crypto.aes` - -Exposes an interface to AES encryption (formerly Rijndael), as defined in U.S. Federal Information Processing Standards Publication 197. - -This uses `CTR` mode. - -#### `crypto.aes.create(key, iv)` - -- `key: Uint8Array` The key, if length `16` then `AES 128` is used. For length `32`, `AES 256` is used. -- `iv: Uint8Array` Must have length `16`. - -Returns `Promise<{decrypt, encrypt}>` - -##### `decrypt(data)` - -- `data: Uint8Array` - -Returns `Promise` - -##### `encrypt(data)` - -- `data: Uint8Array` - -Returns `Promise` - -```js -const crypto = require('libp2p-crypto') - -// Setting up Key and IV - -// A 16 bytes array, 128 Bits, AES-128 is chosen -const key128 = Uint8Array.from([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]) - -// A 16 bytes array, 128 Bits, -const IV = Uint8Array.from([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]) - -async function main () { - const decryptedMessage = 'Hello, world!' - - // Encrypting - const cipher = await crypto.aes.create(key128, IV) - const encryptedBuffer = await cipher.encrypt(Uint8Array.from(decryptedMessage)) - console.log(encryptedBuffer) - // prints: - - // Decrypting - const decipher = await crypto.aes.create(key128, IV) - const decryptedBuffer = await cipher.decrypt(encryptedBuffer) - - console.log(decryptedBuffer) - // prints: - - console.log(decryptedBuffer.toString('utf-8')) - // prints: Hello, world! -} - -main() -``` - -### `crypto.hmac` - -Exposes an interface to the Keyed-Hash Message Authentication Code (HMAC) as defined in U.S. Federal Information Processing Standards Publication 198. An HMAC is a cryptographic hash that uses a key to sign a message. The receiver verifies the hash by recomputing it using the same key. - -#### `crypto.hmac.create(hash, secret)` - -- `hash: String` -- `secret: Uint8Array` - -Returns `Promise<{digest}>` - -##### `digest(data)` - -- `data: Uint8Array` - -Returns `Promise` - -Example: - -```js -const crypto = require('libp2p-crypto') - -async function main () { - const hash = 'SHA1' // 'SHA256' || 'SHA512' - const hmac = await crypto.hmac.create(hash, uint8ArrayFromString('secret')) - const sig = await hmac.digest(uint8ArrayFromString('hello world')) - console.log(sig) -} - -main() -``` - -### `crypto.keys` - -**Supported Key Types** - -The [`generateKeyPair`](#generatekeypairtype-bits), [`marshalPublicKey`](#marshalpublickeykey-type), and [`marshalPrivateKey`](#marshalprivatekeykey-type) functions accept a string `type` argument. - -Currently the `'RSA'`, `'ed25519'`, and `secp256k1` types are supported, although ed25519 and secp256k1 keys support only signing and verification of messages. For encryption / decryption support, RSA keys should be used. - -### `crypto.keys.generateKeyPair(type, bits)` - -- `type: String`, see [Supported Key Types](#supported-key-types) above. -- `bits: Number` Minimum of 1024 - -Returns `Promise<{privateKey, publicKey}>` - -Generates a keypair of the given type and bitsize. - -### `crypto.keys.generateEphemeralKeyPair(curve)` - -- `curve: String`, one of `'P-256'`, `'P-384'`, `'P-521'` is currently supported - -Returns `Promise` - -Generates an ephemeral public key and returns a function that will compute the shared secret key. - -Focuses only on ECDH now, but can be made more general in the future. - -Resolves to an object of the form: - -```js -{ - key: Uint8Array, - genSharedKey: Function -} -``` - -### `crypto.keys.keyStretcher(cipherType, hashType, secret)` - -- `cipherType: String`, one of `'AES-128'`, `'AES-256'`, `'Blowfish'` -- `hashType: String`, one of `'SHA1'`, `SHA256`, `SHA512` -- `secret: Uint8Array` - -Returns `Promise` - -Generates a set of keys for each party by stretching the shared key. - -Resolves to an object of the form: - -```js -{ - k1: { - iv: Uint8Array, - cipherKey: Uint8Array, - macKey: Uint8Array - }, - k2: { - iv: Uint8Array, - cipherKey: Uint8Array, - macKey: Uint8Array - } -} -``` - -### `crypto.keys.marshalPublicKey(key, [type])` - -- `key: keys.rsa.RsaPublicKey | keys.ed25519.Ed25519PublicKey | keys.secp256k1.Secp256k1PublicKey` -- `type: String`, see [Supported Key Types](#supported-key-types) above. Defaults to 'rsa'. - -Returns `Uint8Array` - -Converts a public key object into a protobuf serialized public key. - -### `crypto.keys.unmarshalPublicKey(buf)` - -- `buf: Uint8Array` - -Returns `RsaPublicKey|Ed25519PublicKey|Secp256k1PublicKey` - -Converts a protobuf serialized public key into its representative object. - -### `crypto.keys.marshalPrivateKey(key, [type])` - -- `key: keys.rsa.RsaPrivateKey | keys.ed25519.Ed25519PrivateKey | keys.secp256k1.Secp256k1PrivateKey` -- `type: String`, see [Supported Key Types](#supported-key-types) above. - -Returns `Uint8Array` - -Converts a private key object into a protobuf serialized private key. - -### `crypto.keys.unmarshalPrivateKey(buf)` - -- `buf: Uint8Array` - -Returns `Promise` - -Converts a protobuf serialized private key into its representative object. - -### `crypto.keys.import(encryptedKey, password)` - -- `encryptedKey: string` -- `password: string` - -Returns `Promise` - -Converts an exported private key into its representative object. Supported formats are 'pem' (RSA only) and 'libp2p-key'. - -### `privateKey.export(password, format)` - -- `password: string` -- `format: string` the format to export to: 'pem' (rsa only), 'libp2p-key' - -Returns `string` - -Exports the password protected `PrivateKey`. RSA keys will be exported as password protected PEM by default. Ed25519 and Secp256k1 keys will be exported as password protected AES-GCM base64 encoded strings ('libp2p-key' format). - -### `crypto.randomBytes(number)` - -- `number: Number` - -Returns `Uint8Array` - -Generates a Uint8Array with length `number` populated by random bytes. - -### `crypto.pbkdf2(password, salt, iterations, keySize, hash)` - -- `password: String` -- `salt: String` -- `iterations: Number` -- `keySize: Number` in bytes -- `hash: String` the hashing algorithm ('sha1', 'sha2-512', ...) - -Computes the Password Based Key Derivation Function 2; returning a new password. - -## Contribute +# Contribute Feel free to join in. All welcome. Open an [issue](https://github.com/libp2p/js-libp2p-crypto/issues)! @@ -314,17 +27,17 @@ This repository falls under the IPFS [Code of Conduct](https://github.com/ipfs/c [![](https://cdn.rawgit.com/jbenet/contribute-ipfs-gif/master/img/contribute.gif)](https://github.com/ipfs/community/blob/master/contributing.md) -## API Docs +# API Docs - -## License +# License Licensed under either of - Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) - MIT ([LICENSE-MIT](LICENSE-MIT) / ) -## Contribution +# Contribution Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/packages/crypto/src/aes/index.ts b/packages/crypto/src/aes/index.ts index cf1dd8b875..6a453cf074 100644 --- a/packages/crypto/src/aes/index.ts +++ b/packages/crypto/src/aes/index.ts @@ -1,3 +1,44 @@ +/** + * @packageDocumentation + * + * Exposes an interface to AES encryption (formerly Rijndael), as defined in U.S. Federal Information Processing Standards Publication 197. + * + * This uses `CTR` mode. + * + * /** + * @example + * + * ```js + * import { create } from '@libp2p/crypto/aes' + * + * // Setting up Key and IV + * + * // A 16 bytes array, 128 Bits, AES-128 is chosen + * const key128 = Uint8Array.from([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]) + * + * // A 16 bytes array, 128 Bits, + * const IV = Uint8Array.from([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]) + * + * const decryptedMessage = 'Hello, world!' + * + * // Encrypting + * const cipher = await crypto.aes.create(key128, IV) + * const encryptedBuffer = await encrypt(Uint8Array.from(decryptedMessage)) + * console.log(encryptedBuffer) + * // prints: + * + * // Decrypting + * const decipher = await crypto.aes.create(key128, IV) + * const decryptedBuffer = await decrypt(encryptedBuffer) + * + * console.log(decryptedBuffer) + * // prints: + * + * console.log(decryptedBuffer.toString('utf-8')) + * // prints: Hello, world! + * ``` + */ + import { cipherMode } from './cipher-mode.js' import * as ciphers from './ciphers.js' @@ -6,6 +47,10 @@ export interface AESCipher { decrypt(data: Uint8Array): Promise } +/** + * @param key - The key, if length `16` then `AES 128` is used. For length `32`, `AES 256` is used + * @param iv - Must have length `16` + */ export async function create (key: Uint8Array, iv: Uint8Array): Promise { const mode = cipherMode(key) const cipher = ciphers.createCipheriv(mode, key, iv) diff --git a/packages/crypto/src/hmac/index.ts b/packages/crypto/src/hmac/index.ts index dc2ec68894..f61e3c28fc 100644 --- a/packages/crypto/src/hmac/index.ts +++ b/packages/crypto/src/hmac/index.ts @@ -1,3 +1,20 @@ +/** + * @packageDocumentation + * + * Exposes an interface to the Keyed-Hash Message Authentication Code (HMAC) as defined in U.S. Federal Information Processing Standards Publication 198. An HMAC is a cryptographic hash that uses a key to sign a message. The receiver verifies the hash by recomputing it using the same key. + * + * @example + * + * ```js + * import { create } from '@libp2p/hmac' + * + * const hash = 'SHA1' // 'SHA256' || 'SHA512' + * const hmac = await crypto.hmac.create(hash, uint8ArrayFromString('secret')) + * const sig = await hmac.digest(uint8ArrayFromString('hello world')) + * console.log(sig) + * ``` + */ + import crypto from 'crypto' import lengths from './lengths.js' diff --git a/packages/crypto/src/index.ts b/packages/crypto/src/index.ts index 9e368358eb..6396d1dbd4 100644 --- a/packages/crypto/src/index.ts +++ b/packages/crypto/src/index.ts @@ -1,3 +1,13 @@ +/** + * @packageDocumentation + * + * The `libp2p-crypto` library depends on the [Web Crypto API](https://developer.mozilla.org/en-US/docs/Web/API/Web_Crypto_API) in the browser. Web Crypto is available in all modern browsers, however browsers restrict its usage to [Secure Contexts](https://developer.mozilla.org/en-US/docs/Web/Security/Secure_Contexts). + * + * *This means you will not be able to use some `@libp2p/crypto` functions in the browser when the page is served over HTTP.* + * + * To enable the Web Crypto API and allow `@libp2p/crypto` to work fully, please serve your page over HTTPS. + */ + import * as aes from './aes/index.js' import * as hmac from './hmac/index.js' import * as keys from './keys/index.js' diff --git a/packages/crypto/src/keys/ecdh.ts b/packages/crypto/src/keys/ecdh.ts index 3e0fd30a75..992ee4777b 100644 --- a/packages/crypto/src/keys/ecdh.ts +++ b/packages/crypto/src/keys/ecdh.ts @@ -11,6 +11,11 @@ const curves = { const curveTypes = Object.keys(curves) const names = curveTypes.join(' / ') +/** + * Generates an ephemeral public key and returns a function that will compute the shared secret key. + * + * Focuses only on ECDH now, but can be made more general in the future. + */ export async function generateEphmeralKeyPair (curve: string): Promise { if (curve !== 'P-256' && curve !== 'P-384' && curve !== 'P-521') { throw new CodeError(`Unknown curve: ${curve}. Must be ${names}`, 'ERR_INVALID_CURVE') diff --git a/packages/crypto/src/keys/index.ts b/packages/crypto/src/keys/index.ts index d8192d5abb..f805d81afa 100644 --- a/packages/crypto/src/keys/index.ts +++ b/packages/crypto/src/keys/index.ts @@ -1,3 +1,15 @@ +/** + * @packageDocumentation + * + * **Supported Key Types** + * + * The {@link generateKeyPair}, {@link marshalPublicKey}, and {@link marshalPrivateKey} functions accept a string `type` argument. + * + * Currently the `'RSA'`, `'ed25519'`, and `secp256k1` types are supported, although ed25519 and secp256k1 keys support only signing and verification of messages. + * + * For encryption / decryption support, RSA keys should be used. + */ + import 'node-forge/lib/asn1.js' import 'node-forge/lib/pbe.js' import { CodeError } from '@libp2p/interface/errors' @@ -40,13 +52,21 @@ function typeToKey (type: string): typeof RSA | typeof Ed25519 | typeof Secp256k throw unsupportedKey(type) } -// Generates a keypair of the given type and bitsize +/** + * Generates a keypair of the given type and bitsize + * + * @param type + * @param bits - Minimum of 1024 + */ export async function generateKeyPair (type: KeyTypes, bits?: number): Promise { return typeToKey(type).generateKeyPair(bits ?? 2048) } -// Generates a keypair of the given type and bitsize -// seed is a 32 byte uint8array +/** + * Generates a keypair of the given type and bitsize. + * + * Seed is a 32 byte uint8array + */ export async function generateKeyPairFromSeed (type: KeyTypes, seed: Uint8Array, bits?: number): Promise { if (type.toLowerCase() !== 'ed25519') { throw new CodeError('Seed key derivation is unimplemented for RSA or secp256k1', 'ERR_UNSUPPORTED_KEY_DERIVATION_TYPE') @@ -55,8 +75,9 @@ export async function generateKeyPairFromSeed (type: KeyTypes, seed: Uint8Array, return Ed25519.generateKeyPairFromSeed(seed) } -// Converts a protobuf serialized public key into its -// representative object +/** + * Converts a protobuf serialized public key into its representative object + */ export function unmarshalPublicKey (buf: Uint8Array): PublicKey { const decoded = keysPBM.PublicKey.decode(buf) const data = decoded.Data ?? new Uint8Array() @@ -73,15 +94,18 @@ export function unmarshalPublicKey (buf: Uint8Array): PublicKey { } } -// Converts a public key object into a protobuf serialized public key +/** + * Converts a public key object into a protobuf serialized public key + */ export function marshalPublicKey (key: { bytes: Uint8Array }, type?: string): Uint8Array { type = (type ?? 'rsa').toLowerCase() typeToKey(type) // check type return key.bytes } -// Converts a protobuf serialized private key into its -// representative object +/** + * Converts a protobuf serialized private key into its representative object + */ export async function unmarshalPrivateKey (buf: Uint8Array): Promise { const decoded = keysPBM.PrivateKey.decode(buf) const data = decoded.Data ?? new Uint8Array() @@ -98,7 +122,9 @@ export async function unmarshalPrivateKey (buf: Uint8Array): Promise } } -// Converts a private key object into a protobuf serialized private key +/** + * Converts a private key object into a protobuf serialized private key + */ export function marshalPrivateKey (key: { bytes: Uint8Array }, type?: string): Uint8Array { type = (type ?? 'rsa').toLowerCase() typeToKey(type) // check type @@ -106,9 +132,9 @@ export function marshalPrivateKey (key: { bytes: Uint8Array }, type?: string): U } /** + * Converts an exported private key into its representative object. * - * @param {string} encryptedKey - * @param {string} password + * Supported formats are 'pem' (RSA only) and 'libp2p-key'. */ export async function importKey (encryptedKey: string, password: string): Promise { try { diff --git a/packages/crypto/src/random-bytes.ts b/packages/crypto/src/random-bytes.ts index a85542661c..5de614474b 100644 --- a/packages/crypto/src/random-bytes.ts +++ b/packages/crypto/src/random-bytes.ts @@ -1,6 +1,9 @@ import { CodeError } from '@libp2p/interface/errors' import { randomBytes as randB } from '@noble/hashes/utils' +/** + * Generates a Uint8Array with length `number` populated by random bytes + */ export default function randomBytes (length: number): Uint8Array { if (isNaN(length) || length <= 0) { throw new CodeError('random bytes length must be a Number bigger than 0', 'ERR_INVALID_LENGTH') diff --git a/packages/interface-compliance-tests/README.md b/packages/interface-compliance-tests/README.md index 906d059731..04270ac05e 100644 --- a/packages/interface-compliance-tests/README.md +++ b/packages/interface-compliance-tests/README.md @@ -1,5 +1,3 @@ -# @libp2p/interface-compliance-tests - [![libp2p.io](https://img.shields.io/badge/project-libp2p-yellow.svg?style=flat-square)](http://libp2p.io/) [![Discuss](https://img.shields.io/discourse/https/discuss.libp2p.io/posts.svg?style=flat-square)](https://discuss.libp2p.io) [![codecov](https://img.shields.io/codecov/c/github/libp2p/js-libp2p.svg?style=flat-square)](https://codecov.io/gh/libp2p/js-libp2p) @@ -7,22 +5,13 @@ > Compliance tests for JS libp2p interfaces -## Table of contents - -- [Install](#install) - - [Browser ` ``` -## Usage +# Usage Each [interface](https://npmjs.org/packages/@libp2p/interfaces) has its documentation on how to use the compliance tests and should be used as the source of truth. -## API Docs +# API Docs - -## License +# License Licensed under either of - Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) - MIT ([LICENSE-MIT](LICENSE-MIT) / ) -## Contribution +# Contribution Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/packages/interface-internal/README.md b/packages/interface-internal/README.md index 4d6b738f26..dafd72596c 100644 --- a/packages/interface-internal/README.md +++ b/packages/interface-internal/README.md @@ -1,5 +1,3 @@ -# @libp2p/interface-internal - [![libp2p.io](https://img.shields.io/badge/project-libp2p-yellow.svg?style=flat-square)](http://libp2p.io/) [![Discuss](https://img.shields.io/discourse/https/discuss.libp2p.io/posts.svg?style=flat-square)](https://discuss.libp2p.io) [![codecov](https://img.shields.io/codecov/c/github/libp2p/js-libp2p.svg?style=flat-square)](https://codecov.io/gh/libp2p/js-libp2p) @@ -7,30 +5,23 @@ > Interfaces implemented by internal libp2p components -## Table of contents - -- [Install](#install) -- [API Docs](#api-docs) -- [License](#license) -- [Contribution](#contribution) - -## Install +# Install ```console $ npm i @libp2p/interface-internal ``` -## API Docs +# API Docs - -## License +# License Licensed under either of - Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) - MIT ([LICENSE-MIT](LICENSE-MIT) / ) -## Contribution +# Contribution Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/packages/interface/README.md b/packages/interface/README.md index 384bcb1b91..2ed3298f4a 100644 --- a/packages/interface/README.md +++ b/packages/interface/README.md @@ -1,5 +1,3 @@ -# @libp2p/interface - [![libp2p.io](https://img.shields.io/badge/project-libp2p-yellow.svg?style=flat-square)](http://libp2p.io/) [![Discuss](https://img.shields.io/discourse/https/discuss.libp2p.io/posts.svg?style=flat-square)](https://discuss.libp2p.io) [![codecov](https://img.shields.io/codecov/c/github/libp2p/js-libp2p.svg?style=flat-square)](https://codecov.io/gh/libp2p/js-libp2p) @@ -7,21 +5,13 @@ > The interface implemented by a libp2p node -## Table of contents - -- [Install](#install) - - [Browser ` ``` -## API Docs +# API Docs - -## License +# License Licensed under either of - Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) - MIT ([LICENSE-MIT](LICENSE-MIT) / ) -## Contribution +# Contribution Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/packages/kad-dht/README.md b/packages/kad-dht/README.md index bd231f8c1d..e9fd6de682 100644 --- a/packages/kad-dht/README.md +++ b/packages/kad-dht/README.md @@ -1,5 +1,3 @@ -# @libp2p/kad-dht - [![libp2p.io](https://img.shields.io/badge/project-libp2p-yellow.svg?style=flat-square)](http://libp2p.io/) [![Discuss](https://img.shields.io/discourse/https/discuss.libp2p.io/posts.svg?style=flat-square)](https://discuss.libp2p.io) [![codecov](https://img.shields.io/codecov/c/github/libp2p/js-libp2p.svg?style=flat-square)](https://codecov.io/gh/libp2p/js-libp2p) @@ -7,28 +5,13 @@ > JavaScript implementation of the Kad-DHT for libp2p -## Table of contents - -- [Install](#install) - - [Browser ` -``` - -## Features +# About - Manages the lifecycle of a key - Keys are encrypted at rest @@ -43,7 +15,7 @@ Loading this module through a script tag will make it's exports available as `Li - Enforces NIST SP 800-131A and NIST SP 800-132 - Delays reporting errors to slow down brute force attacks -### KeyInfo +## KeyInfo The key management and naming service API all return a `KeyInfo` object. The `id` is a universally unique identifier for the key. The `name` is local to the key chain. @@ -54,9 +26,11 @@ The key management and naming service API all return a `KeyInfo` object. The `i } ``` -The **key id** is the SHA-256 [multihash](https://github.com/multiformats/multihash) of its public key. The *public key* is a [protobuf encoding](https://github.com/libp2p/js-libp2p-crypto/blob/master/src/keys/keys.proto.js) containing a type and the [DER encoding](https://en.wikipedia.org/wiki/X.690) of the PKCS [SubjectPublicKeyInfo](https://www.ietf.org/rfc/rfc3279.txt). +The **key id** is the SHA-256 [multihash](https://github.com/multiformats/multihash) of its public key. -### Private key storage +The *public key* is a [protobuf encoding](https://github.com/libp2p/js-libp2p-crypto/blob/master/src/keys/keys.proto.js) containing a type and the [DER encoding](https://en.wikipedia.org/wiki/X.690) of the PKCS [SubjectPublicKeyInfo](https://www.ietf.org/rfc/rfc3279.txt). + +## Private key storage A private key is stored as an encrypted PKCS 8 structure in the PEM format. It is protected by a key generated from the key chain's *passPhrase* using **PBKDF2**. @@ -64,7 +38,7 @@ The default options for generating the derived encryption key are in the `dek` o ```js const defaultOptions = { - //See https://cryptosense.com/parameter-choice-for-pbkdf2/ +// See https://cryptosense.com/parameter-choice-for-pbkdf2/ dek: { keyLength: 512 / 8, iterationCount: 1000, @@ -76,9 +50,25 @@ const defaultOptions = { ![key storage](./doc/private-key.png?raw=true) -### Physical storage +## Physical storage + +The actual physical storage of an encrypted key is left to implementations of [interface-datastore](https://github.com/ipfs/interface-datastore/). + +A key benefit is that now the key chain can be used in browser with the [js-datastore-level](https://github.com/ipfs/js-datastore-level) implementation. + +# Install + +```console +$ npm i @libp2p/keychain +``` + +## Browser ` +``` ## API Docs diff --git a/packages/keychain/src/index.ts b/packages/keychain/src/index.ts index f13cc0367f..8507c4c7bf 100644 --- a/packages/keychain/src/index.ts +++ b/packages/keychain/src/index.ts @@ -1,3 +1,55 @@ +/** + * @packageDocumentation + * + * - Manages the lifecycle of a key + * - Keys are encrypted at rest + * - Enforces the use of safe key names + * - Uses encrypted PKCS 8 for key storage + * - Uses PBKDF2 for a "stetched" key encryption key + * - Enforces NIST SP 800-131A and NIST SP 800-132 + * - Delays reporting errors to slow down brute force attacks + * + * ## KeyInfo + * + * The key management and naming service API all return a `KeyInfo` object. The `id` is a universally unique identifier for the key. The `name` is local to the key chain. + * + * ```js + * { + * name: 'rsa-key', + * id: 'QmYWYSUZ4PV6MRFYpdtEDJBiGs4UrmE6g8wmAWSePekXVW' + * } + * ``` + * + * The **key id** is the SHA-256 [multihash](https://github.com/multiformats/multihash) of its public key. + * + * The *public key* is a [protobuf encoding](https://github.com/libp2p/js-libp2p-crypto/blob/master/src/keys/keys.proto.js) containing a type and the [DER encoding](https://en.wikipedia.org/wiki/X.690) of the PKCS [SubjectPublicKeyInfo](https://www.ietf.org/rfc/rfc3279.txt). + * + * ## Private key storage + * + * A private key is stored as an encrypted PKCS 8 structure in the PEM format. It is protected by a key generated from the key chain's *passPhrase* using **PBKDF2**. + * + * The default options for generating the derived encryption key are in the `dek` object. This, along with the passPhrase, is the input to a `PBKDF2` function. + * + * ```js + * const defaultOptions = { + * // See https://cryptosense.com/parameter-choice-for-pbkdf2/ + * dek: { + * keyLength: 512 / 8, + * iterationCount: 1000, + * salt: 'at least 16 characters long', + * hash: 'sha2-512' + * } + * } + * ``` + * ![key storage](./doc/private-key.png?raw=true) + * + * ## Physical storage + * + * The actual physical storage of an encrypted key is left to implementations of [interface-datastore](https://github.com/ipfs/interface-datastore/). + * + * A key benefit is that now the key chain can be used in browser with the [js-datastore-level](https://github.com/ipfs/js-datastore-level) implementation. + */ + /* eslint max-nested-callbacks: ["error", 5] */ import { pbkdf2, randomBytes } from '@libp2p/crypto' diff --git a/packages/libp2p/README.md b/packages/libp2p/README.md index 28dca9a77e..8e2c9bb35d 100644 --- a/packages/libp2p/README.md +++ b/packages/libp2p/README.md @@ -1,48 +1,3 @@ -# libp2p - -[![libp2p.io](https://img.shields.io/badge/project-libp2p-yellow.svg?style=flat-square)](http://libp2p.io/) -[![Discuss](https://img.shields.io/discourse/https/discuss.libp2p.io/posts.svg?style=flat-square)](https://discuss.libp2p.io) -[![codecov](https://img.shields.io/codecov/c/github/libp2p/js-libp2p.svg?style=flat-square)](https://codecov.io/gh/libp2p/js-libp2p) -[![CI](https://img.shields.io/github/actions/workflow/status/libp2p/js-libp2p/main.yml?branch=master\&style=flat-square)](https://github.com/libp2p/js-libp2p/actions/workflows/main.yml?query=branch%3Amaster) - -> JavaScript implementation of libp2p, a modular peer to peer network stack - -## Table of contents - -- [Install](#install) - - [Browser ` -``` -

      libp2p hex logo

      @@ -71,7 +26,9 @@ Loading this module through a script tag will make it's exports available as `Li

      -### Project status +> JavaScript implementation of libp2p, a modular peer to peer network stack + +# Project status We've come a long way, but this project is still in Alpha, lots of development is happening, API might change, beware of the Dragons 🐉.. @@ -82,7 +39,7 @@ If you are looking for the documentation of the latest release, you can view the **Want to update libp2p in your project?** Check our [migrations folder](./doc/migrations). -## Background +# Background libp2p is the product of a long and arduous quest to understand the evolution of the Internet networking stack. In order to build P2P applications, devs have long had to make custom ad-hoc solutions to fit their needs, sometimes making some hard assumptions about their runtimes and the state of the network at the time of their development. Today, looking back more than 20 years, we see a clear pattern in the types of mechanisms built around the Internet Protocol, IP, which can be found throughout many layers of the OSI layer system, libp2p distils these mechanisms into flat categories and defines clear interfaces that once exposed, enable other protocols and applications to use and swap them, enabling upgradability and adaptability for the runtime, without breaking the API. @@ -99,7 +56,7 @@ We are in the process of writing better documentation, blog posts, tutorials and To sum up, libp2p is a "network stack" -- a protocol suite -- that cleanly separates concerns, and enables sophisticated applications to only use the protocols they absolutely need, without giving up interoperability and upgradeability. libp2p grew out of IPFS, but it is built so that lots of people can use it, for lots of different projects. -## Roadmap +# Roadmap The js-libp2p roadmap can be found here: @@ -107,25 +64,25 @@ It represents current projects the js-libp2p maintainers are focused on and prov It is complementary to the overarching libp2p project roadmap: -## Usage +# Usage ### Configuration For all the information on how you can configure libp2p see [CONFIGURATION.md](./doc/CONFIGURATION.md). -### Limits +## Limits For help configuring your node to resist malicious network peers, see [LIMITS.md](./doc/LIMITS.md) -### Getting started +## Getting started If you are starting your journey with `js-libp2p`, read the [GETTING\_STARTED.md](./doc/GETTING_STARTED.md) guide. -### Tutorials and Examples +## Tutorials and Examples You can find multiple examples on the [examples repo](https://github.com/libp2p/js-libp2p-examples) that will guide you through using libp2p for several scenarios. -## Development +# Development **Clone and install dependencies:** @@ -136,9 +93,9 @@ You can find multiple examples on the [examples repo](https://github.com/libp2p/ > npm run build ``` -### Tests +# Tests -#### Run unit tests +## Run unit tests ```sh # run all the unit tsts @@ -151,7 +108,7 @@ You can find multiple examples on the [examples repo](https://github.com/libp2p/ > npm run test:chrome ``` -### Packages +# Packages List of packages currently in existence for libp2p @@ -195,7 +152,7 @@ List of packages currently in existence for libp2p | [`@ChainSafe/libp2p-gossipsub`](//github.com/ChainSafe/js-libp2p-gossipsub) | [![npm](https://img.shields.io/npm/v/%40ChainSafe%2Flibp2p-gossipsub.svg?maxAge=86400\&style=flat-square)](//github.com/ChainSafe/js-libp2p-gossipsub/releases) | [![Deps](https://img.shields.io/librariesio/release/npm/%40ChainSafe%2Flibp2p-gossipsub?logo=Libraries.io\&logoColor=white\&style=flat-square)](//libraries.io/npm/%40ChainSafe%2Flibp2p-gossipsub) | [![GitHub CI](https://img.shields.io/github/actions/workflow/status/ChainSafe/js-libp2p-gossipsub/main.yml?branch=master\&label=ci\&style=flat-square)](//github.com/ChainSafe/js-libp2p-gossipsub/actions?query=branch%3Amaster+workflow%3Aci+) | [![codecov](https://codecov.io/gh/ChainSafe/js-libp2p-gossipsub/branch/master/graph/badge.svg?style=flat-square)](https://codecov.io/gh/ChainSafe/js-libp2p-gossipsub) | | [`@libp2p/floodsub`](//github.com/libp2p/js-libp2p-floodsub) | [![npm](https://img.shields.io/npm/v/%40libp2p%2Ffloodsub.svg?maxAge=86400\&style=flat-square)](//github.com/libp2p/js-libp2p-floodsub/releases) | [![Deps](https://img.shields.io/librariesio/release/npm/%40libp2p%2Ffloodsub?logo=Libraries.io\&logoColor=white\&style=flat-square)](//libraries.io/npm/%40libp2p%2Ffloodsub) | [![GitHub CI](https://img.shields.io/github/actions/workflow/status/libp2p/js-libp2p-floodsub/js-test-and-release.yml?branch=master\&label=ci\&style=flat-square)](//github.com/libp2p/js-libp2p-floodsub/actions?query=branch%3Amaster+workflow%3Aci+) | [![codecov](https://codecov.io/gh/libp2p/js-libp2p-floodsub/branch/master/graph/badge.svg?style=flat-square)](https://codecov.io/gh/libp2p/js-libp2p-floodsub) | -## Used by +# Used by

      @@ -207,7 +164,7 @@ List of packages currently in existence for libp2p And [many others...](https://github.com/libp2p/js-libp2p/network/dependents) -## Contribute +# Contribute The libp2p implementation in JavaScript is a work in progress. As such, there are a few things you can do right now to help out: @@ -215,17 +172,17 @@ The libp2p implementation in JavaScript is a work in progress. As such, there ar - **Perform code reviews**. Most of this has been developed by @diasdavid, which means that more eyes will help a) speed the project along b) ensure quality and c) reduce possible future bugs. - **Add tests**. There can never be enough tests. -## API Docs +# API Docs - -## License +# License Licensed under either of - Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) - MIT ([LICENSE-MIT](LICENSE-MIT) / ) -## Contribution +# Contribution Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/packages/logger/README.md b/packages/logger/README.md index def89c67a1..ce77232376 100644 --- a/packages/logger/README.md +++ b/packages/logger/README.md @@ -1,5 +1,3 @@ -# @libp2p/logger - [![libp2p.io](https://img.shields.io/badge/project-libp2p-yellow.svg?style=flat-square)](http://libp2p.io/) [![Discuss](https://img.shields.io/discourse/https/discuss.libp2p.io/posts.svg?style=flat-square)](https://discuss.libp2p.io) [![codecov](https://img.shields.io/codecov/c/github/libp2p/js-libp2p.svg?style=flat-square)](https://codecov.io/gh/libp2p/js-libp2p) @@ -7,31 +5,7 @@ > A logging component for use in js-libp2p modules -## Table of contents - -- [Install](#install) - - [Browser ` -``` - -## Description +# About A map that reports it's size to the libp2p [Metrics](https://github.com/libp2p/js-libp2p-interfaces/tree/master/packages/libp2p-interfaces/src/metrics#readme) system. @@ -61,17 +35,31 @@ with this base58btc: Qmfoo with this base32: bafyfoo ``` -## API Docs +# Install + +```console +$ npm i @libp2p/logger +``` + +## Browser ` +``` + +# API Docs - -## License +# License Licensed under either of - Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) - MIT ([LICENSE-MIT](LICENSE-MIT) / ) -## Contribution +# Contribution Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/packages/logger/src/index.ts b/packages/logger/src/index.ts index 87f1354d50..1bb24ea8dc 100644 --- a/packages/logger/src/index.ts +++ b/packages/logger/src/index.ts @@ -1,3 +1,34 @@ +/** + * @packageDocumentation + * + * A map that reports it's size to the libp2p [Metrics](https://github.com/libp2p/js-libp2p-interfaces/tree/master/packages/libp2p-interfaces/src/metrics#readme) system. + * + * If metrics are disabled a regular map is used. + * + * @example + * + * ```JavaScript + * import { logger } from '@libp2p/logger' + * + * const log = logger('libp2p:my:component:name') + * + * log('something happened: %s', 'it was ok') + * log.error('something bad happened: %o', err) + * + * log('with this peer: %p', aPeerId) + * log('and this base58btc: %b', aUint8Array) + * log('and this base32: %t', aUint8Array) + * ``` + * ```console + * $ DEBUG=libp2p:* node index.js + * something happened: it was ok + * something bad happened: + * with this peer: 12D3Foo + * with this base58btc: Qmfoo + * with this base32: bafyfoo + * ``` + */ + import debug from 'debug' import { base32 } from 'multiformats/bases/base32' import { base58btc } from 'multiformats/bases/base58' diff --git a/packages/metrics-prometheus/README.md b/packages/metrics-prometheus/README.md index 6dadf9e4e2..42bb982e6f 100644 --- a/packages/metrics-prometheus/README.md +++ b/packages/metrics-prometheus/README.md @@ -1,5 +1,3 @@ -# @libp2p/prometheus-metrics - [![libp2p.io](https://img.shields.io/badge/project-libp2p-yellow.svg?style=flat-square)](http://libp2p.io/) [![Discuss](https://img.shields.io/discourse/https/discuss.libp2p.io/posts.svg?style=flat-square)](https://discuss.libp2p.io) [![codecov](https://img.shields.io/codecov/c/github/libp2p/js-libp2p.svg?style=flat-square)](https://codecov.io/gh/libp2p/js-libp2p) @@ -7,27 +5,7 @@ > Collect libp2p metrics for scraping by Prometheus or Graphana -## Table of contents - -- [Install](#install) -- [Usage](#usage) - - [Queries](#queries) - - [Data sent/received](#data-sentreceived) - - [CPU usage](#cpu-usage) - - [Memory usage](#memory-usage) - - [DHT query time](#dht-query-time) - - [TCP transport dialer errors](#tcp-transport-dialer-errors) -- [API Docs](#api-docs) -- [License](#license) -- [Contribution](#contribution) - -## Install - -```console -$ npm i @libp2p/prometheus-metrics -``` - -## Usage +# About Configure your libp2p node with Prometheus metrics: @@ -93,17 +71,112 @@ libp2p_kad_dht_lan_query_time_seconds rate(libp2p_tcp_dialer_errors_total[30s]) ``` -## API Docs +## Example + +```typescript +import { prometheusMetrics } from '@libp2p/prometheus-metrics' + +const metrics = prometheusMetrics()() +const myMetric = metrics.registerMetric({ + name: 'my_metric', + label: 'my_label', + help: 'my help text' +}) + +myMetric.update(1) +``` + +## Example + +A metric that is expensive to calculate can be created by passing a `calculate` function that will only be invoked when metrics are being scraped: + +```typescript +import { prometheusMetrics } from '@libp2p/prometheus-metrics' + +const metrics = prometheusMetrics()() +const myMetric = metrics.registerMetric({ + name: 'my_metric', + label: 'my_label', + help: 'my help text', + calculate: async () => { + // do something expensive + return 1 + } +}) +``` + +## Example + +If several metrics should be grouped together (e.g. for graphing purposes) `registerMetricGroup` can be used instead: + +```typescript +import { prometheusMetrics } from '@libp2p/prometheus-metrics' + +const metrics = prometheusMetrics()() +const myMetricGroup = metrics.registerMetricGroup({ + name: 'my_metric_group', + label: 'my_label', + help: 'my help text' +}) + +myMetricGroup.increment({ my_label: 'my_value' }) +``` + +There are specific metric groups for tracking libp2p connections and streams: + +## Example + +Track a newly opened multiaddr connection: + +```typescript +import { prometheusMetrics } from '@libp2p/prometheus-metrics' +import { createLibp2p } from 'libp2p' + +const metrics = prometheusMetrics()() + +const libp2p = await createLibp2p({ + metrics: metrics, + }) +// set up a multiaddr connection +const connection = await libp2p.dial('multiaddr') +const connections = metrics.trackMultiaddrConnection(connection) +``` + +## Example + +Track a newly opened stream: + +```typescript +import { prometheusMetrics } from '@libp2p/prometheus-metrics' +import { createLibp2p } from 'libp2p' + +const metrics = prometheusMetrics()() + +const libp2p = await createLibp2p({ + metrics: metrics, +}) + +const stream = await connection.newStream('/my/protocol') +const streams = metrics.trackProtocolStream(stream) +``` + +# Install + +```console +$ npm i @libp2p/prometheus-metrics +``` + +# API Docs - -## License +# License Licensed under either of - Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) - MIT ([LICENSE-MIT](LICENSE-MIT) / ) -## Contribution +# Contribution Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/packages/metrics-prometheus/src/index.ts b/packages/metrics-prometheus/src/index.ts index 46675605d8..ebc0b83d2e 100644 --- a/packages/metrics-prometheus/src/index.ts +++ b/packages/metrics-prometheus/src/index.ts @@ -1,10 +1,69 @@ /** * @packageDocumentation * - * Collect libp2p metrics for scraping by Prometheus or Graphana. - * @module libp2p-prometheus-metrics + * Configure your libp2p node with Prometheus metrics: * - * A tracked metric can be created by calling either `registerMetric` on the metrics object + * ```js + * import { createLibp2p } from 'libp2p' + * import { prometheusMetrics } from '@libp2p/prometheus-metrics' + * + * const node = await createLibp2p({ + * metrics: prometheusMetrics() + * }) + * ``` + * + * Then use the `prom-client` module to supply metrics to the Prometheus/Graphana client using your http framework: + * + * ```js + * import client from 'prom-client' + * + * async handler (request, h) { + * return h.response(await client.register.metrics()) + * .type(client.register.contentType) + * } + * ``` + * + * All Prometheus metrics are global so there's no other work required to extract them. + * + * ### Queries + * + * Some useful queries are: + * + * #### Data sent/received + * + * ``` + * rate(libp2p_data_transfer_bytes_total[30s]) + * ``` + * + * #### CPU usage + * + * ``` + * rate(process_cpu_user_seconds_total[30s]) * 100 + * ``` + * + * #### Memory usage + * + * ``` + * nodejs_memory_usage_bytes + * ``` + * + * #### DHT query time + * + * ``` + * libp2p_kad_dht_wan_query_time_seconds + * ``` + * + * or + * + * ``` + * libp2p_kad_dht_lan_query_time_seconds + * ``` + * + * #### TCP transport dialer errors + * + * ``` + * rate(libp2p_tcp_dialer_errors_total[30s]) + * ``` * * @example * @@ -20,10 +79,11 @@ * * myMetric.update(1) * ``` - * A metric that is expensive to calculate can be created by passing a `calculate` function that will only be invoked when metrics are being scraped: * * @example * + * A metric that is expensive to calculate can be created by passing a `calculate` function that will only be invoked when metrics are being scraped: + * * ```typescript * import { prometheusMetrics } from '@libp2p/prometheus-metrics' * @@ -39,10 +99,10 @@ * }) * ``` * - * If several metrics should be grouped together (e.g. for graphing purposes) `registerMetricGroup` can be used instead: - * * @example * + * If several metrics should be grouped together (e.g. for graphing purposes) `registerMetricGroup` can be used instead: + * * ```typescript * import { prometheusMetrics } from '@libp2p/prometheus-metrics' * @@ -58,14 +118,14 @@ * * There are specific metric groups for tracking libp2p connections and streams: * - * Track a newly opened multiaddr connection: * @example * + * Track a newly opened multiaddr connection: + * * ```typescript * import { prometheusMetrics } from '@libp2p/prometheus-metrics' * import { createLibp2p } from 'libp2p' * - * * const metrics = prometheusMetrics()() * * const libp2p = await createLibp2p({ @@ -76,9 +136,10 @@ * const connections = metrics.trackMultiaddrConnection(connection) * ``` * - * Track a newly opened stream: * @example * + * Track a newly opened stream: + * * ```typescript * import { prometheusMetrics } from '@libp2p/prometheus-metrics' * import { createLibp2p } from 'libp2p' diff --git a/packages/multistream-select/README.md b/packages/multistream-select/README.md index ecb617ad0b..4412a86756 100644 --- a/packages/multistream-select/README.md +++ b/packages/multistream-select/README.md @@ -1,5 +1,3 @@ -# @libp2p/multistream-select - [![libp2p.io](https://img.shields.io/badge/project-libp2p-yellow.svg?style=flat-square)](http://libp2p.io/) [![Discuss](https://img.shields.io/discourse/https/discuss.libp2p.io/posts.svg?style=flat-square)](https://discuss.libp2p.io) [![codecov](https://img.shields.io/codecov/c/github/libp2p/js-libp2p.svg?style=flat-square)](https://codecov.io/gh/libp2p/js-libp2p) @@ -7,38 +5,11 @@ > JavaScript implementation of multistream-select -## Table of contents - -- [Install](#install) - - [Browser ` -``` - -## Background - -### What is `multistream-select`? +# About -TLDR; multistream-select is protocol multiplexing per connection/stream. [Full spec here](https://github.com/multiformats/multistream-select) +multistream-select is protocol multiplexing per connection/stream. [Full spec here](https://github.com/multiformats/multistream-select) -### Select a protocol flow +## Select a protocol flow The caller will send "interactive" messages, expecting for some acknowledgement from the callee, which will "select" the handler for the desired and supported protocol: @@ -54,17 +25,31 @@ The caller will send "interactive" messages, expecting for some acknowledgement > ``` -## API Docs +# Install + +```console +$ npm i @libp2p/multistream-select +``` + +## Browser ` +``` + +# API Docs - -## License +# License Licensed under either of - Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) - MIT ([LICENSE-MIT](LICENSE-MIT) / ) -## Contribution +# Contribution Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/packages/multistream-select/src/index.ts b/packages/multistream-select/src/index.ts index efe37ef346..84968842b0 100644 --- a/packages/multistream-select/src/index.ts +++ b/packages/multistream-select/src/index.ts @@ -1,3 +1,25 @@ +/** + * @packageDocumentation + * + * multistream-select is protocol multiplexing per connection/stream. [Full spec here](https://github.com/multiformats/multistream-select) + * + * ## Select a protocol flow + * + * The caller will send "interactive" messages, expecting for some acknowledgement from the callee, which will "select" the handler for the desired and supported protocol: + * + * ``` + * < /multistream-select/0.3.0 # i speak multistream-select/0.3.0 + * > /multistream-select/0.3.0 # ok, let's speak multistream-select/0.3.0 + * > /ipfs-dht/0.2.3 # i want to speak ipfs-dht/0.2.3 + * < na # ipfs-dht/0.2.3 is not available + * > /ipfs-dht/0.1.9 # What about ipfs-dht/0.1.9 ? + * < /ipfs-dht/0.1.9 # ok let's speak ipfs-dht/0.1.9 -- in a sense acts as an ACK + * > + * > + * > + * ``` + */ + import { PROTOCOL_ID } from './constants.js' import type { AbortOptions } from '@libp2p/interface' import type { Duplex, Source } from 'it-stream-types' diff --git a/packages/peer-collections/README.md b/packages/peer-collections/README.md index 9292ed7402..3112e317a7 100644 --- a/packages/peer-collections/README.md +++ b/packages/peer-collections/README.md @@ -1,5 +1,3 @@ -# @libp2p/peer-collections - [![libp2p.io](https://img.shields.io/badge/project-libp2p-yellow.svg?style=flat-square)](http://libp2p.io/) [![Discuss](https://img.shields.io/discourse/https/discuss.libp2p.io/posts.svg?style=flat-square)](https://discuss.libp2p.io) [![codecov](https://img.shields.io/codecov/c/github/libp2p/js-libp2p.svg?style=flat-square)](https://codecov.io/gh/libp2p/js-libp2p) @@ -7,22 +5,19 @@ > Stores values against a peer id -## Table of contents +# About -- [Install](#install) - - [Browser ` ``` -## Description - -We can't use PeerIds as collection keys because collection keys are compared using same-value-zero equality, so this is just a group of collections that stringifies PeerIds before storing them. - -PeerIds cache stringified versions of themselves so this should be a cheap operation. - -## API Docs +# API Docs - -## License +# License Licensed under either of - Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) - MIT ([LICENSE-MIT](LICENSE-MIT) / ) -## Contribution +# Contribution Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/packages/peer-collections/src/index.ts b/packages/peer-collections/src/index.ts index db2767e619..39bd9479d3 100644 --- a/packages/peer-collections/src/index.ts +++ b/packages/peer-collections/src/index.ts @@ -1,3 +1,11 @@ +/** + * @packageDocumentation + * + * We can't use PeerIds as collection keys because collection keys are compared using same-value-zero equality, so this is just a group of collections that stringifies PeerIds before storing them. + * + * PeerIds cache stringified versions of themselves so this should be a cheap operation. + */ + export { PeerMap } from './map.js' export { PeerSet } from './set.js' export { PeerList } from './list.js' diff --git a/packages/peer-discovery-bootstrap/README.md b/packages/peer-discovery-bootstrap/README.md index c48965d55c..9176c04857 100644 --- a/packages/peer-discovery-bootstrap/README.md +++ b/packages/peer-discovery-bootstrap/README.md @@ -1,5 +1,3 @@ -# @libp2p/bootstrap - [![libp2p.io](https://img.shields.io/badge/project-libp2p-yellow.svg?style=flat-square)](http://libp2p.io/) [![Discuss](https://img.shields.io/discourse/https/discuss.libp2p.io/posts.svg?style=flat-square)](https://discuss.libp2p.io) [![codecov](https://img.shields.io/codecov/c/github/libp2p/js-libp2p.svg?style=flat-square)](https://codecov.io/gh/libp2p/js-libp2p) @@ -7,37 +5,11 @@ > Peer discovery via a list of bootstrap peers -## Table of contents - -- [Install](#install) - - [Browser ` -``` +The configured bootstrap peers will be discovered after the configured timeout. This will ensure there are some peers in the peer store for the node to use to discover other peers. -## Usage - -The configured bootstrap peers will be discovered after the configured timeout. This will ensure -there are some peers in the peer store for the node to use to discover other peers. - -They will be tagged with a tag with the name `'bootstrap'` tag, the value `50` and it will expire -after two minutes which means the nodes connections may be closed if the maximum number of -connections is reached. +They will be tagged with a tag with the name `'bootstrap'` tag, the value `50` and it will expire after two minutes which means the nodes connections may be closed if the maximum number of connections is reached. Clients that need constant connections to bootstrap nodes (e.g. browsers) can set the TTL to `Infinity`. @@ -73,31 +45,38 @@ let options = { ] } -async function start () { - let libp2p = await createLibp2p(options) +const libp2p = await createLibp2p(options) - libp2p.on('peer:discovery', function (peerId) { - console.log('found peer: ', peerId.toB58String()) - }) +libp2p.on('peer:discovery', function (peerId) { + console.log('found peer: ', peerId.toB58String()) +}) +``` - await libp2p.start() +# Install -} +```console +$ npm i @libp2p/bootstrap +``` + +## Browser ` ``` -## API Docs +# API Docs - -## License +# License Licensed under either of - Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) - MIT ([LICENSE-MIT](LICENSE-MIT) / ) -## Contribution +# Contribution Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/packages/peer-discovery-bootstrap/src/index.ts b/packages/peer-discovery-bootstrap/src/index.ts index 7400d494f4..999b14f5e0 100644 --- a/packages/peer-discovery-bootstrap/src/index.ts +++ b/packages/peer-discovery-bootstrap/src/index.ts @@ -1,3 +1,52 @@ +/** + * @packageDocumentation + * + * The configured bootstrap peers will be discovered after the configured timeout. This will ensure there are some peers in the peer store for the node to use to discover other peers. + * + * They will be tagged with a tag with the name `'bootstrap'` tag, the value `50` and it will expire after two minutes which means the nodes connections may be closed if the maximum number of connections is reached. + * + * Clients that need constant connections to bootstrap nodes (e.g. browsers) can set the TTL to `Infinity`. + * + * ```JavaScript + * import { createLibp2p } from 'libp2p' + * import { bootstrap } from '@libp2p/bootstrap' + * import { tcp } from 'libp2p/tcp' + * import { noise } from '@libp2p/noise' + * import { mplex } from '@libp2p/mplex' + * + * let options = { + * transports: [ + * tcp() + * ], + * streamMuxers: [ + * mplex() + * ], + * connectionEncryption: [ + * noise() + * ], + * peerDiscovery: [ + * bootstrap({ + * list: [ // a list of bootstrap peer multiaddrs to connect to on node startup + * "/ip4/104.131.131.82/tcp/4001/ipfs/QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ", + * "/dnsaddr/bootstrap.libp2p.io/ipfs/QmNnooDu7bfjPFoTZYxMNLWUQJyrVwtbZg5gBMjTezGAJN", + * "/dnsaddr/bootstrap.libp2p.io/ipfs/QmQCU2EcMqAqQPR2i9bChDtGNJchTbq5TbXJJ16u19uLTa" + * ], + * timeout: 1000, // in ms, + * tagName: 'bootstrap', + * tagValue: 50, + * tagTTL: 120000 // in ms + * }) + * ] + * } + * + * const libp2p = await createLibp2p(options) + * + * libp2p.on('peer:discovery', function (peerId) { + * console.log('found peer: ', peerId.toB58String()) + * }) + * ``` + */ + import { TypedEventEmitter } from '@libp2p/interface/events' import { peerDiscovery } from '@libp2p/interface/peer-discovery' import { logger } from '@libp2p/logger' diff --git a/packages/peer-discovery-mdns/README.md b/packages/peer-discovery-mdns/README.md index be587d8220..11ebefd4f3 100644 --- a/packages/peer-discovery-mdns/README.md +++ b/packages/peer-discovery-mdns/README.md @@ -1,5 +1,3 @@ -# @libp2p/mdns - [![libp2p.io](https://img.shields.io/badge/project-libp2p-yellow.svg?style=flat-square)](http://libp2p.io/) [![Discuss](https://img.shields.io/discourse/https/discuss.libp2p.io/posts.svg?style=flat-square)](https://discuss.libp2p.io) [![codecov](https://img.shields.io/codecov/c/github/libp2p/js-libp2p.svg?style=flat-square)](https://codecov.io/gh/libp2p/js-libp2p) @@ -7,24 +5,13 @@ > Node.js libp2p mDNS discovery implementation for peer discovery -## Table of contents +# About -- [Install](#install) -- [Usage](#usage) -- [MDNS messages](#mdns-messages) -- [API Docs](#api-docs) -- [License](#license) -- [Contribution](#contribution) +A peer discover mechanism that uses [mDNS](https://datatracker.ietf.org/doc/html/rfc6762) to discover peers on the local network. -## Install +## Example -```console -$ npm i @libp2p/mdns -``` - -## Usage - -```Typescript +```ts import { mdns } from '@libp2p/mdns' const options = { @@ -33,81 +20,84 @@ const options = { ] } -async function start () { - const libp2p = await createLibp2p(options) - - libp2p.on('peer:discovery', function (peerId) { - console.log('found peer: ', peerId.toB58String()) - }) +const libp2p = await createLibp2p(options) - await libp2p.start() -} +libp2p.on('peer:discovery', function (peerId) { + console.log('found peer: ', peerId.toB58String()) +}) +await libp2p.start() ``` -- options - - `peerName` - Peer name to announce (should not be peeer id), default random string - - `multiaddrs` - multiaddrs to announce - - `broadcast` - (true/false) announce our presence through mDNS, default `true` - - `interval` - query interval, default 10 \* 1000 (10 seconds) - - `serviceTag` - name of the service announce , default '_p2p._udp.local\` - ## MDNS messages A query is sent to discover the libp2p nodes on the local network ```js { - type: 'query', - questions: [ { name: '_p2p._udp.local', type: 'PTR' } ] + type: 'query', + questions: [ { name: '_p2p._udp.local', type: 'PTR' } ] } ``` When a query is detected, each libp2p node sends an answer about itself ```js - [ { name: '_p2p._udp.local', - type: 'PTR', - class: 'IN', - ttl: 120, - data: 'QmNPubsDWATVngE3d5WDSNe7eVrFLuk38qb9t6vdLnu2aK._p2p._udp.local' }, - { name: 'QmNPubsDWATVngE3d5WDSNe7eVrFLuk38qb9t6vdLnu2aK._p2p._udp.local', - type: 'SRV', - class: 'IN', - ttl: 120, - data: - { priority: 10, - weight: 1, - port: '20002', - target: 'LAPTOP-G5LJ7VN9' } }, - { name: 'QmNPubsDWATVngE3d5WDSNe7eVrFLuk38qb9t6vdLnu2aK._p2p._udp.local', - type: 'TXT', - class: 'IN', - ttl: 120, - data: ['QmNPubsDWATVngE3d5WDSNe7eVrFLuk38qb9t6vdLnu2aK'] }, - { name: 'LAPTOP-G5LJ7VN9', - type: 'A', - class: 'IN', - ttl: 120, - data: '127.0.0.1' }, - { name: 'LAPTOP-G5LJ7VN9', - type: 'AAAA', - class: 'IN', - ttl: 120, - data: '::1' } ] +[{ + name: '_p2p._udp.local', + type: 'PTR', + class: 'IN', + ttl: 120, + data: 'QmNPubsDWATVngE3d5WDSNe7eVrFLuk38qb9t6vdLnu2aK._p2p._udp.local' +}, { + name: 'QmNPubsDWATVngE3d5WDSNe7eVrFLuk38qb9t6vdLnu2aK._p2p._udp.local', + type: 'SRV', + class: 'IN', + ttl: 120, + data: { + priority: 10, + weight: 1, + port: '20002', + target: 'LAPTOP-G5LJ7VN9' + } +}, { + name: 'QmNPubsDWATVngE3d5WDSNe7eVrFLuk38qb9t6vdLnu2aK._p2p._udp.local', + type: 'TXT', + class: 'IN', + ttl: 120, + data: ['QmNPubsDWATVngE3d5WDSNe7eVrFLuk38qb9t6vdLnu2aK'] +}, { + name: 'LAPTOP-G5LJ7VN9', + type: 'A', + class: 'IN', + ttl: 120, + data: '127.0.0.1' +}, { + name: 'LAPTOP-G5LJ7VN9', + type: 'AAAA', + class: 'IN', + ttl: 120, + data: '::1' +}] +``` + +# Install + +```console +$ npm i @libp2p/mdns ``` -## API Docs +# API Docs - -## License +# License Licensed under either of - Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) - MIT ([LICENSE-MIT](LICENSE-MIT) / ) -## Contribution +# Contribution Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/packages/peer-discovery-mdns/src/index.ts b/packages/peer-discovery-mdns/src/index.ts index 98d568640e..ed37439b57 100644 --- a/packages/peer-discovery-mdns/src/index.ts +++ b/packages/peer-discovery-mdns/src/index.ts @@ -1,3 +1,81 @@ +/** + * @packageDocumentation + * + * A peer discover mechanism that uses [mDNS](https://datatracker.ietf.org/doc/html/rfc6762) to discover peers on the local network. + * + * @example + * + * ```ts + * import { mdns } from '@libp2p/mdns' + * + * const options = { + * peerDiscovery: [ + * mdns() + * ] + * } + * + * const libp2p = await createLibp2p(options) + * + * libp2p.on('peer:discovery', function (peerId) { + * console.log('found peer: ', peerId.toB58String()) + * }) + * + * await libp2p.start() + * ``` + * + * ## MDNS messages + * + * A query is sent to discover the libp2p nodes on the local network + * + * ```js + * { + * type: 'query', + * questions: [ { name: '_p2p._udp.local', type: 'PTR' } ] + * } + * ``` + * + * When a query is detected, each libp2p node sends an answer about itself + * + * ```js + * [{ + * name: '_p2p._udp.local', + * type: 'PTR', + * class: 'IN', + * ttl: 120, + * data: 'QmNPubsDWATVngE3d5WDSNe7eVrFLuk38qb9t6vdLnu2aK._p2p._udp.local' + * }, { + * name: 'QmNPubsDWATVngE3d5WDSNe7eVrFLuk38qb9t6vdLnu2aK._p2p._udp.local', + * type: 'SRV', + * class: 'IN', + * ttl: 120, + * data: { + * priority: 10, + * weight: 1, + * port: '20002', + * target: 'LAPTOP-G5LJ7VN9' + * } + * }, { + * name: 'QmNPubsDWATVngE3d5WDSNe7eVrFLuk38qb9t6vdLnu2aK._p2p._udp.local', + * type: 'TXT', + * class: 'IN', + * ttl: 120, + * data: ['QmNPubsDWATVngE3d5WDSNe7eVrFLuk38qb9t6vdLnu2aK'] + * }, { + * name: 'LAPTOP-G5LJ7VN9', + * type: 'A', + * class: 'IN', + * ttl: 120, + * data: '127.0.0.1' + * }, { + * name: 'LAPTOP-G5LJ7VN9', + * type: 'AAAA', + * class: 'IN', + * ttl: 120, + * data: '::1' + * }] + * ``` + */ + import { CustomEvent, TypedEventEmitter } from '@libp2p/interface/events' import { peerDiscovery } from '@libp2p/interface/peer-discovery' import { logger } from '@libp2p/logger' @@ -12,11 +90,33 @@ import type { AddressManager } from '@libp2p/interface-internal/address-manager' const log = logger('libp2p:mdns') export interface MulticastDNSInit { + /** + * (true/false) announce our presence through mDNS, default `true` + */ broadcast?: boolean + + /** + * query interval, default 10 \* 1000 (10 seconds) + */ interval?: number + + /** + * name of the service announce , default '_p2p._udp.local\` + */ serviceTag?: string + /** + * Peer name to announce (should not be peeer id), default random string + */ peerName?: string + + /** + * UDP port to broadcast to + */ port?: number + + /** + * UDP IP to broadcast to + */ ip?: string } diff --git a/packages/peer-id-factory/README.md b/packages/peer-id-factory/README.md index 7c353cd96b..b430276ed2 100644 --- a/packages/peer-id-factory/README.md +++ b/packages/peer-id-factory/README.md @@ -1,5 +1,3 @@ -# @libp2p/peer-id-factory - [![libp2p.io](https://img.shields.io/badge/project-libp2p-yellow.svg?style=flat-square)](http://libp2p.io/) [![Discuss](https://img.shields.io/discourse/https/discuss.libp2p.io/posts.svg?style=flat-square)](https://discuss.libp2p.io) [![codecov](https://img.shields.io/codecov/c/github/libp2p/js-libp2p.svg?style=flat-square)](https://codecov.io/gh/libp2p/js-libp2p) @@ -7,31 +5,7 @@ > Create PeerId instances -## Table of contents - -- [Install](#install) - - [Browser ` -``` - -## Description +# About Generate, import, and export PeerIDs, for use with [IPFS](https://github.com/ipfs/ipfs). @@ -52,17 +26,31 @@ console.log(id.toString()) 12D3KooWRm8J3iL796zPFi2EtGGtUJn58AG67gcqzMFHZnnsTzqD ``` -## API Docs +# Install + +```console +$ npm i @libp2p/peer-id-factory +``` + +## Browser ` +``` + +# API Docs - -## License +# License Licensed under either of - Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) - MIT ([LICENSE-MIT](LICENSE-MIT) / ) -## Contribution +# Contribution Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/packages/peer-id-factory/src/index.ts b/packages/peer-id-factory/src/index.ts index 626f01eec3..f40646befe 100644 --- a/packages/peer-id-factory/src/index.ts +++ b/packages/peer-id-factory/src/index.ts @@ -1,3 +1,26 @@ +/** + * @packageDocumentation + * + * Generate, import, and export PeerIDs, for use with [IPFS](https://github.com/ipfs/ipfs). + * + * A Peer ID is the SHA-256 [multihash](https://github.com/multiformats/multihash) of a public key. + * + * The public key is a base64 encoded string of a protobuf containing an RSA DER buffer. This uses a node buffer to pass the base64 encoded public key protobuf to the multihash for ID generation. + * + * @example + * + * ```JavaScript + * import { createEd25519PeerId } from '@libp2p/peer-id-factory' + * + * const peerId = await createEd25519PeerId() + * console.log(id.toString()) + * ``` + * + * ```bash + * 12D3KooWRm8J3iL796zPFi2EtGGtUJn58AG67gcqzMFHZnnsTzqD + * ``` + */ + import { generateKeyPair, marshalPrivateKey, unmarshalPrivateKey, marshalPublicKey, unmarshalPublicKey } from '@libp2p/crypto/keys' import { peerIdFromKeys, peerIdFromBytes } from '@libp2p/peer-id' import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string' diff --git a/packages/peer-id/README.md b/packages/peer-id/README.md index 7c2c8c23bc..aafa9396d7 100644 --- a/packages/peer-id/README.md +++ b/packages/peer-id/README.md @@ -1,29 +1,15 @@ -# @libp2p/peer-id - [![libp2p.io](https://img.shields.io/badge/project-libp2p-yellow.svg?style=flat-square)](http://libp2p.io/) [![Discuss](https://img.shields.io/discourse/https/discuss.libp2p.io/posts.svg?style=flat-square)](https://discuss.libp2p.io) [![codecov](https://img.shields.io/codecov/c/github/libp2p/js-libp2p.svg?style=flat-square)](https://codecov.io/gh/libp2p/js-libp2p) [![CI](https://img.shields.io/github/actions/workflow/status/libp2p/js-libp2p/main.yml?branch=master\&style=flat-square)](https://github.com/libp2p/js-libp2p/actions/workflows/main.yml?query=branch%3Amaster) -> Implementation of @libp2p/interface-peer-id - -## Table of contents - -- [Install](#install) - - [Browser ` ``` -## Description - -A basic implementation of a peer id - -## Example - -```JavaScript -import { peerIdFromString } from '@libp2p/peer-id' - -const peer = peerIdFromString('k51qzi5uqu5dkwkqm42v9j9kqcam2jiuvloi16g72i4i4amoo2m8u3ol3mqu6s') - -console.log(peer.toCid()) // CID(bafzaa...) -console.log(peer.toString()) // "12D3K..." -``` - -## API Docs +# API Docs - -## License +# License Licensed under either of - Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) - MIT ([LICENSE-MIT](LICENSE-MIT) / ) -## Contribution +# Contribution Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/packages/peer-id/src/index.ts b/packages/peer-id/src/index.ts index b1dfd2fabe..db722aa171 100644 --- a/packages/peer-id/src/index.ts +++ b/packages/peer-id/src/index.ts @@ -1,3 +1,19 @@ +/** + * @packageDocumentation + * + * An implementation of a peer id + * + * @example + * + * ```JavaScript + * import { peerIdFromString } from '@libp2p/peer-id' + * const peer = peerIdFromString('k51qzi5uqu5dkwkqm42v9j9kqcam2jiuvloi16g72i4i4amoo2m8u3ol3mqu6s') + * + * console.log(peer.toCid()) // CID(bafzaa...) + * console.log(peer.toString()) // "12D3K..." + * ``` + */ + import { CodeError } from '@libp2p/interface/errors' import { type Ed25519PeerId, type PeerIdType, type RSAPeerId, type Secp256k1PeerId, symbol, type PeerId } from '@libp2p/interface/peer-id' import { base58btc } from 'multiformats/bases/base58' diff --git a/packages/peer-record/README.md b/packages/peer-record/README.md index 358efe226b..ae3adc5144 100644 --- a/packages/peer-record/README.md +++ b/packages/peer-record/README.md @@ -1,5 +1,3 @@ -# @libp2p/peer-record - [![libp2p.io](https://img.shields.io/badge/project-libp2p-yellow.svg?style=flat-square)](http://libp2p.io/) [![Discuss](https://img.shields.io/discourse/https/discuss.libp2p.io/posts.svg?style=flat-square)](https://discuss.libp2p.io) [![codecov](https://img.shields.io/codecov/c/github/libp2p/js-libp2p.svg?style=flat-square)](https://codecov.io/gh/libp2p/js-libp2p) @@ -7,44 +5,11 @@ > Used to transfer signed peer data across the network -## Table of contents - -- [Install](#install) - - [Browser ` -``` - -## Description +# About Libp2p nodes need to store data in a public location (e.g. a DHT), or rely on potentially untrustworthy intermediaries to relay information over its lifetime. Accordingly, libp2p nodes need to be able to verify that the data came from a specific peer and that it hasn't been tampered with. -### Envelope +## Envelope Libp2p provides an all-purpose data container called **envelope**. It was created to enable the distribution of verifiable records, which we can prove originated from the addressed peer itself. The envelope includes a signature of the data, so that its authenticity is verified. @@ -52,9 +17,9 @@ This envelope stores a marshaled record implementing the [interface-record](http You can read further about the envelope in [libp2p/specs#217](https://github.com/libp2p/specs/pull/217). -## Usage +## Example -- create an envelope with an instance of an [interface-record](https://github.com/libp2p/js-libp2p-interfaces/tree/master/src/record) implementation and prepare it for being exchanged: +Create an envelope with an instance of an [interface-record](https://github.com/libp2p/js-libp2p-interfaces/tree/master/src/record) implementation and prepare it for being exchanged: ```js // interface-record implementation example with the "libp2p-example" namespace @@ -83,7 +48,9 @@ const e = await PeerEnvelope.seal(rec, peerId) const wireData = e.marshal() ``` -- consume a received envelope (`wireData`) and transform it back to a record: +## Example + +Consume a received envelope (`wireData`) and transform it back to a record: ```js import { PeerEnvelope } from '@libp2p/peer-record' @@ -109,9 +76,9 @@ A peer record contains the peers' publicly reachable listen addresses, and may b You can read further about the Peer Record in [libp2p/specs#217](https://github.com/libp2p/specs/pull/217). -### Usage +## Example -- create a new Peer Record +Create a new Peer Record ```js import { PeerRecord } from '@libp2p/peer-record' @@ -122,7 +89,9 @@ const pr = new PeerRecord({ }) ``` -- create a Peer Record from a protobuf +## Example + +Create a Peer Record from a protobuf ```js import { PeerRecord } from '@libp2p/peer-record' @@ -130,23 +99,21 @@ import { PeerRecord } from '@libp2p/peer-record' const pr = PeerRecord.createFromProtobuf(data) ``` -### Libp2p Flows +## Libp2p Flows -#### Self Record +### Self Record Once a libp2p node has started and is listening on a set of multiaddrs, its own peer record can be created. The identify service is responsible for creating the self record when the identify protocol kicks in for the first time. This record will be stored for future needs of the identify protocol when connecting with other peers. -#### Self record Updates - -***NOT\_YET\_IMPLEMENTED*** +### Self record Updates While creating peer records is fairly trivial, addresses are not static and might be modified at arbitrary times. This can happen via an Address Manager API, or even through AutoRelay/AutoNAT. When a libp2p node changes its listen addresses, the identify service will be informed. Once that happens, the identify service creates a new self record and stores it. With the new record, the identify push/delta protocol will be used to communicate this change to the connected peers. -#### Subsystem receiving a record +### Subsystem receiving a record Considering that a node can discover other peers' addresses from a variety of sources, Libp2p Peerstore can differentiate the addresses that were obtained through a signed peer record. @@ -154,34 +121,48 @@ Once a record is received and its signature properly validated, its envelope is The AddressBook Addresses will be updated with the content of the envelope with a certified property. This allows other subsystems to identify the known certified addresses of a peer. -#### Subsystem providing a record +### Subsystem providing a record Libp2p subsystems that exchange other peers information will provide the envelope that they received by those peers. As a result, other peers can verify if the envelope was really created by the addressed peer. When a subsystem wants to provide a record, it will get it from the AddressBook, if it exists. Other subsystems are also able to provide the self record, since it is also stored in the AddressBook. -### Future Work +## Future Work - Persistence only considering certified addresses? - Peers may not know their own addresses. It's often impossible to automatically infer one's own public address, and peers may need to rely on third party peers to inform them of their observed public addresses. - A peer may inadvertently or maliciously sign an address that they do not control. In other words, a signature isn't a guarantee that a given address is valid. - Some addresses may be ambiguous. For example, addresses on a private subnet are valid within that subnet but are useless on the public internet. - Once all these pieces are in place, we will also need a way to prioritize addresses based on their authenticity, that is, the dialer can prioritize self-certified addresses over addresses from an unknown origin. - - Modular dialer? (taken from go PR notes) - - With the modular dialer, users should easily be able to configure precedence. With dialer v1, anything we do to prioritise dials is gonna be spaghetti and adhoc. With the modular dialer, you’d be able to specify the order of dials when instantiating the pipeline. - - Multiple parallel dials. We already have the issue where new addresses aren't added to existing dials. +- Modular dialer? (taken from go PR notes) + - With the modular dialer, users should easily be able to configure precedence. With dialer v1, anything we do to prioritise dials is gonna be spaghetti and adhoc. With the modular dialer, you’d be able to specify the order of dials when instantiating the pipeline. + - Multiple parallel dials. We already have the issue where new addresses aren't added to existing dials. + +# Install + +```console +$ npm i @libp2p/peer-record +``` + +## Browser ` +``` -## API Docs +# API Docs - -## License +# License Licensed under either of - Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) - MIT ([LICENSE-MIT](LICENSE-MIT) / ) -## Contribution +# Contribution Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/packages/peer-record/src/index.ts b/packages/peer-record/src/index.ts index 51238b79ac..c3207bac39 100644 --- a/packages/peer-record/src/index.ts +++ b/packages/peer-record/src/index.ts @@ -1,3 +1,138 @@ +/** + * @packageDocumentation + * + * Libp2p nodes need to store data in a public location (e.g. a DHT), or rely on potentially untrustworthy intermediaries to relay information over its lifetime. Accordingly, libp2p nodes need to be able to verify that the data came from a specific peer and that it hasn't been tampered with. + * + * ## Envelope + * + * Libp2p provides an all-purpose data container called **envelope**. It was created to enable the distribution of verifiable records, which we can prove originated from the addressed peer itself. The envelope includes a signature of the data, so that its authenticity is verified. + * + * This envelope stores a marshaled record implementing the [interface-record](https://github.com/libp2p/js-libp2p-interfaces/tree/master/src/record). These Records are designed to be serialized to bytes and placed inside of the envelopes before being shared with other peers. + * + * You can read further about the envelope in [libp2p/specs#217](https://github.com/libp2p/specs/pull/217). + * + * @example + * + * Create an envelope with an instance of an [interface-record](https://github.com/libp2p/js-libp2p-interfaces/tree/master/src/record) implementation and prepare it for being exchanged: + * + * ```js + * // interface-record implementation example with the "libp2p-example" namespace + * import { PeerRecord } from '@libp2p/peer-record' + * import { fromString } from 'uint8arrays/from-string' + * + * class ExampleRecord extends PeerRecord { + * constructor () { + * super ('libp2p-example', fromString('0302', 'hex')) + * } + * + * marshal () {} + * + * equals (other) {} + * } + * + * ExampleRecord.createFromProtobuf = () => {} + * ``` + * + * ```js + * import { PeerEnvelope } from '@libp2p/peer-record' + * import { ExampleRecord } from './example-record.js' + * + * const rec = new ExampleRecord() + * const e = await PeerEnvelope.seal(rec, peerId) + * const wireData = e.marshal() + * ``` + * + * @example + * + * Consume a received envelope (`wireData`) and transform it back to a record: + * + * ```js + * import { PeerEnvelope } from '@libp2p/peer-record' + * import { ExampleRecord } from './example-record.js' + * + * const domain = 'libp2p-example' + * let e + * + * try { + * e = await PeerEnvelope.openAndCertify(wireData, domain) + * } catch (err) {} + * + * const rec = ExampleRecord.createFromProtobuf(e.payload) + * ``` + * + * ## Peer Record + * + * All libp2p nodes keep a `PeerStore`, that among other information stores a set of known addresses for each peer, which can come from a variety of sources. + * + * Libp2p peer records were created to enable the distribution of verifiable address records, which we can prove originated from the addressed peer itself. With such guarantees, libp2p is able to prioritize addresses based on their authenticity, with the most strict strategy being to only dial certified addresses (no strategies have been implemented at the time of writing). + * + * A peer record contains the peers' publicly reachable listen addresses, and may be extended in the future to contain additional metadata relevant to routing. It also contains a `seqNumber` field, a timestamp per the spec, so that we can verify the most recent record. + * + * You can read further about the Peer Record in [libp2p/specs#217](https://github.com/libp2p/specs/pull/217). + * + * @example + * + * Create a new Peer Record + * + * ```js + * import { PeerRecord } from '@libp2p/peer-record' + * + * const pr = new PeerRecord({ + * peerId: node.peerId, + * multiaddrs: node.multiaddrs + * }) + * ``` + * + * @example + * + * Create a Peer Record from a protobuf + * + * ```js + * import { PeerRecord } from '@libp2p/peer-record' + * + * const pr = PeerRecord.createFromProtobuf(data) + * ``` + * + * ## Libp2p Flows + * + * ### Self Record + * + * Once a libp2p node has started and is listening on a set of multiaddrs, its own peer record can be created. + * + * The identify service is responsible for creating the self record when the identify protocol kicks in for the first time. This record will be stored for future needs of the identify protocol when connecting with other peers. + * + * ### Self record Updates + * + * While creating peer records is fairly trivial, addresses are not static and might be modified at arbitrary times. This can happen via an Address Manager API, or even through AutoRelay/AutoNAT. + * + * When a libp2p node changes its listen addresses, the identify service will be informed. Once that happens, the identify service creates a new self record and stores it. With the new record, the identify push/delta protocol will be used to communicate this change to the connected peers. + * + * ### Subsystem receiving a record + * + * Considering that a node can discover other peers' addresses from a variety of sources, Libp2p Peerstore can differentiate the addresses that were obtained through a signed peer record. + * + * Once a record is received and its signature properly validated, its envelope is stored in the AddressBook in its byte representation. The `seqNumber` remains unmarshalled so that we can quickly compare it against incoming records to determine the most recent record. + * + * The AddressBook Addresses will be updated with the content of the envelope with a certified property. This allows other subsystems to identify the known certified addresses of a peer. + * + * ### Subsystem providing a record + * + * Libp2p subsystems that exchange other peers information will provide the envelope that they received by those peers. As a result, other peers can verify if the envelope was really created by the addressed peer. + * + * When a subsystem wants to provide a record, it will get it from the AddressBook, if it exists. Other subsystems are also able to provide the self record, since it is also stored in the AddressBook. + * + * ## Future Work + * + * - Persistence only considering certified addresses? + * - Peers may not know their own addresses. It's often impossible to automatically infer one's own public address, and peers may need to rely on third party peers to inform them of their observed public addresses. + * - A peer may inadvertently or maliciously sign an address that they do not control. In other words, a signature isn't a guarantee that a given address is valid. + * - Some addresses may be ambiguous. For example, addresses on a private subnet are valid within that subnet but are useless on the public internet. + * - Once all these pieces are in place, we will also need a way to prioritize addresses based on their authenticity, that is, the dialer can prioritize self-certified addresses over addresses from an unknown origin. + * - Modular dialer? (taken from go PR notes) + * - With the modular dialer, users should easily be able to configure precedence. With dialer v1, anything we do to prioritise dials is gonna be spaghetti and adhoc. With the modular dialer, you’d be able to specify the order of dials when instantiating the pipeline. + * - Multiple parallel dials. We already have the issue where new addresses aren't added to existing dials. + */ + export { RecordEnvelope } from './envelope/index.js' export type { RecordEnvelopeInit } from './envelope/index.js' export { PeerRecord } from './peer-record/index.js' diff --git a/packages/peer-store/README.md b/packages/peer-store/README.md index 41a310aad6..7b7d85b490 100644 --- a/packages/peer-store/README.md +++ b/packages/peer-store/README.md @@ -1,5 +1,3 @@ -# @libp2p/peer-store - [![libp2p.io](https://img.shields.io/badge/project-libp2p-yellow.svg?style=flat-square)](http://libp2p.io/) [![Discuss](https://img.shields.io/discourse/https/discuss.libp2p.io/posts.svg?style=flat-square)](https://discuss.libp2p.io) [![codecov](https://img.shields.io/codecov/c/github/libp2p/js-libp2p.svg?style=flat-square)](https://codecov.io/gh/libp2p/js-libp2p) @@ -7,21 +5,13 @@ > Stores information about peers libp2p knows on the network -## Table of contents - -- [Install](#install) - - [Browser ` ``` -## API Docs +# API Docs - -## License +# License Licensed under either of - Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) - MIT ([LICENSE-MIT](LICENSE-MIT) / ) -## Contribution +# Contribution Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. - -[peer-id]: https://github.com/libp2p/js-peer-id - -[peer-store-events]: [https://github.com/libp2p/js-libp2p/blob/master/doc/API.md#libp2ppeerStore] diff --git a/packages/protocol-perf/README.md b/packages/protocol-perf/README.md index 15ca3f4ada..915e7420ea 100644 --- a/packages/protocol-perf/README.md +++ b/packages/protocol-perf/README.md @@ -1,5 +1,3 @@ -# @libp2p/perf - [![libp2p.io](https://img.shields.io/badge/project-libp2p-yellow.svg?style=flat-square)](http://libp2p.io/) [![Discuss](https://img.shields.io/discourse/https/discuss.libp2p.io/posts.svg?style=flat-square)](https://discuss.libp2p.io) [![codecov](https://img.shields.io/codecov/c/github/libp2p/js-libp2p.svg?style=flat-square)](https://codecov.io/gh/libp2p/js-libp2p) @@ -7,39 +5,58 @@ > Implementation of Perf Protocol -## Table of contents +# About + +The `performanceService` implements the [perf protocol](https://github.com/libp2p/specs/blob/master/perf/perf.md), which is used to measure performance within and across libp2p implementations +addresses. -- [Install](#install) - - [Browser ` ``` -## API Docs +# API Docs - -## License +# License Licensed under either of - Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) - MIT ([LICENSE-MIT](LICENSE-MIT) / ) -## Contribution +# Contribution Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/packages/pubsub-floodsub/README.md b/packages/pubsub-floodsub/README.md index 9fadcbc2ca..a1b7c91b9b 100644 --- a/packages/pubsub-floodsub/README.md +++ b/packages/pubsub-floodsub/README.md @@ -1,5 +1,3 @@ -# @libp2p/floodsub - [![libp2p.io](https://img.shields.io/badge/project-libp2p-yellow.svg?style=flat-square)](http://libp2p.io/) [![Discuss](https://img.shields.io/discourse/https/discuss.libp2p.io/posts.svg?style=flat-square)](https://discuss.libp2p.io) [![codecov](https://img.shields.io/codecov/c/github/libp2p/js-libp2p.svg?style=flat-square)](https://codecov.io/gh/libp2p/js-libp2p) @@ -7,31 +5,9 @@ > libp2p-floodsub, also known as pubsub-flood or just dumbsub, this implementation of pubsub focused on delivering an API for Publish/Subscribe, but with no CastTree Forming (it just floods the network). -## Table of contents - -- [Install](#install) - - [Browser ` -``` +# About -## Don't use this module +> Don't use this module This module is a naive implementation of pubsub. It broadcasts all messages to all network peers, cannot provide older messages and has no protection against bad actors. @@ -39,7 +15,7 @@ It exists for academic purposes only, you should not use it in production. Instead please use [gossipsub](https://www.npmjs.com/package/@chainsafe/libp2p-gossipsub) - a more complete implementation which is also compatible with floodsub. -## Usage +## Example ```JavaScript import { createLibp2pNode } from 'libp2p' @@ -59,17 +35,31 @@ node.pubsub.addEventListener('message', (evt) => { node.pubsub.publish('fruit', new TextEncoder().encode('banana')) ``` -## API Docs +# Install + +```console +$ npm i @libp2p/floodsub +``` + +## Browser ` +``` + +# API Docs - -## License +# License Licensed under either of - Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) - MIT ([LICENSE-MIT](LICENSE-MIT) / ) -## Contribution +# Contribution Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/packages/pubsub-floodsub/src/index.ts b/packages/pubsub-floodsub/src/index.ts index 4d50605173..53a0e41677 100644 --- a/packages/pubsub-floodsub/src/index.ts +++ b/packages/pubsub-floodsub/src/index.ts @@ -1,3 +1,35 @@ +/** + * @packageDocumentation + * + * > Don't use this module + * + * This module is a naive implementation of pubsub. It broadcasts all messages to all network peers, cannot provide older messages and has no protection against bad actors. + * + * It exists for academic purposes only, you should not use it in production. + * + * Instead please use [gossipsub](https://www.npmjs.com/package/@chainsafe/libp2p-gossipsub) - a more complete implementation which is also compatible with floodsub. + * + * @example + * + * ```JavaScript + * import { createLibp2pNode } from 'libp2p' + * import { floodsub } from '@libp2p/floodsub' + * + * const node = await createLibp2pNode({ + * pubsub: floodsub() + * //... other options + * }) + * await node.start() + * + * node.pubsub.subscribe('fruit') + * node.pubsub.addEventListener('message', (evt) => { + * console.log(evt) + * }) + * + * node.pubsub.publish('fruit', new TextEncoder().encode('banana')) + * ``` + */ + import { logger } from '@libp2p/logger' import { PubSubBaseProtocol, type PubSubComponents } from '@libp2p/pubsub' import { toString } from 'uint8arrays/to-string' diff --git a/packages/pubsub/README.md b/packages/pubsub/README.md index a985a40c40..7962231142 100644 --- a/packages/pubsub/README.md +++ b/packages/pubsub/README.md @@ -1,5 +1,3 @@ -# @libp2p/pubsub - [![libp2p.io](https://img.shields.io/badge/project-libp2p-yellow.svg?style=flat-square)](http://libp2p.io/) [![Discuss](https://img.shields.io/discourse/https/discuss.libp2p.io/posts.svg?style=flat-square)](https://discuss.libp2p.io) [![codecov](https://img.shields.io/codecov/c/github/libp2p/js-libp2p.svg?style=flat-square)](https://codecov.io/gh/libp2p/js-libp2p) @@ -7,22 +5,13 @@ > libp2p pubsub base class -## Table of contents - -- [Install](#install) - - [Browser ` ``` -## Usage - -```console -npm i @libp2p/pubsub -``` - -```javascript -import { PubSubBaseProtocol } from '@libp2p/pubsub' - -class MyPubsubImplementation extends PubSubBaseProtocol { - // .. extra methods here -} -``` - -## API Docs +# API Docs - -## License +# License Licensed under either of - Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) - MIT ([LICENSE-MIT](LICENSE-MIT) / ) -## Contribution +# Contribution Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/packages/pubsub/src/index.ts b/packages/pubsub/src/index.ts index 2de4fa3fce..af8fa223de 100644 --- a/packages/pubsub/src/index.ts +++ b/packages/pubsub/src/index.ts @@ -1,3 +1,18 @@ +/** + * @packageDocumentation + * + * A set of components to be extended in order to create a pubsub implementation. + * + * @example + * ```javascript + * import { PubSubBaseProtocol } from '@libp2p/pubsub' + * + * class MyPubsubImplementation extends PubSubBaseProtocol { + * // .. extra methods here + * } + * ``` + */ + import { CodeError } from '@libp2p/interface/errors' import { TypedEventEmitter, CustomEvent } from '@libp2p/interface/events' import { type PubSub, type Message, type StrictNoSign, type StrictSign, type PubSubInit, type PubSubEvents, type PeerStreams, type PubSubRPCMessage, type PubSubRPC, type PubSubRPCSubscription, type SubscriptionChangeData, type PublishResult, type TopicValidatorFn, TopicValidatorResult } from '@libp2p/interface/pubsub' diff --git a/packages/stream-multiplexer-mplex/README.md b/packages/stream-multiplexer-mplex/README.md index ee8b856784..dc8954f6c2 100644 --- a/packages/stream-multiplexer-mplex/README.md +++ b/packages/stream-multiplexer-mplex/README.md @@ -1,5 +1,3 @@ -# @libp2p/mplex - [![libp2p.io](https://img.shields.io/badge/project-libp2p-yellow.svg?style=flat-square)](http://libp2p.io/) [![Discuss](https://img.shields.io/discourse/https/discuss.libp2p.io/posts.svg?style=flat-square)](https://discuss.libp2p.io) [![codecov](https://img.shields.io/codecov/c/github/libp2p/js-libp2p.svg?style=flat-square)](https://codecov.io/gh/libp2p/js-libp2p) @@ -7,22 +5,13 @@ > JavaScript implementation of -## Table of contents - -- [Install](#install) - - [Browser ` ``` -[![](https://github.com/libp2p/interface-stream-muxer/raw/master/img/badge.png)](https://github.com/libp2p/interface-stream-muxer) - -## Usage - -```js -import { mplex } from '@libp2p/mplex' -import { pipe } from 'it-pipe' - -const factory = mplex() - -const muxer = factory.createStreamMuxer(components, { - onStream: stream => { // Receive a duplex stream from the remote - // ...receive data from the remote and optionally send data back - }, - onStreamEnd: stream => { - // ...handle any tracking you may need of stream closures - } -}) - -pipe(conn, muxer, conn) // conn is duplex connection to another peer - -const stream = muxer.newStream() // Create a new duplex stream to the remote - -// Use the duplex stream to send some data to the remote... -pipe([1, 2, 3], stream) -``` - ## API Docs - diff --git a/packages/stream-multiplexer-mplex/examples/dialer.js b/packages/stream-multiplexer-mplex/examples/dialer.js deleted file mode 100644 index 9c33ba34ba..0000000000 --- a/packages/stream-multiplexer-mplex/examples/dialer.js +++ /dev/null @@ -1,45 +0,0 @@ -/* eslint-disable no-console */ -'use strict' - -import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string' -import { toString as uint8ArrayToString } from 'uint8arrays/to-string' -import tcp from 'net' -import { pipe } from 'it-pipe' -import { toIterable } from './util.js' -import { Mplex } from '../dist/src/index.js' - -const socket = toIterable(tcp.connect(9999)) -console.log('[dialer] socket stream opened') - -const controller = new AbortController() - -const factory = new Mplex({ signal: controller.signal }) -const muxer = factory.createStreamMuxer() - -const pipeMuxerToSocket = async () => { - await pipe(muxer, socket, muxer) - console.log('[dialer] socket stream closed') -} - -const sendAndReceive = async () => { - const muxedStream = muxer.newStream('hello') - console.log('[dialer] muxed stream opened') - - await pipe( - [uint8ArrayFromString('hey, how is it going. I am the dialer')], - muxedStream, - async source => { - for await (const chunk of source) { - console.log('[dialer] received:') - console.log(uint8ArrayToString(chunk.slice())) - } - } - ) - console.log('[dialer] muxed stream closed') - - // Close the socket stream after 1s - setTimeout(() => controller.abort(), 1000) -} - -pipeMuxerToSocket() -sendAndReceive() diff --git a/packages/stream-multiplexer-mplex/examples/listener.js b/packages/stream-multiplexer-mplex/examples/listener.js deleted file mode 100644 index 189c945531..0000000000 --- a/packages/stream-multiplexer-mplex/examples/listener.js +++ /dev/null @@ -1,37 +0,0 @@ -/* eslint-disable no-console */ -'use strict' - -import tcp from 'net' -import { pipe } from 'it-pipe' -import { toIterable } from './util.js' -import { Mplex } from '../dist/src/index.js' -import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string' -import { toString as uint8ArrayToString } from 'uint8arrays/to-string' - -const listener = tcp.createServer(async socket => { - console.log('[listener] Got connection!') - - const factory = new Mplex() - socket = toIterable(socket) - const muxer = factory.createStreamMuxer({ - onIncomingStream: async (stream) => { - console.log('[listener] muxed stream opened, id:', stream.id) - await pipe( - stream, - source => (async function * () { - for await (const chunk of source) { - console.log('[listener] received:') - console.log(uint8ArrayToString(chunk.slice())) - yield uint8ArrayFromString('thanks for the message, I am the listener') - } - })(), - stream - ) - console.log('[listener] muxed stream closed') - } - }) - await pipe(socket, muxer, socket) - console.log('[listener] socket stream closed') -}) - -listener.listen(9999, () => console.log('[listener] listening on 9999')) diff --git a/packages/stream-multiplexer-mplex/examples/util.js b/packages/stream-multiplexer-mplex/examples/util.js deleted file mode 100644 index 057c0c6787..0000000000 --- a/packages/stream-multiplexer-mplex/examples/util.js +++ /dev/null @@ -1,17 +0,0 @@ -// Simple convertion of Node.js duplex to iterable duplex (no backpressure) -export const toIterable = socket => { - return { - sink: async source => { - try { - for await (const chunk of source) { - socket.write(chunk) - } - } catch (err) { - // If not an abort then destroy the socket with an error - return socket.destroy(err.code === 'ABORT_ERR' ? null : err) - } - socket.end() - }, - source: socket - } -} diff --git a/packages/stream-multiplexer-mplex/src/index.ts b/packages/stream-multiplexer-mplex/src/index.ts index c7ef9549df..75913bb7b5 100644 --- a/packages/stream-multiplexer-mplex/src/index.ts +++ b/packages/stream-multiplexer-mplex/src/index.ts @@ -1,3 +1,36 @@ +/** + * @packageDocumentation + * + * This is a [simple stream multiplexer(https://docs.libp2p.io/concepts/multiplex/mplex/) that has been deprecated. + * + * Please use [@chainsafe/libp2p-yamux](https://www.npmjs.com/package/@chainsafe/libp2p-yamux) instead. + * + * @example + * + * ```js + * import { mplex } from '@libp2p/mplex' + * import { pipe } from 'it-pipe' + * + * const factory = mplex() + * + * const muxer = factory.createStreamMuxer(components, { + * onStream: stream => { // Receive a duplex stream from the remote + * // ...receive data from the remote and optionally send data back + * }, + * onStreamEnd: stream => { + * // ...handle any tracking you may need of stream closures + * } + * }) + * + * pipe(conn, muxer, conn) // conn is duplex connection to another peer + * + * const stream = muxer.newStream() // Create a new duplex stream to the remote + * + * // Use the duplex stream to send some data to the remote... + * pipe([1, 2, 3], stream) + * ``` + */ + import { MplexStreamMuxer } from './mplex.js' import type { StreamMuxer, StreamMuxerFactory, StreamMuxerInit } from '@libp2p/interface/stream-muxer' diff --git a/packages/transport-tcp/README.md b/packages/transport-tcp/README.md index 83fe40f6fc..a914a9db81 100644 --- a/packages/transport-tcp/README.md +++ b/packages/transport-tcp/README.md @@ -1,5 +1,3 @@ -# @libp2p/tcp - [![libp2p.io](https://img.shields.io/badge/project-libp2p-yellow.svg?style=flat-square)](http://libp2p.io/) [![Discuss](https://img.shields.io/discourse/https/discuss.libp2p.io/posts.svg?style=flat-square)](https://discuss.libp2p.io) [![codecov](https://img.shields.io/codecov/c/github/libp2p/js-libp2p.svg?style=flat-square)](https://codecov.io/gh/libp2p/js-libp2p) @@ -7,21 +5,11 @@ > A TCP transport for libp2p -## Table of contents - -- [Install](#install) -- [Usage](#usage) -- [API Docs](#api-docs) -- [License](#license) -- [Contribution](#contribution) - -## Install +# About -```console -$ npm i @libp2p/tcp -``` +A [libp2p transport](https://docs.libp2p.io/concepts/transports/overview/) based on the TCP networking stack. -## Usage +## Example ```js import { tcp } from '@libp2p/tcp' @@ -71,17 +59,23 @@ new connection opened Value: hello World! ``` -## API Docs +# Install + +```console +$ npm i @libp2p/tcp +``` + +# API Docs - -## License +# License Licensed under either of - Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) - MIT ([LICENSE-MIT](LICENSE-MIT) / ) -## Contribution +# Contribution Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/packages/transport-tcp/src/index.ts b/packages/transport-tcp/src/index.ts index ed526a2182..bf67f831bb 100644 --- a/packages/transport-tcp/src/index.ts +++ b/packages/transport-tcp/src/index.ts @@ -1,3 +1,59 @@ +/** + * @packageDocumentation + * + * A [libp2p transport](https://docs.libp2p.io/concepts/transports/overview/) based on the TCP networking stack. + * + * @example + * + * ```js + * import { tcp } from '@libp2p/tcp' + * import { multiaddr } from '@multiformats/multiaddr' + * import { pipe } from 'it-pipe' + * import all from 'it-all' + * + * // A simple upgrader that just returns the MultiaddrConnection + * const upgrader = { + * upgradeInbound: async maConn => maConn, + * upgradeOutbound: async maConn => maConn + * } + * + * const transport = tcp()() + * + * const listener = transport.createListener({ + * upgrader, + * handler: (socket) => { + * console.log('new connection opened') + * pipe( + * ['hello', ' ', 'World!'], + * socket + * ) + * } + * }) + * + * const addr = multiaddr('/ip4/127.0.0.1/tcp/9090') + * await listener.listen(addr) + * console.log('listening') + * + * const socket = await transport.dial(addr, { upgrader }) + * const values = await pipe( + * socket, + * all + * ) + * console.log(`Value: ${values.toString()}`) + * + * // Close connection after reading + * await listener.close() + * ``` + * + * Outputs: + * + * ```sh + * listening + * new connection opened + * Value: hello World! + * ``` + */ + import net from 'net' import { AbortError, CodeError } from '@libp2p/interface/errors' import { type CreateListenerOptions, type DialOptions, symbol, type Transport, type Listener } from '@libp2p/interface/transport' diff --git a/packages/transport-webrtc/README.md b/packages/transport-webrtc/README.md index 2c0aa57200..c196f307fc 100644 --- a/packages/transport-webrtc/README.md +++ b/packages/transport-webrtc/README.md @@ -1,5 +1,3 @@ -# @libp2p/webrtc - [![libp2p.io](https://img.shields.io/badge/project-libp2p-yellow.svg?style=flat-square)](http://libp2p.io/) [![Discuss](https://img.shields.io/discourse/https/discuss.libp2p.io/posts.svg?style=flat-square)](https://discuss.libp2p.io) [![codecov](https://img.shields.io/codecov/c/github/libp2p/js-libp2p.svg?style=flat-square)](https://codecov.io/gh/libp2p/js-libp2p) @@ -7,40 +5,11 @@ > A libp2p transport using WebRTC connections -## Table of contents - -- [Install](#install) - - [Browser ` -``` +A [libp2p transport](https://docs.libp2p.io/concepts/transports/overview/) based on [WebRTC datachannels](https://webrtc.org/). -## Usage +## Example ```js import { createLibp2p } from 'libp2p' @@ -54,7 +23,7 @@ import { webRTC } from '@libp2p/webrtc' const node = await createLibp2p({ transports: [webRTC()], connectionEncryption: [noise()], -}); +}) await node.start() @@ -65,118 +34,31 @@ const response = await pipe([fromString(message)], stream, async (source) => awa const responseDecoded = toString(response.slice(0, response.length)) ``` -## Interfaces - -### Transport - -![https://github.com/libp2p/js-libp2p-interfaces/tree/master/packages/interface-transport](https://raw.githubusercontent.com/libp2p/js-libp2p-interfaces/master/packages/interface-transport/img/badge.png) - -Browsers can usually only `dial`, but `listen` is supported in the WebRTC -transport when paired with another listener like CircuitV2, where you listen on -a relayed connection. - -### Connection - -![https://github.com/libp2p/js-libp2p-interfaces/tree/master/packages/interface-connection](https://raw.githubusercontent.com/libp2p/js-libp2p-interfaces/master/packages/interface-connection/img/badge.png) - -```js -interface MultiaddrConnection extends Duplex { - close: (err?: Error) => Promise - remoteAddr: Multiaddr - timeline: MultiaddrConnectionTimeline -} - -class WebRTCMultiaddrConnection implements MultiaddrConnection { } -``` - -## Development - -Contributions are welcome! The libp2p implementation in JavaScript is a work in progress. As such, there's a few things you can do right now to help out: - -- [Check out the existing issues](//github.com/little-bear-labs/js-libp2p-webrtc/issues). -- **Perform code reviews**. -- **Add tests**. There can never be enough tests. -- Go through the modules and **check out existing issues**. This is especially useful for modules in active development. Some knowledge of IPFS/libp2p may be required, as well as the infrastructure behind it - for instance, you may need to read up on p2p and more complex operations like muxing to be able to help technically. - -Please be aware that all interactions related to libp2p are subject to the IPFS [Code of Conduct](https://github.com/ipfs/community/blob/master/code-of-conduct.md). - -Small note: If editing the README, please conform to the [standard-readme](https://github.com/RichardLitt/standard-readme) specification. - -This module leans heavily on (Aegir)\[] for most of the `package.json` scripts. - -### Build - -The build script is a wrapper to `aegir build`. To build this package: +# Install -```shell -npm run build -``` - -The build will be located in the `/dist` folder. - -### Protocol Buffers - -There is also `npm run generate:proto` script that uses protoc to populate the generated code directory `proto_ts` based on `*.proto` files in src. Don't forget to run this step before `build` any time you make a change to any of the `*.proto` files. - -### Test - -To run all tests: - -```shell -npm test -``` - -To run tests for Chrome only: - -```shell -npm run test:chrome -``` - -To run tests for Firefox only: - -```shell -npm run test:firefox -``` - -### Lint - -Aegir is also used to lint the code, which follows the [Standard](https://github.com/standard/standard) JS linter. -The VS Code plugin for this standard is located at . -To lint this repo: - -```shell -npm run lint -``` - -You can also auto-fix when applicable: - -```shell -npm run lint:fix +```console +$ npm i @libp2p/webrtc ``` -### Clean - -```shell -npm run clean -``` +## Browser ` ``` -## API Docs +# API Docs - -## License +# License Licensed under either of - Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) - MIT ([LICENSE-MIT](LICENSE-MIT) / ) -## Contribution +# Contribution Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/packages/transport-webrtc/src/index.ts b/packages/transport-webrtc/src/index.ts index a8bbf37e75..6e27a5da6d 100644 --- a/packages/transport-webrtc/src/index.ts +++ b/packages/transport-webrtc/src/index.ts @@ -1,3 +1,34 @@ +/** + * @packageDocumentation + * + * A [libp2p transport](https://docs.libp2p.io/concepts/transports/overview/) based on [WebRTC datachannels](https://webrtc.org/). + * + * @example + * + * ```js + * import { createLibp2p } from 'libp2p' + * import { noise } from '@chainsafe/libp2p-noise' + * import { multiaddr } from '@multiformats/multiaddr' + * import first from 'it-first' + * import { pipe } from 'it-pipe' + * import { fromString, toString } from 'uint8arrays' + * import { webRTC } from '@libp2p/webrtc' + * + * const node = await createLibp2p({ + * transports: [webRTC()], + * connectionEncryption: [noise()], + * }) + * + * await node.start() + * + * const ma = multiaddr('/ip4/0.0.0.0/udp/56093/webrtc/certhash/uEiByaEfNSLBexWBNFZy_QB1vAKEj7JAXDizRs4_SnTflsQ') + * const stream = await node.dialProtocol(ma, ['/my-protocol/1.0.0']) + * const message = `Hello js-libp2p-webrtc\n` + * const response = await pipe([fromString(message)], stream, async (source) => await first(source)) + * const responseDecoded = toString(response.slice(0, response.length)) + * ``` + */ + import { WebRTCTransport } from './private-to-private/transport.js' import { WebRTCDirectTransport, type WebRTCTransportDirectInit, type WebRTCDirectTransportComponents } from './private-to-public/transport.js' import type { WebRTCTransportComponents, WebRTCTransportInit } from './private-to-private/transport.js' diff --git a/packages/transport-websockets/README.md b/packages/transport-websockets/README.md index 79d7aee6ea..7f61346cbb 100644 --- a/packages/transport-websockets/README.md +++ b/packages/transport-websockets/README.md @@ -1,5 +1,3 @@ -# @libp2p/websockets - [![libp2p.io](https://img.shields.io/badge/project-libp2p-yellow.svg?style=flat-square)](http://libp2p.io/) [![Discuss](https://img.shields.io/discourse/https/discuss.libp2p.io/posts.svg?style=flat-square)](https://discuss.libp2p.io) [![codecov](https://img.shields.io/codecov/c/github/libp2p/js-libp2p.svg?style=flat-square)](https://codecov.io/gh/libp2p/js-libp2p) @@ -7,27 +5,13 @@ > JavaScript implementation of the WebSockets module that libp2p uses and that implements the interface-transport spec -## Table of contents - -- [Install](#install) - - [Browser ` ``` -[![](https://raw.githubusercontent.com/libp2p/interface-transport/master/img/badge.png)](https://github.com/libp2p/interface-transport) -[![](https://raw.githubusercontent.com/libp2p/interface-connection/master/img/badge.png)](https://github.com/libp2p/interface-connection) - -## Usage - -```sh -> npm i @libp2p/websockets -``` - -### Constructor properties - -```js -import { createLibp2pNode } from 'libp2p' -import { webSockets } from '@libp2p/webrtc-direct' - -const node = await createLibp2p({ - transports: [ - webSockets() - ] - //... other config -}) -await node.start() -await node.dial('/ip4/127.0.0.1/tcp/9090/ws') -``` - -| Name | Type | Description | Default | -| -------- | -------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------- | ------------------------------------------------------------------------ | -| upgrader | [`Upgrader`](https://github.com/libp2p/js-libp2p-interfaces/tree/master/packages/libp2p-interfaces/src/transport#upgrader) | connection upgrader object with `upgradeOutbound` and `upgradeInbound` | **REQUIRED** | -| filter | `(multiaddrs: Array) => Array` | override transport addresses filter | **Browser:** DNS+WSS multiaddrs / **Node.js:** DNS+\[WS, WSS] multiaddrs | - -You can create your own address filters for this transports, or rely in the filters [provided](./src/filters.js). - -The available filters are: - -- `filters.all` - - Returns all TCP and DNS based addresses, both with `ws` or `wss`. -- `filters.dnsWss` - - Returns all DNS based addresses with `wss`. -- `filters.dnsWsOrWss` - - Returns all DNS based addresses, both with `ws` or `wss`. - -## Libp2p Usage Example - -```js -import { createLibp2pNode } from 'libp2p' -import { websockets } from '@libp2p/websockets' -import filters from '@libp2p/websockets/filters' -import { mplex } from '@libp2p/mplex' -import { noise } from '@libp2p/noise' - -const transportKey = Websockets.prototype[Symbol.toStringTag] -const node = await Libp2p.create({ - transport: [ - websockets({ - // connect to all sockets, even insecure ones - filter: filters.all - }) - ], - streamMuxers: [ - mplex() - ], - connectionEncryption: [ - noise() - ] -}) -``` - -For more information see [libp2p/js-libp2p/doc/CONFIGURATION.md#customizing-transports](https://github.com/libp2p/js-libp2p/blob/master/doc/CONFIGURATION.md#customizing-transports). - -## API - -### Transport - -[![](https://raw.githubusercontent.com/libp2p/interface-transport/master/img/badge.png)](https://github.com/libp2p/interface-transport) - -### Connection - -[![](https://raw.githubusercontent.com/libp2p/interface-connection/master/img/badge.png)](https://github.com/libp2p/interface-connection) - -## API Docs +# API Docs - -## License +# License Licensed under either of - Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) - MIT ([LICENSE-MIT](LICENSE-MIT) / ) -## Contribution +# Contribution Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/packages/transport-websockets/src/index.ts b/packages/transport-websockets/src/index.ts index 932b1a042e..09dbec822e 100644 --- a/packages/transport-websockets/src/index.ts +++ b/packages/transport-websockets/src/index.ts @@ -1,3 +1,68 @@ +/** + * @packageDocumentation + * + * A [libp2p transport](https://docs.libp2p.io/concepts/transports/overview/) based on [WebSockets](https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API). + * + * @example + * + * ```js + * import { createLibp2pNode } from 'libp2p' + * import { webSockets } from '@libp2p/webrtc-direct' + * + * const node = await createLibp2p({ + * transports: [ + * webSockets() + * ] + * //... other config + * }) + * await node.start() + * await node.dial('/ip4/127.0.0.1/tcp/9090/ws') + * ``` + * + * ## Filters + * + * When run in a browser by default this module will only connect to secure web socket addresses. + * + * To change this you should pass a filter to the factory function. + * + * You can create your own address filters for this transports, or rely in the filters [provided](./src/filters.js). + * + * The available filters are: + * + * - `filters.all` + * - Returns all TCP and DNS based addresses, both with `ws` or `wss`. + * - `filters.dnsWss` + * - Returns all DNS based addresses with `wss`. + * - `filters.dnsWsOrWss` + * - Returns all DNS based addresses, both with `ws` or `wss`. + * + * @example + * + * ```js + * import { createLibp2pNode } from 'libp2p' + * import { websockets } from '@libp2p/websockets' + * import filters from '@libp2p/websockets/filters' + * import { mplex } from '@libp2p/mplex' + * import { noise } from '@libp2p/noise' + * + * const transportKey = Websockets.prototype[Symbol.toStringTag] + * const node = await Libp2p.create({ + * transport: [ + * websockets({ + * // connect to all sockets, even insecure ones + * filter: filters.all + * }) + * ], + * streamMuxers: [ + * mplex() + * ], + * connectionEncryption: [ + * noise() + * ] + * }) + * ``` + */ + import { AbortError, CodeError } from '@libp2p/interface/errors' import { type Transport, type MultiaddrFilter, symbol, type CreateListenerOptions, type DialOptions, type Listener } from '@libp2p/interface/transport' import { logger } from '@libp2p/logger' diff --git a/packages/transport-webtransport/README.md b/packages/transport-webtransport/README.md index b5bb4e72d0..f3338b7948 100644 --- a/packages/transport-webtransport/README.md +++ b/packages/transport-webtransport/README.md @@ -1,5 +1,3 @@ -# @libp2p/webtransport - [![libp2p.io](https://img.shields.io/badge/project-libp2p-yellow.svg?style=flat-square)](http://libp2p.io/) [![Discuss](https://img.shields.io/discourse/https/discuss.libp2p.io/posts.svg?style=flat-square)](https://discuss.libp2p.io) [![codecov](https://img.shields.io/codecov/c/github/libp2p/js-libp2p.svg?style=flat-square)](https://codecov.io/gh/libp2p/js-libp2p) @@ -7,48 +5,11 @@ > JavaScript implementation of the WebTransport module that libp2p uses and that implements the interface-transport spec -## Table of contents - -- [Install](#install) - - [Browser ` -``` - -[![](https://raw.githubusercontent.com/libp2p/interface-transport/master/img/badge.png)](https://github.com/libp2p/interface-transport) -[![](https://raw.githubusercontent.com/libp2p/interface-connection/master/img/badge.png)](https://github.com/libp2p/interface-connection) - -## Description +# About -`libp2p-webtransport` is the WebTransport transport implementation compatible with libp2p. +A [libp2p transport](https://docs.libp2p.io/concepts/transports/overview/) based on [WebTransport](https://www.w3.org/TR/webtransport/). -## Usage - -```sh -> npm i @libp2p/webtransport -``` - -## Libp2p Usage Example +## Example ```js import { createLibp2pNode } from 'libp2p' @@ -65,30 +26,34 @@ const node = await createLibp2pNode({ }) ``` -For more information see [libp2p/js-libp2p/doc/CONFIGURATION.md#customizing-transports](https://github.com/libp2p/js-libp2p/blob/master/doc/CONFIGURATION.md#customizing-transports). +# Install -## API +```console +$ npm i @libp2p/webtransport +``` -### Transport +## Browser ` +``` -[![](https://raw.githubusercontent.com/libp2p/interface-connection/master/img/badge.png)](https://github.com/libp2p/interface-connection) +For more information see [libp2p/js-libp2p/doc/CONFIGURATION.md#customizing-transports](https://github.com/libp2p/js-libp2p/blob/master/doc/CONFIGURATION.md#customizing-transports). -## API Docs +# API Docs - -## License +# License Licensed under either of - Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) - MIT ([LICENSE-MIT](LICENSE-MIT) / ) -## Contribution +# Contribution Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/packages/transport-webtransport/src/index.ts b/packages/transport-webtransport/src/index.ts index d37e5a6564..33b272fee6 100644 --- a/packages/transport-webtransport/src/index.ts +++ b/packages/transport-webtransport/src/index.ts @@ -1,3 +1,26 @@ +/** + * @packageDocumentation + * + * A [libp2p transport](https://docs.libp2p.io/concepts/transports/overview/) based on [WebTransport](https://www.w3.org/TR/webtransport/). + * + * @example + * + * ```js + * import { createLibp2pNode } from 'libp2p' + * import { webTransport } from '@libp2p/webtransport' + * import { noise } from 'libp2p-noise' + * + * const node = await createLibp2pNode({ + * transports: [ + * webTransport() + * ], + * connectionEncryption: [ + * noise() + * ] + * }) + * ``` + */ + import { noise } from '@chainsafe/libp2p-noise' import { type Transport, symbol, type CreateListenerOptions, type DialOptions, type Listener } from '@libp2p/interface/transport' import { logger } from '@libp2p/logger' diff --git a/packages/utils/README.md b/packages/utils/README.md index 4fbd0f1a5f..a8be91fe20 100644 --- a/packages/utils/README.md +++ b/packages/utils/README.md @@ -1,5 +1,3 @@ -# @libp2p/utils - [![libp2p.io](https://img.shields.io/badge/project-libp2p-yellow.svg?style=flat-square)](http://libp2p.io/) [![Discuss](https://img.shields.io/discourse/https/discuss.libp2p.io/posts.svg?style=flat-square)](https://discuss.libp2p.io) [![codecov](https://img.shields.io/codecov/c/github/libp2p/js-libp2p.svg?style=flat-square)](https://codecov.io/gh/libp2p/js-libp2p) @@ -7,22 +5,13 @@ > Package to aggregate shared logic and dependencies for the libp2p ecosystem -## Table of contents - -- [Install](#install) - - [Browser ` ``` -The libp2p ecosystem has lots of repos with it comes several problems like: - -- Domain logic dedupe - all modules shared a lot of logic like validation, streams handling, etc. -- Dependencies management - it's really easy with so many repos for dependencies to go out of control, they become outdated, different repos use different modules to do the same thing (like merging defaults options), browser bundles ends up with multiple versions of the same package, bumping versions is cumbersome to do because we need to go through several repos, etc. - -These problems are the motivation for this package, having shared logic in this package avoids creating cyclic dependencies, centralizes common use modules/functions (exactly like aegir does for the tooling), semantic versioning for 3rd party dependencies is handled in one single place (a good example is going from streams 2 to 3) and maintainers should only care about having `libp2p-utils` updated. - -## Usage - -Each function should be imported directly. - -```js -import ipAndPortToMultiaddr from '@libp2p/utils/ip-port-to-multiaddr' - -const ma = ipAndPortToMultiaddr('127.0.0.1', 9000) -``` - -You can check the [API docs](https://libp2p.github.io/js-libp2p-utils). - -## API Docs +# API Docs - -## License +# License Licensed under either of - Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) - MIT ([LICENSE-MIT](LICENSE-MIT) / ) -## Contribution +# Contribution Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/packages/utils/src/index.ts b/packages/utils/src/index.ts index 336ce12bb9..cd0c2aa243 100644 --- a/packages/utils/src/index.ts +++ b/packages/utils/src/index.ts @@ -1 +1,22 @@ +/** + * @packageDocumentation + * + * The libp2p ecosystem has lots of repos with it comes several problems like: + * + * - Domain logic dedupe - all modules shared a lot of logic like validation, streams handling, etc. + * - Dependencies management - it's really easy with so many repos for dependencies to go out of control, they become outdated, different repos use different modules to do the same thing (like merging defaults options), browser bundles ends up with multiple versions of the same package, bumping versions is cumbersome to do because we need to go through several repos, etc. + * + * These problems are the motivation for this package, having shared logic in this package avoids creating cyclic dependencies, centralizes common use modules/functions (exactly like aegir does for the tooling), semantic versioning for 3rd party dependencies is handled in one single place (a good example is going from streams 2 to 3) and maintainers should only care about having `libp2p-utils` updated. + * + * @example + * + * Each function should be imported directly. + * + * ```js + * import ipAndPortToMultiaddr from '@libp2p/utils/ip-port-to-multiaddr' + * + * const ma = ipAndPortToMultiaddr('127.0.0.1', 9000) + * ``` + */ + export {} diff --git a/typedoc.json b/typedoc.json index 55b1f87a5f..ecae64aac9 100644 --- a/typedoc.json +++ b/typedoc.json @@ -1,4 +1,8 @@ { "$schema": "https://typedoc.org/schema.json", - "name": "libp2p" + "name": "libp2p", + "exclude": [ + "interop", + "doc" + ] } From 50442d7a213053f06910a74e42535415c48707e4 Mon Sep 17 00:00:00 2001 From: Cayman Date: Tue, 31 Oct 2023 07:45:20 -0400 Subject: [PATCH 17/24] refactor: move setMaxListeners to @libp2p/interface (#2154) - Discussed in https://github.com/libp2p/js-libp2p/discussions/2138 - Move `setMaxListeners` handling into a single wrapped function exported from `@libp2p/interface/events` - Instead of setting `"browser": {"events": false}` as was discussed in #2138, an actual file is given. Without doing this, an annoying warning is produced in this package and every consumer package in the monorepo! --- packages/interface/package.json | 3 +++ packages/interface/src/events.browser.ts | 2 ++ packages/interface/src/events.ts | 11 ++++++++++ packages/kad-dht/package.json | 3 +-- packages/kad-dht/src/query-self.ts | 8 ++----- packages/kad-dht/src/query/manager.ts | 21 ++++--------------- packages/libp2p/package.json | 3 +-- packages/libp2p/src/autonat/index.ts | 12 +++-------- .../libp2p/src/circuit-relay/server/index.ts | 8 ++----- .../src/connection-manager/dial-queue.ts | 7 ++----- .../libp2p/src/connection-manager/utils.ts | 12 +++-------- packages/libp2p/src/connection/index.ts | 7 ++----- packages/libp2p/src/fetch/index.ts | 7 ++----- packages/libp2p/src/identify/identify.ts | 12 +++-------- packages/libp2p/src/libp2p.ts | 9 +++----- packages/libp2p/src/upgrader.ts | 12 +++-------- 16 files changed, 47 insertions(+), 90 deletions(-) create mode 100644 packages/interface/src/events.browser.ts diff --git a/packages/interface/package.json b/packages/interface/package.json index b2a5a1e909..699521a54c 100644 --- a/packages/interface/package.json +++ b/packages/interface/package.json @@ -39,6 +39,9 @@ "!dist/test", "!**/*.tsbuildinfo" ], + "browser": { + "events": "./dist/src/events.browser.js" + }, "exports": { ".": { "types": "./dist/src/index.d.ts", diff --git a/packages/interface/src/events.browser.ts b/packages/interface/src/events.browser.ts new file mode 100644 index 0000000000..7c1fabd36c --- /dev/null +++ b/packages/interface/src/events.browser.ts @@ -0,0 +1,2 @@ +/** Noop for browser compatibility */ +export function setMaxListeners (): void {} diff --git a/packages/interface/src/events.ts b/packages/interface/src/events.ts index 2f4e863b0e..4c4a498fc3 100644 --- a/packages/interface/src/events.ts +++ b/packages/interface/src/events.ts @@ -1,3 +1,5 @@ +import { setMaxListeners as nodeSetMaxListeners } from 'events' + export interface EventCallback { (evt: EventType): void } export interface EventObject { handleEvent: EventCallback } export type EventHandler = EventCallback | EventObject @@ -117,3 +119,12 @@ export const CustomEvent = globalThis.CustomEvent ?? CustomEventPolyfill // TODO: remove this in v1 export { TypedEventEmitter as EventEmitter } + +// create a setMaxListeners that doesn't break browser usage +export const setMaxListeners: typeof nodeSetMaxListeners = (n, ...eventTargets) => { + try { + nodeSetMaxListeners(n, ...eventTargets) + } catch { + // swallow error, gulp + } +} diff --git a/packages/kad-dht/package.json b/packages/kad-dht/package.json index 2578d27c08..f4b8568d83 100644 --- a/packages/kad-dht/package.json +++ b/packages/kad-dht/package.json @@ -49,7 +49,7 @@ "test:chrome-webworker": "aegir test -t webworker", "test:firefox": "aegir test -t browser -- --browser firefox", "test:firefox-webworker": "aegir test -t webworker -- --browser firefox", - "dep-check": "aegir dep-check -i events" + "dep-check": "aegir dep-check" }, "dependencies": { "@libp2p/crypto": "^2.0.6", @@ -63,7 +63,6 @@ "abortable-iterator": "^5.0.1", "any-signal": "^4.1.1", "datastore-core": "^9.0.1", - "events": "^3.3.0", "hashlru": "^2.3.0", "interface-datastore": "^8.2.0", "it-all": "^3.0.2", diff --git a/packages/kad-dht/src/query-self.ts b/packages/kad-dht/src/query-self.ts index 06c74d98e3..cad60e88c0 100644 --- a/packages/kad-dht/src/query-self.ts +++ b/packages/kad-dht/src/query-self.ts @@ -1,4 +1,4 @@ -import { setMaxListeners } from 'events' +import { setMaxListeners } from '@libp2p/interface/events' import { logger, type Logger } from '@libp2p/logger' import { anySignal } from 'any-signal' import length from 'it-length' @@ -110,11 +110,7 @@ export class QuerySelf implements Startable { const signal = anySignal([this.controller.signal, AbortSignal.timeout(this.queryTimeout)]) // this controller will get used for lots of dial attempts so make sure we don't cause warnings to be logged - try { - if (setMaxListeners != null) { - setMaxListeners(Infinity, signal) - } - } catch {} // fails on node < 15.4 + setMaxListeners(Infinity, signal) try { if (this.routingTable.size === 0) { diff --git a/packages/kad-dht/src/query/manager.ts b/packages/kad-dht/src/query/manager.ts index 675c9a9f81..a163099c40 100644 --- a/packages/kad-dht/src/query/manager.ts +++ b/packages/kad-dht/src/query/manager.ts @@ -1,6 +1,5 @@ -import { setMaxListeners } from 'events' import { AbortError } from '@libp2p/interface/errors' -import { TypedEventEmitter, CustomEvent } from '@libp2p/interface/events' +import { TypedEventEmitter, CustomEvent, setMaxListeners } from '@libp2p/interface/events' import { logger } from '@libp2p/logger' import { PeerSet } from '@libp2p/peer-collections' import { anySignal } from 'any-signal' @@ -75,11 +74,7 @@ export class QueryManager implements Startable { // allow us to stop queries on shut down this.shutDownController = new AbortController() // make sure we don't make a lot of noise in the logs - try { - if (setMaxListeners != null) { - setMaxListeners(Infinity, this.shutDownController.signal) - } - } catch {} // fails on node < 15.4 + setMaxListeners(Infinity, this.shutDownController.signal) } isStarted (): boolean { @@ -122,22 +117,14 @@ export class QueryManager implements Startable { // this signal will get listened to for network requests, etc // so make sure we don't make a lot of noise in the logs - try { - if (setMaxListeners != null) { - setMaxListeners(Infinity, options.signal) - } - } catch {} // fails on node < 15.4 + setMaxListeners(Infinity, options.signal) } const signal = anySignal([this.shutDownController.signal, options.signal]) // this signal will get listened to for every invocation of queryFunc // so make sure we don't make a lot of noise in the logs - try { - if (setMaxListeners != null) { - setMaxListeners(Infinity, signal) - } - } catch {} // fails on node < 15.4 + setMaxListeners(Infinity, signal) const log = logger(`libp2p:kad-dht:${this.lan ? 'lan' : 'wan'}:query:` + uint8ArrayToString(key, 'base58btc')) diff --git a/packages/libp2p/package.json b/packages/libp2p/package.json index f02973ff06..8d77c25950 100644 --- a/packages/libp2p/package.json +++ b/packages/libp2p/package.json @@ -100,7 +100,7 @@ "scripts": { "clean": "aegir clean", "lint": "aegir lint", - "dep-check": "aegir dep-check -i events", + "dep-check": "aegir dep-check", "prepublishOnly": "node scripts/update-version.js && npm run build", "build": "aegir build", "generate": "run-s generate:proto:*", @@ -139,7 +139,6 @@ "any-signal": "^4.1.1", "datastore-core": "^9.0.1", "delay": "^6.0.0", - "events": "^3.3.0", "interface-datastore": "^8.2.0", "it-all": "^3.0.2", "it-drain": "^3.0.2", diff --git a/packages/libp2p/src/autonat/index.ts b/packages/libp2p/src/autonat/index.ts index 3f70e6a850..f958d76621 100644 --- a/packages/libp2p/src/autonat/index.ts +++ b/packages/libp2p/src/autonat/index.ts @@ -19,8 +19,8 @@ * ``` */ -import { setMaxListeners } from 'events' import { CodeError } from '@libp2p/interface/errors' +import { setMaxListeners } from '@libp2p/interface/events' import { logger } from '@libp2p/logger' import { peerIdFromBytes } from '@libp2p/peer-id' import { createEd25519PeerId } from '@libp2p/peer-id-factory' @@ -164,10 +164,7 @@ class DefaultAutoNATService implements Startable { // this controller may be used while dialing lots of peers so prevent MaxListenersExceededWarning // appearing in the console - try { - // fails on node < 15.4 - setMaxListeners?.(Infinity, signal) - } catch {} + setMaxListeners(Infinity, signal) const ourHosts = this.components.addressManager.getAddresses() .map(ma => ma.toOptions().host) @@ -432,10 +429,7 @@ class DefaultAutoNATService implements Startable { // this controller may be used while dialing lots of peers so prevent MaxListenersExceededWarning // appearing in the console - try { - // fails on node < 15.4 - setMaxListeners?.(Infinity, signal) - } catch {} + setMaxListeners(Infinity, signal) const self = this diff --git a/packages/libp2p/src/circuit-relay/server/index.ts b/packages/libp2p/src/circuit-relay/server/index.ts index 8fce918570..8da847d95b 100644 --- a/packages/libp2p/src/circuit-relay/server/index.ts +++ b/packages/libp2p/src/circuit-relay/server/index.ts @@ -1,5 +1,4 @@ -import { setMaxListeners } from 'events' -import { TypedEventEmitter } from '@libp2p/interface/events' +import { TypedEventEmitter, setMaxListeners } from '@libp2p/interface/events' import { logger } from '@libp2p/logger' import { peerIdFromBytes } from '@libp2p/peer-id' import { RecordEnvelope } from '@libp2p/peer-record' @@ -134,10 +133,7 @@ class CircuitRelayServer extends TypedEventEmitter implements this.maxOutboundHopStreams = init.maxOutboundHopStreams this.maxOutboundStopStreams = init.maxOutboundStopStreams ?? defaults.maxOutboundStopStreams - try { - // fails on node < 15.4 - setMaxListeners?.(Infinity, this.shutdownController.signal) - } catch { } + setMaxListeners(Infinity, this.shutdownController.signal) if (init.advertise != null && init.advertise !== false) { this.advertService = new AdvertService(components, init.advertise === true ? undefined : init.advertise) diff --git a/packages/libp2p/src/connection-manager/dial-queue.ts b/packages/libp2p/src/connection-manager/dial-queue.ts index 3ba2b956bb..232d2e39e1 100644 --- a/packages/libp2p/src/connection-manager/dial-queue.ts +++ b/packages/libp2p/src/connection-manager/dial-queue.ts @@ -1,5 +1,5 @@ -import { setMaxListeners } from 'events' import { AbortError, CodeError } from '@libp2p/interface/errors' +import { setMaxListeners } from '@libp2p/interface/events' import { logger } from '@libp2p/logger' import { defaultAddressSort } from '@libp2p/utils/address-sort' import { type Multiaddr, type Resolver, resolvers } from '@multiformats/multiaddr' @@ -96,10 +96,7 @@ export class DialQueue { this.transportManager = components.transportManager this.shutDownController = new AbortController() - try { - // This emitter gets listened to a lot - setMaxListeners?.(Infinity, this.shutDownController.signal) - } catch {} + setMaxListeners(Infinity, this.shutDownController.signal) this.pendingDialCount = components.metrics?.registerMetric('libp2p_dialler_pending_dials') this.inProgressDialCount = components.metrics?.registerMetric('libp2p_dialler_in_progress_dials') diff --git a/packages/libp2p/src/connection-manager/utils.ts b/packages/libp2p/src/connection-manager/utils.ts index e195e48bf6..0bec4506ab 100644 --- a/packages/libp2p/src/connection-manager/utils.ts +++ b/packages/libp2p/src/connection-manager/utils.ts @@ -1,4 +1,4 @@ -import { setMaxListeners } from 'events' +import { setMaxListeners } from '@libp2p/interface/events' import { logger } from '@libp2p/logger' import { type AbortOptions, multiaddr, type Multiaddr } from '@multiformats/multiaddr' import { type ClearableSignal, anySignal } from 'any-signal' @@ -55,10 +55,7 @@ export function combineSignals (...signals: Array): Cle for (const sig of signals) { if (sig != null) { - try { - // fails on node < 15.4 - setMaxListeners?.(Infinity, sig) - } catch { } + setMaxListeners(Infinity, sig) sigs.push(sig) } } @@ -66,10 +63,7 @@ export function combineSignals (...signals: Array): Cle // let any signal abort the dial const signal = anySignal(sigs) - try { - // fails on node < 15.4 - setMaxListeners?.(Infinity, signal) - } catch {} + setMaxListeners(Infinity, signal) return signal } diff --git a/packages/libp2p/src/connection/index.ts b/packages/libp2p/src/connection/index.ts index 4066e78c93..bd5128b112 100644 --- a/packages/libp2p/src/connection/index.ts +++ b/packages/libp2p/src/connection/index.ts @@ -1,6 +1,6 @@ -import { setMaxListeners } from 'events' import { symbol } from '@libp2p/interface/connection' import { CodeError } from '@libp2p/interface/errors' +import { setMaxListeners } from '@libp2p/interface/events' import { logger } from '@libp2p/logger' import type { AbortOptions } from '@libp2p/interface' import type { Direction, Connection, Stream, ConnectionTimeline, ConnectionStatus, NewStreamOptions } from '@libp2p/interface/connection' @@ -152,10 +152,7 @@ export class ConnectionImpl implements Connection { options.signal = options?.signal ?? AbortSignal.timeout(CLOSE_TIMEOUT) - try { - // fails on node < 15.4 - setMaxListeners?.(Infinity, options.signal) - } catch { } + setMaxListeners(Infinity, options.signal) try { log.trace('closing all streams') diff --git a/packages/libp2p/src/fetch/index.ts b/packages/libp2p/src/fetch/index.ts index 3523b2b17d..6e345f0d58 100644 --- a/packages/libp2p/src/fetch/index.ts +++ b/packages/libp2p/src/fetch/index.ts @@ -1,5 +1,5 @@ -import { setMaxListeners } from 'events' import { CodeError } from '@libp2p/interface/errors' +import { setMaxListeners } from '@libp2p/interface/events' import { logger } from '@libp2p/logger' import first from 'it-first' import * as lp from 'it-length-prefixed' @@ -146,10 +146,7 @@ class DefaultFetchService implements Startable, FetchService { log('using default timeout of %d ms', this.init.timeout) signal = AbortSignal.timeout(this.init.timeout ?? DEFAULT_TIMEOUT) - try { - // fails on node < 15.4 - setMaxListeners?.(Infinity, signal) - } catch {} + setMaxListeners(Infinity, signal) } try { diff --git a/packages/libp2p/src/identify/identify.ts b/packages/libp2p/src/identify/identify.ts index 940533ef50..48e5a98c51 100644 --- a/packages/libp2p/src/identify/identify.ts +++ b/packages/libp2p/src/identify/identify.ts @@ -1,5 +1,5 @@ -import { setMaxListeners } from 'events' import { CodeError } from '@libp2p/interface/errors' +import { setMaxListeners } from '@libp2p/interface/events' import { logger } from '@libp2p/logger' import { peerIdFromKeys } from '@libp2p/peer-id' import { RecordEnvelope, PeerRecord } from '@libp2p/peer-record' @@ -187,10 +187,7 @@ export class DefaultIdentifyService implements Startable, IdentifyService { const signal = AbortSignal.timeout(this.timeout) - try { - // fails on node < 15.4 - setMaxListeners?.(Infinity, signal) - } catch {} + setMaxListeners(Infinity, signal) try { stream = await connection.newStream([this.identifyPushProtocolStr], { @@ -345,10 +342,7 @@ export class DefaultIdentifyService implements Startable, IdentifyService { const signal = AbortSignal.timeout(this.timeout) - try { - // fails on node < 15.4 - setMaxListeners?.(Infinity, signal) - } catch {} + setMaxListeners(Infinity, signal) try { const publicKey = this.peerId.publicKey ?? new Uint8Array(0) diff --git a/packages/libp2p/src/libp2p.ts b/packages/libp2p/src/libp2p.ts index cdc0c5caa8..5708aa59e3 100644 --- a/packages/libp2p/src/libp2p.ts +++ b/packages/libp2p/src/libp2p.ts @@ -1,8 +1,7 @@ -import { setMaxListeners } from 'events' import { unmarshalPublicKey } from '@libp2p/crypto/keys' import { type ContentRouting, contentRouting } from '@libp2p/interface/content-routing' import { CodeError } from '@libp2p/interface/errors' -import { TypedEventEmitter, CustomEvent } from '@libp2p/interface/events' +import { TypedEventEmitter, CustomEvent, setMaxListeners } from '@libp2p/interface/events' import { peerDiscovery } from '@libp2p/interface/peer-discovery' import { type PeerRouting, peerRouting } from '@libp2p/interface/peer-routing' import { DefaultKeyChain } from '@libp2p/keychain' @@ -70,10 +69,8 @@ export class Libp2pNode> extends return internalResult || externalResult } - try { - // This emitter gets listened to a lot - setMaxListeners?.(Infinity, events) - } catch {} + // This emitter gets listened to a lot + setMaxListeners(Infinity, events) this.#started = false this.peerId = init.peerId diff --git a/packages/libp2p/src/upgrader.ts b/packages/libp2p/src/upgrader.ts index ad27ba02db..4000cde7a8 100644 --- a/packages/libp2p/src/upgrader.ts +++ b/packages/libp2p/src/upgrader.ts @@ -1,5 +1,5 @@ -import { setMaxListeners } from 'events' import { CodeError } from '@libp2p/interface/errors' +import { setMaxListeners } from '@libp2p/interface/events' import { logger } from '@libp2p/logger' import * as mss from '@libp2p/multistream-select' import { peerIdFromString } from '@libp2p/peer-id' @@ -170,10 +170,7 @@ export class DefaultUpgrader implements Upgrader { signal.addEventListener('abort', onAbort, { once: true }) - try { - // fails on node < 15.4 - setMaxListeners?.(Infinity, signal) - } catch { } + setMaxListeners(Infinity, signal) try { if ((await this.components.connectionGater.denyInboundConnection?.(maConn)) === true) { @@ -444,10 +441,7 @@ export class DefaultUpgrader implements Upgrader { options.signal = AbortSignal.timeout(30000) - try { - // fails on node < 15.4 - setMaxListeners?.(Infinity, options.signal) - } catch { } + setMaxListeners(Infinity, options.signal) } const { stream, protocol } = await mss.select(muxedStream, protocols, options) From 346ff5a2b81bded9f9b26051501ab9d25246961c Mon Sep 17 00:00:00 2001 From: Alex Potsides Date: Wed, 1 Nov 2023 13:04:14 +0000 Subject: [PATCH 18/24] fix: opt-in to toplogy notifications on transient connections (#2049) Adds a `notifyOnTransient` option when registering a network topology to opt-in to being notified when peers that support the registered protocol connect over transient connections. False by default. The logic has been switched to check each connection's transient property and only notify if the user has opted in. The side effect here is that if `notifyOnTransient` is true, and the peer ends up opening a direct connection (for example they dial us via circuit relay, open a stream to do the WebRTC SDP exchange, then open a WebRTC connection), identify will run on the second connection so the topology will receive two notifications. This is not a breaking change since the previous behaviour would have been to only notify on the initial transient connection, which you can't do data-heavy things like bitswap over, or long-lived things like GossipSub so is probably a bug. Fixes #2036 --------- Co-authored-by: Chad Nehemiah --- packages/interface/src/index.ts | 5 + packages/interface/src/topology/index.ts | 15 ++ .../src/circuit-relay/transport/discovery.ts | 1 + packages/libp2p/src/dcutr/dcutr.ts | 1 + packages/libp2p/src/identify/identify.ts | 47 +++--- packages/libp2p/src/registrar.ts | 69 +++----- packages/libp2p/test/identify/service.node.ts | 26 +-- .../libp2p/test/registrar/registrar.spec.ts | 157 ++++++++++++++++-- packages/pubsub/src/index.ts | 5 + packages/pubsub/test/utils/index.ts | 6 +- 10 files changed, 235 insertions(+), 97 deletions(-) diff --git a/packages/interface/src/index.ts b/packages/interface/src/index.ts index d50e335d69..5b1463e4c2 100644 --- a/packages/interface/src/index.ts +++ b/packages/interface/src/index.ts @@ -99,6 +99,11 @@ export interface IdentifyResult { * If sent by the remote peer this is the deserialized signed peer record */ signedPeerRecord?: SignedPeerRecord + + /** + * The connection that the identify protocol ran over + */ + connection: Connection } /** diff --git a/packages/interface/src/topology/index.ts b/packages/interface/src/topology/index.ts index 0772df3b38..25c321201b 100644 --- a/packages/interface/src/topology/index.ts +++ b/packages/interface/src/topology/index.ts @@ -5,6 +5,21 @@ export interface Topology { min?: number max?: number + /** + * If true, invoke `onConnect` for this topology on transient (e.g. short-lived + * and/or data-limited) connections. (default: false) + */ + notifyOnTransient?: boolean + + /** + * Invoked when a new connection is opened to a peer that supports the + * registered protocol + */ onConnect?(peerId: PeerId, conn: Connection): void + + /** + * Invoked when the last connection to a peer that supports the registered + * protocol closes + */ onDisconnect?(peerId: PeerId): void } diff --git a/packages/libp2p/src/circuit-relay/transport/discovery.ts b/packages/libp2p/src/circuit-relay/transport/discovery.ts index 77a4af1208..80bfa1f4d2 100644 --- a/packages/libp2p/src/circuit-relay/transport/discovery.ts +++ b/packages/libp2p/src/circuit-relay/transport/discovery.ts @@ -57,6 +57,7 @@ export class RelayDiscovery extends TypedEventEmitter impl // register a topology listener for when new peers are encountered // that support the hop protocol this.topologyId = await this.registrar.register(RELAY_V2_HOP_CODEC, { + notifyOnTransient: true, onConnect: (peerId) => { this.safeDispatchEvent('relay:discover', { detail: peerId }) } diff --git a/packages/libp2p/src/dcutr/dcutr.ts b/packages/libp2p/src/dcutr/dcutr.ts index e6852b6d03..39aeecd7ae 100644 --- a/packages/libp2p/src/dcutr/dcutr.ts +++ b/packages/libp2p/src/dcutr/dcutr.ts @@ -72,6 +72,7 @@ export class DefaultDCUtRService implements Startable { // register for notifications of when peers that support DCUtR connect // nb. requires the identify service to be enabled this.topologyId = await this.registrar.register(multicodec, { + notifyOnTransient: true, onConnect: (peerId, connection) => { if (!connection.transient) { // the connection is already direct, no upgrade is required diff --git a/packages/libp2p/src/identify/identify.ts b/packages/libp2p/src/identify/identify.ts index 48e5a98c51..906e5fddb8 100644 --- a/packages/libp2p/src/identify/identify.ts +++ b/packages/libp2p/src/identify/identify.ts @@ -315,22 +315,7 @@ export class DefaultIdentifyService implements Startable, IdentifyService { this.addressManager.addObservedAddr(cleanObservedAddr) } - const signedPeerRecord = await this.#consumeIdentifyMessage(connection.remotePeer, message) - - const result: IdentifyResult = { - peerId: id, - protocolVersion: message.protocolVersion, - agentVersion: message.agentVersion, - publicKey: message.publicKey, - listenAddrs: message.listenAddrs.map(buf => multiaddr(buf)), - observedAddr: message.observedAddr == null ? undefined : multiaddr(message.observedAddr), - protocols: message.protocols, - signedPeerRecord - } - - this.events.safeDispatchEvent('peer:identify', { detail: result }) - - return result + return this.#consumeIdentifyMessage(connection, message) } /** @@ -405,7 +390,7 @@ export class DefaultIdentifyService implements Startable, IdentifyService { const message = await pb.read(options) await stream.close(options) - await this.#consumeIdentifyMessage(connection.remotePeer, message) + await this.#consumeIdentifyMessage(connection, message) } catch (err: any) { log.error('received invalid message', err) stream.abort(err) @@ -415,8 +400,8 @@ export class DefaultIdentifyService implements Startable, IdentifyService { log('handled push from %p', connection.remotePeer) } - async #consumeIdentifyMessage (remotePeer: PeerId, message: Identify): Promise { - log('received identify from %p', remotePeer) + async #consumeIdentifyMessage (connection: Connection, message: Identify): Promise { + log('received identify from %p', connection.remotePeer) if (message == null) { throw new Error('Message was null or undefined') @@ -436,7 +421,7 @@ export class DefaultIdentifyService implements Startable, IdentifyService { // if the peer record has been sent, prefer the addresses in the record as they are signed by the remote peer if (message.signedPeerRecord != null) { - log('received signedPeerRecord in push from %p', remotePeer) + log('received signedPeerRecord in push from %p', connection.remotePeer) let peerRecordEnvelope = message.signedPeerRecord const envelope = await RecordEnvelope.openAndCertify(peerRecordEnvelope, PeerRecord.DOMAIN) @@ -448,7 +433,7 @@ export class DefaultIdentifyService implements Startable, IdentifyService { } // Make sure remote peer is the one sending the record - if (!remotePeer.equals(peerRecord.peerId)) { + if (!connection.remotePeer.equals(peerRecord.peerId)) { throw new Error('signing key does not match remote PeerId') } @@ -494,7 +479,7 @@ export class DefaultIdentifyService implements Startable, IdentifyService { addresses: peerRecord.multiaddrs } } else { - log('%p did not send a signed peer record', remotePeer) + log('%p did not send a signed peer record', connection.remotePeer) } if (message.agentVersion != null) { @@ -505,9 +490,23 @@ export class DefaultIdentifyService implements Startable, IdentifyService { peer.metadata.set('ProtocolVersion', uint8ArrayFromString(message.protocolVersion)) } - await this.peerStore.patch(remotePeer, peer) + await this.peerStore.patch(connection.remotePeer, peer) - return output + const result: IdentifyResult = { + peerId: connection.remotePeer, + protocolVersion: message.protocolVersion, + agentVersion: message.agentVersion, + publicKey: message.publicKey, + listenAddrs: message.listenAddrs.map(buf => multiaddr(buf)), + observedAddr: message.observedAddr == null ? undefined : multiaddr(message.observedAddr), + protocols: message.protocols, + signedPeerRecord: output, + connection + } + + this.events.safeDispatchEvent('peer:identify', { detail: result }) + + return result } } diff --git a/packages/libp2p/src/registrar.ts b/packages/libp2p/src/registrar.ts index 268a35c364..c2998583a2 100644 --- a/packages/libp2p/src/registrar.ts +++ b/packages/libp2p/src/registrar.ts @@ -2,7 +2,7 @@ import { CodeError } from '@libp2p/interface/errors' import { logger } from '@libp2p/logger' import merge from 'merge-options' import { codes } from './errors.js' -import type { Libp2pEvents, PeerUpdate } from '@libp2p/interface' +import type { IdentifyResult, Libp2pEvents, PeerUpdate } from '@libp2p/interface' import type { TypedEventTarget } from '@libp2p/interface/events' import type { PeerId } from '@libp2p/interface/peer-id' import type { PeerStore } from '@libp2p/interface/peer-store' @@ -37,11 +37,11 @@ export class DefaultRegistrar implements Registrar { this._onDisconnect = this._onDisconnect.bind(this) this._onPeerUpdate = this._onPeerUpdate.bind(this) - this._onConnect = this._onConnect.bind(this) + this._onPeerIdentify = this._onPeerIdentify.bind(this) this.components.events.addEventListener('peer:disconnect', this._onDisconnect) - this.components.events.addEventListener('peer:connect', this._onConnect) this.components.events.addEventListener('peer:update', this._onPeerUpdate) + this.components.events.addEventListener('peer:identify', this._onPeerIdentify) } getProtocols (): string[] { @@ -183,52 +183,12 @@ export class DefaultRegistrar implements Registrar { } /** - * On peer connected if we already have their protocols. Usually used for reconnects - * as change:protocols event won't be emitted due to identical protocols. - */ - _onConnect (evt: CustomEvent): void { - const remotePeer = evt.detail - - void this.components.peerStore.get(remotePeer) - .then(peer => { - const connection = this.components.connectionManager.getConnections(peer.id)[0] - - if (connection == null) { - log('peer %p connected but the connection manager did not have a connection', peer) - // peer disconnected while we were loading their details from the peer store - return - } - - for (const protocol of peer.protocols) { - const topologies = this.topologies.get(protocol) - - if (topologies == null) { - // no topologies are interested in this protocol - continue - } - - for (const topology of topologies.values()) { - topology.onConnect?.(remotePeer, connection) - } - } - }) - .catch(err => { - if (err.code === codes.ERR_NOT_FOUND) { - // peer has not completed identify so they are not in the peer store - return - } - - log.error('could not inform topologies of connecting peer %p', remotePeer, err) - }) - } - - /** - * Check if a new peer support the multicodecs for this topology + * When a peer is updated, if they have removed supported protocols notify any + * topologies interested in the removed protocols. */ _onPeerUpdate (evt: CustomEvent): void { const { peer, previous } = evt.detail const removed = (previous?.protocols ?? []).filter(protocol => !peer.protocols.includes(protocol)) - const added = peer.protocols.filter(protocol => !(previous?.protocols ?? []).includes(protocol)) for (const protocol of removed) { const topologies = this.topologies.get(protocol) @@ -242,8 +202,18 @@ export class DefaultRegistrar implements Registrar { topology.onDisconnect?.(peer.id) } } + } - for (const protocol of added) { + /** + * After identify has completed and we have received the list of supported + * protocols, notify any topologies interested in those protocols. + */ + _onPeerIdentify (evt: CustomEvent): void { + const protocols = evt.detail.protocols + const connection = evt.detail.connection + const peerId = evt.detail.peerId + + for (const protocol of protocols) { const topologies = this.topologies.get(protocol) if (topologies == null) { @@ -252,12 +222,11 @@ export class DefaultRegistrar implements Registrar { } for (const topology of topologies.values()) { - const connection = this.components.connectionManager.getConnections(peer.id)[0] - - if (connection == null) { + if (connection.transient && topology.notifyOnTransient !== true) { continue } - topology.onConnect?.(peer.id, connection) + + topology.onConnect?.(peerId, connection) } } } diff --git a/packages/libp2p/test/identify/service.node.ts b/packages/libp2p/test/identify/service.node.ts index e7ce86b685..bae39bc2d6 100644 --- a/packages/libp2p/test/identify/service.node.ts +++ b/packages/libp2p/test/identify/service.node.ts @@ -65,13 +65,15 @@ describe('identify', () => { expect(connection).to.exist() // wait for identify to run on the new connection - await eventPromise + const identifyResult = await eventPromise + + // should have run on the new connection + expect(identifyResult).to.have.nested.property('detail.connection', connection) // assert we have received certified announce addresses - const peer = await libp2p.peerStore.get(remoteLibp2p.peerId) - expect(peer.addresses).to.have.lengthOf(1) - expect(peer.addresses[0].isCertified).to.be.true('did not receive certified address via identify') - expect(peer.addresses[0].multiaddr.toString()).to.startWith('/dns4/localhost/', 'did not receive announce address via identify') + expect(identifyResult).to.have.deep.nested.property('detail.signedPeerRecord.addresses', [ + multiaddr(`/dns4/localhost/tcp/${REMOTE_PORT}`) + ], 'did not receive announce address via identify') }) it('should run identify automatically for inbound connections', async () => { @@ -88,14 +90,16 @@ describe('identify', () => { const connection = await remoteLibp2p.dial(multiaddr(`/ip4/127.0.0.1/tcp/${LOCAL_PORT}/p2p/${libp2p.peerId.toString()}`)) expect(connection).to.exist() - // wait for identify to run on the new connection - await eventPromise + // wait for identify to run + const identifyResult = await eventPromise + + // should have run on the new connection + expect(identifyResult).to.have.nested.property('detail.connection', connection) // assert we have received certified announce addresses - const peer = await libp2p.peerStore.get(remoteLibp2p.peerId) - expect(peer.addresses).to.have.lengthOf(1) - expect(peer.addresses[0].isCertified).to.be.true('did not receive certified address via identify') - expect(peer.addresses[0].multiaddr.toString()).to.startWith('/dns4/localhost/', 'did not receive announce address via identify') + expect(identifyResult).to.have.deep.nested.property('detail.signedPeerRecord.addresses', [ + multiaddr(`/dns4/localhost/tcp/${LOCAL_PORT}`) + ], 'did not receive announce address via identify') }) it('should identify connection on dial and get proper announce addresses', async () => { diff --git a/packages/libp2p/test/registrar/registrar.spec.ts b/packages/libp2p/test/registrar/registrar.spec.ts index 138b45b30e..302e773121 100644 --- a/packages/libp2p/test/registrar/registrar.spec.ts +++ b/packages/libp2p/test/registrar/registrar.spec.ts @@ -1,7 +1,6 @@ /* eslint-env mocha */ import { yamux } from '@chainsafe/libp2p-yamux' -import { CodeError } from '@libp2p/interface/errors' import { TypedEventEmitter, type TypedEventTarget } from '@libp2p/interface/events' import { mockDuplex, mockMultiaddrConnection, mockUpgrader, mockConnection } from '@libp2p/interface-compliance-tests/mocks' import { mplex } from '@libp2p/mplex' @@ -14,7 +13,6 @@ import pDefer from 'p-defer' import { type StubbedInstance, stubInterface } from 'sinon-ts' import { type Components, defaultComponents } from '../../src/components.js' import { DefaultConnectionManager } from '../../src/connection-manager/index.js' -import { codes } from '../../src/errors.js' import { plaintext } from '../../src/insecure/index.js' import { createLibp2pNode, type Libp2pNode } from '../../src/libp2p.js' import { DefaultRegistrar } from '../../src/registrar.js' @@ -141,7 +139,7 @@ describe('registrar', () => { const conn = mockConnection(mockMultiaddrConnection(mockDuplex(), remotePeerId)) // return connection from connection manager - connectionManager.getConnections.withArgs(matchPeerId(remotePeerId)).returns([conn]) + connectionManager.getConnections.withArgs(remotePeerId).returns([conn]) const topology: Topology = { onConnect: (peerId, connection) => { @@ -170,8 +168,12 @@ describe('registrar', () => { }) // remote peer connects - events.safeDispatchEvent('peer:connect', { - detail: remotePeerId + events.safeDispatchEvent('peer:identify', { + detail: { + peerId: remotePeerId, + protocols: [protocol], + connection: conn + } }) await onConnectDefer.promise @@ -206,12 +208,13 @@ describe('registrar', () => { // Register protocol await registrar.register(protocol, topology) - // No details before identify - peerStore.get.withArgs(matchPeerId(conn.remotePeer)).rejects(new CodeError('Not found', codes.ERR_NOT_FOUND)) - // remote peer connects - events.safeDispatchEvent('peer:connect', { - detail: remotePeerId + events.safeDispatchEvent('peer:identify', { + detail: { + peerId: remotePeerId, + protocols: [protocol], + connection: conn + } }) // Can get details after identify @@ -261,6 +264,140 @@ describe('registrar', () => { await onDisconnectDefer.promise }) + it('should not call topology handlers for transient connection', async () => { + const onConnectDefer = pDefer() + const onDisconnectDefer = pDefer() + + // Setup connections before registrar + const remotePeerId = await createEd25519PeerId() + const conn = mockConnection(mockMultiaddrConnection(mockDuplex(), remotePeerId)) + + // connection is transient + conn.transient = true + + // return connection from connection manager + connectionManager.getConnections.withArgs(matchPeerId(remotePeerId)).returns([conn]) + + const topology: Topology = { + onConnect: () => { + onConnectDefer.reject(new Error('Topolgy onConnect called for transient connection')) + }, + onDisconnect: () => { + onDisconnectDefer.reject(new Error('Topolgy onDisconnect called for transient connection')) + } + } + + // Register topology for protocol + await registrar.register(protocol, topology) + + // remote peer connects + events.safeDispatchEvent('peer:identify', { + detail: { + peerId: remotePeerId, + protocols: [protocol], + connection: conn + } + }) + + await expect(Promise.any([ + onConnectDefer.promise, + onDisconnectDefer.promise, + new Promise((resolve) => { + setTimeout(() => { + resolve() + }, 1000) + }) + ])).to.eventually.not.be.rejected() + }) + + it('should call topology onConnect handler for transient connection when explicitly requested', async () => { + const onConnectDefer = pDefer() + + // Setup connections before registrar + const remotePeerId = await createEd25519PeerId() + const conn = mockConnection(mockMultiaddrConnection(mockDuplex(), remotePeerId)) + + // connection is transient + conn.transient = true + + // return connection from connection manager + connectionManager.getConnections.withArgs(matchPeerId(remotePeerId)).returns([conn]) + + const topology: Topology = { + notifyOnTransient: true, + onConnect: () => { + onConnectDefer.resolve() + } + } + + // Register topology for protocol + await registrar.register(protocol, topology) + + // remote peer connects + events.safeDispatchEvent('peer:identify', { + detail: { + peerId: remotePeerId, + protocols: [protocol], + connection: conn + } + }) + + await expect(onConnectDefer.promise).to.eventually.be.undefined() + }) + + it('should call topology handlers for non-transient connection opened after transient connection', async () => { + const onConnectDefer = pDefer() + let callCount = 0 + + const topology: Topology = { + notifyOnTransient: true, + onConnect: () => { + callCount++ + + if (callCount === 2) { + onConnectDefer.resolve() + } + } + } + + // Register topology for protocol + await registrar.register(protocol, topology) + + // Setup connections before registrar + const remotePeerId = await createEd25519PeerId() + const transientConnection = mockConnection(mockMultiaddrConnection(mockDuplex(), remotePeerId)) + transientConnection.transient = true + + const nonTransientConnection = mockConnection(mockMultiaddrConnection(mockDuplex(), remotePeerId)) + nonTransientConnection.transient = false + + // return connection from connection manager + connectionManager.getConnections.withArgs(matchPeerId(remotePeerId)).returns([ + transientConnection, + nonTransientConnection + ]) + + // remote peer connects over transient connection + events.safeDispatchEvent('peer:identify', { + detail: { + peerId: remotePeerId, + protocols: [protocol], + connection: transientConnection + } + }) + + // remote peer opens non-transient connection + events.safeDispatchEvent('peer:identify', { + detail: { + peerId: remotePeerId, + protocols: [protocol], + connection: nonTransientConnection + } + }) + + await expect(onConnectDefer.promise).to.eventually.be.undefined() + }) + it('should be able to register and unregister a handler', async () => { const deferred = pDefer() diff --git a/packages/pubsub/src/index.ts b/packages/pubsub/src/index.ts index af8fa223de..ba467f6e88 100644 --- a/packages/pubsub/src/index.ts +++ b/packages/pubsub/src/index.ts @@ -213,6 +213,11 @@ export abstract class PubSubBaseProtocol = Pu protected _onPeerConnected (peerId: PeerId, conn: Connection): void { log('connected %p', peerId) + // if this connection is already in use for pubsub, ignore it + if (conn.streams.find(stream => stream.protocol != null && this.multicodecs.includes(stream.protocol)) != null) { + return + } + void Promise.resolve().then(async () => { try { const stream = await conn.newStream(this.multicodecs) diff --git a/packages/pubsub/test/utils/index.ts b/packages/pubsub/test/utils/index.ts index b98c78b76f..fdd7e5b535 100644 --- a/packages/pubsub/test/utils/index.ts +++ b/packages/pubsub/test/utils/index.ts @@ -136,7 +136,8 @@ export const ConnectionPair = (): [Connection, Connection] => { ...d0, protocol: protocol[0], closeWrite: async () => {} - }) + }), + streams: [] }, { // @ts-expect-error incomplete implementation @@ -144,7 +145,8 @@ export const ConnectionPair = (): [Connection, Connection] => { ...d1, protocol: protocol[0], closeWrite: async () => {} - }) + }), + streams: [] } ] } From 24ff6e939def30e9cb406779f9b12e9d053b36b9 Mon Sep 17 00:00:00 2001 From: Alex Potsides Date: Wed, 1 Nov 2023 18:04:14 +0000 Subject: [PATCH 19/24] deps(dev): update sinon-ts to 2.x.x (#2186) Updates sinon-ts to 2.x --- packages/interface/package.json | 2 +- packages/libp2p/package.json | 2 +- .../test/addresses/address-manager.spec.ts | 6 ++--- .../test/connection-manager/auto-dial.spec.ts | 22 ++++++++--------- .../test/connection-manager/direct.node.ts | 24 +++++++++---------- .../peer-discovery-bootstrap/package.json | 2 +- packages/transport-webrtc/package.json | 2 +- .../transport-webrtc/test/listener.spec.ts | 5 ++-- 8 files changed, 33 insertions(+), 32 deletions(-) diff --git a/packages/interface/package.json b/packages/interface/package.json index 699521a54c..5c57784506 100644 --- a/packages/interface/package.json +++ b/packages/interface/package.json @@ -177,6 +177,6 @@ "it-all": "^3.0.3", "it-drain": "^3.0.3", "sinon": "^17.0.0", - "sinon-ts": "^1.0.0" + "sinon-ts": "^2.0.0" } } diff --git a/packages/libp2p/package.json b/packages/libp2p/package.json index 8d77c25950..3a574256ae 100644 --- a/packages/libp2p/package.json +++ b/packages/libp2p/package.json @@ -193,7 +193,7 @@ "p-wait-for": "^5.0.2", "protons": "^7.0.2", "sinon": "^17.0.0", - "sinon-ts": "^1.0.0" + "sinon-ts": "^2.0.0" }, "browser": { "./dist/src/connection-manager/constants.js": "./dist/src/connection-manager/constants.browser.js", diff --git a/packages/libp2p/test/addresses/address-manager.spec.ts b/packages/libp2p/test/addresses/address-manager.spec.ts index 5bee38bb70..cb08202392 100644 --- a/packages/libp2p/test/addresses/address-manager.spec.ts +++ b/packages/libp2p/test/addresses/address-manager.spec.ts @@ -5,6 +5,7 @@ import { createEd25519PeerId } from '@libp2p/peer-id-factory' import { multiaddr } from '@multiformats/multiaddr' import { expect } from 'aegir/chai' import delay from 'delay' +import Sinon from 'sinon' import { type StubbedInstance, stubInterface } from 'sinon-ts' import { type AddressFilter, DefaultAddressManager } from '../../src/address-manager/index.js' import type { Libp2pEvents } from '@libp2p/interface' @@ -23,8 +24,7 @@ describe('Address Manager', () => { beforeEach(async () => { peerId = await createEd25519PeerId() peerStore = stubInterface({ - // @ts-expect-error incorrect return type - patch: Promise.resolve({}) + patch: Sinon.stub().resolves({}) }) events = new TypedEventEmitter() }) @@ -147,7 +147,7 @@ describe('Address Manager', () => { const am = new DefaultAddressManager({ peerId, transportManager: stubInterface({ - getAddrs: [] + getAddrs: Sinon.stub().returns([]) }), peerStore, events diff --git a/packages/libp2p/test/connection-manager/auto-dial.spec.ts b/packages/libp2p/test/connection-manager/auto-dial.spec.ts index 13634b49e1..9e45ae8c7b 100644 --- a/packages/libp2p/test/connection-manager/auto-dial.spec.ts +++ b/packages/libp2p/test/connection-manager/auto-dial.spec.ts @@ -69,8 +69,8 @@ describe('auto-dial', () => { await peerStore.save(peerWithoutAddress.id, peerWithoutAddress) const connectionManager = stubInterface({ - getConnectionsMap: new PeerMap(), - getDialQueue: [] + getConnectionsMap: Sinon.stub().returns(new PeerMap()), + getDialQueue: Sinon.stub().returns([]) }) autoDialler = new AutoDial({ @@ -123,8 +123,8 @@ describe('auto-dial', () => { connectionMap.set(connectedPeer.id, [stubInterface()]) const connectionManager = stubInterface({ - getConnectionsMap: connectionMap, - getDialQueue: [] + getConnectionsMap: Sinon.stub().returns(connectionMap), + getDialQueue: Sinon.stub().returns([]) }) autoDialler = new AutoDial({ @@ -172,13 +172,13 @@ describe('auto-dial', () => { await peerStore.save(peerNotInDialQueue.id, peerNotInDialQueue) const connectionManager = stubInterface({ - getConnectionsMap: new PeerMap(), - getDialQueue: [{ + getConnectionsMap: Sinon.stub().returns(new PeerMap()), + getDialQueue: Sinon.stub().returns([{ id: 'foo', peerId: peerInDialQueue.id, multiaddrs: [], status: 'queued' - }] + }]) }) autoDialler = new AutoDial({ @@ -203,8 +203,8 @@ describe('auto-dial', () => { const peerStoreAllSpy = Sinon.spy(peerStore, 'all') const connectionManager = stubInterface({ - getConnectionsMap: new PeerMap(), - getDialQueue: [] + getConnectionsMap: Sinon.stub().returns(new PeerMap()), + getDialQueue: Sinon.stub().returns([]) }) autoDialler = new AutoDial({ @@ -254,8 +254,8 @@ describe('auto-dial', () => { await peerStore.save(undialablePeer.id, undialablePeer) const connectionManager = stubInterface({ - getConnectionsMap: new PeerMap(), - getDialQueue: [] + getConnectionsMap: Sinon.stub().returns(new PeerMap()), + getDialQueue: Sinon.stub().returns([]) }) autoDialler = new AutoDial({ diff --git a/packages/libp2p/test/connection-manager/direct.node.ts b/packages/libp2p/test/connection-manager/direct.node.ts index ae5ff3aed3..72f478d332 100644 --- a/packages/libp2p/test/connection-manager/direct.node.ts +++ b/packages/libp2p/test/connection-manager/direct.node.ts @@ -22,7 +22,7 @@ import { pipe } from 'it-pipe' import { pushable } from 'it-pushable' import pDefer from 'p-defer' import pWaitFor from 'p-wait-for' -import sinon from 'sinon' +import Sinon from 'sinon' import { stubInterface } from 'sinon-ts' import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string' import { DefaultAddressManager } from '../../src/address-manager/index.js' @@ -49,10 +49,10 @@ describe('dialing (direct, TCP)', () => { let remoteAddr: Multiaddr let remoteComponents: Components let localComponents: Components - let resolver: sinon.SinonStub<[Multiaddr], Promise> + let resolver: Sinon.SinonStub<[Multiaddr], Promise> beforeEach(async () => { - resolver = sinon.stub<[Multiaddr], Promise>() + resolver = Sinon.stub<[Multiaddr], Promise>() const [localPeerId, remotePeerId] = await Promise.all([ createEd25519PeerId(), createEd25519PeerId() @@ -66,7 +66,7 @@ describe('dialing (direct, TCP)', () => { upgrader: mockUpgrader({ events: remoteEvents }), connectionGater: mockConnectionGater(), transportManager: stubInterface({ - getAddrs: [] + getAddrs: Sinon.stub().returns([]) }) }) remoteComponents.peerStore = new PersistentPeerStore(remoteComponents) @@ -109,7 +109,7 @@ describe('dialing (direct, TCP)', () => { }) afterEach(() => { - sinon.restore() + Sinon.restore() }) it('should be able to connect to a remote node via its multiaddr', async () => { @@ -194,7 +194,7 @@ describe('dialing (direct, TCP)', () => { const dialer = new DialQueue(localComponents) - sinon.spy(localTM, 'dial') + Sinon.spy(localTM, 'dial') const connection = await dialer.dial(peerId) expect(localTM.dial).to.have.property('callCount', remoteAddrs.length) expect(connection).to.exist() @@ -207,7 +207,7 @@ describe('dialing (direct, TCP)', () => { dialTimeout: 50 }) - sinon.stub(localTM, 'dial').callsFake(async (addr, options = {}) => { + Sinon.stub(localTM, 'dial').callsFake(async (addr, options = {}) => { expect(options.signal).to.exist() expect(options.signal?.aborted).to.equal(false) expect(addr.toString()).to.eql(remoteAddr.toString()) @@ -235,7 +235,7 @@ describe('dialing (direct, TCP)', () => { }) const deferredDial = pDefer() - const transportManagerDialStub = sinon.stub(localTM, 'dial') + const transportManagerDialStub = Sinon.stub(localTM, 'dial') transportManagerDialStub.callsFake(async () => deferredDial.promise) // Perform 3 multiaddr dials @@ -273,7 +273,7 @@ describe('dialing (direct, TCP)', () => { maxParallelDialsPerPeer: 10 }) - const transportManagerDialStub = sinon.stub(localTM, 'dial') + const transportManagerDialStub = Sinon.stub(localTM, 'dial') transportManagerDialStub.callsFake(async (ma) => { await delay(10) return mockConnection(mockMultiaddrConnection(mockDuplex(), remoteComponents.peerId)) @@ -340,7 +340,7 @@ describe('libp2p.dialer (direct, TCP)', () => { }) afterEach(async () => { - sinon.restore() + Sinon.restore() if (libp2p != null) { await libp2p.stop() @@ -515,7 +515,7 @@ describe('libp2p.dialer (direct, TCP)', () => { connectionProtector: () => protector }) - const protectorProtectSpy = sinon.spy(protector, 'protect') + const protectorProtectSpy = Sinon.spy(protector, 'protect') remoteLibp2p.components.connectionProtector = preSharedKey({ psk: swarmKeyBuffer })() @@ -589,7 +589,7 @@ describe('libp2p.dialer (direct, TCP)', () => { const dials = 10 const error = new Error('Boom') - sinon.stub(libp2p.components.transportManager, 'dial').callsFake(async () => Promise.reject(error)) + Sinon.stub(libp2p.components.transportManager, 'dial').callsFake(async () => Promise.reject(error)) await libp2p.peerStore.patch(remotePeerId, { multiaddrs: remoteLibp2p.getMultiaddrs() diff --git a/packages/peer-discovery-bootstrap/package.json b/packages/peer-discovery-bootstrap/package.json index cb98579924..b41498deb6 100644 --- a/packages/peer-discovery-bootstrap/package.json +++ b/packages/peer-discovery-bootstrap/package.json @@ -58,6 +58,6 @@ "devDependencies": { "@libp2p/interface-compliance-tests": "^4.1.2", "aegir": "^41.0.2", - "sinon-ts": "^1.0.0" + "sinon-ts": "^2.0.0" } } diff --git a/packages/transport-webrtc/package.json b/packages/transport-webrtc/package.json index a6e8d801dc..2d55c579a6 100644 --- a/packages/transport-webrtc/package.json +++ b/packages/transport-webrtc/package.json @@ -89,7 +89,7 @@ "p-retry": "^6.1.0", "protons": "^7.0.2", "sinon": "^17.0.0", - "sinon-ts": "^1.0.0" + "sinon-ts": "^2.0.0" }, "browser": { "./dist/src/webrtc/index.js": "./dist/src/webrtc/index.browser.js" diff --git a/packages/transport-webrtc/test/listener.spec.ts b/packages/transport-webrtc/test/listener.spec.ts index 036e727d7c..7280feadc3 100644 --- a/packages/transport-webrtc/test/listener.spec.ts +++ b/packages/transport-webrtc/test/listener.spec.ts @@ -1,6 +1,7 @@ import { createEd25519PeerId } from '@libp2p/peer-id-factory' import { multiaddr } from '@multiformats/multiaddr' import { expect } from 'aegir/chai' +import Sinon from 'sinon' import { stubInterface } from 'sinon-ts' import { WebRTCPeerListener } from '../src/private-to-private/listener.js' import type { Listener } from '@libp2p/interface/transport' @@ -21,11 +22,11 @@ describe('webrtc private-to-private listener', () => { }) const otherListener = stubInterface({ - getAddrs: [multiaddr(otherListenAddress)] + getAddrs: Sinon.stub().returns([multiaddr(otherListenAddress)]) }) const relayListener = stubInterface({ - getAddrs: [multiaddr(relayedAddress)] + getAddrs: Sinon.stub().returns([multiaddr(relayedAddress)]) }) transportManager.getListeners.returns([ From 29eb61098bff694981193e6948048938f8a28941 Mon Sep 17 00:00:00 2001 From: Alex Potsides Date: Wed, 1 Nov 2023 18:22:37 +0000 Subject: [PATCH 20/24] refactor: extract DCUtR utils (#2184) In order to get a better view on testing DCUtR, split the utility functions out to test them separately starting with `isPublicAndDialable`. --- packages/libp2p/src/dcutr/dcutr.ts | 38 ++--------------------- packages/libp2p/src/dcutr/utils.ts | 33 ++++++++++++++++++++ packages/libp2p/test/dcutr/utils.spec.ts | 39 ++++++++++++++++++++++++ 3 files changed, 75 insertions(+), 35 deletions(-) create mode 100644 packages/libp2p/src/dcutr/utils.ts create mode 100644 packages/libp2p/test/dcutr/utils.spec.ts diff --git a/packages/libp2p/src/dcutr/dcutr.ts b/packages/libp2p/src/dcutr/dcutr.ts index 39aeecd7ae..ce9146d593 100644 --- a/packages/libp2p/src/dcutr/dcutr.ts +++ b/packages/libp2p/src/dcutr/dcutr.ts @@ -1,12 +1,11 @@ import { CodeError } from '@libp2p/interface/errors' import { logger } from '@libp2p/logger' import { type Multiaddr, multiaddr } from '@multiformats/multiaddr' -import { Circuit, IP, DNS } from '@multiformats/multiaddr-matcher' import delay from 'delay' import { pbStream } from 'it-protobuf-stream' -import isPrivate from 'private-ip' import { codes } from '../errors.js' import { HolePunch } from './pb/message.js' +import { isPublicAndDialable } from './utils.js' import { multicodec } from './index.js' import type { DCUtRServiceComponents, DCUtRServiceInit } from './index.js' import type { Connection, Stream } from '@libp2p/interface/connection' @@ -242,7 +241,7 @@ export class DefaultDCUtRService implements Startable { return ma }) .filter(ma => { - return this.isPublicAndDialable(ma) + return isPublicAndDialable(ma, this.transportManager) }) if (publicAddresses.length > 0) { @@ -366,7 +365,7 @@ export class DefaultDCUtRService implements Startable { try { const ma = multiaddr(addr) - if (!this.isPublicAndDialable(ma)) { + if (!isPublicAndDialable(ma, this.transportManager)) { continue } @@ -376,35 +375,4 @@ export class DefaultDCUtRService implements Startable { return output } - - /** - * Returns true if the passed multiaddr is public, not relayed and we have a - * transport that can dial it - */ - isPublicAndDialable (ma: Multiaddr): boolean { - // ignore circuit relay - if (Circuit.matches(ma)) { - return false - } - - // dns addresses are probably public? - if (DNS.matches(ma)) { - return true - } - - // ensure we have only IPv4/IPv6 addresses - if (!IP.matches(ma)) { - return false - } - - const transport = this.transportManager.transportForMultiaddr(ma) - - if (transport == null) { - return false - } - - const options = ma.toOptions() - - return isPrivate(options.host) === false - } } diff --git a/packages/libp2p/src/dcutr/utils.ts b/packages/libp2p/src/dcutr/utils.ts new file mode 100644 index 0000000000..c56a139778 --- /dev/null +++ b/packages/libp2p/src/dcutr/utils.ts @@ -0,0 +1,33 @@ +import { type Multiaddr } from '@multiformats/multiaddr' +import { Circuit, IP, DNS } from '@multiformats/multiaddr-matcher' +import isPrivate from 'private-ip' +import type { TransportManager } from '@libp2p/interface-internal/src/transport-manager' + +/** + * Returns true if the passed multiaddr is public, not relayed and we have a + * transport that can dial it + */ +export function isPublicAndDialable (ma: Multiaddr, transportManager: TransportManager): boolean { + // ignore circuit relay + if (Circuit.matches(ma)) { + return false + } + + const transport = transportManager.transportForMultiaddr(ma) + + if (transport == null) { + return false + } + + // dns addresses are probably public? + if (DNS.matches(ma)) { + return true + } + + // ensure we have only IPv4/IPv6 addresses + if (!IP.matches(ma)) { + return false + } + + return isPrivate(ma.toOptions().host) === false +} diff --git a/packages/libp2p/test/dcutr/utils.spec.ts b/packages/libp2p/test/dcutr/utils.spec.ts new file mode 100644 index 0000000000..53a5d205a5 --- /dev/null +++ b/packages/libp2p/test/dcutr/utils.spec.ts @@ -0,0 +1,39 @@ +/* eslint-env mocha */ + +import { multiaddr } from '@multiformats/multiaddr' +import { expect } from 'aegir/chai' +import { stubInterface } from 'sinon-ts' +import { isPublicAndDialable } from '../../src/dcutr/utils.js' +import type { Transport } from '@libp2p/interface/transport' +import type { TransportManager } from '@libp2p/interface-internal/transport-manager' + +describe('dcutr utils', () => { + describe('isPublicAndDialable', () => { + const testCases = { + // good addresses + '/ip4/123.123.123.123/tcp/80/p2p/12D3KooWbtp1AcgweFSArD7dbKWYpAr8MZR1tofwNwLFLjeNGLWa': true, + '/dnsaddr/example.com/p2p/12D3KooWbtp1AcgweFSArD7dbKWYpAr8MZR1tofwNwLFLjeNGLWa': true, + '/ip4/123.123.123.123/tcp/80/p2p/12D3KooWbtp1AcgweFSArD7dbKWYpAr8MZR1tofwNwLFLjeNGLWa/p2p-circuit/webrtc/p2p/QmNnooDu7bfjPFoTZYxMNLWUQJyrVwtbZg5gBMjTezGAJN': true, + + // bad addresses + '/dnsaddr/example.com/p2p/12D3KooWbtp1AcgweFSArD7dbKWYpAr8MZR1tofwNwLFLjeNGLWa/p2p-circuit/p2p/QmNnooDu7bfjPFoTZYxMNLWUQJyrVwtbZg5gBMjTezGAJN': false, + '/ip4/10.0.0.1/tcp/123/p2p/12D3KooWbtp1AcgweFSArD7dbKWYpAr8MZR1tofwNwLFLjeNGLWa': false + } + + for (const [key, value] of Object.entries(testCases)) { + it(`should ${value ? '' : 'not '}allow ${key}`, () => { + const transportManager = stubInterface({ + transportForMultiaddr: stubInterface() + }) + + expect(isPublicAndDialable(multiaddr(key), transportManager)).to.equal(value) + }) + } + + it('should not allow addresses for which there is no transport', () => { + const transportManager = stubInterface() + + expect(isPublicAndDialable(multiaddr('/ip4/123.123.123.123/p2p/12D3KooWbtp1AcgweFSArD7dbKWYpAr8MZR1tofwNwLFLjeNGLWa'), transportManager)).to.be.false() + }) + }) +}) From 8297aa860c7f3f3620d5fc71536da9483ecd8759 Mon Sep 17 00:00:00 2001 From: achingbrain Date: Wed, 1 Nov 2023 18:34:52 +0000 Subject: [PATCH 21/24] chore: fix dcutr test --- packages/libp2p/test/dcutr/utils.spec.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/libp2p/test/dcutr/utils.spec.ts b/packages/libp2p/test/dcutr/utils.spec.ts index 53a5d205a5..f5ed2b5fcb 100644 --- a/packages/libp2p/test/dcutr/utils.spec.ts +++ b/packages/libp2p/test/dcutr/utils.spec.ts @@ -2,6 +2,7 @@ import { multiaddr } from '@multiformats/multiaddr' import { expect } from 'aegir/chai' +import Sinon from 'sinon' import { stubInterface } from 'sinon-ts' import { isPublicAndDialable } from '../../src/dcutr/utils.js' import type { Transport } from '@libp2p/interface/transport' @@ -23,7 +24,7 @@ describe('dcutr utils', () => { for (const [key, value] of Object.entries(testCases)) { it(`should ${value ? '' : 'not '}allow ${key}`, () => { const transportManager = stubInterface({ - transportForMultiaddr: stubInterface() + transportForMultiaddr: Sinon.stub().returns(stubInterface()) }) expect(isPublicAndDialable(multiaddr(key), transportManager)).to.equal(value) From eb0a21097d9e3190f9d0172698142e5f62342a48 Mon Sep 17 00:00:00 2001 From: Chad Nehemiah Date: Wed, 1 Nov 2023 15:58:05 -0500 Subject: [PATCH 22/24] refactor: rename multidim interop test script (#2162) --- interop/package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/interop/package.json b/interop/package.json index dd4d3fdece..a3b0ff64c5 100644 --- a/interop/package.json +++ b/interop/package.json @@ -47,7 +47,8 @@ "start": "node index.js", "build": "aegir build", "lint": "aegir lint", - "test:interop:multidim": "aegir test" + "test:interop:multidim": "aegir test", + "test:transport:interop": "aegir test" }, "dependencies": { "@chainsafe/libp2p-noise": "^13.0.0", From 3bdaad3956cb015af1657f3f23061b47463953da Mon Sep 17 00:00:00 2001 From: Alex Potsides Date: Thu, 2 Nov 2023 08:14:08 +0000 Subject: [PATCH 23/24] fix: append peer id to connection remote addr if not present (#2182) If we dial an address like `/ip4/123.123.123.123/tcp/123` we'll get a peer id back after the connection upgrade - append it to the remote addr to make it easier to test if we already have a connection to a given multiaddr. Co-authored-by: Chad Nehemiah --- packages/libp2p/src/connection/index.ts | 4 + packages/libp2p/test/connection/index.spec.ts | 113 +++++++----------- 2 files changed, 47 insertions(+), 70 deletions(-) diff --git a/packages/libp2p/src/connection/index.ts b/packages/libp2p/src/connection/index.ts index bd5128b112..3aca11759b 100644 --- a/packages/libp2p/src/connection/index.ts +++ b/packages/libp2p/src/connection/index.ts @@ -93,6 +93,10 @@ export class ConnectionImpl implements Connection { this.encryption = init.encryption this.transient = init.transient ?? false + if (this.remoteAddr.getPeerId() == null) { + this.remoteAddr = this.remoteAddr.encapsulate(`/p2p/${this.remotePeer}`) + } + this._newStream = newStream this._close = close this._abort = abort diff --git a/packages/libp2p/test/connection/index.spec.ts b/packages/libp2p/test/connection/index.spec.ts index 03c21202be..d249731f55 100644 --- a/packages/libp2p/test/connection/index.spec.ts +++ b/packages/libp2p/test/connection/index.spec.ts @@ -1,86 +1,59 @@ -import * as PeerIdFactory from '@libp2p/peer-id-factory' +import { createEd25519PeerId } from '@libp2p/peer-id-factory' import { multiaddr } from '@multiformats/multiaddr' +import { expect } from 'aegir/chai' +import Sinon from 'sinon' import { createConnection } from '../../src/connection/index.js' -import { pair } from './fixtures/pair.js' -import type { Stream } from '@libp2p/interface/connection' -const peers = [{ - id: 'QmNMMAqSxPetRS1cVMmutW5BCN1qQQyEr4u98kUvZjcfEw', - privKey: 'CAASpQkwggShAgEAAoIBAQDPek2aeHMa0blL42RTKd6xgtkk4Zkldvq4LHxzcag5uXepiQzWANEUvoD3KcUTmMRmx14PvsxdLCNst7S2JSa0R2n5wSRs14zGy6892lx4H4tLBD1KSpQlJ6vabYM1CJhIQRG90BtzDPrJ/X1iJ2HA0PPDz0Mflam2QUMDDrU0IuV2m7gSCJ5r4EmMs3U0xnH/1gShkVx4ir0WUdoWf5KQUJOmLn1clTRHYPv4KL9A/E38+imNAXfkH3c2T7DrCcYRkZSpK+WecjMsH1dCX15hhhggNqfp3iulO1tGPxHjm7PDGTPUjpCWKpD5e50sLqsUwexac1ja6ktMfszIR+FPAgMBAAECggEAB2H2uPRoRCAKU+T3gO4QeoiJaYKNjIO7UCplE0aMEeHDnEjAKC1HQ1G0DRdzZ8sb0fxuIGlNpFMZv5iZ2ZFg2zFfV//DaAwTek9tIOpQOAYHUtgHxkj5FIlg2BjlflGb+ZY3J2XsVB+2HNHkUEXOeKn2wpTxcoJE07NmywkO8Zfr1OL5oPxOPlRN1gI4ffYH2LbfaQVtRhwONR2+fs5ISfubk5iKso6BX4moMYkxubYwZbpucvKKi/rIjUA3SK86wdCUnno1KbDfdXSgCiUlvxt/IbRFXFURQoTV6BOi3sP5crBLw8OiVubMr9/8WE6KzJ0R7hPd5+eeWvYiYnWj4QKBgQD6jRlAFo/MgPO5NZ/HRAk6LUG+fdEWexA+GGV7CwJI61W/Dpbn9ZswPDhRJKo3rquyDFVZPdd7+RlXYg1wpmp1k54z++L1srsgj72vlg4I8wkZ4YLBg0+zVgHlQ0kxnp16DvQdOgiRFvMUUMEgetsoIx1CQWTd67hTExGsW+WAZQKBgQDT/WaHWvwyq9oaZ8G7F/tfeuXvNTk3HIJdfbWGgRXB7lJ7Gf6FsX4x7PeERfL5a67JLV6JdiLLVuYC2CBhipqLqC2DB962aKMvxobQpSljBBZvZyqP1IGPoKskrSo+2mqpYkeCLbDMuJ1nujgMP7gqVjabs2zj6ACKmmpYH/oNowJ/T0ZVtvFsjkg+1VsiMupUARRQuPUWMwa9HOibM1NIZcoQV2NGXB5Z++kR6JqxQO0DZlKArrviclderUdY+UuuY4VRiSEprpPeoW7ZlbTku/Ap8QZpWNEzZorQDro7bnfBW91fX9/81ets/gCPGrfEn+58U3pdb9oleCOQc/ifpQKBgBTYGbi9bYbd9vgZs6bd2M2um+VFanbMytS+g5bSIn2LHXkVOT2UEkB+eGf9KML1n54QY/dIMmukA8HL1oNAyalpw+/aWj+9Ui5kauUhGEywHjSeBEVYM9UXizxz+m9rsoktLLLUI0o97NxCJzitG0Kub3gn0FEogsUeIc7AdinZAoGBANnM1vcteSQDs7x94TDEnvvqwSkA2UWyLidD2jXgE0PG4V6tTkK//QPBmC9eq6TIqXkzYlsErSw4XeKO91knFofmdBzzVh/ddgx/NufJV4tXF+a2iTpqYBUJiz9wpIKgf43/Ob+P1EA99GAhSdxz1ess9O2aTqf3ANzn6v6g62Pv', - pubKey: 'CAASpgIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDPek2aeHMa0blL42RTKd6xgtkk4Zkldvq4LHxzcag5uXepiQzWANEUvoD3KcUTmMRmx14PvsxdLCNst7S2JSa0R2n5wSRs14zGy6892lx4H4tLBD1KSpQlJ6vabYM1CJhIQRG90BtzDPrJ/X1iJ2HA0PPDz0Mflam2QUMDDrU0IuV2m7gSCJ5r4EmMs3U0xnH/1gShkVx4ir0WUdoWf5KQUJOmLn1clTRHYPv4KL9A/E38+imNAXfkH3c2T7DrCcYRkZSpK+WecjMsH1dCX15hhhggNqfp3iulO1tGPxHjm7PDGTPUjpCWKpD5e50sLqsUwexac1ja6ktMfszIR+FPAgMBAAE=' -}, { - id: 'QmW8rAgaaA6sRydK1k6vonShQME47aDxaFidbtMevWs73t', - privKey: 'CAASpwkwggSjAgEAAoIBAQCTU3gVDv3SRXLOsFln9GEf1nJ/uCEDhOG10eC0H9l9IPpVxjuPT1ep+ykFUdvefq3D3q+W3hbmiHm81o8dYv26RxZIEioToUWp7Ec5M2B/niYoE93za9/ZDwJdl7eh2hNKwAdxTmdbXUPjkIU4vLyHKRFbJIn9X8w9djldz8hoUvC1BK4L1XrT6F2l0ruJXErH2ZwI1youfSzo87TdXIoFKdrQLuW6hOtDCGKTiS+ab/DkMODc6zl8N47Oczv7vjzoWOJMUJs1Pg0ZsD1zmISY38P0y/QyEhatZn0B8BmSWxlLQuukatzOepQI6k+HtfyAAjn4UEqnMaXTP1uwLldVAgMBAAECggEAHq2f8MqpYjLiAFZKl9IUs3uFZkEiZsgx9BmbMAb91Aec+WWJG4OLHrNVTG1KWp+IcaQablEa9bBvoToQnS7y5OpOon1d066egg7Ymfmv24NEMM5KRpktCNcOSA0CySpPIB6yrg6EiUr3ixiaFUGABKkxmwgVz/Q15IqM0ZMmCUsC174PMAz1COFZxD0ZX0zgHblOJQW3dc0X3XSzhht8vU02SMoVObQHQfeXEHv3K/RiVj/Ax0bTc5JVkT8dm8xksTtsFCNOzRBqFS6MYqX6U/u0Onz3Jm5Jt7fLWb5n97gZR4SleyGrqxYNb46d9X7mP0ie7E6bzFW0DsWBIeAqVQKBgQDW0We2L1n44yOvJaMs3evpj0nps13jWidt2I3RlZXjWzWHiYQfvhWUWqps/xZBnAYgnN/38xbKzHZeRNhrqOo+VB0WK1IYl0lZVE4l6TNKCsLsUfQzsb1pePkd1eRZA+TSqsi+I/IOQlQU7HA0bMrah/5FYyUBP0jYvCOvYTlZuwKBgQCvkcVRydVlzjUgv7lY5lYvT8IHV5iYO4Qkk2q6Wjv9VUKAJZauurMdiy05PboWfs5kbETdwFybXMBcknIvZO4ihxmwL8mcoNwDVZHI4bXapIKMTCyHgUKvJ9SeTcKGC7ZuQJ8mslRmYox/HloTOXEJgQgPRxXcwa3amzvdZI+6LwKBgQCLsnQqgxKUi0m6bdR2qf7vzTH4258z6X34rjpT0F5AEyF1edVFOz0XU/q+lQhpNEi7zqjLuvbYfSyA026WXKuwSsz7jMJ/oWqev/duKgAjp2npesY/E9gkjfobD+zGgoS9BzkyhXe1FCdP0A6L2S/1+zg88WOwMvJxl6/xLl24XwKBgCm60xSajX8yIQyUpWBM9yUtpueJ2Xotgz4ST+bVNbcEAddll8gWFiaqgug9FLLuFu5lkYTHiPtgc1RNdphvO+62/9MRuLDixwh/2TPO+iNqwKDKJjda8Nei9vVddCPaOtU/xNQ0xLzFJbG9LBmvqH9izOCcu8SJwGHaTcNUeJj/AoGADCJ26cY30c13F/8awAAmFYpZWCuTP5ppTsRmjd63ixlrqgkeLGpJ7kYb5fXkcTycRGYgP0e1kssBGcmE7DuG955fx3ZJESX3GQZ+XfMHvYGONwF1EiK1f0p6+GReC2VlQ7PIkoD9o0hojM6SnWvv9EXNjCPALEbfPFFvcniKVsE=', - pubKey: 'CAASpgIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCTU3gVDv3SRXLOsFln9GEf1nJ/uCEDhOG10eC0H9l9IPpVxjuPT1ep+ykFUdvefq3D3q+W3hbmiHm81o8dYv26RxZIEioToUWp7Ec5M2B/niYoE93za9/ZDwJdl7eh2hNKwAdxTmdbXUPjkIU4vLyHKRFbJIn9X8w9djldz8hoUvC1BK4L1XrT6F2l0ruJXErH2ZwI1youfSzo87TdXIoFKdrQLuW6hOtDCGKTiS+ab/DkMODc6zl8N47Oczv7vjzoWOJMUJs1Pg0ZsD1zmISY38P0y/QyEhatZn0B8BmSWxlLQuukatzOepQI6k+HtfyAAjn4UEqnMaXTP1uwLldVAgMBAAE=' -}, { - id: 'QmZqCdSzgpsmB3Qweb9s4fojAoqELWzqku21UVrqtVSKi4', - privKey: 'CAASpgkwggSiAgEAAoIBAQCdbSEsTmw7lp5HagRcx57DaLiSUEkh4iBcKc7Y+jHICEIA8NIVi9FlfGEZj9G21FpiTR4Cy+BLVEuf8Nm90bym4iV+cSumeS21fvD8xGTEbeKGljs6OYHy3M45JhWF85gqHQJOqZufI2NRDuRgMZEO2+qGEXmSlv9mMXba/+9ecze8nSpB7bG2Z2pnKDeYwhF9Cz+ElMyn7TBWDjJERGVgFbTpdM3rBnbhB/TGpvs732QqZmIBlxnDb/Jn0l1gNZCgkEDcJ/0NDMBJTQ8vbvcdmaw3eaMPLkn1ix4wdu9QWCA0IBtuY1R7vSUtf4irnLJG7DnAw2GfM5QrF3xF1GLXAgMBAAECggEAQ1N0qHoxl5pmvqv8iaFlqLSUmx5y6GbI6CGJMQpvV9kQQU68yjItr3VuIXx8d/CBZyEMAK4oko7OeOyMcr3MLKLy3gyQWnXgsopDjhZ/8fH8uwps8g2+IZuFJrO+6LaxEPGvFu06fOiphPUVfn40R2KN/iBjGeox+AaXijmCqaV2vEdNJJPpMfz6VKZBDLTrbiqvo/3GN1U99PUqfPWpOWR29oAhh/Au6blSqvqTUPXB2+D/X6e1JXv31mxMPK68atDHSUjZWKB9lE4FMK1bkSKJRbyXmNIlbZ9V8X4/0r8/6T7JnW7ZT8ugRkquohmwgG7KkDXB1YsOCKXYUqzVYQKBgQDtnopFXWYl7XUyePJ/2MA5i7eoko9jmF44L31irqmHc5unNf6JlNBjlxTNx3WyfzhUzrn3c18psnGkqtow0tkBj5hmqn8/WaPbc5UA/5R1FNaNf8W5khn7MDm6KtYRPjN9djqTDiVHyC6ljONYd+5S+MqyKVWZ3t/xvG60sw85qwKBgQCpmpDtL+2JBwkfeUr3LyDcQxvbfzcv8lXj2otopWxWiLiZF1HzcqgAa2CIwu9kCGEt9Zr+9E4uINbe1To0b01/FhvR6xKO/ukceGA/mBB3vsKDcRmvpBUp+3SmnhY0nOk+ArQl4DhJ34k8pDM3EDPrixPf8SfVdU/8IM32lsdHhQKBgHLgpvCKCwxjFLnmBzcPzz8C8TOqR3BbBZIcQ34l+wflOGdKj1hsfaLoM8KYn6pAHzfBCd88A9Hg11hI0VuxVACRL5jS7NnvuGwsIOluppNEE8Ys86aXn7/0vLPoab3EWJhbRE48FIHzobmft3nZ4XpzlWs02JGfUp1IAC2UM9QpAoGAeWy3pZhSr2/iEC5+hUmwdQF2yEbj8+fDpkWo2VrVnX506uXPPkQwE1zM2Bz31t5I9OaJ+U5fSpcoPpDaAwBMs1fYwwlRWB8YNdHY1q6/23svN3uZsC4BGPV2JnO34iMUudilsRg+NGVdk5TbNejbwx7nM8Urh59djFzQGGMKeSECgYA0QMCARPpdMY50Mf2xQaCP7HfMJhESSPaBq9V3xY6ToEOEnXgAR5pNjnU85wnspHp+82r5XrKfEQlFxGpj2YA4DRRmn239sjDa29qP42UNAFg1+C3OvXTht1d5oOabaGhU0udwKmkEKUbb0bG5xPQJ5qeSJ5T1gLzLk3SIP0GlSw==', - pubKey: 'CAASpgIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCdbSEsTmw7lp5HagRcx57DaLiSUEkh4iBcKc7Y+jHICEIA8NIVi9FlfGEZj9G21FpiTR4Cy+BLVEuf8Nm90bym4iV+cSumeS21fvD8xGTEbeKGljs6OYHy3M45JhWF85gqHQJOqZufI2NRDuRgMZEO2+qGEXmSlv9mMXba/+9ecze8nSpB7bG2Z2pnKDeYwhF9Cz+ElMyn7TBWDjJERGVgFbTpdM3rBnbhB/TGpvs732QqZmIBlxnDb/Jn0l1gNZCgkEDcJ/0NDMBJTQ8vbvcdmaw3eaMPLkn1ix4wdu9QWCA0IBtuY1R7vSUtf4irnLJG7DnAw2GfM5QrF3xF1GLXAgMBAAE=' -}, { - id: 'QmR5VwgsL7jyfZHAGyp66tguVrQhCRQuRc3NokocsCZ3fA', - privKey: 'CAASpwkwggSjAgEAAoIBAQCGXYU+uc2nn1zuJhfdFOl34upztnrD1gpHu58ousgHdGlGgYgbqLBAvIAauXdEL0+e30HofjA634SQxE+9nV+0FQBam1DDzHQlXsuwHV+2SKvSDkk4bVllMFpu2SJtts6VH+OXC/2ANJOm+eTALykQPYXgLIBxrhp/eD+Jz5r6wW2nq3k6OmYyK/4pgGzFjo5UyX+fa/171AJ68UPboFpDy6BZCcUjS0ondxPvD7cv5jMNqqMKIB/7rpi8n+Q3oeccRqVL56wH+FE3/QLjwYHwY6ILNRyvNXRqHjwBEXB2R5moXN0AFUWTw9rt3KhFiEjR1U81BTw5/xS7W2Iu0FgZAgMBAAECggEAS64HK8JZfE09eYGJNWPe8ECmD1C7quw21BpwVe+GVPSTizvQHswPohbKDMNj0srXDMPxCnNw1OgqcaOwyjsGuZaOoXoTroTM8nOHRIX27+PUqzaStS6aCG2IsiCozKUHjGTuupftS7XRaF4eIsUtWtFcQ1ytZ9pJYHypRQTi5NMSrTze5ThjnWxtHilK7gnBXik+aR0mYEVfSn13czQEC4rMOs+b9RAc/iibDNoLopfIdvmCCvfxzmySnR7Cu1iSUAONkir7PB+2Mt/qRFCH6P+jMamtCgQ8AmifXgVmDUlun+4MnKg3KrPd6ZjOEKhVe9mCHtGozk65RDREShfDdQKBgQDi+x2MuRa9peEMOHnOyXTS+v+MFcfmG0InsO08rFNBKZChLB+c9UHBdIvexpfBHigSyERfuDye4z6lxi8ZnierWMYJP30nxmrnxwTGTk1MQquhfs1A0kpmDnPsjlOS/drEIEIssNx2WbfJ7YtMxLWBtp+BJzGpQmr0LKC+NHRSrwKBgQCXiy2kJESIUkIs2ihV55hhT6/bZo1B1O5DPA2nkjOBXqXF6fvijzMDX82JjLd07lQZlI0n1Q/Hw0p4iYi9YVd2bLkLXF5UIb2qOeHj76enVFOrPHUSkC9Y2g/0Xs+60Ths2xRd8RrrfQU3kl5iVpBywkCIrb2M5+wRnNTk1W3TtwKBgQCvplyrteAfSurpJhs9JzE8w/hWU9SqAZYkWQp91W1oE95Um2yrbjBAoQxMjaqKS+f/APPIjy56Vqj4aHGyhW11b/Fw3qzfxvCcBKtxOs8eoMlo5FO6QgJJEA4tlcafDcvp0nzjUMqK28safLU7503+33B35fjMXxWdd5u9FaKfCQKBgC4W6j6tuRosymuRvgrCcRnHfpify/5loEFallyMnpWOD6Tt0OnK25z/GifnYDRz96gAAh5HMpFy18dpLOlMHamqz2yhHx8/U8vd5tHIJZlCkF/X91M5/uxrBccwvsT2tM6Got8fYSyVzWxlW8dUxIHiinYHQUsFjkqdBDLEpq5pAoGASoTw5RBEWFM0GuAZdXsyNyxU+4S+grkTS7WdW/Ymkukh+bJZbnvF9a6MkSehqXnknthmufonds2AFNS//63gixENsoOhzT5+2cdfc6tJECvJ9xXVXkf85AoQ6T/RrXF0W4m9yQyCngNJUrKUOIH3oDIfdZITlYzOC3u1ojj7VuQ=', - pubKey: 'CAASpgIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCGXYU+uc2nn1zuJhfdFOl34upztnrD1gpHu58ousgHdGlGgYgbqLBAvIAauXdEL0+e30HofjA634SQxE+9nV+0FQBam1DDzHQlXsuwHV+2SKvSDkk4bVllMFpu2SJtts6VH+OXC/2ANJOm+eTALykQPYXgLIBxrhp/eD+Jz5r6wW2nq3k6OmYyK/4pgGzFjo5UyX+fa/171AJ68UPboFpDy6BZCcUjS0ondxPvD7cv5jMNqqMKIB/7rpi8n+Q3oeccRqVL56wH+FE3/QLjwYHwY6ILNRyvNXRqHjwBEXB2R5moXN0AFUWTw9rt3KhFiEjR1U81BTw5/xS7W2Iu0FgZAgMBAAE=' -}, { - id: 'QmScLDqRg7H6ipCYxm9fVk152UWavQFKscTdoT4YNHxgqp', - privKey: 'CAASpwkwggSjAgEAAoIBAQCWEHaTZ6LBLFP5OPrUqjDM/cF4b2zrfh1Zm3kd02ZtgQB3iYtZqRPJT5ctT3A7WdVF/7dCxPGOCkJlLekTx4Y4gD8JtjA+EfN9fR/2RBKbti2N3CD4vkGp9ss4hbBFcXIhl8zuD/ELHutbV6b8b4QXJGnxfp/B+1kNPnyd7SJznS0QyvI8OLI1nAkVKdYLDRW8kPKeHyx1xhdNDuTQVTFyAjRGQ4e3UYFB7bYIHW3E6kCtCoJDlj+JPC02Yt1LHzIzZVLvPvNFnYY2mag6OiGFuh/oMBIqvnPc1zRZ3eLUqeGZjQVaoR0kdgZUKz7Q2TBeNldxK/s6XO0DnkQTlelNAgMBAAECggEAdmt1dyswR2p4tdIeNpY7Pnj9JNIhTNDPznefI0dArCdBvBMhkVaYk6MoNIxcj6l7YOrDroAF8sXr0TZimMY6B/pERKCt/z1hPWTxRQBBAvnHhwvwRPq2jK6BfhAZoyM8IoBNKowP9mum5QUNdGV4Al8s73KyFX0IsCfgZSvNpRdlt+DzPh+hu/CyoZaMpRchJc1UmK8Fyk3KfO+m0DZNfHP5P08lXNfM6MZLgTJVVgERHyG+vBOzTd2RElMe19nVCzHwb3dPPRZSQ7Fnz3rA+GeLqsM2Zi4HNhfbD1OcD9C4wDj5tYL6hWTkdz4IlfVcjCeUHxgIOhdDV2K+OwbuAQKBgQD0FjUZ09UW2FQ/fitbvIB5f1SkXWPxTF9l6mAeuXhoGv2EtQUO4vq/PK6N08RjrZdWQy6UsqHgffi7lVQ8o3hvCKdbtf4sP+cM92OrY0WZV89os79ndj4tyvmnP8WojwRjt/2XEfgdoWcgWxW9DiYINTOQVimZX+X/3on4s8hEgQKBgQCdY3kOMbyQeLTRkqHXjVTY4ddO+v4S4wOUa1l4rTqAbq1W3JYWwoDQgFuIu3limIHmjnSJpCD4EioXFsM7p6csenoc20sHxsaHnJ6Mn5Te41UYmY9EW0otkQ0C3KbXM0hwQkjyplnEmZawGKmjEHW8DJ3vRYTv9TUCgYKxDHgOzQKBgB4A/NYH7BG61eBYKgxEx6YnuMfbkwV+Vdu5S8d7FQn3B2LgvZZu4FPRqcNVXLbEB+5ao8czjiKCWaj1Wj15+rvrXGcxn+Tglg5J+r5+nXeUC7LbJZQaPNp0MOwWMr3dlrSLUWjYlJ9Pz9VyXOG4c4Rexc/gR4zK9QLW4C7qKpwBAoGAZzyUb0cYlPtYQA+asTU3bnvVKy1f8yuNcZFowst+EDiI4u0WVh+HNzy6zdmLKa03p+/RaWeLaK0hhrubnEnAUmCUMNF3ScaM+u804LDcicc8TkKLwx7ObU0z56isl4RAA8K27tNHFrpYKXJD834cfBkaj5ReOrfw6Y/iFhhDuBECgYEA8gbC76uz7LSHhW30DSRTcqOzTyoe2oYKQaxuxYNp7vSSOkcdRen+mrdflDvud2q/zN2QdL4pgqdldHlR35M/lJ0f0B6zp74jlzbO9700wzsOqreezGc5eWiroDL100U9uIZ50BKb8CKtixIHpinUSPIUcVDkSAZ2y7mbfCxQwqQ=', - pubKey: 'CAASpgIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCWEHaTZ6LBLFP5OPrUqjDM/cF4b2zrfh1Zm3kd02ZtgQB3iYtZqRPJT5ctT3A7WdVF/7dCxPGOCkJlLekTx4Y4gD8JtjA+EfN9fR/2RBKbti2N3CD4vkGp9ss4hbBFcXIhl8zuD/ELHutbV6b8b4QXJGnxfp/B+1kNPnyd7SJznS0QyvI8OLI1nAkVKdYLDRW8kPKeHyx1xhdNDuTQVTFyAjRGQ4e3UYFB7bYIHW3E6kCtCoJDlj+JPC02Yt1LHzIzZVLvPvNFnYY2mag6OiGFuh/oMBIqvnPc1zRZ3eLUqeGZjQVaoR0kdgZUKz7Q2TBeNldxK/s6XO0DnkQTlelNAgMBAAE=' -}, { - id: 'QmckxVrJw1Yo8LqvmDJNUmdAsKtSbiKWmrXJFyKmUraBoN', - privKey: 'CAASpwkwggSjAgEAAoIBAQC1/GFud/7xutux7qRfMj1sIdMRh99/chR6HqVj6LQqrgk4jil0mdN/LCk/tqPqmDtObHdmEhCoybzuhLbCKgUqryKDwO6yBJHSKWY9QqrKZtLJ37SgKwGjE3+NUD4r1dJHhtQrICFdOdSCBzs/v8gi+J+KZLHo7+Nms4z09ysy7qZh94Pd7cW4gmSMergqUeANLD9C0ERw1NXolswOW7Bi7UGr7yuBxejICLO3nkxe0OtpQBrYrqdCD9vs3t/HQZbPWVoiRj4VO7fxkAPKLl30HzcIfxj/ayg8NHcH59d08D+N2v5Sdh28gsiYKIPE9CXvuw//HUY2WVRY5fDC5JglAgMBAAECggEBAKb5aN/1w3pBqz/HqRMbQpYLNuD33M3PexBNPAy+P0iFpDo63bh5Rz+A4lvuFNmzUX70MFz7qENlzi6+n/zolxMB29YtWBUH8k904rTEjXXl//NviQgITZk106tx+4k2x5gPEm57LYGfBOdFAUzNhzDnE2LkXwRNzkS161f7zKwOEsaGWRscj6UvhO4MIFxjb32CVwt5eK4yOVqtyMs9u30K4Og+AZYTlhtm+bHg6ndCCBO6CQurCQ3jD6YOkT+L3MotKqt1kORpvzIB0ujZRf49Um8wlcjC5G9aexBeGriXaVdPF62zm7GA7RMsbQM/6aRbA1fEQXvJhHUNF9UFeaECgYEA8wCjKqQA7UQnHjRwTsktdwG6szfxd7z+5MTqHHTWhWzgcQLgdh5/dO/zanEoOThadMk5C1Bqjq96gH2xim8dg5XQofSVtV3Ui0dDa+XRB3E3fyY4D3RF5hHv85O0GcvQc6DIb+Ja1oOhvHowFB1C+CT3yEgwzX/EK9xpe+KtYAkCgYEAv7hCnj/DcZFU3fAfS+unBLuVoVJT/drxv66P686s7J8UM6tW+39yDBZ1IcwY9vHFepBvxY2fFfEeLI02QFM+lZXVhNGzFkP90agNHK01psGgrmIufl9zAo8WOKgkLgbYbSHzkkDeqyjEPU+B0QSsZOCE+qLCHSdsnTmo/TjQhj0CgYAz1+j3yfGgrS+jVBC53lXi0+2fGspbf2jqKdDArXSvFqFzuudki/EpY6AND4NDYfB6hguzjD6PnoSGMUrVfAtR7X6LbwEZpqEX7eZGeMt1yQPMDr1bHrVi9mS5FMQR1NfuM1lP9Xzn00GIUpE7WVrWUhzDEBPJY/7YVLf0hFH08QKBgDWBRQZJIVBmkNrHktRrVddaSq4U/d/Q5LrsCrpymYwH8WliHgpeTQPWmKXwAd+ZJdXIzYjCt202N4eTeVqGYOb6Q/anV2WVYBbM4avpIxoA28kPGY6nML+8EyWIt2ApBOmgGgvtEreNzwaVU9NzjHEyv6n7FlVwlT1jxCe3XWq5AoGASYPKQoPeDlW+NmRG7z9EJXJRPVtmLL40fmGgtju9QIjLnjuK8XaczjAWT+ySI93Whu+Eujf2Uj7Q+NfUjvAEzJgwzuOd3jlQvoALq11kuaxlNQTn7rx0A1QhBgUJE8AkvShPC9FEnA4j/CLJU0re9H/8VvyN6qE0Mho0+YbjpP8=', - pubKey: 'CAASpgIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC1/GFud/7xutux7qRfMj1sIdMRh99/chR6HqVj6LQqrgk4jil0mdN/LCk/tqPqmDtObHdmEhCoybzuhLbCKgUqryKDwO6yBJHSKWY9QqrKZtLJ37SgKwGjE3+NUD4r1dJHhtQrICFdOdSCBzs/v8gi+J+KZLHo7+Nms4z09ysy7qZh94Pd7cW4gmSMergqUeANLD9C0ERw1NXolswOW7Bi7UGr7yuBxejICLO3nkxe0OtpQBrYrqdCD9vs3t/HQZbPWVoiRj4VO7fxkAPKLl30HzcIfxj/ayg8NHcH59d08D+N2v5Sdh28gsiYKIPE9CXvuw//HUY2WVRY5fDC5JglAgMBAAE=' -}] +function defaultConnectionInit (): any { + return { + timeline: { + open: Date.now() - 10, + upgraded: Date.now() + }, + direction: 'outbound', + encryption: '/secio/1.0.0', + multiplexer: '/mplex/6.7.0', + status: 'open', + newStream: Sinon.stub(), + close: Sinon.stub(), + abort: Sinon.stub(), + getStreams: Sinon.stub() + } +} describe('connection', () => { it('should not require local or remote addrs', async () => { - const remotePeer = await PeerIdFactory.createFromJSON(peers[1]) - - let openStreams: any[] = [] - let streamId = 0 + const remotePeer = await createEd25519PeerId() return createConnection({ remotePeer, remoteAddr: multiaddr('/ip4/127.0.0.1/tcp/4002'), - timeline: { - open: Date.now() - 10, - upgraded: Date.now() - }, - direction: 'outbound', - encryption: '/secio/1.0.0', - multiplexer: '/mplex/6.7.0', - status: 'open', - newStream: async (protocols) => { - const id = `${streamId++}` - const stream: Stream = { - ...pair(), - close: async () => { - await stream.sink(async function * () {}()) + ...defaultConnectionInit() + }) + }) - openStreams = openStreams.filter(s => s.id !== id) - }, - closeRead: async () => {}, - closeWrite: async () => { - await stream.sink(async function * () {}()) - }, - id, - abort: () => {}, - direction: 'outbound', - protocol: protocols[0], - timeline: { - open: 0 - }, - metadata: {}, - status: 'open', - writeStatus: 'ready', - readStatus: 'ready' - } + it('should append remote peer id to address if not already present', async () => { + const remotePeer = await createEd25519PeerId() - openStreams.push(stream) + const conn = createConnection({ + remotePeer, + remoteAddr: multiaddr('/ip4/127.0.0.1/tcp/4002'), + ...defaultConnectionInit() + }) - return stream - }, - close: async () => {}, - abort: () => {}, - getStreams: () => openStreams + expect(conn.remoteAddr.getPeerId()).to.equal(remotePeer.toString()) + }) + + it('should not append remote peer id to address if present', async () => { + const remotePeer = await createEd25519PeerId() + const otherPeer = await createEd25519PeerId() + + const conn = createConnection({ + remotePeer, + remoteAddr: multiaddr(`/ip4/127.0.0.1/tcp/4002/p2p/${otherPeer}`), + ...defaultConnectionInit() }) + + expect(conn.remoteAddr.getPeerId()).to.equal(otherPeer.toString()) }) }) From 16a87076ebff5b563a814147f10b8b858d0009cc Mon Sep 17 00:00:00 2001 From: Alex Potsides Date: Thu, 2 Nov 2023 12:28:35 +0000 Subject: [PATCH 24/24] chore: fix pubsub interop tests (#2191) When opening outbound streams, only make sure no outbound pubsub streams exist on the connection, not just any pubsub streams. Fixes a race condition where the remote peer can open streams before us which then prevents us opening streams. --- packages/libp2p/test/interop.ts | 5 ++++- packages/pubsub/src/index.ts | 13 ++++++++++--- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/packages/libp2p/test/interop.ts b/packages/libp2p/test/interop.ts index 871b47b3c9..5e34db58e6 100644 --- a/packages/libp2p/test/interop.ts +++ b/packages/libp2p/test/interop.ts @@ -129,7 +129,10 @@ async function createJsPeer (options: SpawnOptions): Promise { }, transports: [tcp(), circuitRelayTransport()], streamMuxers: [], - connectionEncryption: [noise()] + connectionEncryption: [noise()], + connectionManager: { + minConnections: 0 + } } const services: ServiceFactoryMap = { diff --git a/packages/pubsub/src/index.ts b/packages/pubsub/src/index.ts index ba467f6e88..dc78665470 100644 --- a/packages/pubsub/src/index.ts +++ b/packages/pubsub/src/index.ts @@ -214,7 +214,8 @@ export abstract class PubSubBaseProtocol = Pu log('connected %p', peerId) // if this connection is already in use for pubsub, ignore it - if (conn.streams.find(stream => stream.protocol != null && this.multicodecs.includes(stream.protocol)) != null) { + if (conn.streams.find(stream => stream.direction === 'outbound' && stream.protocol != null && this.multicodecs.includes(stream.protocol)) != null) { + log('outbound pubsub streams already present on connection from %p', peerId) return } @@ -533,8 +534,14 @@ export abstract class PubSubBaseProtocol = Pu sendRpc (peer: PeerId, rpc: PubSubRPC): void { const peerStreams = this.peers.get(peer) - if (peerStreams == null || !peerStreams.isWritable) { - log.error('Cannot send RPC to %p as there is no open stream to it available', peer) + if (peerStreams == null) { + log.error('Cannot send RPC to %p as there are no streams to it available', peer) + + return + } + + if (!peerStreams.isWritable) { + log.error('Cannot send RPC to %p as there is no outbound stream to it available', peer) return }

      HQ{JjW6n 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