@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.
- package/CHANGELOG.md +34 -0
- package/bundle/{base_protocol-84d9b670.js → base_protocol-2a0c882e.js} +182 -130
- package/bundle/{browser-bde977a3.js → browser-90197c87.js} +26 -1
- package/bundle/index.js +19159 -2228
- package/bundle/lib/base_protocol.js +2 -2
- package/bundle/lib/message/version_0.js +2 -2
- package/bundle/{version_0-74b4b9db.js → version_0-f4afd324.js} +33 -21
- package/dist/.tsbuildinfo +1 -1
- package/dist/lib/connection_manager.d.ts +15 -3
- package/dist/lib/connection_manager.js +83 -25
- package/dist/lib/connection_manager.js.map +1 -1
- package/dist/lib/filter/index.js +25 -20
- package/dist/lib/filter/index.js.map +1 -1
- package/dist/lib/keep_alive_manager.d.ts +1 -0
- package/dist/lib/keep_alive_manager.js +38 -14
- package/dist/lib/keep_alive_manager.js.map +1 -1
- package/dist/lib/light_push/index.js +49 -31
- package/dist/lib/light_push/index.js.map +1 -1
- package/dist/lib/light_push/push_rpc.d.ts +1 -1
- package/dist/lib/light_push/push_rpc.js +2 -2
- package/dist/lib/message/version_0.d.ts +13 -13
- package/dist/lib/message/version_0.js +19 -16
- package/dist/lib/message/version_0.js.map +1 -1
- package/dist/lib/store/history_rpc.d.ts +1 -1
- package/dist/lib/store/history_rpc.js +1 -1
- package/dist/lib/store/index.d.ts +1 -1
- package/dist/lib/store/index.js +37 -10
- package/dist/lib/store/index.js.map +1 -1
- package/dist/lib/stream_manager.d.ts +1 -1
- package/dist/lib/stream_manager.js +5 -2
- package/dist/lib/stream_manager.js.map +1 -1
- package/dist/lib/wait_for_remote_peer.d.ts +2 -2
- package/dist/lib/wait_for_remote_peer.js +10 -7
- package/dist/lib/wait_for_remote_peer.js.map +1 -1
- package/dist/lib/waku.d.ts +4 -3
- package/dist/lib/waku.js +5 -3
- package/dist/lib/waku.js.map +1 -1
- package/package.json +8 -18
- package/src/lib/connection_manager.ts +118 -31
- package/src/lib/filter/index.ts +36 -23
- package/src/lib/keep_alive_manager.ts +49 -16
- package/src/lib/light_push/index.ts +56 -31
- package/src/lib/light_push/push_rpc.ts +2 -2
- package/src/lib/message/version_0.ts +22 -13
- package/src/lib/store/history_rpc.ts +2 -2
- package/src/lib/store/index.ts +53 -14
- package/src/lib/stream_manager.ts +7 -4
- package/src/lib/wait_for_remote_peer.ts +10 -7
- package/src/lib/waku.ts +4 -1
- package/dist/lib/push_or_init_map.d.ts +0 -1
- package/dist/lib/push_or_init_map.js +0 -9
- package/dist/lib/push_or_init_map.js.map +0 -1
- 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
|
-
|
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.
|
50
|
+
this.pubsubTopics = options?.pubsubTopics ?? [DefaultPubSubTopic];
|
49
51
|
}
|
50
52
|
|
51
53
|
private async preparePushMessage(
|
52
54
|
encoder: IEncoder,
|
53
55
|
message: IMessage,
|
54
|
-
|
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,
|
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 {
|
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
|
-
|
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
|
107
|
-
|
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
|
-
|
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
|
137
|
+
return { recipients, error: SendError.GENERIC_FAIL };
|
139
138
|
}
|
140
139
|
|
141
|
-
|
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
|
-
|
10
|
+
pubsubTopic: string
|
11
11
|
): PushRpc {
|
12
12
|
return new PushRpc({
|
13
13
|
requestId: uuid(),
|
14
14
|
request: {
|
15
15
|
message: message,
|
16
|
-
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
|
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 [
|
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.
|
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(
|
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
|
-
|
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(
|
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.
|
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(
|
179
|
-
|
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
|
-
|
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.
|
62
|
+
pubsubTopic: params.pubsubTopic,
|
63
63
|
contentFilters,
|
64
64
|
pagingInfo,
|
65
65
|
startTime,
|
package/src/lib/store/index.ts
CHANGED
@@ -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
|
-
|
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.
|
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
|
-
|
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
|
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
|
-
|
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.
|
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.
|
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
|
13
|
-
* {@link @waku/sdk
|
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
|
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
|
-
|
106
|
-
|
107
|
-
|
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 =
|
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 +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"}
|