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