@waku/core 0.0.10 → 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.
Files changed (86) hide show
  1. package/CHANGELOG.md +66 -1
  2. package/bundle/browser-2f1afe46.js +726 -0
  3. package/bundle/index.js +9166 -12074
  4. package/bundle/lib/base_protocol.js +108 -0
  5. package/bundle/lib/message/topic_only_message.js +3 -2
  6. package/bundle/lib/message/version_0.js +3 -2
  7. package/bundle/peer_exchange-1229c8b0.js +4302 -0
  8. package/bundle/{topic_only_message-b1eddea1.js → topic_only_message-e8406994.js} +12 -8
  9. package/bundle/{version_0-862a05e0.js → version_0-e9a6cfb0.js} +35 -35
  10. package/dist/.tsbuildinfo +1 -0
  11. package/dist/index.d.ts +4 -1
  12. package/dist/index.js +3 -1
  13. package/dist/index.js.map +1 -1
  14. package/dist/lib/base_protocol.d.ts +21 -0
  15. package/dist/lib/base_protocol.js +33 -0
  16. package/dist/lib/base_protocol.js.map +1 -0
  17. package/dist/lib/connection_manager.d.ts +31 -0
  18. package/dist/lib/connection_manager.js +146 -0
  19. package/dist/lib/connection_manager.js.map +1 -0
  20. package/dist/lib/filter/filter_rpc.d.ts +8 -8
  21. package/dist/lib/filter/filter_rpc.js +6 -6
  22. package/dist/lib/filter/index.d.ts +5 -22
  23. package/dist/lib/filter/index.js +31 -86
  24. package/dist/lib/filter/index.js.map +1 -1
  25. package/dist/lib/group_by.d.ts +1 -1
  26. package/dist/lib/group_by.js.map +1 -1
  27. package/dist/lib/keep_alive_manager.d.ts +17 -0
  28. package/dist/lib/keep_alive_manager.js +62 -0
  29. package/dist/lib/keep_alive_manager.js.map +1 -0
  30. package/dist/lib/light_push/index.d.ts +3 -19
  31. package/dist/lib/light_push/index.js +13 -39
  32. package/dist/lib/light_push/index.js.map +1 -1
  33. package/dist/lib/light_push/push_rpc.d.ts +5 -5
  34. package/dist/lib/light_push/push_rpc.js +6 -6
  35. package/dist/lib/message/topic_only_message.d.ts +5 -3
  36. package/dist/lib/message/topic_only_message.js +8 -5
  37. package/dist/lib/message/topic_only_message.js.map +1 -1
  38. package/dist/lib/message/version_0.d.ts +12 -12
  39. package/dist/lib/message/version_0.js +29 -30
  40. package/dist/lib/message/version_0.js.map +1 -1
  41. package/dist/lib/predefined_bootstrap_nodes.js +1 -1
  42. package/dist/lib/predefined_bootstrap_nodes.js.map +1 -1
  43. package/dist/lib/relay/index.d.ts +4 -18
  44. package/dist/lib/relay/index.js +47 -26
  45. package/dist/lib/relay/index.js.map +1 -1
  46. package/dist/lib/relay/message_validator.d.ts +4 -0
  47. package/dist/lib/relay/message_validator.js +25 -0
  48. package/dist/lib/relay/message_validator.js.map +1 -0
  49. package/dist/lib/store/history_rpc.d.ts +4 -4
  50. package/dist/lib/store/history_rpc.js +9 -9
  51. package/dist/lib/store/history_rpc.js.map +1 -1
  52. package/dist/lib/store/index.d.ts +4 -25
  53. package/dist/lib/store/index.js +20 -37
  54. package/dist/lib/store/index.js.map +1 -1
  55. package/dist/lib/to_proto_message.js +3 -2
  56. package/dist/lib/to_proto_message.js.map +1 -1
  57. package/dist/lib/wait_for_remote_peer.js +12 -23
  58. package/dist/lib/wait_for_remote_peer.js.map +1 -1
  59. package/dist/lib/waku.d.ts +8 -15
  60. package/dist/lib/waku.js +34 -97
  61. package/dist/lib/waku.js.map +1 -1
  62. package/package.json +50 -61
  63. package/src/index.ts +11 -3
  64. package/src/lib/base_protocol.ts +47 -0
  65. package/src/lib/connection_manager.ts +220 -0
  66. package/src/lib/filter/filter_rpc.ts +10 -10
  67. package/src/lib/filter/index.ts +52 -147
  68. package/src/lib/group_by.ts +1 -1
  69. package/src/lib/keep_alive_manager.ts +89 -0
  70. package/src/lib/light_push/index.ts +17 -78
  71. package/src/lib/light_push/push_rpc.ts +9 -9
  72. package/src/lib/message/topic_only_message.ts +11 -5
  73. package/src/lib/message/version_0.ts +42 -37
  74. package/src/lib/predefined_bootstrap_nodes.ts +1 -1
  75. package/src/lib/relay/index.ts +77 -52
  76. package/src/lib/relay/message_validator.ts +35 -0
  77. package/src/lib/store/history_rpc.ts +12 -12
  78. package/src/lib/store/index.ts +30 -84
  79. package/src/lib/to_proto_message.ts +3 -2
  80. package/src/lib/wait_for_remote_peer.ts +13 -29
  81. package/src/lib/waku.ts +54 -136
  82. package/bundle/peer_exchange-df95c3a7.js +0 -11801
  83. package/dist/lib/random_subset.d.ts +0 -4
  84. package/dist/lib/random_subset.js +0 -25
  85. package/dist/lib/random_subset.js.map +0 -1
  86. 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 { FilterCodec } from "./filter/index.js";
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, peerExchange) {
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(components);
13
+ this.store = store(libp2p);
21
14
  }
22
15
  if (filter) {
23
- this.filter = filter(components);
16
+ this.filter = filter(libp2p);
24
17
  }
25
18
  if (lightPush) {
26
- this.lightPush = lightPush(components);
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.connectionManager.addEventListener("peer:connect", (evt) => {
44
- this.startKeepAlive(evt.detail.remotePeer, pingKeepAlive, relayKeepAlive);
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
- RelayCodecs.forEach((codec) => codecs.push(codec));
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
- codecs.push(StoreCodec);
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
- codecs.push(LightPushCodec);
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
- codecs.push(FilterCodec);
96
- }
97
- if (_protocols.includes(Protocols.PeerExchange)) {
98
- codecs.push(PeerExchangeCodec);
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.stopAllKeepAlives();
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, true);
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) {
@@ -1 +1 @@
1
- {"version":3,"file":"waku.js","sourceRoot":"","sources":["../../src/lib/waku.ts"],"names":[],"mappings":"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"}
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.10",
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 --ext .ts --ext .cjs --fix",
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 --ext .ts",
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": "^5.2.1",
80
- "@libp2p/interface-connection": "^3.0.3",
81
- "@libp2p/interface-peer-discovery": "^1.0.0",
82
- "@libp2p/interface-peer-id": "^1.0.6",
83
- "@libp2p/interface-peer-info": "^1.0.4",
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": "^1.0.6",
98
- "it-length-prefixed": "^8.0.2",
99
- "it-pipe": "^2.0.4",
100
- "libp2p": "0.40.0",
89
+ "it-all": "^2.0.0",
90
+ "it-length-prefixed": "^8.0.4",
91
+ "it-pipe": "^2.0.5",
101
92
  "p-event": "^5.0.1",
102
- "uint8arraylist": "^2.3.2",
103
- "uint8arrays": "^4.0.2",
93
+ "uint8arraylist": "^2.4.3",
104
94
  "uuid": "^9.0.0"
105
95
  },
106
96
  "devDependencies": {
107
- "@rollup/plugin-commonjs": "^22.0.0",
108
- "@rollup/plugin-json": "^4.1.0",
109
- "@rollup/plugin-node-resolve": "^13.3.0",
110
- "@types/app-root-path": "^1.2.4",
111
- "@types/chai": "^4.2.15",
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",
112
108
  "@types/debug": "^4.1.7",
113
- "@types/mocha": "^9.1.0",
114
- "@types/node": "^18.11.17",
115
- "@types/tail": "^2.0.0",
116
- "@types/uuid": "^8.3.0",
117
- "@typescript-eslint/eslint-plugin": "^5.8.1",
118
- "@typescript-eslint/parser": "^5.8.1",
119
- "app-root-path": "^3.0.0",
120
- "cspell": "^6.17.0",
121
- "eslint": "^8.6.0",
122
- "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",
123
118
  "eslint-plugin-eslint-comments": "^3.2.0",
124
- "eslint-plugin-functional": "^4.0.2",
125
- "eslint-plugin-import": "^2.25.3",
126
- "eslint-plugin-prettier": "^4.0.0",
127
- "gh-pages": "^3.2.3",
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",
128
123
  "ignore-loader": "^0.1.2",
129
124
  "isomorphic-fetch": "^3.0.0",
130
- "jsdom": "^19.0.0",
131
- "jsdom-global": "^3.0.2",
132
- "karma": "^6.3.12",
133
- "karma-chrome-launcher": "^3.1.0",
125
+ "karma": "^6.4.1",
126
+ "karma-chrome-launcher": "^3.1.1",
134
127
  "karma-mocha": "^2.0.1",
135
128
  "karma-webpack": "^5.0.0",
136
- "mocha": "^9.1.3",
137
- "chai": "^4.3.4",
138
- "fast-check": "^2.14.0",
129
+ "mocha": "^10.2.0",
139
130
  "npm-run-all": "^4.1.5",
140
- "p-timeout": "^6.0.0",
141
- "portfinder": "^1.0.28",
142
- "prettier": "^2.1.1",
131
+ "prettier": "^2.8.4",
143
132
  "process": "^0.11.10",
144
- "puppeteer": "^13.0.1",
145
- "rollup": "^2.75.0",
146
- "tail": "^2.2.0",
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.6.3"
137
+ "typescript": "^4.9.5"
150
138
  },
151
139
  "peerDependencies": {
152
- "@multiformats/multiaddr": "^11.0.6"
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
- createEncoder,
6
- createDecoder,
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
+ }