@waku/core 0.0.10 → 0.0.12

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 (87) hide show
  1. package/CHANGELOG.md +85 -1
  2. package/README.md +2 -3
  3. package/bundle/browser-2f1afe46.js +726 -0
  4. package/bundle/index.js +9190 -12103
  5. package/bundle/lib/base_protocol.js +108 -0
  6. package/bundle/lib/message/topic_only_message.js +3 -2
  7. package/bundle/lib/message/version_0.js +3 -2
  8. package/bundle/peer_exchange-1229c8b0.js +4302 -0
  9. package/bundle/{topic_only_message-b1eddea1.js → topic_only_message-e8406994.js} +12 -8
  10. package/bundle/{version_0-862a05e0.js → version_0-e9a6cfb0.js} +35 -35
  11. package/dist/.tsbuildinfo +1 -0
  12. package/dist/index.d.ts +4 -1
  13. package/dist/index.js +3 -1
  14. package/dist/index.js.map +1 -1
  15. package/dist/lib/base_protocol.d.ts +21 -0
  16. package/dist/lib/base_protocol.js +33 -0
  17. package/dist/lib/base_protocol.js.map +1 -0
  18. package/dist/lib/connection_manager.d.ts +31 -0
  19. package/dist/lib/connection_manager.js +146 -0
  20. package/dist/lib/connection_manager.js.map +1 -0
  21. package/dist/lib/filter/filter_rpc.d.ts +8 -8
  22. package/dist/lib/filter/filter_rpc.js +6 -6
  23. package/dist/lib/filter/index.d.ts +5 -22
  24. package/dist/lib/filter/index.js +31 -86
  25. package/dist/lib/filter/index.js.map +1 -1
  26. package/dist/lib/group_by.d.ts +1 -1
  27. package/dist/lib/group_by.js.map +1 -1
  28. package/dist/lib/keep_alive_manager.d.ts +17 -0
  29. package/dist/lib/keep_alive_manager.js +62 -0
  30. package/dist/lib/keep_alive_manager.js.map +1 -0
  31. package/dist/lib/light_push/index.d.ts +3 -19
  32. package/dist/lib/light_push/index.js +14 -40
  33. package/dist/lib/light_push/index.js.map +1 -1
  34. package/dist/lib/light_push/push_rpc.d.ts +5 -5
  35. package/dist/lib/light_push/push_rpc.js +6 -6
  36. package/dist/lib/message/topic_only_message.d.ts +5 -3
  37. package/dist/lib/message/topic_only_message.js +8 -5
  38. package/dist/lib/message/topic_only_message.js.map +1 -1
  39. package/dist/lib/message/version_0.d.ts +12 -12
  40. package/dist/lib/message/version_0.js +29 -30
  41. package/dist/lib/message/version_0.js.map +1 -1
  42. package/dist/lib/predefined_bootstrap_nodes.js +1 -1
  43. package/dist/lib/predefined_bootstrap_nodes.js.map +1 -1
  44. package/dist/lib/relay/index.d.ts +4 -19
  45. package/dist/lib/relay/index.js +41 -26
  46. package/dist/lib/relay/index.js.map +1 -1
  47. package/dist/lib/relay/message_validator.d.ts +4 -0
  48. package/dist/lib/relay/message_validator.js +25 -0
  49. package/dist/lib/relay/message_validator.js.map +1 -0
  50. package/dist/lib/store/history_rpc.d.ts +4 -4
  51. package/dist/lib/store/history_rpc.js +9 -9
  52. package/dist/lib/store/history_rpc.js.map +1 -1
  53. package/dist/lib/store/index.d.ts +4 -26
  54. package/dist/lib/store/index.js +21 -40
  55. package/dist/lib/store/index.js.map +1 -1
  56. package/dist/lib/to_proto_message.js +3 -2
  57. package/dist/lib/to_proto_message.js.map +1 -1
  58. package/dist/lib/wait_for_remote_peer.js +12 -23
  59. package/dist/lib/wait_for_remote_peer.js.map +1 -1
  60. package/dist/lib/waku.d.ts +8 -15
  61. package/dist/lib/waku.js +34 -97
  62. package/dist/lib/waku.js.map +1 -1
  63. package/package.json +50 -61
  64. package/src/index.ts +11 -3
  65. package/src/lib/base_protocol.ts +47 -0
  66. package/src/lib/connection_manager.ts +220 -0
  67. package/src/lib/filter/filter_rpc.ts +10 -10
  68. package/src/lib/filter/index.ts +52 -147
  69. package/src/lib/group_by.ts +1 -1
  70. package/src/lib/keep_alive_manager.ts +89 -0
  71. package/src/lib/light_push/index.ts +18 -79
  72. package/src/lib/light_push/push_rpc.ts +9 -9
  73. package/src/lib/message/topic_only_message.ts +11 -5
  74. package/src/lib/message/version_0.ts +42 -37
  75. package/src/lib/predefined_bootstrap_nodes.ts +1 -1
  76. package/src/lib/relay/index.ts +64 -53
  77. package/src/lib/relay/message_validator.ts +35 -0
  78. package/src/lib/store/history_rpc.ts +12 -12
  79. package/src/lib/store/index.ts +31 -88
  80. package/src/lib/to_proto_message.ts +3 -2
  81. package/src/lib/wait_for_remote_peer.ts +13 -29
  82. package/src/lib/waku.ts +54 -136
  83. package/bundle/peer_exchange-df95c3a7.js +0 -11801
  84. package/dist/lib/random_subset.d.ts +0 -4
  85. package/dist/lib/random_subset.js +0 -25
  86. package/dist/lib/random_subset.js.map +0 -1
  87. package/src/lib/random_subset.ts +0 -30
@@ -1,32 +1,28 @@
1
- import type { Connection } from "@libp2p/interface-connection";
2
- import type { ConnectionManager } from "@libp2p/interface-connection-manager";
1
+ import type { Stream } from "@libp2p/interface-connection";
2
+ import type { Libp2p } from "@libp2p/interface-libp2p";
3
3
  import type { PeerId } from "@libp2p/interface-peer-id";
4
- import type { Peer, PeerStore } from "@libp2p/interface-peer-store";
5
4
  import { sha256 } from "@noble/hashes/sha256";
6
- import { concat, utf8ToBytes } from "@waku/byte-utils";
7
5
  import {
8
6
  Cursor,
9
7
  IDecodedMessage,
10
8
  IDecoder,
11
- Index,
12
9
  IStore,
10
+ ProtocolCreateOptions,
13
11
  } from "@waku/interfaces";
14
- import {
15
- getPeersForProtocol,
16
- selectConnection,
17
- selectPeerForProtocol,
18
- } from "@waku/libp2p-utils";
19
12
  import { proto_store as proto } from "@waku/proto";
13
+ import { isDefined } from "@waku/utils";
14
+ import { concat, utf8ToBytes } from "@waku/utils/bytes";
20
15
  import debug from "debug";
21
16
  import all from "it-all";
22
17
  import * as lp from "it-length-prefixed";
23
18
  import { pipe } from "it-pipe";
24
19
  import { Uint8ArrayList } from "uint8arraylist";
25
20
 
21
+ import { BaseProtocol } from "../base_protocol.js";
26
22
  import { DefaultPubSubTopic } from "../constants.js";
27
23
  import { toProtoMessage } from "../to_proto_message.js";
28
24
 
29
- import { HistoryRPC, PageDirection, Params } from "./history_rpc.js";
25
+ import { HistoryRpc, PageDirection, Params } from "./history_rpc.js";
30
26
 
31
27
  import HistoryError = proto.HistoryResponse.HistoryError;
32
28
 
@@ -38,23 +34,6 @@ export const DefaultPageSize = 10;
38
34
 
39
35
  export { PageDirection };
40
36
 
41
- export interface StoreComponents {
42
- peerStore: PeerStore;
43
- connectionManager: ConnectionManager;
44
- }
45
-
46
- export interface CreateOptions {
47
- /**
48
- * The PubSub Topic to use. Defaults to {@link DefaultPubSubTopic}.
49
- *
50
- * The usage of the default pubsub topic is recommended.
51
- * See [Waku v2 Topic Usage Recommendations](https://rfc.vac.dev/spec/23/) for details.
52
- *
53
- * @default {@link DefaultPubSubTopic}
54
- */
55
- pubSubTopic?: string;
56
- }
57
-
58
37
  export interface TimeFilter {
59
38
  startTime: Date;
60
39
  endTime: Date;
@@ -65,11 +44,6 @@ export interface QueryOptions {
65
44
  * The peer to query. If undefined, a pseudo-random peer is selected from the connected Waku Store peers.
66
45
  */
67
46
  peerId?: PeerId;
68
- /**
69
- * The pubsub topic to pass to the query.
70
- * See [Waku v2 Topic Usage Recommendations](https://rfc.vac.dev/spec/23/).
71
- */
72
- pubSubTopic?: string;
73
47
  /**
74
48
  * The direction in which pages are retrieved:
75
49
  * - { @link PageDirection.BACKWARD }: Most recent page first.
@@ -104,11 +78,12 @@ export interface QueryOptions {
104
78
  *
105
79
  * The Waku Store protocol can be used to retrieved historical messages.
106
80
  */
107
- class Store implements IStore {
108
- pubSubTopic: string;
81
+ class Store extends BaseProtocol implements IStore {
82
+ options: ProtocolCreateOptions;
109
83
 
110
- constructor(public components: StoreComponents, options?: CreateOptions) {
111
- this.pubSubTopic = options?.pubSubTopic ?? DefaultPubSubTopic;
84
+ constructor(public libp2p: Libp2p, options?: ProtocolCreateOptions) {
85
+ super(StoreCodec, libp2p.peerStore, libp2p.getConnections.bind(libp2p));
86
+ this.options = options ?? {};
112
87
  }
113
88
 
114
89
  /**
@@ -219,6 +194,8 @@ class Store implements IStore {
219
194
  decoders: IDecoder<T>[],
220
195
  options?: QueryOptions
221
196
  ): AsyncGenerator<Promise<T | undefined>[]> {
197
+ const { pubSubTopic = DefaultPubSubTopic } = this.options;
198
+
222
199
  let startTime, endTime;
223
200
 
224
201
  if (options?.timeFilter) {
@@ -240,7 +217,7 @@ class Store implements IStore {
240
217
 
241
218
  const queryOpts = Object.assign(
242
219
  {
243
- pubSubTopic: this.pubSubTopic,
220
+ pubSubTopic: pubSubTopic,
244
221
  pageDirection: PageDirection.BACKWARD,
245
222
  pageSize: DefaultPageSize,
246
223
  },
@@ -253,27 +230,10 @@ class Store implements IStore {
253
230
  peerId: options?.peerId?.toString(),
254
231
  });
255
232
 
256
- const res = await selectPeerForProtocol(
257
- this.components.peerStore,
258
- [StoreCodec],
259
- options?.peerId
260
- );
261
-
262
- if (!res) {
263
- throw new Error("Failed to get a peer");
264
- }
265
- const { peer, protocol } = res;
266
-
267
- const connections = this.components.connectionManager.getConnections(
268
- peer.id
269
- );
270
- const connection = selectConnection(connections);
271
-
272
- if (!connection) throw "Failed to get a connection to the peer";
233
+ const peer = await this.getPeer(options?.peerId);
273
234
 
274
235
  for await (const messages of paginate<T>(
275
- connection,
276
- protocol,
236
+ this.newStream.bind(this, peer),
277
237
  queryOpts,
278
238
  decodersAsMap,
279
239
  options?.cursor
@@ -281,23 +241,10 @@ class Store implements IStore {
281
241
  yield messages;
282
242
  }
283
243
  }
284
-
285
- /**
286
- * Returns known peers from the address book (`libp2p.peerStore`) that support
287
- * store protocol. Waku may or may not be currently connected to these peers.
288
- */
289
- async peers(): Promise<Peer[]> {
290
- return getPeersForProtocol(this.components.peerStore, [StoreCodec]);
291
- }
292
-
293
- get peerStore(): PeerStore {
294
- return this.components.peerStore;
295
- }
296
244
  }
297
245
 
298
246
  async function* paginate<T extends IDecodedMessage>(
299
- connection: Connection,
300
- protocol: string,
247
+ streamFactory: () => Promise<Stream>,
301
248
  queryOpts: Params,
302
249
  decoders: Map<string, IDecoder<T>>,
303
250
  cursor?: Cursor
@@ -315,16 +262,16 @@ async function* paginate<T extends IDecodedMessage>(
315
262
  while (true) {
316
263
  queryOpts.cursor = currentCursor;
317
264
 
318
- const stream = await connection.newStream(protocol);
319
- const historyRpcQuery = HistoryRPC.createQuery(queryOpts);
265
+ const historyRpcQuery = HistoryRpc.createQuery(queryOpts);
320
266
 
321
267
  log(
322
268
  "Querying store peer",
323
- connection.remoteAddr.toString(),
324
269
  `for (${queryOpts.pubSubTopic})`,
325
270
  queryOpts.contentTopics
326
271
  );
327
272
 
273
+ const stream = await streamFactory();
274
+
328
275
  const res = await pipe(
329
276
  [historyRpcQuery.encode()],
330
277
  lp.encode(),
@@ -347,10 +294,7 @@ async function* paginate<T extends IDecodedMessage>(
347
294
 
348
295
  const response = reply.response as proto.HistoryResponse;
349
296
 
350
- if (
351
- response.error &&
352
- response.error !== HistoryError.ERROR_NONE_UNSPECIFIED
353
- ) {
297
+ if (response.error && response.error !== HistoryError.NONE) {
354
298
  throw "History response contains an Error: " + response.error;
355
299
  }
356
300
 
@@ -368,7 +312,10 @@ async function* paginate<T extends IDecodedMessage>(
368
312
  if (typeof contentTopic !== "undefined") {
369
313
  const decoder = decoders.get(contentTopic);
370
314
  if (decoder) {
371
- return decoder.fromProtoObj(toProtoMessage(protoMsg));
315
+ return decoder.fromProtoObj(
316
+ queryOpts.pubSubTopic,
317
+ toProtoMessage(protoMsg)
318
+ );
372
319
  }
373
320
  }
374
321
  return Promise.resolve(undefined);
@@ -399,14 +346,10 @@ async function* paginate<T extends IDecodedMessage>(
399
346
  }
400
347
  }
401
348
 
402
- export function isDefined<T>(msg: T | undefined): msg is T {
403
- return !!msg;
404
- }
405
-
406
349
  export async function createCursor(
407
350
  message: IDecodedMessage,
408
351
  pubsubTopic: string = DefaultPubSubTopic
409
- ): Promise<Index> {
352
+ ): Promise<Cursor> {
410
353
  if (
411
354
  !message ||
412
355
  !message.timestamp ||
@@ -426,12 +369,12 @@ export async function createCursor(
426
369
  digest,
427
370
  pubsubTopic,
428
371
  senderTime: messageTime,
429
- receivedTime: messageTime,
372
+ receiverTime: messageTime,
430
373
  };
431
374
  }
432
375
 
433
376
  export function wakuStore(
434
- init: Partial<CreateOptions> = {}
435
- ): (components: StoreComponents) => IStore {
436
- return (components: StoreComponents) => new Store(components, init);
377
+ init: Partial<ProtocolCreateOptions> = {}
378
+ ): (libp2p: Libp2p) => IStore {
379
+ return (libp2p: Libp2p) => new Store(libp2p, init);
437
380
  }
@@ -2,10 +2,11 @@ import { IProtoMessage } from "@waku/interfaces";
2
2
  import { WakuMessage as WakuMessageProto } from "@waku/proto";
3
3
 
4
4
  const EmptyMessage: IProtoMessage = {
5
- payload: undefined,
6
- contentTopic: undefined,
5
+ payload: new Uint8Array(),
6
+ contentTopic: "",
7
7
  version: undefined,
8
8
  timestamp: undefined,
9
+ meta: undefined,
9
10
  rateLimitProof: undefined,
10
11
  ephemeral: undefined,
11
12
  };
@@ -1,14 +1,9 @@
1
- import { PeerProtocolsChangeData } from "@libp2p/interface-peer-store";
1
+ import type { PeerProtocolsChangeData } from "@libp2p/interface-peer-store";
2
2
  import type { IRelay, PointToPointProtocol, Waku } from "@waku/interfaces";
3
3
  import { Protocols } from "@waku/interfaces";
4
- import { PeerExchangeCodec } from "@waku/peer-exchange";
5
4
  import debug from "debug";
6
5
  import { pEvent } from "p-event";
7
6
 
8
- import { FilterCodec } from "./filter/index.js";
9
- import { LightPushCodec } from "./light_push/index.js";
10
- import { StoreCodec } from "./store/index.js";
11
-
12
7
  const log = debug("waku:wait-for-remote-peer");
13
8
 
14
9
  /**
@@ -50,27 +45,19 @@ export async function waitForRemotePeer(
50
45
  if (protocols.includes(Protocols.Store)) {
51
46
  if (!waku.store)
52
47
  throw new Error("Cannot wait for Store peer: protocol not mounted");
53
- promises.push(waitForConnectedPeer(waku.store, [StoreCodec]));
48
+ promises.push(waitForConnectedPeer(waku.store));
54
49
  }
55
50
 
56
51
  if (protocols.includes(Protocols.LightPush)) {
57
52
  if (!waku.lightPush)
58
53
  throw new Error("Cannot wait for LightPush peer: protocol not mounted");
59
- promises.push(waitForConnectedPeer(waku.lightPush, [LightPushCodec]));
54
+ promises.push(waitForConnectedPeer(waku.lightPush));
60
55
  }
61
56
 
62
57
  if (protocols.includes(Protocols.Filter)) {
63
58
  if (!waku.filter)
64
59
  throw new Error("Cannot wait for Filter peer: protocol not mounted");
65
- promises.push(waitForConnectedPeer(waku.filter, [FilterCodec]));
66
- }
67
-
68
- if (protocols.includes(Protocols.PeerExchange)) {
69
- if (!waku.peerExchange)
70
- throw new Error(
71
- "Cannot wait for Peer Exchange peer: protocol not mounted"
72
- );
73
- promises.push(waitForConnectedPeer(waku.peerExchange, [PeerExchangeCodec]));
60
+ promises.push(waitForConnectedPeer(waku.filter));
74
61
  }
75
62
 
76
63
  if (timeoutMs) {
@@ -88,28 +75,25 @@ export async function waitForRemotePeer(
88
75
  * Wait for a peer with the given protocol to be connected.
89
76
  */
90
77
  async function waitForConnectedPeer(
91
- waku: PointToPointProtocol,
92
- codecs: string[]
78
+ protocol: PointToPointProtocol
93
79
  ): Promise<void> {
94
- const peers = await waku.peers();
80
+ const codec = protocol.multicodec;
81
+ const peers = await protocol.peers();
95
82
 
96
83
  if (peers.length) {
97
- log(`${codecs} peer found: `, peers[0].id.toString());
84
+ log(`${codec} peer found: `, peers[0].id.toString());
98
85
  return;
99
86
  }
100
87
 
101
88
  await new Promise<void>((resolve) => {
102
89
  const cb = (evt: CustomEvent<PeerProtocolsChangeData>): void => {
103
- for (const codec of codecs) {
104
- if (evt.detail.protocols.includes(codec)) {
105
- log("Resolving for", codec, evt.detail.protocols);
106
- waku.peerStore.removeEventListener("change:protocols", cb);
107
- resolve();
108
- break;
109
- }
90
+ if (evt.detail.protocols.includes(codec)) {
91
+ log("Resolving for", codec, evt.detail.protocols);
92
+ protocol.peerStore.removeEventListener("change:protocols", cb);
93
+ resolve();
110
94
  }
111
95
  };
112
- waku.peerStore.addEventListener("change:protocols", cb);
96
+ protocol.peerStore.addEventListener("change:protocols", cb);
113
97
  });
114
98
  }
115
99
 
package/src/lib/waku.ts CHANGED
@@ -1,27 +1,20 @@
1
1
  import type { Stream } from "@libp2p/interface-connection";
2
+ import type { Libp2p } from "@libp2p/interface-libp2p";
2
3
  import type { PeerId } from "@libp2p/interface-peer-id";
3
4
  import type { PubSub } from "@libp2p/interface-pubsub";
4
5
  import type { Multiaddr } from "@multiformats/multiaddr";
5
6
  import type {
6
7
  IFilter,
7
8
  ILightPush,
8
- IPeerExchange,
9
9
  IRelay,
10
10
  IStore,
11
- PeerExchangeComponents,
12
11
  Waku,
13
12
  } from "@waku/interfaces";
14
13
  import { Protocols } from "@waku/interfaces";
15
- import { PeerExchangeCodec } from "@waku/peer-exchange";
16
14
  import debug from "debug";
17
- import type { Libp2p } from "libp2p";
18
15
 
19
- import { FilterCodec, FilterComponents } from "./filter/index.js";
20
- import { LightPushCodec, LightPushComponents } from "./light_push/index.js";
21
- import { createEncoder } from "./message/version_0.js";
16
+ import { ConnectionManager } from "./connection_manager.js";
22
17
  import * as relayConstants from "./relay/constants.js";
23
- import { RelayCodecs, RelayPingContentTopic } from "./relay/constants.js";
24
- import { StoreCodec, StoreComponents } from "./store/index.js";
25
18
 
26
19
  export const DefaultPingKeepAliveValueSecs = 0;
27
20
  export const DefaultRelayKeepAliveValueSecs = 5 * 60;
@@ -34,19 +27,19 @@ export interface WakuOptions {
34
27
  * Set keep alive frequency in seconds: Waku will send a `/ipfs/ping/1.0.0`
35
28
  * request to each peer after the set number of seconds. Set to 0 to disable.
36
29
  *
37
- * @default {@link DefaultPingKeepAliveValueSecs}
30
+ * @default {@link @waku/core.DefaultPingKeepAliveValueSecs}
38
31
  */
39
32
  pingKeepAlive?: number;
40
33
  /**
41
34
  * Set keep alive frequency in seconds: Waku will send a ping message over
42
35
  * relay to each peer after the set number of seconds. Set to 0 to disable.
43
36
  *
44
- * @default {@link DefaultRelayKeepAliveValueSecs}
37
+ * @default {@link @waku/core.DefaultRelayKeepAliveValueSecs}
45
38
  */
46
39
  relayKeepAlive?: number;
47
40
  /**
48
41
  * Set the user agent string to be used in identification of the node.
49
- * @default {@link DefaultUserAgent}
42
+ * @default {@link @waku/core.DefaultUserAgent}
50
43
  */
51
44
  userAgent?: string;
52
45
  }
@@ -57,90 +50,52 @@ export class WakuNode implements Waku {
57
50
  public store?: IStore;
58
51
  public filter?: IFilter;
59
52
  public lightPush?: ILightPush;
60
- public peerExchange?: IPeerExchange;
61
-
62
- private pingKeepAliveTimers: {
63
- [peer: string]: ReturnType<typeof setInterval>;
64
- };
65
- private relayKeepAliveTimers: {
66
- [peer: string]: ReturnType<typeof setInterval>;
67
- };
53
+ public connectionManager: ConnectionManager;
68
54
 
69
55
  constructor(
70
56
  options: WakuOptions,
71
57
  libp2p: Libp2p,
72
- store?: (components: StoreComponents) => IStore,
73
- lightPush?: (components: LightPushComponents) => ILightPush,
74
- filter?: (components: FilterComponents) => IFilter,
75
- peerExchange?: (components: PeerExchangeComponents) => IPeerExchange
58
+ store?: (libp2p: Libp2p) => IStore,
59
+ lightPush?: (libp2p: Libp2p) => ILightPush,
60
+ filter?: (libp2p: Libp2p) => IFilter
76
61
  ) {
77
62
  this.libp2p = libp2p;
78
63
 
79
- const { peerStore, connectionManager, registrar } = libp2p;
80
- const components = { peerStore, connectionManager, registrar };
81
-
82
64
  if (store) {
83
- this.store = store(components);
65
+ this.store = store(libp2p);
84
66
  }
85
67
  if (filter) {
86
- this.filter = filter(components);
68
+ this.filter = filter(libp2p);
87
69
  }
88
70
  if (lightPush) {
89
- this.lightPush = lightPush(components);
90
- }
91
-
92
- if (peerExchange) {
93
- this.peerExchange = peerExchange(components);
71
+ this.lightPush = lightPush(libp2p);
94
72
  }
95
73
 
96
74
  if (isRelay(libp2p.pubsub)) {
97
75
  this.relay = libp2p.pubsub;
98
76
  }
99
77
 
100
- log(
101
- "Waku node created",
102
- this.libp2p.peerId.toString(),
103
- `relay: ${!!this.relay}, store: ${!!this.store}, light push: ${!!this
104
- .lightPush}, filter: ${!!this.filter}, peer exchange: ${!!this
105
- .peerExchange} `
106
- );
107
-
108
- this.pingKeepAliveTimers = {};
109
- this.relayKeepAliveTimers = {};
110
-
111
78
  const pingKeepAlive =
112
79
  options.pingKeepAlive || DefaultPingKeepAliveValueSecs;
113
80
  const relayKeepAlive = this.relay
114
81
  ? options.relayKeepAlive || DefaultRelayKeepAliveValueSecs
115
82
  : 0;
116
83
 
117
- libp2p.connectionManager.addEventListener("peer:connect", (evt) => {
118
- this.startKeepAlive(evt.detail.remotePeer, pingKeepAlive, relayKeepAlive);
119
- });
84
+ const peerId = this.libp2p.peerId.toString();
120
85
 
121
- /**
122
- * NOTE: Event is not being emitted on closing nor losing a connection.
123
- * @see https://github.com/libp2p/js-libp2p/issues/939
124
- * @see https://github.com/status-im/js-waku/issues/252
125
- *
126
- * >This event will be triggered anytime we are disconnected from another peer,
127
- * >regardless of the circumstances of that disconnection.
128
- * >If we happen to have multiple connections to a peer,
129
- * >this event will **only** be triggered when the last connection is closed.
130
- * @see https://github.com/libp2p/js-libp2p/blob/bad9e8c0ff58d60a78314077720c82ae331cc55b/doc/API.md?plain=1#L2100
131
- */
132
- libp2p.connectionManager.addEventListener("peer:disconnect", (evt) => {
133
- this.stopKeepAlive(evt.detail.remotePeer);
134
- });
86
+ this.connectionManager = ConnectionManager.create(
87
+ peerId,
88
+ libp2p,
89
+ { pingKeepAlive, relayKeepAlive },
90
+ this.relay
91
+ );
135
92
 
136
- // Trivial handling of discovered peers, to be refined.
137
- libp2p.addEventListener("peer:discovery", (evt) => {
138
- const peerId = evt.detail.id;
139
- log(`Found peer ${peerId.toString()}, dialing.`);
140
- libp2p.dial(peerId).catch((err) => {
141
- log(`Fail to dial ${peerId}`, err);
142
- });
143
- });
93
+ log(
94
+ "Waku node created",
95
+ peerId,
96
+ `relay: ${!!this.relay}, store: ${!!this.store}, light push: ${!!this
97
+ .lightPush}, filter: ${!!this.filter}`
98
+ );
144
99
  }
145
100
 
146
101
  /**
@@ -160,25 +115,44 @@ export class WakuNode implements Waku {
160
115
  this.store && _protocols.push(Protocols.Store);
161
116
  this.filter && _protocols.push(Protocols.Filter);
162
117
  this.lightPush && _protocols.push(Protocols.LightPush);
163
- this.peerExchange && _protocols.push(Protocols.PeerExchange);
164
118
  }
165
119
 
166
120
  const codecs: string[] = [];
167
121
  if (_protocols.includes(Protocols.Relay)) {
168
- RelayCodecs.forEach((codec) => codecs.push(codec));
122
+ if (this.relay) {
123
+ this.relay.multicodecs.forEach((codec) => codecs.push(codec));
124
+ } else {
125
+ log(
126
+ "Relay codec not included in dial codec: protocol not mounted locally"
127
+ );
128
+ }
169
129
  }
170
130
  if (_protocols.includes(Protocols.Store)) {
171
- codecs.push(StoreCodec);
131
+ if (this.store) {
132
+ codecs.push(this.store.multicodec);
133
+ } else {
134
+ log(
135
+ "Store codec not included in dial codec: protocol not mounted locally"
136
+ );
137
+ }
172
138
  }
173
139
  if (_protocols.includes(Protocols.LightPush)) {
174
- codecs.push(LightPushCodec);
140
+ if (this.lightPush) {
141
+ codecs.push(this.lightPush.multicodec);
142
+ } else {
143
+ log(
144
+ "Light Push codec not included in dial codec: protocol not mounted locally"
145
+ );
146
+ }
175
147
  }
176
148
  if (_protocols.includes(Protocols.Filter)) {
177
- codecs.push(FilterCodec);
178
- }
179
-
180
- if (_protocols.includes(Protocols.PeerExchange)) {
181
- codecs.push(PeerExchangeCodec);
149
+ if (this.filter) {
150
+ codecs.push(this.filter.multicodec);
151
+ } else {
152
+ log(
153
+ "Filter codec not included in dial codec: protocol not mounted locally"
154
+ );
155
+ }
182
156
  }
183
157
 
184
158
  log(`Dialing to ${peer.toString()} with protocols ${_protocols}`);
@@ -191,7 +165,7 @@ export class WakuNode implements Waku {
191
165
  }
192
166
 
193
167
  async stop(): Promise<void> {
194
- this.stopAllKeepAlives();
168
+ this.connectionManager.stop();
195
169
  await this.libp2p.stop();
196
170
  }
197
171
 
@@ -213,62 +187,6 @@ export class WakuNode implements Waku {
213
187
  }
214
188
  return localMultiaddr + "/p2p/" + this.libp2p.peerId.toString();
215
189
  }
216
-
217
- private startKeepAlive(
218
- peerId: PeerId,
219
- pingPeriodSecs: number,
220
- relayPeriodSecs: number
221
- ): void {
222
- // Just in case a timer already exist for this peer
223
- this.stopKeepAlive(peerId);
224
-
225
- const peerIdStr = peerId.toString();
226
-
227
- if (pingPeriodSecs !== 0) {
228
- this.pingKeepAliveTimers[peerIdStr] = setInterval(() => {
229
- this.libp2p.ping(peerId).catch((e) => {
230
- log(`Ping failed (${peerIdStr})`, e);
231
- });
232
- }, pingPeriodSecs * 1000);
233
- }
234
-
235
- const relay = this.relay;
236
- if (relay && relayPeriodSecs !== 0) {
237
- const encoder = createEncoder(RelayPingContentTopic, true);
238
- this.relayKeepAliveTimers[peerIdStr] = setInterval(() => {
239
- log("Sending Waku Relay ping message");
240
- relay
241
- .send(encoder, { payload: new Uint8Array() })
242
- .catch((e) => log("Failed to send relay ping", e));
243
- }, relayPeriodSecs * 1000);
244
- }
245
- }
246
-
247
- private stopKeepAlive(peerId: PeerId): void {
248
- const peerIdStr = peerId.toString();
249
-
250
- if (this.pingKeepAliveTimers[peerIdStr]) {
251
- clearInterval(this.pingKeepAliveTimers[peerIdStr]);
252
- delete this.pingKeepAliveTimers[peerIdStr];
253
- }
254
-
255
- if (this.relayKeepAliveTimers[peerIdStr]) {
256
- clearInterval(this.relayKeepAliveTimers[peerIdStr]);
257
- delete this.relayKeepAliveTimers[peerIdStr];
258
- }
259
- }
260
-
261
- private stopAllKeepAlives(): void {
262
- for (const timer of [
263
- ...Object.values(this.pingKeepAliveTimers),
264
- ...Object.values(this.relayKeepAliveTimers),
265
- ]) {
266
- clearInterval(timer);
267
- }
268
-
269
- this.pingKeepAliveTimers = {};
270
- this.relayKeepAliveTimers = {};
271
- }
272
190
  }
273
191
 
274
192
  function isRelay(pubsub: PubSub): pubsub is IRelay {