@waku/core 0.0.22 → 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 (73) hide show
  1. package/CHANGELOG.md +61 -0
  2. package/bundle/base_protocol-2a0c882e.js +1250 -0
  3. package/bundle/{browser-bde977a3.js → browser-90197c87.js} +26 -1
  4. package/bundle/index.js +20048 -3236
  5. package/bundle/lib/base_protocol.js +2 -116
  6. package/bundle/lib/message/version_0.js +2 -2
  7. package/bundle/lib/predefined_bootstrap_nodes.js +6 -6
  8. package/bundle/{version_0-86411fdf.js → version_0-f4afd324.js} +907 -814
  9. package/dist/.tsbuildinfo +1 -0
  10. package/dist/index.d.ts +5 -4
  11. package/dist/index.js +4 -3
  12. package/dist/index.js.map +1 -1
  13. package/dist/lib/base_protocol.d.ts +18 -5
  14. package/dist/lib/base_protocol.js +25 -8
  15. package/dist/lib/base_protocol.js.map +1 -1
  16. package/dist/lib/connection_manager.d.ts +15 -3
  17. package/dist/lib/connection_manager.js +92 -34
  18. package/dist/lib/connection_manager.js.map +1 -1
  19. package/dist/lib/filter/filter_rpc.js +4 -4
  20. package/dist/lib/filter/index.d.ts +4 -0
  21. package/dist/lib/filter/index.js +38 -29
  22. package/dist/lib/filter/index.js.map +1 -1
  23. package/dist/lib/filterPeers.d.ts +10 -0
  24. package/dist/lib/filterPeers.js +31 -0
  25. package/dist/lib/filterPeers.js.map +1 -0
  26. package/dist/lib/keep_alive_manager.d.ts +4 -2
  27. package/dist/lib/keep_alive_manager.js +62 -19
  28. package/dist/lib/keep_alive_manager.js.map +1 -1
  29. package/dist/lib/light_push/index.js +85 -38
  30. package/dist/lib/light_push/index.js.map +1 -1
  31. package/dist/lib/light_push/push_rpc.d.ts +1 -1
  32. package/dist/lib/light_push/push_rpc.js +3 -3
  33. package/dist/lib/message/version_0.d.ts +13 -13
  34. package/dist/lib/message/version_0.js +21 -18
  35. package/dist/lib/message/version_0.js.map +1 -1
  36. package/dist/lib/predefined_bootstrap_nodes.js +6 -6
  37. package/dist/lib/store/history_rpc.d.ts +1 -1
  38. package/dist/lib/store/history_rpc.js +4 -4
  39. package/dist/lib/store/index.d.ts +1 -6
  40. package/dist/lib/store/index.js +91 -47
  41. package/dist/lib/store/index.js.map +1 -1
  42. package/dist/lib/stream_manager.d.ts +15 -0
  43. package/dist/lib/stream_manager.js +56 -0
  44. package/dist/lib/stream_manager.js.map +1 -0
  45. package/dist/lib/to_proto_message.js +1 -1
  46. package/dist/lib/wait_for_remote_peer.d.ts +2 -2
  47. package/dist/lib/wait_for_remote_peer.js +10 -7
  48. package/dist/lib/wait_for_remote_peer.js.map +1 -1
  49. package/dist/lib/waku.d.ts +6 -5
  50. package/dist/lib/waku.js +6 -4
  51. package/dist/lib/waku.js.map +1 -1
  52. package/package.json +17 -33
  53. package/src/index.ts +6 -9
  54. package/src/lib/base_protocol.ts +49 -18
  55. package/src/lib/connection_manager.ts +132 -41
  56. package/src/lib/filter/filter_rpc.ts +4 -4
  57. package/src/lib/filter/index.ts +53 -41
  58. package/src/lib/filterPeers.ts +43 -0
  59. package/src/lib/keep_alive_manager.ts +79 -22
  60. package/src/lib/light_push/index.ts +132 -51
  61. package/src/lib/light_push/push_rpc.ts +3 -3
  62. package/src/lib/message/version_0.ts +27 -15
  63. package/src/lib/predefined_bootstrap_nodes.ts +7 -7
  64. package/src/lib/store/history_rpc.ts +6 -6
  65. package/src/lib/store/index.ts +121 -63
  66. package/src/lib/stream_manager.ts +72 -0
  67. package/src/lib/to_proto_message.ts +1 -1
  68. package/src/lib/wait_for_remote_peer.ts +11 -8
  69. package/src/lib/waku.ts +7 -4
  70. package/dist/lib/push_or_init_map.d.ts +0 -1
  71. package/dist/lib/push_or_init_map.js +0 -9
  72. package/dist/lib/push_or_init_map.js.map +0 -1
  73. package/src/lib/push_or_init_map.ts +0 -13
@@ -0,0 +1,43 @@
1
+ import { Peer } from "@libp2p/interface/peer-store";
2
+ import { Tags } from "@waku/interfaces";
3
+
4
+ /**
5
+ * Retrieves a list of peers based on the specified criteria.
6
+ *
7
+ * @param peers - The list of peers to filter from.
8
+ * @param numPeers - The total number of peers to retrieve. If 0, all peers are returned.
9
+ * @param maxBootstrapPeers - The maximum number of bootstrap peers to retrieve.
10
+ * @returns A Promise that resolves to an array of peers based on the specified criteria.
11
+ */
12
+ export async function filterPeers(
13
+ peers: Peer[],
14
+ numPeers: number,
15
+ maxBootstrapPeers: number
16
+ ): Promise<Peer[]> {
17
+ // Collect the bootstrap peers up to the specified maximum
18
+ const bootstrapPeers = peers
19
+ .filter((peer) => peer.tags.has(Tags.BOOTSTRAP))
20
+ .slice(0, maxBootstrapPeers);
21
+
22
+ // Collect non-bootstrap peers
23
+ const nonBootstrapPeers = peers.filter(
24
+ (peer) => !peer.tags.has(Tags.BOOTSTRAP)
25
+ );
26
+
27
+ // If numPeers is 0, return all peers
28
+ if (numPeers === 0) {
29
+ return [...bootstrapPeers, ...nonBootstrapPeers];
30
+ }
31
+
32
+ // Initialize the list of selected peers with the bootstrap peers
33
+ const selectedPeers: Peer[] = [...bootstrapPeers];
34
+
35
+ // Fill up to numPeers with remaining random peers if needed
36
+ while (selectedPeers.length < numPeers && nonBootstrapPeers.length > 0) {
37
+ const randomIndex = Math.floor(Math.random() * nonBootstrapPeers.length);
38
+ const randomPeer = nonBootstrapPeers.splice(randomIndex, 1)[0];
39
+ selectedPeers.push(randomPeer);
40
+ }
41
+
42
+ return selectedPeers;
43
+ }
@@ -1,17 +1,19 @@
1
- import type { PeerId } from "@libp2p/interface-peer-id";
2
- import type { IRelay } from "@waku/interfaces";
1
+ import type { PeerId } from "@libp2p/interface/peer-id";
2
+ import type { PeerStore } from "@libp2p/interface/peer-store";
3
+ import type { IRelay, PeerIdStr } from "@waku/interfaces";
3
4
  import type { KeepAliveOptions } from "@waku/interfaces";
5
+ import { utf8ToBytes } from "@waku/utils/bytes";
4
6
  import debug from "debug";
5
7
  import type { PingService } from "libp2p/ping";
6
8
 
7
- import { createEncoder } from "../index.js";
9
+ import { createEncoder } from "./message/version_0.js";
8
10
 
9
11
  export const RelayPingContentTopic = "/relay-ping/1/ping/null";
10
12
  const log = debug("waku:keep-alive");
11
13
 
12
14
  export class KeepAliveManager {
13
15
  private pingKeepAliveTimers: Map<string, ReturnType<typeof setInterval>>;
14
- private relayKeepAliveTimers: Map<PeerId, ReturnType<typeof setInterval>>;
16
+ private relayKeepAliveTimers: Map<PeerId, ReturnType<typeof setInterval>[]>;
15
17
  private options: KeepAliveOptions;
16
18
  private relay?: IRelay;
17
19
 
@@ -22,8 +24,12 @@ export class KeepAliveManager {
22
24
  this.relay = relay;
23
25
  }
24
26
 
25
- public start(peerId: PeerId, libp2pPing: PingService): void {
26
- // Just in case a timer already exist for this peer
27
+ public start(
28
+ peerId: PeerId,
29
+ libp2pPing: PingService,
30
+ peerStore: PeerStore
31
+ ): void {
32
+ // Just in case a timer already exists for this peer
27
33
  this.stop(peerId);
28
34
 
29
35
  const { pingKeepAlive: pingPeriodSecs, relayKeepAlive: relayPeriodSecs } =
@@ -31,28 +37,51 @@ export class KeepAliveManager {
31
37
 
32
38
  const peerIdStr = peerId.toString();
33
39
 
40
+ // Ping the peer every pingPeriodSecs seconds
41
+ // if pingPeriodSecs is 0, don't ping the peer
34
42
  if (pingPeriodSecs !== 0) {
35
43
  const interval = setInterval(() => {
36
- libp2pPing.ping(peerId).catch((e) => {
37
- log(`Ping failed (${peerIdStr})`, e);
38
- });
44
+ void (async () => {
45
+ let ping: number;
46
+ try {
47
+ // ping the peer for keep alive
48
+ // also update the peer store with the latency
49
+ try {
50
+ ping = await libp2pPing.ping(peerId);
51
+ log(`Ping succeeded (${peerIdStr})`, ping);
52
+ } catch (error) {
53
+ log(`Ping failed for peer (${peerIdStr}).
54
+ Next ping will be attempted in ${pingPeriodSecs} seconds.
55
+ `);
56
+ return;
57
+ }
58
+
59
+ try {
60
+ await peerStore.patch(peerId, {
61
+ metadata: {
62
+ ping: utf8ToBytes(ping.toString())
63
+ }
64
+ });
65
+ } catch (e) {
66
+ log("Failed to update ping", e);
67
+ }
68
+ } catch (e) {
69
+ log(`Ping failed (${peerIdStr})`, e);
70
+ }
71
+ })();
39
72
  }, pingPeriodSecs * 1000);
73
+
40
74
  this.pingKeepAliveTimers.set(peerIdStr, interval);
41
75
  }
42
76
 
43
77
  const relay = this.relay;
44
78
  if (relay && relayPeriodSecs !== 0) {
45
- const encoder = createEncoder({
46
- contentTopic: RelayPingContentTopic,
47
- ephemeral: true,
48
- });
49
- const interval = setInterval(() => {
50
- log("Sending Waku Relay ping message");
51
- relay
52
- .send(encoder, { payload: new Uint8Array([1]) })
53
- .catch((e) => log("Failed to send relay ping", e));
54
- }, relayPeriodSecs * 1000);
55
- this.relayKeepAliveTimers.set(peerId, interval);
79
+ const intervals = this.scheduleRelayPings(
80
+ relay,
81
+ relayPeriodSecs,
82
+ peerId.toString()
83
+ );
84
+ this.relayKeepAliveTimers.set(peerId, intervals);
56
85
  }
57
86
  }
58
87
 
@@ -65,7 +94,7 @@ export class KeepAliveManager {
65
94
  }
66
95
 
67
96
  if (this.relayKeepAliveTimers.has(peerId)) {
68
- clearInterval(this.relayKeepAliveTimers.get(peerId));
97
+ this.relayKeepAliveTimers.get(peerId)?.map(clearInterval);
69
98
  this.relayKeepAliveTimers.delete(peerId);
70
99
  }
71
100
  }
@@ -73,7 +102,7 @@ export class KeepAliveManager {
73
102
  public stopAll(): void {
74
103
  for (const timer of [
75
104
  ...Object.values(this.pingKeepAliveTimers),
76
- ...Object.values(this.relayKeepAliveTimers),
105
+ ...Object.values(this.relayKeepAliveTimers)
77
106
  ]) {
78
107
  clearInterval(timer);
79
108
  }
@@ -81,4 +110,32 @@ export class KeepAliveManager {
81
110
  this.pingKeepAliveTimers.clear();
82
111
  this.relayKeepAliveTimers.clear();
83
112
  }
113
+
114
+ private scheduleRelayPings(
115
+ relay: IRelay,
116
+ relayPeriodSecs: number,
117
+ peerIdStr: PeerIdStr
118
+ ): NodeJS.Timeout[] {
119
+ // send a ping message to each PubSubTopic the peer is part of
120
+ const intervals: NodeJS.Timeout[] = [];
121
+ for (const topic of relay.pubsubTopics) {
122
+ const meshPeers = relay.getMeshPeers(topic);
123
+ if (!meshPeers.includes(peerIdStr)) continue;
124
+
125
+ const encoder = createEncoder({
126
+ pubsubTopic: topic,
127
+ contentTopic: RelayPingContentTopic,
128
+ ephemeral: true
129
+ });
130
+ const interval = setInterval(() => {
131
+ log("Sending Waku Relay ping message");
132
+ relay
133
+ .send(encoder, { payload: new Uint8Array([1]) })
134
+ .catch((e) => log("Failed to send relay ping", e));
135
+ }, relayPeriodSecs * 1000);
136
+ intervals.push(interval);
137
+ }
138
+
139
+ return intervals;
140
+ }
84
141
  }
@@ -1,16 +1,17 @@
1
- import type { PeerId } from "@libp2p/interface-peer-id";
1
+ import type { Stream } from "@libp2p/interface/connection";
2
+ import type { PeerId } from "@libp2p/interface/peer-id";
2
3
  import {
3
4
  IEncoder,
4
5
  ILightPush,
5
6
  IMessage,
6
7
  Libp2p,
7
8
  ProtocolCreateOptions,
8
- ProtocolOptions,
9
+ PubSubTopic,
9
10
  SendError,
10
- SendResult,
11
+ SendResult
11
12
  } from "@waku/interfaces";
12
13
  import { PushResponse } from "@waku/proto";
13
- import { isSizeValid } from "@waku/utils";
14
+ import { ensurePubsubTopicIsConfigured, isSizeValid } from "@waku/utils";
14
15
  import debug from "debug";
15
16
  import all from "it-all";
16
17
  import * as lp from "it-length-prefixed";
@@ -27,80 +28,160 @@ const log = debug("waku:light-push");
27
28
  export const LightPushCodec = "/vac/waku/lightpush/2.0.0-beta1";
28
29
  export { PushResponse };
29
30
 
31
+ type PreparePushMessageResult =
32
+ | {
33
+ query: PushRpc;
34
+ error: null;
35
+ }
36
+ | {
37
+ query: null;
38
+ error: SendError;
39
+ };
40
+
30
41
  /**
31
42
  * Implements the [Waku v2 Light Push protocol](https://rfc.vac.dev/spec/19/).
32
43
  */
33
44
  class LightPush extends BaseProtocol implements ILightPush {
34
- options: ProtocolCreateOptions;
45
+ private readonly pubsubTopics: PubSubTopic[];
46
+ private readonly NUM_PEERS_PROTOCOL = 1;
35
47
 
36
48
  constructor(libp2p: Libp2p, options?: ProtocolCreateOptions) {
37
49
  super(LightPushCodec, libp2p.components);
38
- this.options = options || {};
50
+ this.pubsubTopics = options?.pubsubTopics ?? [DefaultPubSubTopic];
39
51
  }
40
52
 
41
- async send(
53
+ private async preparePushMessage(
42
54
  encoder: IEncoder,
43
55
  message: IMessage,
44
- opts?: ProtocolOptions
45
- ): Promise<SendResult> {
46
- const { pubSubTopic = DefaultPubSubTopic } = this.options;
47
-
48
- const peer = await this.getPeer(opts?.peerId);
49
- const stream = await this.newStream(peer);
50
-
51
- const recipients: PeerId[] = [];
52
- let error: undefined | SendError = undefined;
53
-
56
+ pubsubTopic: string
57
+ ): Promise<PreparePushMessageResult> {
54
58
  try {
55
59
  if (!isSizeValid(message.payload)) {
56
- log("Failed to send waku light push: message is bigger that 1MB");
57
- return {
58
- recipients,
59
- error: SendError.SIZE_TOO_BIG,
60
- };
60
+ log("Failed to send waku light push: message is bigger than 1MB");
61
+ return { query: null, error: SendError.SIZE_TOO_BIG };
61
62
  }
62
63
 
63
64
  const protoMessage = await encoder.toProtoObj(message);
64
65
  if (!protoMessage) {
65
66
  log("Failed to encode to protoMessage, aborting push");
66
67
  return {
67
- recipients,
68
- error: SendError.ENCODE_FAILED,
68
+ query: null,
69
+ error: SendError.ENCODE_FAILED
69
70
  };
70
71
  }
71
- const query = PushRpc.createRequest(protoMessage, pubSubTopic);
72
- const res = await pipe(
73
- [query.encode()],
74
- lp.encode,
75
- stream,
76
- lp.decode,
77
- async (source) => await all(source)
78
- );
72
+
73
+ const query = PushRpc.createRequest(protoMessage, pubsubTopic);
74
+ return { query, error: null };
75
+ } catch (error) {
76
+ log("Failed to prepare push message", error);
77
+
78
+ return {
79
+ query: null,
80
+ error: SendError.GENERIC_FAIL
81
+ };
82
+ }
83
+ }
84
+
85
+ async send(encoder: IEncoder, message: IMessage): Promise<SendResult> {
86
+ const { pubsubTopic } = encoder;
87
+ ensurePubsubTopicIsConfigured(pubsubTopic, this.pubsubTopics);
88
+
89
+ const recipients: PeerId[] = [];
90
+
91
+ const { query, error: preparationError } = await this.preparePushMessage(
92
+ encoder,
93
+ message,
94
+ pubsubTopic
95
+ );
96
+
97
+ if (preparationError || !query) {
98
+ return {
99
+ recipients,
100
+ errors: [preparationError]
101
+ };
102
+ }
103
+
104
+ //TODO: get a relevant peer for the topic/shard
105
+ const peers = await this.getPeers({
106
+ maxBootstrapPeers: 1,
107
+ numPeers: this.NUM_PEERS_PROTOCOL
108
+ });
109
+
110
+ if (!peers.length) {
111
+ return {
112
+ recipients,
113
+ errors: [SendError.NO_PEER_AVAILABLE]
114
+ };
115
+ }
116
+
117
+ const promises = peers.map(async (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
+ }
125
+
126
+ let res: Uint8ArrayList[] | undefined;
127
+ try {
128
+ res = await pipe(
129
+ [query.encode()],
130
+ lp.encode,
131
+ stream,
132
+ lp.decode,
133
+ async (source) => await all(source)
134
+ );
135
+ } catch (err) {
136
+ log("Failed to send waku light push request", err);
137
+ return { recipients, error: SendError.GENERIC_FAIL };
138
+ }
139
+
140
+ const bytes = new Uint8ArrayList();
141
+ res.forEach((chunk) => {
142
+ bytes.append(chunk);
143
+ });
144
+
145
+ let response: PushResponse | undefined;
79
146
  try {
80
- const bytes = new Uint8ArrayList();
81
- res.forEach((chunk) => {
82
- bytes.append(chunk);
83
- });
84
-
85
- const response = PushRpc.decode(bytes).response;
86
-
87
- if (response?.isSuccess) {
88
- recipients.push(peer.id);
89
- } else {
90
- log("No response in PushRPC");
91
- error = SendError.NO_RPC_RESPONSE;
92
- }
147
+ response = PushRpc.decode(bytes).response;
93
148
  } catch (err) {
94
149
  log("Failed to decode push reply", err);
95
- error = SendError.DECODE_FAILED;
150
+ return { recipients, error: SendError.DECODE_FAILED };
96
151
  }
97
- } catch (err) {
98
- log("Failed to send waku light push request", err);
99
- error = SendError.GENERIC_FAIL;
100
- }
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 };
167
+ });
168
+
169
+ const results = await Promise.allSettled(promises);
170
+ const errors = results
171
+ .filter(
172
+ (
173
+ result
174
+ ): result is PromiseFulfilledResult<{
175
+ recipients: PeerId[];
176
+ error: SendError | undefined;
177
+ }> => result.status === "fulfilled"
178
+ )
179
+ .map((result) => result.value.error)
180
+ .filter((error) => error !== undefined) as SendError[];
181
+
101
182
  return {
102
- error,
103
183
  recipients,
184
+ errors
104
185
  };
105
186
  }
106
187
  }
@@ -7,15 +7,15 @@ 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
- response: undefined,
18
+ response: undefined
19
19
  });
20
20
  }
21
21
 
@@ -7,10 +7,13 @@ import type {
7
7
  IMetaSetter,
8
8
  IProtoMessage,
9
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
 
@@ -18,7 +21,10 @@ export const Version = 0;
18
21
  export { proto };
19
22
 
20
23
  export class DecodedMessage implements IDecodedMessage {
21
- constructor(public pubSubTopic: string, protected proto: proto.WakuMessage) {}
24
+ constructor(
25
+ public pubsubTopic: string,
26
+ protected proto: proto.WakuMessage
27
+ ) {}
22
28
 
23
29
  get ephemeral(): boolean {
24
30
  return Boolean(this.proto.ephemeral);
@@ -70,6 +76,7 @@ export class Encoder implements IEncoder {
70
76
  constructor(
71
77
  public contentTopic: string,
72
78
  public ephemeral: boolean = false,
79
+ public pubsubTopic: PubSubTopic,
73
80
  public metaSetter?: IMetaSetter
74
81
  ) {
75
82
  if (!contentTopic || contentTopic === "") {
@@ -91,7 +98,7 @@ export class Encoder implements IEncoder {
91
98
  timestamp: BigInt(timestamp.valueOf()) * OneMillion,
92
99
  meta: undefined,
93
100
  rateLimitProof: message.rateLimitProof,
94
- ephemeral: this.ephemeral,
101
+ ephemeral: this.ephemeral
95
102
  };
96
103
 
97
104
  if (this.metaSetter) {
@@ -106,22 +113,25 @@ export class Encoder implements IEncoder {
106
113
  /**
107
114
  * Creates an encoder that encode messages without Waku level encryption or signature.
108
115
  *
109
- * 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/)
110
117
  * format to be sent over the Waku network. The resulting encoder can then be
111
- * pass to { @link @waku/interfaces.LightPush.push } or
112
- * { @link @waku/interfaces.Relay.send } to automatically encode outgoing
118
+ * pass to { @link @waku/interfaces!ISender.send } to automatically encode outgoing
113
119
  * messages.
114
120
  */
115
121
  export function createEncoder({
122
+ pubsubTopic = DefaultPubSubTopic,
116
123
  contentTopic,
117
124
  ephemeral,
118
- metaSetter,
125
+ metaSetter
119
126
  }: EncoderOptions): Encoder {
120
- return new Encoder(contentTopic, ephemeral, metaSetter);
127
+ return new Encoder(contentTopic, ephemeral, pubsubTopic, metaSetter);
121
128
  }
122
129
 
123
130
  export class Decoder implements IDecoder<DecodedMessage> {
124
- constructor(public contentTopic: string) {
131
+ constructor(
132
+ public pubsubTopic: PubSubTopic,
133
+ public contentTopic: string
134
+ ) {
125
135
  if (!contentTopic || contentTopic === "") {
126
136
  throw new Error("Content topic must be specified");
127
137
  }
@@ -137,12 +147,12 @@ export class Decoder implements IDecoder<DecodedMessage> {
137
147
  timestamp: protoMessage.timestamp ?? undefined,
138
148
  meta: protoMessage.meta ?? undefined,
139
149
  rateLimitProof: protoMessage.rateLimitProof ?? undefined,
140
- ephemeral: protoMessage.ephemeral ?? false,
150
+ ephemeral: protoMessage.ephemeral ?? false
141
151
  });
142
152
  }
143
153
 
144
154
  async fromProtoObj(
145
- pubSubTopic: string,
155
+ pubsubTopic: string,
146
156
  proto: IProtoMessage
147
157
  ): Promise<DecodedMessage | undefined> {
148
158
  // https://rfc.vac.dev/spec/14/
@@ -157,7 +167,7 @@ export class Decoder implements IDecoder<DecodedMessage> {
157
167
  return Promise.resolve(undefined);
158
168
  }
159
169
 
160
- return new DecodedMessage(pubSubTopic, proto);
170
+ return new DecodedMessage(pubsubTopic, proto);
161
171
  }
162
172
  }
163
173
 
@@ -166,12 +176,14 @@ export class Decoder implements IDecoder<DecodedMessage> {
166
176
  *
167
177
  * A decoder is used to decode messages from the [14/WAKU2-MESSAGE](https://rfc.vac.dev/spec/14/)
168
178
  * format when received from the Waku network. The resulting decoder can then be
169
- * pass to { @link @waku/interfaces.Filter.subscribe } or
170
- * { @link @waku/interfaces.Relay.subscribe } to automatically decode incoming
179
+ * pass to { @link @waku/interfaces!IReceiver.subscribe } to automatically decode incoming
171
180
  * messages.
172
181
  *
173
182
  * @param contentTopic The resulting decoder will only decode messages with this content topic.
174
183
  */
175
- export function createDecoder(contentTopic: string): Decoder {
176
- return new Decoder(contentTopic);
184
+ export function createDecoder(
185
+ contentTopic: string,
186
+ pubsubTopic: PubSubTopic = DefaultPubSubTopic
187
+ ): Decoder {
188
+ return new Decoder(pubsubTopic, contentTopic);
177
189
  }
@@ -4,7 +4,7 @@ export const DefaultWantedNumber = 1;
4
4
 
5
5
  export enum Fleet {
6
6
  Prod = "prod",
7
- Test = "test",
7
+ Test = "test"
8
8
  }
9
9
 
10
10
  /**
@@ -51,8 +51,8 @@ export const fleets = {
51
51
  "node-01.do-ams3.wakuv2.prod":
52
52
  "/dns4/node-01.do-ams3.wakuv2.prod.statusim.net/tcp/8000/wss/p2p/16Uiu2HAmL5okWopX7NqZWBUKVqW8iUxCEmd5GMHLVPwCgzYzQv3e",
53
53
  "node-01.gc-us-central1-a.wakuv2.prod":
54
- "/dns4/node-01.gc-us-central1-a.wakuv2.prod.statusim.net/tcp/8000/wss/p2p/16Uiu2HAmVkKntsECaYfefR1V2yCR79CegLATuTPE6B9TxgxBiiiA",
55
- },
54
+ "/dns4/node-01.gc-us-central1-a.wakuv2.prod.statusim.net/tcp/8000/wss/p2p/16Uiu2HAmVkKntsECaYfefR1V2yCR79CegLATuTPE6B9TxgxBiiiA"
55
+ }
56
56
  },
57
57
  "wakuv2.test": {
58
58
  "waku-websocket": {
@@ -61,8 +61,8 @@ export const fleets = {
61
61
  "node-01.do-ams3.wakuv2.test":
62
62
  "/dns4/node-01.do-ams3.wakuv2.test.statusim.net/tcp/8000/wss/p2p/16Uiu2HAmPLe7Mzm8TsYUubgCAW1aJoeFScxrLj8ppHFivPo97bUZ",
63
63
  "node-01.gc-us-central1-a.wakuv2.test":
64
- "/dns4/node-01.gc-us-central1-a.wakuv2.test.statusim.net/tcp/8000/wss/p2p/16Uiu2HAmJb2e28qLXxT5kZxVUUoJt72EMzNGXB47Rxx5hw3q4YjS",
65
- },
66
- },
67
- },
64
+ "/dns4/node-01.gc-us-central1-a.wakuv2.test.statusim.net/tcp/8000/wss/p2p/16Uiu2HAmJb2e28qLXxT5kZxVUUoJt72EMzNGXB47Rxx5hw3q4YjS"
65
+ }
66
+ }
67
+ }
68
68
  };
@@ -6,12 +6,12 @@ const OneMillion = BigInt(1_000_000);
6
6
 
7
7
  export enum PageDirection {
8
8
  BACKWARD = "backward",
9
- FORWARD = "forward",
9
+ FORWARD = "forward"
10
10
  }
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;
@@ -43,7 +43,7 @@ export class HistoryRpc {
43
43
  const pagingInfo = {
44
44
  pageSize: BigInt(params.pageSize),
45
45
  cursor: params.cursor,
46
- direction,
46
+ direction
47
47
  } as proto.PagingInfo;
48
48
 
49
49
  let startTime, endTime;
@@ -59,13 +59,13 @@ 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,
66
- endTime,
66
+ endTime
67
67
  },
68
- response: undefined,
68
+ response: undefined
69
69
  });
70
70
  }
71
71