@waku/core 0.0.23 → 0.0.24

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 (53) hide show
  1. package/CHANGELOG.md +34 -0
  2. package/bundle/{base_protocol-84d9b670.js → base_protocol-2a0c882e.js} +182 -130
  3. package/bundle/{browser-bde977a3.js → browser-90197c87.js} +26 -1
  4. package/bundle/index.js +19159 -2228
  5. package/bundle/lib/base_protocol.js +2 -2
  6. package/bundle/lib/message/version_0.js +2 -2
  7. package/bundle/{version_0-74b4b9db.js → version_0-f4afd324.js} +33 -21
  8. package/dist/.tsbuildinfo +1 -1
  9. package/dist/lib/connection_manager.d.ts +15 -3
  10. package/dist/lib/connection_manager.js +83 -25
  11. package/dist/lib/connection_manager.js.map +1 -1
  12. package/dist/lib/filter/index.js +25 -20
  13. package/dist/lib/filter/index.js.map +1 -1
  14. package/dist/lib/keep_alive_manager.d.ts +1 -0
  15. package/dist/lib/keep_alive_manager.js +38 -14
  16. package/dist/lib/keep_alive_manager.js.map +1 -1
  17. package/dist/lib/light_push/index.js +49 -31
  18. package/dist/lib/light_push/index.js.map +1 -1
  19. package/dist/lib/light_push/push_rpc.d.ts +1 -1
  20. package/dist/lib/light_push/push_rpc.js +2 -2
  21. package/dist/lib/message/version_0.d.ts +13 -13
  22. package/dist/lib/message/version_0.js +19 -16
  23. package/dist/lib/message/version_0.js.map +1 -1
  24. package/dist/lib/store/history_rpc.d.ts +1 -1
  25. package/dist/lib/store/history_rpc.js +1 -1
  26. package/dist/lib/store/index.d.ts +1 -1
  27. package/dist/lib/store/index.js +37 -10
  28. package/dist/lib/store/index.js.map +1 -1
  29. package/dist/lib/stream_manager.d.ts +1 -1
  30. package/dist/lib/stream_manager.js +5 -2
  31. package/dist/lib/stream_manager.js.map +1 -1
  32. package/dist/lib/wait_for_remote_peer.d.ts +2 -2
  33. package/dist/lib/wait_for_remote_peer.js +10 -7
  34. package/dist/lib/wait_for_remote_peer.js.map +1 -1
  35. package/dist/lib/waku.d.ts +4 -3
  36. package/dist/lib/waku.js +5 -3
  37. package/dist/lib/waku.js.map +1 -1
  38. package/package.json +8 -18
  39. package/src/lib/connection_manager.ts +118 -31
  40. package/src/lib/filter/index.ts +36 -23
  41. package/src/lib/keep_alive_manager.ts +49 -16
  42. package/src/lib/light_push/index.ts +56 -31
  43. package/src/lib/light_push/push_rpc.ts +2 -2
  44. package/src/lib/message/version_0.ts +22 -13
  45. package/src/lib/store/history_rpc.ts +2 -2
  46. package/src/lib/store/index.ts +53 -14
  47. package/src/lib/stream_manager.ts +7 -4
  48. package/src/lib/wait_for_remote_peer.ts +10 -7
  49. package/src/lib/waku.ts +4 -1
  50. package/dist/lib/push_or_init_map.d.ts +0 -1
  51. package/dist/lib/push_or_init_map.js +0 -9
  52. package/dist/lib/push_or_init_map.js.map +0 -1
  53. package/src/lib/push_or_init_map.ts +0 -13
@@ -1,3 +1,4 @@
1
+ import type { Stream } from "@libp2p/interface/connection";
1
2
  import type { PeerId } from "@libp2p/interface/peer-id";
2
3
  import {
3
4
  IEncoder,
@@ -5,11 +6,12 @@ import {
5
6
  IMessage,
6
7
  Libp2p,
7
8
  ProtocolCreateOptions,
9
+ PubSubTopic,
8
10
  SendError,
9
11
  SendResult
10
12
  } from "@waku/interfaces";
11
13
  import { PushResponse } from "@waku/proto";
12
- import { isSizeValid } from "@waku/utils";
14
+ import { ensurePubsubTopicIsConfigured, isSizeValid } from "@waku/utils";
13
15
  import debug from "debug";
14
16
  import all from "it-all";
15
17
  import * as lp from "it-length-prefixed";
@@ -40,18 +42,18 @@ type PreparePushMessageResult =
40
42
  * Implements the [Waku v2 Light Push protocol](https://rfc.vac.dev/spec/19/).
41
43
  */
42
44
  class LightPush extends BaseProtocol implements ILightPush {
43
- options: ProtocolCreateOptions;
45
+ private readonly pubsubTopics: PubSubTopic[];
44
46
  private readonly NUM_PEERS_PROTOCOL = 1;
45
47
 
46
48
  constructor(libp2p: Libp2p, options?: ProtocolCreateOptions) {
47
49
  super(LightPushCodec, libp2p.components);
48
- this.options = options || {};
50
+ this.pubsubTopics = options?.pubsubTopics ?? [DefaultPubSubTopic];
49
51
  }
50
52
 
51
53
  private async preparePushMessage(
52
54
  encoder: IEncoder,
53
55
  message: IMessage,
54
- pubSubTopic: string
56
+ pubsubTopic: string
55
57
  ): Promise<PreparePushMessageResult> {
56
58
  try {
57
59
  if (!isSizeValid(message.payload)) {
@@ -68,7 +70,7 @@ class LightPush extends BaseProtocol implements ILightPush {
68
70
  };
69
71
  }
70
72
 
71
- const query = PushRpc.createRequest(protoMessage, pubSubTopic);
73
+ const query = PushRpc.createRequest(protoMessage, pubsubTopic);
72
74
  return { query, error: null };
73
75
  } catch (error) {
74
76
  log("Failed to prepare push message", error);
@@ -81,13 +83,15 @@ class LightPush extends BaseProtocol implements ILightPush {
81
83
  }
82
84
 
83
85
  async send(encoder: IEncoder, message: IMessage): Promise<SendResult> {
84
- const { pubSubTopic = DefaultPubSubTopic } = this.options;
86
+ const { pubsubTopic } = encoder;
87
+ ensurePubsubTopicIsConfigured(pubsubTopic, this.pubsubTopics);
88
+
85
89
  const recipients: PeerId[] = [];
86
90
 
87
91
  const { query, error: preparationError } = await this.preparePushMessage(
88
92
  encoder,
89
93
  message,
90
- pubSubTopic
94
+ pubsubTopic
91
95
  );
92
96
 
93
97
  if (preparationError || !query) {
@@ -97,48 +101,69 @@ class LightPush extends BaseProtocol implements ILightPush {
97
101
  };
98
102
  }
99
103
 
104
+ //TODO: get a relevant peer for the topic/shard
100
105
  const peers = await this.getPeers({
101
106
  maxBootstrapPeers: 1,
102
107
  numPeers: this.NUM_PEERS_PROTOCOL
103
108
  });
104
109
 
110
+ if (!peers.length) {
111
+ return {
112
+ recipients,
113
+ errors: [SendError.NO_PEER_AVAILABLE]
114
+ };
115
+ }
116
+
105
117
  const promises = peers.map(async (peer) => {
106
- let error: SendError | undefined;
107
- const stream = await this.getStream(peer);
118
+ let stream: Stream | undefined;
119
+ try {
120
+ stream = await this.getStream(peer);
121
+ } catch (err) {
122
+ log(`Failed to get a stream for remote peer${peer.id.toString()}`, err);
123
+ return { recipients, error: SendError.REMOTE_PEER_FAULT };
124
+ }
108
125
 
126
+ let res: Uint8ArrayList[] | undefined;
109
127
  try {
110
- const res = await pipe(
128
+ res = await pipe(
111
129
  [query.encode()],
112
130
  lp.encode,
113
131
  stream,
114
132
  lp.decode,
115
133
  async (source) => await all(source)
116
134
  );
117
- try {
118
- const bytes = new Uint8ArrayList();
119
- res.forEach((chunk) => {
120
- bytes.append(chunk);
121
- });
122
-
123
- const response = PushRpc.decode(bytes).response;
124
-
125
- if (response?.isSuccess) {
126
- recipients.some((recipient) => recipient.equals(peer.id)) ||
127
- recipients.push(peer.id);
128
- } else {
129
- log("No response in PushRPC");
130
- error = SendError.NO_RPC_RESPONSE;
131
- }
132
- } catch (err) {
133
- log("Failed to decode push reply", err);
134
- error = SendError.DECODE_FAILED;
135
- }
136
135
  } catch (err) {
137
136
  log("Failed to send waku light push request", err);
138
- error = SendError.GENERIC_FAIL;
137
+ return { recipients, error: SendError.GENERIC_FAIL };
139
138
  }
140
139
 
141
- return { recipients, error };
140
+ const bytes = new Uint8ArrayList();
141
+ res.forEach((chunk) => {
142
+ bytes.append(chunk);
143
+ });
144
+
145
+ let response: PushResponse | undefined;
146
+ try {
147
+ response = PushRpc.decode(bytes).response;
148
+ } catch (err) {
149
+ log("Failed to decode push reply", err);
150
+ return { recipients, error: SendError.DECODE_FAILED };
151
+ }
152
+
153
+ if (!response) {
154
+ log("Remote peer fault: No response in PushRPC");
155
+ return { recipients, error: SendError.REMOTE_PEER_FAULT };
156
+ }
157
+
158
+ if (!response.isSuccess) {
159
+ log("Remote peer rejected the message: ", response.info);
160
+ return { recipients, error: SendError.REMOTE_PEER_REJECTED };
161
+ }
162
+
163
+ recipients.some((recipient) => recipient.equals(peer.id)) ||
164
+ recipients.push(peer.id);
165
+
166
+ return { recipients };
142
167
  });
143
168
 
144
169
  const results = await Promise.allSettled(promises);
@@ -7,13 +7,13 @@ export class PushRpc {
7
7
 
8
8
  static createRequest(
9
9
  message: proto.WakuMessage,
10
- pubSubTopic: string
10
+ pubsubTopic: string
11
11
  ): PushRpc {
12
12
  return new PushRpc({
13
13
  requestId: uuid(),
14
14
  request: {
15
15
  message: message,
16
- pubsubTopic: pubSubTopic
16
+ pubsubTopic: pubsubTopic
17
17
  },
18
18
  response: undefined
19
19
  });
@@ -6,11 +6,14 @@ import type {
6
6
  IMessage,
7
7
  IMetaSetter,
8
8
  IProtoMessage,
9
- IRateLimitProof
9
+ IRateLimitProof,
10
+ PubSubTopic
10
11
  } from "@waku/interfaces";
11
12
  import { proto_message as proto } from "@waku/proto";
12
13
  import debug from "debug";
13
14
 
15
+ import { DefaultPubSubTopic } from "../constants.js";
16
+
14
17
  const log = debug("waku:message:version-0");
15
18
  const OneMillion = BigInt(1_000_000);
16
19
 
@@ -19,7 +22,7 @@ export { proto };
19
22
 
20
23
  export class DecodedMessage implements IDecodedMessage {
21
24
  constructor(
22
- public pubSubTopic: string,
25
+ public pubsubTopic: string,
23
26
  protected proto: proto.WakuMessage
24
27
  ) {}
25
28
 
@@ -73,6 +76,7 @@ export class Encoder implements IEncoder {
73
76
  constructor(
74
77
  public contentTopic: string,
75
78
  public ephemeral: boolean = false,
79
+ public pubsubTopic: PubSubTopic,
76
80
  public metaSetter?: IMetaSetter
77
81
  ) {
78
82
  if (!contentTopic || contentTopic === "") {
@@ -109,22 +113,25 @@ export class Encoder implements IEncoder {
109
113
  /**
110
114
  * Creates an encoder that encode messages without Waku level encryption or signature.
111
115
  *
112
- * An encoder is used to encode messages in the [`14/WAKU2-MESSAGE](https://rfc.vac.dev/spec/14/)
116
+ * An encoder is used to encode messages in the [14/WAKU2-MESSAGE](https://rfc.vac.dev/spec/14/)
113
117
  * format to be sent over the Waku network. The resulting encoder can then be
114
- * pass to { @link @waku/interfaces.LightPush.push } or
115
- * { @link @waku/interfaces.Relay.send } to automatically encode outgoing
118
+ * pass to { @link @waku/interfaces!ISender.send } to automatically encode outgoing
116
119
  * messages.
117
120
  */
118
121
  export function createEncoder({
122
+ pubsubTopic = DefaultPubSubTopic,
119
123
  contentTopic,
120
124
  ephemeral,
121
125
  metaSetter
122
126
  }: EncoderOptions): Encoder {
123
- return new Encoder(contentTopic, ephemeral, metaSetter);
127
+ return new Encoder(contentTopic, ephemeral, pubsubTopic, metaSetter);
124
128
  }
125
129
 
126
130
  export class Decoder implements IDecoder<DecodedMessage> {
127
- constructor(public contentTopic: string) {
131
+ constructor(
132
+ public pubsubTopic: PubSubTopic,
133
+ public contentTopic: string
134
+ ) {
128
135
  if (!contentTopic || contentTopic === "") {
129
136
  throw new Error("Content topic must be specified");
130
137
  }
@@ -145,7 +152,7 @@ export class Decoder implements IDecoder<DecodedMessage> {
145
152
  }
146
153
 
147
154
  async fromProtoObj(
148
- pubSubTopic: string,
155
+ pubsubTopic: string,
149
156
  proto: IProtoMessage
150
157
  ): Promise<DecodedMessage | undefined> {
151
158
  // https://rfc.vac.dev/spec/14/
@@ -160,7 +167,7 @@ export class Decoder implements IDecoder<DecodedMessage> {
160
167
  return Promise.resolve(undefined);
161
168
  }
162
169
 
163
- return new DecodedMessage(pubSubTopic, proto);
170
+ return new DecodedMessage(pubsubTopic, proto);
164
171
  }
165
172
  }
166
173
 
@@ -169,12 +176,14 @@ export class Decoder implements IDecoder<DecodedMessage> {
169
176
  *
170
177
  * A decoder is used to decode messages from the [14/WAKU2-MESSAGE](https://rfc.vac.dev/spec/14/)
171
178
  * format when received from the Waku network. The resulting decoder can then be
172
- * pass to { @link @waku/interfaces.Filter.subscribe } or
173
- * { @link @waku/interfaces.Relay.subscribe } to automatically decode incoming
179
+ * pass to { @link @waku/interfaces!IReceiver.subscribe } to automatically decode incoming
174
180
  * messages.
175
181
  *
176
182
  * @param contentTopic The resulting decoder will only decode messages with this content topic.
177
183
  */
178
- export function createDecoder(contentTopic: string): Decoder {
179
- return new Decoder(contentTopic);
184
+ export function createDecoder(
185
+ contentTopic: string,
186
+ pubsubTopic: PubSubTopic = DefaultPubSubTopic
187
+ ): Decoder {
188
+ return new Decoder(pubsubTopic, contentTopic);
180
189
  }
@@ -11,7 +11,7 @@ export enum PageDirection {
11
11
 
12
12
  export interface Params {
13
13
  contentTopics: string[];
14
- pubSubTopic: string;
14
+ pubsubTopic: string;
15
15
  pageDirection: PageDirection;
16
16
  pageSize: number;
17
17
  startTime?: Date;
@@ -59,7 +59,7 @@ export class HistoryRpc {
59
59
  return new HistoryRpc({
60
60
  requestId: uuid(),
61
61
  query: {
62
- pubsubTopic: params.pubSubTopic,
62
+ pubsubTopic: params.pubsubTopic,
63
63
  contentFilters,
64
64
  pagingInfo,
65
65
  startTime,
@@ -6,10 +6,11 @@ import {
6
6
  IDecoder,
7
7
  IStore,
8
8
  Libp2p,
9
- ProtocolCreateOptions
9
+ ProtocolCreateOptions,
10
+ PubSubTopic
10
11
  } from "@waku/interfaces";
11
12
  import { proto_store as proto } from "@waku/proto";
12
- import { isDefined } from "@waku/utils";
13
+ import { ensurePubsubTopicIsConfigured, isDefined } from "@waku/utils";
13
14
  import { concat, utf8ToBytes } from "@waku/utils/bytes";
14
15
  import debug from "debug";
15
16
  import all from "it-all";
@@ -74,12 +75,12 @@ export interface QueryOptions {
74
75
  * The Waku Store protocol can be used to retrieved historical messages.
75
76
  */
76
77
  class Store extends BaseProtocol implements IStore {
77
- options: ProtocolCreateOptions;
78
+ private readonly pubsubTopics: PubSubTopic[];
78
79
  private readonly NUM_PEERS_PROTOCOL = 1;
79
80
 
80
81
  constructor(libp2p: Libp2p, options?: ProtocolCreateOptions) {
81
82
  super(StoreCodec, libp2p.components);
82
- this.options = options ?? {};
83
+ this.pubsubTopics = options?.pubsubTopics ?? [DefaultPubSubTopic];
83
84
  }
84
85
 
85
86
  /**
@@ -206,12 +207,20 @@ class Store extends BaseProtocol implements IStore {
206
207
  * @throws If not able to reach a Waku Store peer to query,
207
208
  * or if an error is encountered when processing the reply,
208
209
  * or if two decoders with the same content topic are passed.
210
+ *
211
+ * This API only supports querying a single pubsub topic at a time.
212
+ * If multiple decoders are provided, they must all have the same pubsub topic.
213
+ * @throws If multiple decoders with different pubsub topics are provided.
214
+ * @throws If no decoders are provided.
215
+ * @throws If no decoders are found for the provided pubsub topic.
209
216
  */
210
217
  async *queryGenerator<T extends IDecodedMessage>(
211
218
  decoders: IDecoder<T>[],
212
219
  options?: QueryOptions
213
220
  ): AsyncGenerator<Promise<T | undefined>[]> {
214
- const { pubSubTopic = DefaultPubSubTopic } = this.options;
221
+ if (decoders.length === 0) {
222
+ throw new Error("No decoders provided");
223
+ }
215
224
 
216
225
  let startTime, endTime;
217
226
 
@@ -220,6 +229,33 @@ class Store extends BaseProtocol implements IStore {
220
229
  endTime = options.timeFilter.endTime;
221
230
  }
222
231
 
232
+ // convert array to set to remove duplicates
233
+ const uniquePubSubTopicsInQuery = Array.from(
234
+ new Set(decoders.map((decoder) => decoder.pubsubTopic))
235
+ );
236
+
237
+ // If multiple pubsub topics are provided, throw an error
238
+ if (uniquePubSubTopicsInQuery.length > 1) {
239
+ throw new Error(
240
+ "API does not support querying multiple pubsub topics at once"
241
+ );
242
+ }
243
+
244
+ // we can be certain that there is only one pubsub topic in the query
245
+ const pubSubTopicForQuery = uniquePubSubTopicsInQuery[0];
246
+
247
+ ensurePubsubTopicIsConfigured(pubSubTopicForQuery, this.pubsubTopics);
248
+
249
+ // check that the pubsubTopic from the Cursor and Decoder match
250
+ if (
251
+ options?.cursor?.pubsubTopic &&
252
+ options.cursor.pubsubTopic !== pubSubTopicForQuery
253
+ ) {
254
+ throw new Error(
255
+ `Cursor pubsub topic (${options?.cursor?.pubsubTopic}) does not match decoder pubsub topic (${pubSubTopicForQuery})`
256
+ );
257
+ }
258
+
223
259
  const decodersAsMap = new Map();
224
260
  decoders.forEach((dec) => {
225
261
  if (decodersAsMap.has(dec.contentTopic)) {
@@ -230,11 +266,17 @@ class Store extends BaseProtocol implements IStore {
230
266
  decodersAsMap.set(dec.contentTopic, dec);
231
267
  });
232
268
 
233
- const contentTopics = decoders.map((dec) => dec.contentTopic);
269
+ const contentTopics = decoders
270
+ .filter((decoder) => decoder.pubsubTopic === pubSubTopicForQuery)
271
+ .map((dec) => dec.contentTopic);
272
+
273
+ if (contentTopics.length === 0) {
274
+ throw new Error("No decoders found for topic " + pubSubTopicForQuery);
275
+ }
234
276
 
235
277
  const queryOpts = Object.assign(
236
278
  {
237
- pubSubTopic: pubSubTopic,
279
+ pubsubTopic: pubSubTopicForQuery,
238
280
  pageDirection: PageDirection.BACKWARD,
239
281
  pageSize: DefaultPageSize
240
282
  },
@@ -285,7 +327,7 @@ async function* paginate<T extends IDecodedMessage>(
285
327
 
286
328
  log(
287
329
  "Querying store peer",
288
- `for (${queryOpts.pubSubTopic})`,
330
+ `for (${queryOpts.pubsubTopic})`,
289
331
  queryOpts.contentTopics
290
332
  );
291
333
 
@@ -332,7 +374,7 @@ async function* paginate<T extends IDecodedMessage>(
332
374
  const decoder = decoders.get(contentTopic);
333
375
  if (decoder) {
334
376
  return decoder.fromProtoObj(
335
- queryOpts.pubSubTopic,
377
+ queryOpts.pubsubTopic,
336
378
  toProtoMessage(protoMsg)
337
379
  );
338
380
  }
@@ -365,10 +407,7 @@ async function* paginate<T extends IDecodedMessage>(
365
407
  }
366
408
  }
367
409
 
368
- export async function createCursor(
369
- message: IDecodedMessage,
370
- pubsubTopic: string = DefaultPubSubTopic
371
- ): Promise<Cursor> {
410
+ export async function createCursor(message: IDecodedMessage): Promise<Cursor> {
372
411
  if (
373
412
  !message ||
374
413
  !message.timestamp ||
@@ -386,7 +425,7 @@ export async function createCursor(
386
425
 
387
426
  return {
388
427
  digest,
389
- pubsubTopic,
428
+ pubsubTopic: message.pubsubTopic,
390
429
  senderTime: messageTime,
391
430
  receiverTime: messageTime
392
431
  };
@@ -6,8 +6,8 @@ import { selectConnection } from "@waku/utils/libp2p";
6
6
  import debug from "debug";
7
7
 
8
8
  export class StreamManager {
9
- private streamPool: Map<string, Promise<Stream>>;
10
- private log: debug.Debugger;
9
+ private streamPool: Map<string, Promise<Stream | void>>;
10
+ private readonly log: debug.Debugger;
11
11
 
12
12
  constructor(
13
13
  public multicodec: string,
@@ -38,7 +38,7 @@ export class StreamManager {
38
38
 
39
39
  const stream = await streamPromise;
40
40
 
41
- if (stream.status === "closed") {
41
+ if (!stream || stream.status === "closed") {
42
42
  return this.newStream(peer); // fallback by creating a new stream on the spot
43
43
  }
44
44
 
@@ -55,7 +55,10 @@ export class StreamManager {
55
55
  }
56
56
 
57
57
  private prepareNewStream(peer: Peer): void {
58
- const streamPromise = this.newStream(peer);
58
+ const streamPromise = this.newStream(peer).catch(() => {
59
+ // No error thrown as this call is not triggered by the user
60
+ this.log(`Failed to prepare a new stream for ${peer.id.toString()}`);
61
+ });
59
62
  this.streamPool.set(peer.id.toString(), streamPromise);
60
63
  }
61
64
 
@@ -9,8 +9,8 @@ const log = debug("waku:wait-for-remote-peer");
9
9
  /**
10
10
  * Wait for a remote peer to be ready given the passed protocols.
11
11
  * Must be used after attempting to connect to nodes, using
12
- * {@link @waku/core.WakuNode.dial} or a bootstrap method with
13
- * {@link @waku/sdk.createLightNode}.
12
+ * {@link @waku/core!WakuNode.dial} or a bootstrap method with
13
+ * {@link @waku/sdk!createLightNode}.
14
14
  *
15
15
  * If the passed protocols is a GossipSub protocol, then it resolves only once
16
16
  * a peer is in a mesh, to help ensure that other peers will send and receive
@@ -96,15 +96,18 @@ async function waitForConnectedPeer(protocol: IBaseProtocol): Promise<void> {
96
96
  }
97
97
 
98
98
  /**
99
- * Wait for a peer with the given protocol to be connected and in the gossipsub
100
- * mesh.
99
+ * Wait for at least one peer with the given protocol to be connected and in the gossipsub
100
+ * mesh for all pubsubTopics.
101
101
  */
102
102
  async function waitForGossipSubPeerInMesh(waku: IRelay): Promise<void> {
103
103
  let peers = waku.getMeshPeers();
104
+ const pubsubTopics = waku.pubsubTopics;
104
105
 
105
- while (peers.length == 0) {
106
- await pEvent(waku.gossipSub, "gossipsub:heartbeat");
107
- peers = waku.getMeshPeers();
106
+ for (const topic of pubsubTopics) {
107
+ while (peers.length == 0) {
108
+ await pEvent(waku.gossipSub, "gossipsub:heartbeat");
109
+ peers = waku.getMeshPeers(topic);
110
+ }
108
111
  }
109
112
  }
110
113
 
package/src/lib/waku.ts CHANGED
@@ -7,6 +7,7 @@ import type {
7
7
  IRelay,
8
8
  IStore,
9
9
  Libp2p,
10
+ PubSubTopic,
10
11
  Waku
11
12
  } from "@waku/interfaces";
12
13
  import { Protocols } from "@waku/interfaces";
@@ -14,7 +15,7 @@ import debug from "debug";
14
15
 
15
16
  import { ConnectionManager } from "./connection_manager.js";
16
17
 
17
- export const DefaultPingKeepAliveValueSecs = 0;
18
+ export const DefaultPingKeepAliveValueSecs = 5 * 60;
18
19
  export const DefaultRelayKeepAliveValueSecs = 5 * 60;
19
20
  export const DefaultUserAgent = "js-waku";
20
21
 
@@ -52,6 +53,7 @@ export class WakuNode implements Waku {
52
53
 
53
54
  constructor(
54
55
  options: WakuOptions,
56
+ public readonly pubsubTopics: PubSubTopic[],
55
57
  libp2p: Libp2p,
56
58
  store?: (libp2p: Libp2p) => IStore,
57
59
  lightPush?: (libp2p: Libp2p) => ILightPush,
@@ -86,6 +88,7 @@ export class WakuNode implements Waku {
86
88
  peerId,
87
89
  libp2p,
88
90
  { pingKeepAlive, relayKeepAlive },
91
+ pubsubTopics,
89
92
  this.relay
90
93
  );
91
94
 
@@ -1 +0,0 @@
1
- export declare function pushOrInitMapSet<K, V>(map: Map<K, Set<V>>, key: K, newValue: V): void;
@@ -1,9 +0,0 @@
1
- export function pushOrInitMapSet(map, key, newValue) {
2
- let arr = map.get(key);
3
- if (typeof arr === "undefined") {
4
- map.set(key, new Set());
5
- arr = map.get(key);
6
- }
7
- arr.add(newValue);
8
- }
9
- //# sourceMappingURL=push_or_init_map.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"push_or_init_map.js","sourceRoot":"","sources":["../../src/lib/push_or_init_map.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,gBAAgB,CAC9B,GAAmB,EACnB,GAAM,EACN,QAAW;IAEX,IAAI,GAAG,GAAG,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACvB,IAAI,OAAO,GAAG,KAAK,WAAW,EAAE;QAC9B,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,GAAG,EAAE,CAAC,CAAC;QACxB,GAAG,GAAG,GAAG,CAAC,GAAG,CAAC,GAAG,CAAW,CAAC;KAC9B;IAED,GAAG,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;AACpB,CAAC"}
@@ -1,13 +0,0 @@
1
- export function pushOrInitMapSet<K, V>(
2
- map: Map<K, Set<V>>,
3
- key: K,
4
- newValue: V
5
- ): void {
6
- let arr = map.get(key);
7
- if (typeof arr === "undefined") {
8
- map.set(key, new Set());
9
- arr = map.get(key) as Set<V>;
10
- }
11
-
12
- arr.add(newValue);
13
- }