@waku/core 0.0.9 → 0.0.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +78 -2
- package/bundle/browser-2f1afe46.js +726 -0
- package/bundle/index.js +9166 -12074
- package/bundle/lib/base_protocol.js +108 -0
- package/bundle/lib/message/topic_only_message.js +3 -2
- package/bundle/lib/message/version_0.js +3 -2
- package/bundle/peer_exchange-1229c8b0.js +4302 -0
- package/bundle/{topic_only_message-ece0fef9.js → topic_only_message-e8406994.js} +12 -8
- package/bundle/{version_0-b1fc527d.js → version_0-e9a6cfb0.js} +35 -35
- package/dist/.tsbuildinfo +1 -0
- package/dist/index.d.ts +4 -1
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/lib/base_protocol.d.ts +21 -0
- package/dist/lib/base_protocol.js +33 -0
- package/dist/lib/base_protocol.js.map +1 -0
- package/dist/lib/connection_manager.d.ts +31 -0
- package/dist/lib/connection_manager.js +146 -0
- package/dist/lib/connection_manager.js.map +1 -0
- package/dist/lib/filter/filter_rpc.d.ts +8 -8
- package/dist/lib/filter/filter_rpc.js +6 -6
- package/dist/lib/filter/index.d.ts +5 -22
- package/dist/lib/filter/index.js +31 -86
- package/dist/lib/filter/index.js.map +1 -1
- package/dist/lib/group_by.d.ts +1 -1
- package/dist/lib/group_by.js.map +1 -1
- package/dist/lib/keep_alive_manager.d.ts +17 -0
- package/dist/lib/keep_alive_manager.js +62 -0
- package/dist/lib/keep_alive_manager.js.map +1 -0
- package/dist/lib/light_push/index.d.ts +3 -19
- package/dist/lib/light_push/index.js +13 -39
- package/dist/lib/light_push/index.js.map +1 -1
- package/dist/lib/light_push/push_rpc.d.ts +5 -5
- package/dist/lib/light_push/push_rpc.js +6 -6
- package/dist/lib/message/topic_only_message.d.ts +5 -3
- package/dist/lib/message/topic_only_message.js +8 -5
- package/dist/lib/message/topic_only_message.js.map +1 -1
- package/dist/lib/message/version_0.d.ts +12 -12
- package/dist/lib/message/version_0.js +29 -30
- package/dist/lib/message/version_0.js.map +1 -1
- package/dist/lib/predefined_bootstrap_nodes.js +1 -1
- package/dist/lib/predefined_bootstrap_nodes.js.map +1 -1
- package/dist/lib/relay/index.d.ts +4 -18
- package/dist/lib/relay/index.js +47 -26
- package/dist/lib/relay/index.js.map +1 -1
- package/dist/lib/relay/message_validator.d.ts +4 -0
- package/dist/lib/relay/message_validator.js +25 -0
- package/dist/lib/relay/message_validator.js.map +1 -0
- package/dist/lib/store/history_rpc.d.ts +4 -4
- package/dist/lib/store/history_rpc.js +9 -9
- package/dist/lib/store/history_rpc.js.map +1 -1
- package/dist/lib/store/index.d.ts +4 -25
- package/dist/lib/store/index.js +20 -37
- package/dist/lib/store/index.js.map +1 -1
- package/dist/lib/to_proto_message.js +3 -2
- package/dist/lib/to_proto_message.js.map +1 -1
- package/dist/lib/wait_for_remote_peer.js +12 -23
- package/dist/lib/wait_for_remote_peer.js.map +1 -1
- package/dist/lib/waku.d.ts +8 -15
- package/dist/lib/waku.js +34 -97
- package/dist/lib/waku.js.map +1 -1
- package/package.json +50 -61
- package/src/index.ts +11 -3
- package/src/lib/base_protocol.ts +47 -0
- package/src/lib/connection_manager.ts +220 -0
- package/src/lib/filter/filter_rpc.ts +10 -10
- package/src/lib/filter/index.ts +52 -147
- package/src/lib/group_by.ts +1 -1
- package/src/lib/keep_alive_manager.ts +89 -0
- package/src/lib/light_push/index.ts +17 -78
- package/src/lib/light_push/push_rpc.ts +9 -9
- package/src/lib/message/topic_only_message.ts +11 -5
- package/src/lib/message/version_0.ts +42 -37
- package/src/lib/predefined_bootstrap_nodes.ts +1 -1
- package/src/lib/relay/index.ts +77 -52
- package/src/lib/relay/message_validator.ts +35 -0
- package/src/lib/store/history_rpc.ts +12 -12
- package/src/lib/store/index.ts +30 -84
- package/src/lib/to_proto_message.ts +3 -2
- package/src/lib/wait_for_remote_peer.ts +13 -29
- package/src/lib/waku.ts +54 -136
- package/bundle/peer_exchange-53df2b11.js +0 -11824
- package/dist/lib/random_subset.d.ts +0 -4
- package/dist/lib/random_subset.js +0 -25
- package/dist/lib/random_subset.js.map +0 -1
- package/src/lib/random_subset.ts +0 -30
package/dist/lib/waku.js
CHANGED
@@ -1,70 +1,34 @@
|
|
1
1
|
import { Protocols } from "@waku/interfaces";
|
2
|
-
import { PeerExchangeCodec } from "@waku/peer-exchange";
|
3
2
|
import debug from "debug";
|
4
|
-
import {
|
5
|
-
import { LightPushCodec } from "./light_push/index.js";
|
6
|
-
import { createEncoder } from "./message/version_0.js";
|
3
|
+
import { ConnectionManager } from "./connection_manager.js";
|
7
4
|
import * as relayConstants from "./relay/constants.js";
|
8
|
-
import { RelayCodecs, RelayPingContentTopic } from "./relay/constants.js";
|
9
|
-
import { StoreCodec } from "./store/index.js";
|
10
5
|
export const DefaultPingKeepAliveValueSecs = 0;
|
11
6
|
export const DefaultRelayKeepAliveValueSecs = 5 * 60;
|
12
7
|
export const DefaultUserAgent = "js-waku";
|
13
8
|
const log = debug("waku:waku");
|
14
9
|
export class WakuNode {
|
15
|
-
constructor(options, libp2p, store, lightPush, filter
|
10
|
+
constructor(options, libp2p, store, lightPush, filter) {
|
16
11
|
this.libp2p = libp2p;
|
17
|
-
const { peerStore, connectionManager, registrar } = libp2p;
|
18
|
-
const components = { peerStore, connectionManager, registrar };
|
19
12
|
if (store) {
|
20
|
-
this.store = store(
|
13
|
+
this.store = store(libp2p);
|
21
14
|
}
|
22
15
|
if (filter) {
|
23
|
-
this.filter = filter(
|
16
|
+
this.filter = filter(libp2p);
|
24
17
|
}
|
25
18
|
if (lightPush) {
|
26
|
-
this.lightPush = lightPush(
|
27
|
-
}
|
28
|
-
if (peerExchange) {
|
29
|
-
this.peerExchange = peerExchange(components);
|
19
|
+
this.lightPush = lightPush(libp2p);
|
30
20
|
}
|
31
21
|
if (isRelay(libp2p.pubsub)) {
|
32
22
|
this.relay = libp2p.pubsub;
|
33
23
|
}
|
34
|
-
log("Waku node created", this.libp2p.peerId.toString(), `relay: ${!!this.relay}, store: ${!!this.store}, light push: ${!!this
|
35
|
-
.lightPush}, filter: ${!!this.filter}, peer exchange: ${!!this
|
36
|
-
.peerExchange} `);
|
37
|
-
this.pingKeepAliveTimers = {};
|
38
|
-
this.relayKeepAliveTimers = {};
|
39
24
|
const pingKeepAlive = options.pingKeepAlive || DefaultPingKeepAliveValueSecs;
|
40
25
|
const relayKeepAlive = this.relay
|
41
26
|
? options.relayKeepAlive || DefaultRelayKeepAliveValueSecs
|
42
27
|
: 0;
|
43
|
-
libp2p.
|
44
|
-
|
45
|
-
}
|
46
|
-
|
47
|
-
* NOTE: Event is not being emitted on closing nor losing a connection.
|
48
|
-
* @see https://github.com/libp2p/js-libp2p/issues/939
|
49
|
-
* @see https://github.com/status-im/js-waku/issues/252
|
50
|
-
*
|
51
|
-
* >This event will be triggered anytime we are disconnected from another peer,
|
52
|
-
* >regardless of the circumstances of that disconnection.
|
53
|
-
* >If we happen to have multiple connections to a peer,
|
54
|
-
* >this event will **only** be triggered when the last connection is closed.
|
55
|
-
* @see https://github.com/libp2p/js-libp2p/blob/bad9e8c0ff58d60a78314077720c82ae331cc55b/doc/API.md?plain=1#L2100
|
56
|
-
*/
|
57
|
-
libp2p.connectionManager.addEventListener("peer:disconnect", (evt) => {
|
58
|
-
this.stopKeepAlive(evt.detail.remotePeer);
|
59
|
-
});
|
60
|
-
// Trivial handling of discovered peers, to be refined.
|
61
|
-
libp2p.addEventListener("peer:discovery", (evt) => {
|
62
|
-
const peerId = evt.detail.id;
|
63
|
-
log(`Found peer ${peerId.toString()}, dialing.`);
|
64
|
-
libp2p.dial(peerId).catch((err) => {
|
65
|
-
log(`Fail to dial ${peerId}`, err);
|
66
|
-
});
|
67
|
-
});
|
28
|
+
const peerId = this.libp2p.peerId.toString();
|
29
|
+
this.connectionManager = ConnectionManager.create(peerId, libp2p, { pingKeepAlive, relayKeepAlive }, this.relay);
|
30
|
+
log("Waku node created", peerId, `relay: ${!!this.relay}, store: ${!!this.store}, light push: ${!!this
|
31
|
+
.lightPush}, filter: ${!!this.filter}`);
|
68
32
|
}
|
69
33
|
/**
|
70
34
|
* Dials to the provided peer.
|
@@ -79,23 +43,39 @@ export class WakuNode {
|
|
79
43
|
this.store && _protocols.push(Protocols.Store);
|
80
44
|
this.filter && _protocols.push(Protocols.Filter);
|
81
45
|
this.lightPush && _protocols.push(Protocols.LightPush);
|
82
|
-
this.peerExchange && _protocols.push(Protocols.PeerExchange);
|
83
46
|
}
|
84
47
|
const codecs = [];
|
85
48
|
if (_protocols.includes(Protocols.Relay)) {
|
86
|
-
|
49
|
+
if (this.relay) {
|
50
|
+
this.relay.multicodecs.forEach((codec) => codecs.push(codec));
|
51
|
+
}
|
52
|
+
else {
|
53
|
+
log("Relay codec not included in dial codec: protocol not mounted locally");
|
54
|
+
}
|
87
55
|
}
|
88
56
|
if (_protocols.includes(Protocols.Store)) {
|
89
|
-
|
57
|
+
if (this.store) {
|
58
|
+
codecs.push(this.store.multicodec);
|
59
|
+
}
|
60
|
+
else {
|
61
|
+
log("Store codec not included in dial codec: protocol not mounted locally");
|
62
|
+
}
|
90
63
|
}
|
91
64
|
if (_protocols.includes(Protocols.LightPush)) {
|
92
|
-
|
65
|
+
if (this.lightPush) {
|
66
|
+
codecs.push(this.lightPush.multicodec);
|
67
|
+
}
|
68
|
+
else {
|
69
|
+
log("Light Push codec not included in dial codec: protocol not mounted locally");
|
70
|
+
}
|
93
71
|
}
|
94
72
|
if (_protocols.includes(Protocols.Filter)) {
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
73
|
+
if (this.filter) {
|
74
|
+
codecs.push(this.filter.multicodec);
|
75
|
+
}
|
76
|
+
else {
|
77
|
+
log("Filter codec not included in dial codec: protocol not mounted locally");
|
78
|
+
}
|
99
79
|
}
|
100
80
|
log(`Dialing to ${peer.toString()} with protocols ${_protocols}`);
|
101
81
|
return this.libp2p.dialProtocol(peer, codecs);
|
@@ -104,7 +84,7 @@ export class WakuNode {
|
|
104
84
|
await this.libp2p.start();
|
105
85
|
}
|
106
86
|
async stop() {
|
107
|
-
this.
|
87
|
+
this.connectionManager.stop();
|
108
88
|
await this.libp2p.stop();
|
109
89
|
}
|
110
90
|
isStarted() {
|
@@ -124,49 +104,6 @@ export class WakuNode {
|
|
124
104
|
}
|
125
105
|
return localMultiaddr + "/p2p/" + this.libp2p.peerId.toString();
|
126
106
|
}
|
127
|
-
startKeepAlive(peerId, pingPeriodSecs, relayPeriodSecs) {
|
128
|
-
// Just in case a timer already exist for this peer
|
129
|
-
this.stopKeepAlive(peerId);
|
130
|
-
const peerIdStr = peerId.toString();
|
131
|
-
if (pingPeriodSecs !== 0) {
|
132
|
-
this.pingKeepAliveTimers[peerIdStr] = setInterval(() => {
|
133
|
-
this.libp2p.ping(peerId).catch((e) => {
|
134
|
-
log(`Ping failed (${peerIdStr})`, e);
|
135
|
-
});
|
136
|
-
}, pingPeriodSecs * 1000);
|
137
|
-
}
|
138
|
-
const relay = this.relay;
|
139
|
-
if (relay && relayPeriodSecs !== 0) {
|
140
|
-
const encoder = createEncoder(RelayPingContentTopic);
|
141
|
-
this.relayKeepAliveTimers[peerIdStr] = setInterval(() => {
|
142
|
-
log("Sending Waku Relay ping message");
|
143
|
-
relay
|
144
|
-
.send(encoder, { payload: new Uint8Array() })
|
145
|
-
.catch((e) => log("Failed to send relay ping", e));
|
146
|
-
}, relayPeriodSecs * 1000);
|
147
|
-
}
|
148
|
-
}
|
149
|
-
stopKeepAlive(peerId) {
|
150
|
-
const peerIdStr = peerId.toString();
|
151
|
-
if (this.pingKeepAliveTimers[peerIdStr]) {
|
152
|
-
clearInterval(this.pingKeepAliveTimers[peerIdStr]);
|
153
|
-
delete this.pingKeepAliveTimers[peerIdStr];
|
154
|
-
}
|
155
|
-
if (this.relayKeepAliveTimers[peerIdStr]) {
|
156
|
-
clearInterval(this.relayKeepAliveTimers[peerIdStr]);
|
157
|
-
delete this.relayKeepAliveTimers[peerIdStr];
|
158
|
-
}
|
159
|
-
}
|
160
|
-
stopAllKeepAlives() {
|
161
|
-
for (const timer of [
|
162
|
-
...Object.values(this.pingKeepAliveTimers),
|
163
|
-
...Object.values(this.relayKeepAliveTimers),
|
164
|
-
]) {
|
165
|
-
clearInterval(timer);
|
166
|
-
}
|
167
|
-
this.pingKeepAliveTimers = {};
|
168
|
-
this.relayKeepAliveTimers = {};
|
169
|
-
}
|
170
107
|
}
|
171
108
|
function isRelay(pubsub) {
|
172
109
|
if (pubsub) {
|
package/dist/lib/waku.js.map
CHANGED
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"waku.js","sourceRoot":"","sources":["../../src/lib/waku.ts"],"names":[],"mappings":"
|
1
|
+
{"version":3,"file":"waku.js","sourceRoot":"","sources":["../../src/lib/waku.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@waku/core",
|
3
|
-
"version": "0.0.
|
3
|
+
"version": "0.0.11",
|
4
4
|
"description": "TypeScript implementation of the Waku v2 protocol",
|
5
5
|
"types": "./dist/index.d.ts",
|
6
6
|
"module": "./dist/index.js",
|
@@ -20,6 +20,10 @@
|
|
20
20
|
"./lib/message/topic_only_message": {
|
21
21
|
"types": "./dist/lib/message/topic_only_message.d.ts",
|
22
22
|
"import": "./dist/lib/message/topic_only_message.js"
|
23
|
+
},
|
24
|
+
"./lib/base_protocol": {
|
25
|
+
"types": "./dist/lib/base_protocol.d.ts",
|
26
|
+
"import": "./dist/lib/base_protocol.js"
|
23
27
|
}
|
24
28
|
},
|
25
29
|
"typesVersions": {
|
@@ -53,7 +57,7 @@
|
|
53
57
|
"build:bundle": "rollup --config rollup.config.js",
|
54
58
|
"fix": "run-s fix:*",
|
55
59
|
"fix:prettier": "prettier . --write",
|
56
|
-
"fix:lint": "eslint src
|
60
|
+
"fix:lint": "eslint src *.js --fix",
|
57
61
|
"pretest": "run-s pretest:*",
|
58
62
|
"pretest:1-init-git-submodules": "[ -f '../../nwaku/build/wakunode2' ] || git submodule update --init --recursive",
|
59
63
|
"pretest:2-build-nwaku": "[ -f '../../nwaku/build/wakunode2' ] || run-s nwaku:build",
|
@@ -61,7 +65,7 @@
|
|
61
65
|
"nwaku:force-build": "(cd ../../nwaku && rm -rf ./build/ ./vendor) && run-s nwaku:build",
|
62
66
|
"check": "run-s check:*",
|
63
67
|
"check:tsc": "tsc -p tsconfig.dev.json",
|
64
|
-
"check:lint": "eslint src
|
68
|
+
"check:lint": "eslint src *.js",
|
65
69
|
"check:prettier": "prettier . --list-different",
|
66
70
|
"check:spelling": "cspell \"{README.md,src/**/*.ts}\"",
|
67
71
|
"test": "run-s test:*",
|
@@ -76,80 +80,65 @@
|
|
76
80
|
"node": ">=16"
|
77
81
|
},
|
78
82
|
"dependencies": {
|
79
|
-
"@chainsafe/libp2p-gossipsub": "^
|
80
|
-
"@
|
81
|
-
"@
|
82
|
-
"@
|
83
|
-
"@
|
84
|
-
"@libp2p/interface-peer-store": "^1.2.3",
|
85
|
-
"@libp2p/interface-pubsub": "^3.0.1",
|
86
|
-
"@libp2p/interface-registrar": "^2.0.4",
|
87
|
-
"@libp2p/interfaces": "^3.0.4",
|
88
|
-
"@libp2p/peer-id": "^1.1.10",
|
89
|
-
"@multiformats/multiaddr": "^11.0.6",
|
90
|
-
"@noble/hashes": "^1.1.3",
|
91
|
-
"@waku/byte-utils": "*",
|
92
|
-
"@waku/interfaces": "*",
|
93
|
-
"@waku/libp2p-utils": "*",
|
94
|
-
"@waku/peer-exchange": "*",
|
95
|
-
"@waku/proto": "*",
|
83
|
+
"@chainsafe/libp2p-gossipsub": "^6.1.0",
|
84
|
+
"@noble/hashes": "^1.2.0",
|
85
|
+
"@waku/interfaces": "0.0.8",
|
86
|
+
"@waku/proto": "0.0.3",
|
87
|
+
"@waku/utils": "0.0.2",
|
96
88
|
"debug": "^4.3.4",
|
97
|
-
"it-all": "^
|
98
|
-
"it-length-prefixed": "^8.0.
|
99
|
-
"it-pipe": "^2.0.
|
100
|
-
"libp2p": "0.40.0",
|
101
|
-
"chai": "^4.3.4",
|
102
|
-
"fast-check": "^2.14.0",
|
89
|
+
"it-all": "^2.0.0",
|
90
|
+
"it-length-prefixed": "^8.0.4",
|
91
|
+
"it-pipe": "^2.0.5",
|
103
92
|
"p-event": "^5.0.1",
|
104
|
-
"uint8arraylist": "^2.3
|
105
|
-
"uint8arrays": "^4.0.2",
|
93
|
+
"uint8arraylist": "^2.4.3",
|
106
94
|
"uuid": "^9.0.0"
|
107
95
|
},
|
108
96
|
"devDependencies": {
|
109
|
-
"@
|
110
|
-
"@
|
111
|
-
"@
|
112
|
-
"@
|
113
|
-
"@
|
97
|
+
"@libp2p/interface-connection": "^3.0.8",
|
98
|
+
"@libp2p/interface-libp2p": "^1.1.1",
|
99
|
+
"@libp2p/interface-peer-id": "^2.0.1",
|
100
|
+
"@libp2p/interface-peer-store": "^1.2.8",
|
101
|
+
"@libp2p/interface-pubsub": "^3.0.6",
|
102
|
+
"@libp2p/interface-registrar": "^2.0.8",
|
103
|
+
"@multiformats/multiaddr": "^11.4.0",
|
104
|
+
"@rollup/plugin-commonjs": "^24.0.1",
|
105
|
+
"@rollup/plugin-json": "^6.0.0",
|
106
|
+
"@rollup/plugin-node-resolve": "^15.0.1",
|
107
|
+
"@types/chai": "^4.3.4",
|
114
108
|
"@types/debug": "^4.1.7",
|
115
|
-
"@types/mocha": "^
|
116
|
-
"@types/
|
117
|
-
"@
|
118
|
-
"@
|
119
|
-
"@
|
120
|
-
"
|
121
|
-
"
|
122
|
-
"
|
123
|
-
"eslint": "^8.6.0",
|
124
|
-
"eslint-config-prettier": "^8.3.0",
|
109
|
+
"@types/mocha": "^10.0.1",
|
110
|
+
"@types/uuid": "^9.0.1",
|
111
|
+
"@typescript-eslint/eslint-plugin": "^5.54.1",
|
112
|
+
"@typescript-eslint/parser": "^5.51.0",
|
113
|
+
"@waku/build-utils": "*",
|
114
|
+
"chai": "^4.3.7",
|
115
|
+
"cspell": "^6.28.0",
|
116
|
+
"eslint": "^8.35.0",
|
117
|
+
"eslint-config-prettier": "^8.6.0",
|
125
118
|
"eslint-plugin-eslint-comments": "^3.2.0",
|
126
|
-
"eslint-plugin-functional": "^
|
127
|
-
"eslint-plugin-import": "^2.
|
128
|
-
"eslint-plugin-prettier": "^4.
|
129
|
-
"
|
119
|
+
"eslint-plugin-functional": "^5.0.4",
|
120
|
+
"eslint-plugin-import": "^2.27.5",
|
121
|
+
"eslint-plugin-prettier": "^4.2.1",
|
122
|
+
"fast-check": "^3.7.0",
|
130
123
|
"ignore-loader": "^0.1.2",
|
131
124
|
"isomorphic-fetch": "^3.0.0",
|
132
|
-
"
|
133
|
-
"
|
134
|
-
"karma": "^6.3.12",
|
135
|
-
"karma-chrome-launcher": "^3.1.0",
|
125
|
+
"karma": "^6.4.1",
|
126
|
+
"karma-chrome-launcher": "^3.1.1",
|
136
127
|
"karma-mocha": "^2.0.1",
|
137
128
|
"karma-webpack": "^5.0.0",
|
138
|
-
"mocha": "^
|
129
|
+
"mocha": "^10.2.0",
|
139
130
|
"npm-run-all": "^4.1.5",
|
140
|
-
"
|
141
|
-
"portfinder": "^1.0.28",
|
142
|
-
"prettier": "^2.1.1",
|
131
|
+
"prettier": "^2.8.4",
|
143
132
|
"process": "^0.11.10",
|
144
|
-
"puppeteer": "^
|
145
|
-
"rollup": "^
|
146
|
-
"
|
147
|
-
"ts-loader": "^9.3.1",
|
133
|
+
"puppeteer": "^19.7.2",
|
134
|
+
"rollup": "^3.15.0",
|
135
|
+
"ts-loader": "^9.4.2",
|
148
136
|
"ts-node": "^10.9.1",
|
149
|
-
"typescript": "^4.
|
137
|
+
"typescript": "^4.9.5"
|
150
138
|
},
|
151
139
|
"peerDependencies": {
|
152
|
-
"@multiformats/multiaddr": "^11.0
|
140
|
+
"@multiformats/multiaddr": "^11.4.0",
|
141
|
+
"libp2p": "^0.42.2"
|
153
142
|
},
|
154
143
|
"peerDependenciesMeta": {
|
155
144
|
"@multiformats/multiaddr": {
|
package/src/index.ts
CHANGED
@@ -1,9 +1,10 @@
|
|
1
1
|
export { DefaultPubSubTopic } from "./lib/constants.js";
|
2
2
|
export { DefaultUserAgent } from "./lib/waku.js";
|
3
3
|
|
4
|
-
export {
|
5
|
-
|
6
|
-
|
4
|
+
export { createEncoder, createDecoder } from "./lib/message/version_0.js";
|
5
|
+
export type {
|
6
|
+
Encoder,
|
7
|
+
Decoder,
|
7
8
|
DecodedMessage,
|
8
9
|
} from "./lib/message/version_0.js";
|
9
10
|
export * as message from "./lib/message/index.js";
|
@@ -29,3 +30,10 @@ export {
|
|
29
30
|
} from "./lib/store/index.js";
|
30
31
|
|
31
32
|
export { waitForRemotePeer } from "./lib/wait_for_remote_peer.js";
|
33
|
+
|
34
|
+
export { ConnectionManager } from "./lib/connection_manager.js";
|
35
|
+
|
36
|
+
export {
|
37
|
+
KeepAliveManager,
|
38
|
+
KeepAliveOptions,
|
39
|
+
} from "./lib/keep_alive_manager.js";
|
@@ -0,0 +1,47 @@
|
|
1
|
+
import type { Connection, Stream } from "@libp2p/interface-connection";
|
2
|
+
import type { PeerId } from "@libp2p/interface-peer-id";
|
3
|
+
import { Peer, PeerStore } from "@libp2p/interface-peer-store";
|
4
|
+
import {
|
5
|
+
getPeersForProtocol,
|
6
|
+
selectConnection,
|
7
|
+
selectPeerForProtocol,
|
8
|
+
} from "@waku/utils/libp2p";
|
9
|
+
|
10
|
+
/**
|
11
|
+
* A class with predefined helpers, to be used as a base to implement Waku
|
12
|
+
* Protocols.
|
13
|
+
*/
|
14
|
+
export class BaseProtocol {
|
15
|
+
constructor(
|
16
|
+
public multicodec: string,
|
17
|
+
public peerStore: PeerStore,
|
18
|
+
protected getConnections: (peerId?: PeerId) => Connection[]
|
19
|
+
) {}
|
20
|
+
|
21
|
+
/**
|
22
|
+
* Returns known peers from the address book (`libp2p.peerStore`) that support
|
23
|
+
* the class protocol. Waku may or may not be currently connected to these
|
24
|
+
* peers.
|
25
|
+
*/
|
26
|
+
async peers(): Promise<Peer[]> {
|
27
|
+
return getPeersForProtocol(this.peerStore, [this.multicodec]);
|
28
|
+
}
|
29
|
+
|
30
|
+
protected async getPeer(peerId?: PeerId): Promise<Peer> {
|
31
|
+
const { peer } = await selectPeerForProtocol(
|
32
|
+
this.peerStore,
|
33
|
+
[this.multicodec],
|
34
|
+
peerId
|
35
|
+
);
|
36
|
+
return peer;
|
37
|
+
}
|
38
|
+
protected async newStream(peer: Peer): Promise<Stream> {
|
39
|
+
const connections = this.getConnections(peer.id);
|
40
|
+
const connection = selectConnection(connections);
|
41
|
+
if (!connection) {
|
42
|
+
throw new Error("Failed to get a connection to the peer");
|
43
|
+
}
|
44
|
+
|
45
|
+
return connection.newStream(this.multicodec);
|
46
|
+
}
|
47
|
+
}
|
@@ -0,0 +1,220 @@
|
|
1
|
+
import type { Connection } from "@libp2p/interface-connection";
|
2
|
+
import type { Libp2p } from "@libp2p/interface-libp2p";
|
3
|
+
import type { PeerId } from "@libp2p/interface-peer-id";
|
4
|
+
import type { PeerInfo } from "@libp2p/interface-peer-info";
|
5
|
+
import type { ConnectionManagerOptions, IRelay } from "@waku/interfaces";
|
6
|
+
import { Tags } from "@waku/interfaces";
|
7
|
+
import debug from "debug";
|
8
|
+
|
9
|
+
import { KeepAliveManager, KeepAliveOptions } from "./keep_alive_manager.js";
|
10
|
+
|
11
|
+
const log = debug("waku:connection-manager");
|
12
|
+
|
13
|
+
export const DEFAULT_MAX_BOOTSTRAP_PEERS_ALLOWED = 1;
|
14
|
+
export const DEFAULT_MAX_DIAL_ATTEMPTS_FOR_PEER = 3;
|
15
|
+
|
16
|
+
export class ConnectionManager {
|
17
|
+
private static instances = new Map<string, ConnectionManager>();
|
18
|
+
private keepAliveManager: KeepAliveManager;
|
19
|
+
private options: ConnectionManagerOptions;
|
20
|
+
private libp2pComponents: Libp2p;
|
21
|
+
private dialAttemptsForPeer: Map<string, number> = new Map();
|
22
|
+
|
23
|
+
public static create(
|
24
|
+
peerId: string,
|
25
|
+
libp2p: Libp2p,
|
26
|
+
keepAliveOptions: KeepAliveOptions,
|
27
|
+
relay?: IRelay,
|
28
|
+
options?: ConnectionManagerOptions
|
29
|
+
): ConnectionManager {
|
30
|
+
let instance = ConnectionManager.instances.get(peerId);
|
31
|
+
if (!instance) {
|
32
|
+
instance = new ConnectionManager(
|
33
|
+
libp2p,
|
34
|
+
keepAliveOptions,
|
35
|
+
relay,
|
36
|
+
options
|
37
|
+
);
|
38
|
+
ConnectionManager.instances.set(peerId, instance);
|
39
|
+
}
|
40
|
+
|
41
|
+
return instance;
|
42
|
+
}
|
43
|
+
|
44
|
+
private constructor(
|
45
|
+
libp2pComponents: Libp2p,
|
46
|
+
keepAliveOptions: KeepAliveOptions,
|
47
|
+
relay?: IRelay,
|
48
|
+
options?: Partial<ConnectionManagerOptions>
|
49
|
+
) {
|
50
|
+
this.libp2pComponents = libp2pComponents;
|
51
|
+
this.options = {
|
52
|
+
maxDialAttemptsForPeer: DEFAULT_MAX_DIAL_ATTEMPTS_FOR_PEER,
|
53
|
+
maxBootstrapPeersAllowed: DEFAULT_MAX_BOOTSTRAP_PEERS_ALLOWED,
|
54
|
+
...options,
|
55
|
+
};
|
56
|
+
|
57
|
+
this.keepAliveManager = new KeepAliveManager(keepAliveOptions, relay);
|
58
|
+
|
59
|
+
this.run()
|
60
|
+
.then(() => log(`Connection Manager is now running`))
|
61
|
+
.catch((error) => log(`Unexpected error while running service`, error));
|
62
|
+
}
|
63
|
+
|
64
|
+
private async run(): Promise<void> {
|
65
|
+
// start event listeners
|
66
|
+
this.startPeerDiscoveryListener();
|
67
|
+
this.startPeerConnectionListener();
|
68
|
+
this.startPeerDisconnectionListener();
|
69
|
+
}
|
70
|
+
|
71
|
+
stop(): void {
|
72
|
+
this.keepAliveManager.stopAll();
|
73
|
+
this.libp2pComponents.removeEventListener(
|
74
|
+
"peer:connect",
|
75
|
+
this.onEventHandlers["peer:connect"]
|
76
|
+
);
|
77
|
+
this.libp2pComponents.removeEventListener(
|
78
|
+
"peer:disconnect",
|
79
|
+
this.onEventHandlers["peer:disconnect"]
|
80
|
+
);
|
81
|
+
this.libp2pComponents.removeEventListener(
|
82
|
+
"peer:discovery",
|
83
|
+
this.onEventHandlers["peer:discovery"]
|
84
|
+
);
|
85
|
+
}
|
86
|
+
|
87
|
+
private async dialPeer(peerId: PeerId): Promise<void> {
|
88
|
+
let dialAttempt = 0;
|
89
|
+
while (dialAttempt <= this.options.maxDialAttemptsForPeer) {
|
90
|
+
try {
|
91
|
+
log(`Dialing peer ${peerId.toString()}`);
|
92
|
+
await this.libp2pComponents.dial(peerId);
|
93
|
+
|
94
|
+
const tags = await this.getTagNamesForPeer(peerId);
|
95
|
+
// add tag to connection describing discovery mechanism
|
96
|
+
// don't add duplicate tags
|
97
|
+
this.libp2pComponents
|
98
|
+
.getConnections(peerId)
|
99
|
+
.forEach(
|
100
|
+
(conn) => (conn.tags = Array.from(new Set([...conn.tags, ...tags])))
|
101
|
+
);
|
102
|
+
|
103
|
+
this.dialAttemptsForPeer.delete(peerId.toString());
|
104
|
+
return;
|
105
|
+
} catch (error) {
|
106
|
+
log(`
|
107
|
+
Error dialing peer ${peerId.toString()}`);
|
108
|
+
dialAttempt = this.dialAttemptsForPeer.get(peerId.toString()) ?? 1;
|
109
|
+
this.dialAttemptsForPeer.set(peerId.toString(), dialAttempt + 1);
|
110
|
+
|
111
|
+
if (dialAttempt <= this.options.maxDialAttemptsForPeer) {
|
112
|
+
log(`Reattempting dial (${dialAttempt})`);
|
113
|
+
}
|
114
|
+
}
|
115
|
+
}
|
116
|
+
|
117
|
+
try {
|
118
|
+
log(`Deleting undialable peer ${peerId.toString()} from peer store`);
|
119
|
+
return await this.libp2pComponents.peerStore.delete(peerId);
|
120
|
+
} catch (error) {
|
121
|
+
throw `Error deleting undialable peer ${peerId.toString()} from peer store - ${error}`;
|
122
|
+
}
|
123
|
+
}
|
124
|
+
|
125
|
+
private startPeerDiscoveryListener(): void {
|
126
|
+
this.libp2pComponents.peerStore.addEventListener(
|
127
|
+
"peer",
|
128
|
+
this.onEventHandlers["peer:discovery"]
|
129
|
+
);
|
130
|
+
}
|
131
|
+
|
132
|
+
private startPeerConnectionListener(): void {
|
133
|
+
this.libp2pComponents.addEventListener(
|
134
|
+
"peer:connect",
|
135
|
+
this.onEventHandlers["peer:connect"]
|
136
|
+
);
|
137
|
+
}
|
138
|
+
|
139
|
+
private startPeerDisconnectionListener(): void {
|
140
|
+
// TODO: ensure that these following issues are updated and confirmed
|
141
|
+
/**
|
142
|
+
* NOTE: Event is not being emitted on closing nor losing a connection.
|
143
|
+
* @see https://github.com/libp2p/js-libp2p/issues/939
|
144
|
+
* @see https://github.com/status-im/js-waku/issues/252
|
145
|
+
*
|
146
|
+
* >This event will be triggered anytime we are disconnected from another peer,
|
147
|
+
* >regardless of the circumstances of that disconnection.
|
148
|
+
* >If we happen to have multiple connections to a peer,
|
149
|
+
* >this event will **only** be triggered when the last connection is closed.
|
150
|
+
* @see https://github.com/libp2p/js-libp2p/blob/bad9e8c0ff58d60a78314077720c82ae331cc55b/doc/API.md?plain=1#L2100
|
151
|
+
*/
|
152
|
+
this.libp2pComponents.addEventListener(
|
153
|
+
"peer:disconnect",
|
154
|
+
this.onEventHandlers["peer:disconnect"]
|
155
|
+
);
|
156
|
+
}
|
157
|
+
|
158
|
+
private onEventHandlers = {
|
159
|
+
"peer:discovery": async (evt: CustomEvent<PeerInfo>): Promise<void> => {
|
160
|
+
const { id: peerId } = evt.detail;
|
161
|
+
if (!(await this.shouldDialPeer(peerId))) return;
|
162
|
+
|
163
|
+
this.dialPeer(peerId).catch((err) =>
|
164
|
+
log(`Error dialing peer ${peerId.toString()} : ${err}`)
|
165
|
+
);
|
166
|
+
},
|
167
|
+
"peer:connect": (evt: CustomEvent<Connection>): void => {
|
168
|
+
{
|
169
|
+
this.keepAliveManager.start(
|
170
|
+
evt.detail.remotePeer,
|
171
|
+
this.libp2pComponents.ping.bind(this)
|
172
|
+
);
|
173
|
+
}
|
174
|
+
},
|
175
|
+
"peer:disconnect": () => {
|
176
|
+
return (evt: CustomEvent<Connection>): void => {
|
177
|
+
this.keepAliveManager.stop(evt.detail.remotePeer);
|
178
|
+
};
|
179
|
+
},
|
180
|
+
};
|
181
|
+
|
182
|
+
/**
|
183
|
+
* Checks if the peer is dialable based on the following conditions:
|
184
|
+
* 1. If the peer is a bootstrap peer, it is only dialable if the number of current bootstrap connections is less than the max allowed.
|
185
|
+
* 2. If the peer is not a bootstrap peer
|
186
|
+
*/
|
187
|
+
private async shouldDialPeer(peerId: PeerId): Promise<boolean> {
|
188
|
+
const isConnected = this.libp2pComponents.getConnections(peerId).length > 0;
|
189
|
+
|
190
|
+
if (isConnected) return false;
|
191
|
+
|
192
|
+
const isBootstrap = (await this.getTagNamesForPeer(peerId)).some(
|
193
|
+
(tagName) => tagName === Tags.BOOTSTRAP
|
194
|
+
);
|
195
|
+
|
196
|
+
if (isBootstrap) {
|
197
|
+
const currentBootstrapConnections = this.libp2pComponents
|
198
|
+
.getConnections()
|
199
|
+
.filter((conn) => {
|
200
|
+
conn.tags.find((name) => name === Tags.BOOTSTRAP);
|
201
|
+
}).length;
|
202
|
+
if (currentBootstrapConnections < this.options.maxBootstrapPeersAllowed)
|
203
|
+
return true;
|
204
|
+
} else {
|
205
|
+
return true;
|
206
|
+
}
|
207
|
+
|
208
|
+
return false;
|
209
|
+
}
|
210
|
+
|
211
|
+
/**
|
212
|
+
* Fetches the tag names for a given peer
|
213
|
+
*/
|
214
|
+
private async getTagNamesForPeer(peerId: PeerId): Promise<string[]> {
|
215
|
+
const tags = (await this.libp2pComponents.peerStore.getTags(peerId)).map(
|
216
|
+
(tag) => tag.name
|
217
|
+
);
|
218
|
+
return tags;
|
219
|
+
}
|
220
|
+
}
|