@waku/core 0.0.15 → 0.0.17

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.
@@ -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.15",
3
+ "version": "0.0.17",
4
4
  "description": "TypeScript implementation of the Waku v2 protocol",
5
5
  "types": "./dist/index.d.ts",
6
6
  "module": "./dist/index.js",
@@ -56,17 +56,11 @@
56
56
  "build:esm": "tsc",
57
57
  "build:bundle": "rollup --config rollup.config.js",
58
58
  "fix": "run-s fix:*",
59
- "fix:prettier": "prettier . --write",
60
59
  "fix:lint": "eslint src *.js --fix",
61
60
  "pretest": "run-s pretest:*",
62
- "pretest:1-init-git-submodules": "[ -f '../../nwaku/build/wakunode2' ] || git submodule update --init --recursive",
63
- "pretest:2-build-nwaku": "[ -f '../../nwaku/build/wakunode2' ] || run-s nwaku:build",
64
- "nwaku:build": "(PROC=$(nproc --all 2>/dev/null || echo 2); cd ../../nwaku; make -j$PROC update; NIMFLAGS=\"-d:chronicles_colors=off -d:chronicles_sinks=textlines -d:chronicles_log_level=TRACE\" make -j$PROC wakunode2)",
65
- "nwaku:force-build": "(cd ../../nwaku && rm -rf ./build/ ./vendor) && run-s nwaku:build",
66
61
  "check": "run-s check:*",
67
62
  "check:tsc": "tsc -p tsconfig.dev.json",
68
63
  "check:lint": "eslint src *.js",
69
- "check:prettier": "prettier . --list-different",
70
64
  "check:spelling": "cspell \"{README.md,src/**/*.ts}\"",
71
65
  "test": "run-s test:*",
72
66
  "test:node": "TS_NODE_PROJECT=./tsconfig.dev.json mocha",
@@ -81,13 +75,14 @@
81
75
  },
82
76
  "dependencies": {
83
77
  "@chainsafe/libp2p-gossipsub": "^6.1.0",
78
+ "@libp2p/interface-pubsub": "^3.0.7",
84
79
  "@noble/hashes": "^1.3.0",
85
- "@waku/interfaces": "0.0.10",
80
+ "@waku/interfaces": "0.0.12",
86
81
  "@waku/proto": "0.0.4",
87
- "@waku/utils": "0.0.3",
82
+ "@waku/utils": "0.0.5",
88
83
  "debug": "^4.3.4",
89
- "it-all": "^2.0.0",
90
- "it-length-prefixed": "^8.0.4",
84
+ "it-all": "^3.0.1",
85
+ "it-length-prefixed": "^9.0.1",
91
86
  "it-pipe": "^2.0.5",
92
87
  "p-event": "^5.0.1",
93
88
  "uint8arraylist": "^2.4.3",
@@ -98,12 +93,11 @@
98
93
  "@libp2p/interface-libp2p": "^1.1.2",
99
94
  "@libp2p/interface-peer-id": "^2.0.1",
100
95
  "@libp2p/interface-peer-store": "^1.2.8",
101
- "@libp2p/interface-pubsub": "^3.0.6",
102
96
  "@libp2p/interface-registrar": "^2.0.8",
103
97
  "@multiformats/multiaddr": "^12.0.0",
104
98
  "@rollup/plugin-commonjs": "^24.0.1",
105
99
  "@rollup/plugin-json": "^6.0.0",
106
- "@rollup/plugin-node-resolve": "^15.0.1",
100
+ "@rollup/plugin-node-resolve": "^15.0.2",
107
101
  "@types/chai": "^4.3.4",
108
102
  "@types/debug": "^4.1.7",
109
103
  "@types/mocha": "^10.0.1",
@@ -119,7 +113,7 @@
119
113
  "eslint-plugin-functional": "^5.0.4",
120
114
  "eslint-plugin-import": "^2.27.5",
121
115
  "eslint-plugin-prettier": "^4.2.1",
122
- "fast-check": "^3.7.1",
116
+ "fast-check": "^3.8.1",
123
117
  "ignore-loader": "^0.1.2",
124
118
  "isomorphic-fetch": "^3.0.0",
125
119
  "karma": "^6.4.1",
@@ -128,10 +122,10 @@
128
122
  "karma-webpack": "^5.0.0",
129
123
  "mocha": "^10.2.0",
130
124
  "npm-run-all": "^4.1.5",
131
- "prettier": "^2.8.4",
125
+ "prettier": "^2.8.8",
132
126
  "process": "^0.11.10",
133
127
  "puppeteer": "^19.8.2",
134
- "rollup": "^3.15.0",
128
+ "rollup": "^3.21.3",
135
129
  "ts-loader": "^9.4.2",
136
130
  "ts-node": "^10.9.1",
137
131
  "typescript": "^4.9.5"
package/src/index.ts CHANGED
@@ -19,7 +19,11 @@ export * as waku_light_push from "./lib/light_push/index.js";
19
19
  export { wakuLightPush, LightPushCodec } from "./lib/light_push/index.js";
20
20
 
21
21
  export * as waku_relay from "./lib/relay/index.js";
22
- export { wakuRelay, RelayCreateOptions } from "./lib/relay/index.js";
22
+ export {
23
+ wakuRelay,
24
+ RelayCreateOptions,
25
+ wakuGossipSub,
26
+ } from "./lib/relay/index.js";
23
27
 
24
28
  export * as waku_store from "./lib/store/index.js";
25
29
  export {
@@ -2,7 +2,9 @@ import type { Libp2p } from "@libp2p/interface-libp2p";
2
2
  import type { Peer } from "@libp2p/interface-peer-store";
3
3
  import type { IncomingStreamData } from "@libp2p/interface-registrar";
4
4
  import type {
5
+ ActiveSubscriptions,
5
6
  Callback,
7
+ IAsyncIterator,
6
8
  IDecodedMessage,
7
9
  IDecoder,
8
10
  IFilter,
@@ -10,6 +12,7 @@ import type {
10
12
  ProtocolOptions,
11
13
  } from "@waku/interfaces";
12
14
  import { WakuMessage as WakuMessageProto } from "@waku/proto";
15
+ import { toAsyncIterator } from "@waku/utils";
13
16
  import debug from "debug";
14
17
  import all from "it-all";
15
18
  import * as lp from "it-length-prefixed";
@@ -58,19 +61,20 @@ class Filter extends BaseProtocol implements IFilter {
58
61
  }
59
62
 
60
63
  /**
61
- * @param decoders Array of Decoders to use to decode messages, it also specifies the content topics.
64
+ * @param decoders Decoder or array of Decoders to use to decode messages, it also specifies the content topics.
62
65
  * @param callback A function that will be called on each message returned by the filter.
63
66
  * @param opts The FilterSubscriptionOpts used to narrow which messages are returned, and which peer to connect to.
64
67
  * @returns Unsubscribe function that can be used to end the subscription.
65
68
  */
66
69
  async subscribe<T extends IDecodedMessage>(
67
- decoders: IDecoder<T>[],
70
+ decoders: IDecoder<T> | IDecoder<T>[],
68
71
  callback: Callback<T>,
69
72
  opts?: ProtocolOptions
70
73
  ): Promise<UnsubscribeFunction> {
74
+ const decodersArray = Array.isArray(decoders) ? decoders : [decoders];
71
75
  const { pubSubTopic = DefaultPubSubTopic } = this.options;
72
76
 
73
- const contentTopics = Array.from(groupByContentTopic(decoders).keys());
77
+ const contentTopics = Array.from(groupByContentTopic(decodersArray).keys());
74
78
 
75
79
  const contentFilters = contentTopics.map((contentTopic) => ({
76
80
  contentTopic,
@@ -90,9 +94,9 @@ class Filter extends BaseProtocol implements IFilter {
90
94
  try {
91
95
  const res = await pipe(
92
96
  [request.encode()],
93
- lp.encode(),
97
+ lp.encode,
94
98
  stream,
95
- lp.decode(),
99
+ lp.decode,
96
100
  async (source) => await all(source)
97
101
  );
98
102
 
@@ -109,7 +113,11 @@ class Filter extends BaseProtocol implements IFilter {
109
113
  throw e;
110
114
  }
111
115
 
112
- const subscription: Subscription<T> = { callback, decoders, pubSubTopic };
116
+ const subscription: Subscription<T> = {
117
+ callback,
118
+ decoders: decodersArray,
119
+ pubSubTopic,
120
+ };
113
121
  this.subscriptions.set(requestId, subscription);
114
122
 
115
123
  return async () => {
@@ -118,10 +126,33 @@ class Filter extends BaseProtocol implements IFilter {
118
126
  };
119
127
  }
120
128
 
129
+ public toSubscriptionIterator<T extends IDecodedMessage>(
130
+ decoders: IDecoder<T> | IDecoder<T>[],
131
+ opts?: ProtocolOptions | undefined
132
+ ): Promise<IAsyncIterator<T>> {
133
+ return toAsyncIterator(this, decoders, opts);
134
+ }
135
+
136
+ public getActiveSubscriptions(): ActiveSubscriptions {
137
+ const map: ActiveSubscriptions = new Map();
138
+ const subscriptions = this.subscriptions as Map<
139
+ RequestID,
140
+ Subscription<IDecodedMessage>
141
+ >;
142
+
143
+ for (const item of subscriptions.values()) {
144
+ const values = map.get(item.pubSubTopic) || [];
145
+ const nextValues = item.decoders.map((decoder) => decoder.contentTopic);
146
+ map.set(item.pubSubTopic, [...values, ...nextValues]);
147
+ }
148
+
149
+ return map;
150
+ }
151
+
121
152
  private onRequest(streamData: IncomingStreamData): void {
122
153
  log("Receiving message push");
123
154
  try {
124
- pipe(streamData.stream, lp.decode(), async (source) => {
155
+ pipe(streamData.stream, lp.decode, async (source) => {
125
156
  for await (const bytes of source) {
126
157
  const res = FilterRpc.decode(bytes.slice());
127
158
  if (res.requestId && res.push?.messages?.length) {
@@ -203,7 +234,7 @@ class Filter extends BaseProtocol implements IFilter {
203
234
 
204
235
  const stream = await this.newStream(peer);
205
236
  try {
206
- await pipe([unsubscribeRequest.encode()], lp.encode(), stream.sink);
237
+ await pipe([unsubscribeRequest.encode()], lp.encode, stream.sink);
207
238
  } catch (e) {
208
239
  log("Error unsubscribing", e);
209
240
  throw e;
@@ -57,9 +57,9 @@ class LightPush extends BaseProtocol implements ILightPush {
57
57
  const query = PushRpc.createRequest(protoMessage, pubSubTopic);
58
58
  const res = await pipe(
59
59
  [query.encode()],
60
- lp.encode(),
60
+ lp.encode,
61
61
  stream,
62
- lp.decode(),
62
+ lp.decode,
63
63
  async (source) => await all(source)
64
64
  );
65
65
  try {
@@ -71,7 +71,11 @@ export class Encoder implements IEncoder {
71
71
  public contentTopic: string,
72
72
  public ephemeral: boolean = false,
73
73
  public metaSetter?: IMetaSetter
74
- ) {}
74
+ ) {
75
+ if (!contentTopic || contentTopic === "") {
76
+ throw new Error("Content topic must be specified");
77
+ }
78
+ }
75
79
 
76
80
  async toWire(message: IMessage): Promise<Uint8Array> {
77
81
  return proto.WakuMessage.encode(await this.toProtoObj(message));
@@ -117,7 +121,11 @@ export function createEncoder({
117
121
  }
118
122
 
119
123
  export class Decoder implements IDecoder<DecodedMessage> {
120
- constructor(public contentTopic: string) {}
124
+ constructor(public contentTopic: string) {
125
+ if (!contentTopic || contentTopic === "") {
126
+ throw new Error("Content topic must be specified");
127
+ }
128
+ }
121
129
 
122
130
  fromWireToProtoObj(bytes: Uint8Array): Promise<IProtoMessage | undefined> {
123
131
  const protoMessage = proto.WakuMessage.decode(bytes);
@@ -6,22 +6,28 @@ import {
6
6
  } from "@chainsafe/libp2p-gossipsub";
7
7
  import type { PeerIdStr, TopicStr } from "@chainsafe/libp2p-gossipsub/types";
8
8
  import { SignaturePolicy } from "@chainsafe/libp2p-gossipsub/types";
9
+ import type { Libp2p } from "@libp2p/interface-libp2p";
10
+ import type { PubSub } from "@libp2p/interface-pubsub";
11
+ import { sha256 } from "@noble/hashes/sha256";
9
12
  import type {
10
13
  ActiveSubscriptions,
11
14
  Callback,
15
+ IAsyncIterator,
12
16
  IDecodedMessage,
13
17
  IDecoder,
14
18
  IEncoder,
15
19
  IMessage,
16
20
  IRelay,
17
21
  ProtocolCreateOptions,
22
+ ProtocolOptions,
18
23
  SendResult,
19
24
  } from "@waku/interfaces";
25
+ import { toAsyncIterator } from "@waku/utils";
20
26
  import debug from "debug";
21
27
 
22
28
  import { DefaultPubSubTopic } from "../constants.js";
29
+ import { groupByContentTopic } from "../group_by.js";
23
30
  import { TopicOnlyDecoder } from "../message/topic_only_message.js";
24
- import { pushOrInitMapSet } from "../push_or_init_map.js";
25
31
 
26
32
  import * as constants from "./constants.js";
27
33
  import { messageValidator } from "./message_validator.js";
@@ -38,14 +44,14 @@ export type ContentTopic = string;
38
44
 
39
45
  /**
40
46
  * Implements the [Waku v2 Relay protocol](https://rfc.vac.dev/spec/11/).
41
- * Must be passed as a `pubsub` module to a `Libp2p` instance.
42
- *
43
- * @implements {require('libp2p-interfaces/src/pubsub')}
47
+ * Throws if libp2p.pubsub does not support Waku Relay
44
48
  */
45
- class Relay extends GossipSub implements IRelay {
49
+ class Relay implements IRelay {
46
50
  private readonly pubSubTopic: string;
47
- defaultDecoder: IDecoder<IDecodedMessage>;
51
+ private defaultDecoder: IDecoder<IDecodedMessage>;
52
+
48
53
  public static multicodec: string = constants.RelayCodecs[0];
54
+ public readonly gossipSub: GossipSub;
49
55
 
50
56
  /**
51
57
  * observers called when receiving new message.
@@ -53,21 +59,20 @@ class Relay extends GossipSub implements IRelay {
53
59
  */
54
60
  private observers: Map<ContentTopic, Set<unknown>>;
55
61
 
56
- constructor(
57
- components: GossipSubComponents,
58
- options?: Partial<RelayCreateOptions>
59
- ) {
60
- options = Object.assign(options ?? {}, {
61
- // Ensure that no signature is included nor expected in the messages.
62
- globalSignaturePolicy: SignaturePolicy.StrictNoSign,
63
- fallbackToFloodsub: false,
64
- });
65
-
66
- super(components, options);
67
- this.multicodecs = constants.RelayCodecs;
62
+ constructor(libp2p: Libp2p, options?: Partial<RelayCreateOptions>) {
63
+ if (!this.isRelayPubSub(libp2p.pubsub)) {
64
+ throw Error(
65
+ `Failed to initialize Relay. libp2p.pubsub does not support ${Relay.multicodec}`
66
+ );
67
+ }
68
68
 
69
+ this.gossipSub = libp2p.pubsub as GossipSub;
69
70
  this.pubSubTopic = options?.pubSubTopic ?? DefaultPubSubTopic;
70
71
 
72
+ if (this.gossipSub.isStarted()) {
73
+ this.gossipSubSubscribe(this.pubSubTopic);
74
+ }
75
+
71
76
  this.observers = new Map();
72
77
 
73
78
  // TODO: User might want to decide what decoder should be used (e.g. for RLN)
@@ -82,8 +87,12 @@ class Relay extends GossipSub implements IRelay {
82
87
  * @returns {void}
83
88
  */
84
89
  public async start(): Promise<void> {
85
- await super.start();
86
- this.subscribe(this.pubSubTopic);
90
+ if (this.gossipSub.isStarted()) {
91
+ throw Error("GossipSub already started.");
92
+ }
93
+
94
+ await this.gossipSub.start();
95
+ this.gossipSubSubscribe(this.pubSubTopic);
87
96
  }
88
97
 
89
98
  /**
@@ -96,7 +105,7 @@ class Relay extends GossipSub implements IRelay {
96
105
  return { recipients: [] };
97
106
  }
98
107
 
99
- return this.publish(this.pubSubTopic, msg);
108
+ return this.gossipSub.publish(this.pubSubTopic, msg);
100
109
  }
101
110
 
102
111
  /**
@@ -104,32 +113,59 @@ class Relay extends GossipSub implements IRelay {
104
113
  *
105
114
  * @returns Function to delete the observer
106
115
  */
107
- addObserver<T extends IDecodedMessage>(
108
- decoder: IDecoder<T>,
116
+ public subscribe<T extends IDecodedMessage>(
117
+ decoders: IDecoder<T> | IDecoder<T>[],
109
118
  callback: Callback<T>
110
119
  ): () => void {
111
- const observer = {
112
- decoder,
113
- callback,
114
- };
115
- const contentTopic = decoder.contentTopic;
120
+ const contentTopicToObservers = Array.isArray(decoders)
121
+ ? toObservers(decoders, callback)
122
+ : toObservers([decoders], callback);
116
123
 
117
- pushOrInitMapSet(this.observers, contentTopic, observer);
124
+ for (const contentTopic of contentTopicToObservers.keys()) {
125
+ const currObservers = this.observers.get(contentTopic) || new Set();
126
+ const newObservers =
127
+ contentTopicToObservers.get(contentTopic) || new Set();
128
+
129
+ this.observers.set(contentTopic, union(currObservers, newObservers));
130
+ }
118
131
 
119
132
  return () => {
120
- const observers = this.observers.get(contentTopic);
121
- if (observers) {
122
- observers.delete(observer);
133
+ for (const contentTopic of contentTopicToObservers.keys()) {
134
+ const currentObservers = this.observers.get(contentTopic) || new Set();
135
+ const observersToRemove =
136
+ contentTopicToObservers.get(contentTopic) || new Set();
137
+
138
+ const nextObservers = leftMinusJoin(
139
+ currentObservers,
140
+ observersToRemove
141
+ );
142
+
143
+ if (nextObservers.size) {
144
+ this.observers.set(contentTopic, nextObservers);
145
+ } else {
146
+ this.observers.delete(contentTopic);
147
+ }
123
148
  }
124
149
  };
125
150
  }
126
151
 
152
+ public toSubscriptionIterator<T extends IDecodedMessage>(
153
+ decoders: IDecoder<T> | IDecoder<T>[],
154
+ opts?: ProtocolOptions | undefined
155
+ ): Promise<IAsyncIterator<T>> {
156
+ return toAsyncIterator(this, decoders, opts);
157
+ }
158
+
127
159
  public getActiveSubscriptions(): ActiveSubscriptions {
128
160
  const map = new Map();
129
161
  map.set(this.pubSubTopic, this.observers.keys());
130
162
  return map;
131
163
  }
132
164
 
165
+ public getMeshPeers(topic?: TopicStr): PeerIdStr[] {
166
+ return this.gossipSub.getMeshPeers(topic ?? this.pubSubTopic);
167
+ }
168
+
133
169
  private async processIncomingMessage<T extends IDecodedMessage>(
134
170
  pubSubTopic: string,
135
171
  bytes: Uint8Array
@@ -168,8 +204,8 @@ class Relay extends GossipSub implements IRelay {
168
204
  *
169
205
  * @override
170
206
  */
171
- subscribe(pubSubTopic: string): void {
172
- this.addEventListener(
207
+ private gossipSubSubscribe(pubSubTopic: string): void {
208
+ this.gossipSub.addEventListener(
173
209
  "gossipsub:message",
174
210
  async (event: CustomEvent<GossipsubMessage>) => {
175
211
  if (event.detail.msg.topic !== pubSubTopic) return;
@@ -182,24 +218,77 @@ class Relay extends GossipSub implements IRelay {
182
218
  }
183
219
  );
184
220
 
185
- this.topicValidators.set(pubSubTopic, messageValidator);
186
- super.subscribe(pubSubTopic);
221
+ this.gossipSub.topicValidators.set(pubSubTopic, messageValidator);
222
+ this.gossipSub.subscribe(pubSubTopic);
187
223
  }
188
224
 
189
- unsubscribe(pubSubTopic: TopicStr): void {
190
- super.unsubscribe(pubSubTopic);
191
- this.topicValidators.delete(pubSubTopic);
192
- }
193
-
194
- getMeshPeers(topic?: TopicStr): PeerIdStr[] {
195
- return super.getMeshPeers(topic ?? this.pubSubTopic);
225
+ private isRelayPubSub(pubsub: PubSub): boolean {
226
+ return pubsub?.multicodecs?.includes(Relay.multicodec) || false;
196
227
  }
197
228
  }
198
229
 
199
- Relay.multicodec = constants.RelayCodecs[constants.RelayCodecs.length - 1];
200
-
201
230
  export function wakuRelay(
231
+ init: Partial<ProtocolCreateOptions> = {}
232
+ ): (libp2p: Libp2p) => IRelay {
233
+ return (libp2p: Libp2p) => new Relay(libp2p, init);
234
+ }
235
+
236
+ export function wakuGossipSub(
202
237
  init: Partial<RelayCreateOptions> = {}
203
- ): (components: GossipSubComponents) => IRelay {
204
- return (components: GossipSubComponents) => new Relay(components, init);
238
+ ): (components: GossipSubComponents) => GossipSub {
239
+ return (components: GossipSubComponents) => {
240
+ init = {
241
+ ...init,
242
+ msgIdFn: ({ data }) => sha256(data),
243
+ // Ensure that no signature is included nor expected in the messages.
244
+ globalSignaturePolicy: SignaturePolicy.StrictNoSign,
245
+ fallbackToFloodsub: false,
246
+ };
247
+ const pubsub = new GossipSub(components, init);
248
+ pubsub.multicodecs = constants.RelayCodecs;
249
+ return pubsub;
250
+ };
251
+ }
252
+
253
+ function toObservers<T extends IDecodedMessage>(
254
+ decoders: IDecoder<T>[],
255
+ callback: Callback<T>
256
+ ): Map<ContentTopic, Set<Observer<T>>> {
257
+ const contentTopicToDecoders = Array.from(
258
+ groupByContentTopic(decoders).entries()
259
+ );
260
+
261
+ const contentTopicToObserversEntries = contentTopicToDecoders.map(
262
+ ([contentTopic, decoders]) =>
263
+ [
264
+ contentTopic,
265
+ new Set(
266
+ decoders.map(
267
+ (decoder) =>
268
+ ({
269
+ decoder,
270
+ callback,
271
+ } as Observer<T>)
272
+ )
273
+ ),
274
+ ] as [ContentTopic, Set<Observer<T>>]
275
+ );
276
+
277
+ return new Map(contentTopicToObserversEntries);
278
+ }
279
+
280
+ function union(left: Set<unknown>, right: Set<unknown>): Set<unknown> {
281
+ for (const val of right.values()) {
282
+ left.add(val);
283
+ }
284
+ return left;
285
+ }
286
+
287
+ function leftMinusJoin(left: Set<unknown>, right: Set<unknown>): Set<unknown> {
288
+ for (const val of right.values()) {
289
+ if (left.has(val)) {
290
+ left.delete(val);
291
+ }
292
+ }
293
+ return left;
205
294
  }
@@ -274,9 +274,9 @@ async function* paginate<T extends IDecodedMessage>(
274
274
 
275
275
  const res = await pipe(
276
276
  [historyRpcQuery.encode()],
277
- lp.encode(),
277
+ lp.encode,
278
278
  stream,
279
- lp.decode(),
279
+ lp.decode,
280
280
  async (source) => await all(source)
281
281
  );
282
282
 
@@ -105,7 +105,7 @@ async function waitForGossipSubPeerInMesh(waku: IRelay): Promise<void> {
105
105
  let peers = waku.getMeshPeers();
106
106
 
107
107
  while (peers.length == 0) {
108
- await pEvent(waku, "gossipsub:heartbeat");
108
+ await pEvent(waku.gossipSub, "gossipsub:heartbeat");
109
109
  peers = waku.getMeshPeers();
110
110
  }
111
111
  }
package/src/lib/waku.ts CHANGED
@@ -1,8 +1,9 @@
1
1
  import type { Stream } from "@libp2p/interface-connection";
2
2
  import type { Libp2p } from "@libp2p/interface-libp2p";
3
3
  import type { PeerId } from "@libp2p/interface-peer-id";
4
- import type { PubSub } from "@libp2p/interface-pubsub";
5
- import type { Multiaddr } from "@multiformats/multiaddr";
4
+ import { isPeerId } from "@libp2p/interface-peer-id";
5
+ import type { Multiaddr, MultiaddrInput } from "@multiformats/multiaddr";
6
+ import { multiaddr } from "@multiformats/multiaddr";
6
7
  import type {
7
8
  IFilter,
8
9
  ILightPush,
@@ -14,7 +15,6 @@ import { Protocols } from "@waku/interfaces";
14
15
  import debug from "debug";
15
16
 
16
17
  import { ConnectionManager } from "./connection_manager.js";
17
- import * as relayConstants from "./relay/constants.js";
18
18
 
19
19
  export const DefaultPingKeepAliveValueSecs = 0;
20
20
  export const DefaultRelayKeepAliveValueSecs = 5 * 60;
@@ -57,7 +57,8 @@ export class WakuNode implements Waku {
57
57
  libp2p: Libp2p,
58
58
  store?: (libp2p: Libp2p) => IStore,
59
59
  lightPush?: (libp2p: Libp2p) => ILightPush,
60
- filter?: (libp2p: Libp2p) => IFilter
60
+ filter?: (libp2p: Libp2p) => IFilter,
61
+ relay?: (libp2p: Libp2p) => IRelay
61
62
  ) {
62
63
  this.libp2p = libp2p;
63
64
 
@@ -71,8 +72,8 @@ export class WakuNode implements Waku {
71
72
  this.lightPush = lightPush(libp2p);
72
73
  }
73
74
 
74
- if (isRelay(libp2p.pubsub)) {
75
- this.relay = libp2p.pubsub;
75
+ if (relay) {
76
+ this.relay = relay(libp2p);
76
77
  }
77
78
 
78
79
  const pingKeepAlive =
@@ -105,10 +106,11 @@ export class WakuNode implements Waku {
105
106
  * @param protocols Waku protocols we expect from the peer; Defaults to mounted protocols
106
107
  */
107
108
  async dial(
108
- peer: PeerId | Multiaddr,
109
+ peer: PeerId | MultiaddrInput,
109
110
  protocols?: Protocols[]
110
111
  ): Promise<Stream> {
111
112
  const _protocols = protocols ?? [];
113
+ const peerId = mapToPeerIdOrMultiaddr(peer);
112
114
 
113
115
  if (typeof protocols === "undefined") {
114
116
  this.relay && _protocols.push(Protocols.Relay);
@@ -120,7 +122,9 @@ export class WakuNode implements Waku {
120
122
  const codecs: string[] = [];
121
123
  if (_protocols.includes(Protocols.Relay)) {
122
124
  if (this.relay) {
123
- this.relay.multicodecs.forEach((codec) => codecs.push(codec));
125
+ this.relay.gossipSub.multicodecs.forEach((codec: string) =>
126
+ codecs.push(codec)
127
+ );
124
128
  } else {
125
129
  log(
126
130
  "Relay codec not included in dial codec: protocol not mounted locally"
@@ -155,9 +159,9 @@ export class WakuNode implements Waku {
155
159
  }
156
160
  }
157
161
 
158
- log(`Dialing to ${peer.toString()} with protocols ${_protocols}`);
162
+ log(`Dialing to ${peerId.toString()} with protocols ${_protocols}`);
159
163
 
160
- return this.libp2p.dialProtocol(peer, codecs);
164
+ return this.libp2p.dialProtocol(peerId, codecs);
161
165
  }
162
166
 
163
167
  async start(): Promise<void> {
@@ -189,15 +193,8 @@ export class WakuNode implements Waku {
189
193
  }
190
194
  }
191
195
 
192
- function isRelay(pubsub: PubSub): pubsub is IRelay {
193
- if (pubsub) {
194
- try {
195
- return pubsub.multicodecs.includes(
196
- relayConstants.RelayCodecs[relayConstants.RelayCodecs.length - 1]
197
- );
198
- // Exception is expected if `libp2p` was not instantiated with pubsub
199
- // eslint-disable-next-line no-empty
200
- } catch (e) {}
201
- }
202
- return false;
196
+ function mapToPeerIdOrMultiaddr(
197
+ peerId: PeerId | MultiaddrInput
198
+ ): PeerId | Multiaddr {
199
+ return isPeerId(peerId) ? peerId : multiaddr(peerId);
203
200
  }