@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.
- package/CHANGELOG.md +61 -0
- package/bundle/base_protocol-2a0c882e.js +1250 -0
- package/bundle/{browser-bde977a3.js → browser-90197c87.js} +26 -1
- package/bundle/index.js +20048 -3236
- package/bundle/lib/base_protocol.js +2 -116
- package/bundle/lib/message/version_0.js +2 -2
- package/bundle/lib/predefined_bootstrap_nodes.js +6 -6
- package/bundle/{version_0-86411fdf.js → version_0-f4afd324.js} +907 -814
- package/dist/.tsbuildinfo +1 -0
- package/dist/index.d.ts +5 -4
- package/dist/index.js +4 -3
- package/dist/index.js.map +1 -1
- package/dist/lib/base_protocol.d.ts +18 -5
- package/dist/lib/base_protocol.js +25 -8
- package/dist/lib/base_protocol.js.map +1 -1
- package/dist/lib/connection_manager.d.ts +15 -3
- package/dist/lib/connection_manager.js +92 -34
- package/dist/lib/connection_manager.js.map +1 -1
- package/dist/lib/filter/filter_rpc.js +4 -4
- package/dist/lib/filter/index.d.ts +4 -0
- package/dist/lib/filter/index.js +38 -29
- package/dist/lib/filter/index.js.map +1 -1
- package/dist/lib/filterPeers.d.ts +10 -0
- package/dist/lib/filterPeers.js +31 -0
- package/dist/lib/filterPeers.js.map +1 -0
- package/dist/lib/keep_alive_manager.d.ts +4 -2
- package/dist/lib/keep_alive_manager.js +62 -19
- package/dist/lib/keep_alive_manager.js.map +1 -1
- package/dist/lib/light_push/index.js +85 -38
- 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 +3 -3
- package/dist/lib/message/version_0.d.ts +13 -13
- package/dist/lib/message/version_0.js +21 -18
- package/dist/lib/message/version_0.js.map +1 -1
- package/dist/lib/predefined_bootstrap_nodes.js +6 -6
- package/dist/lib/store/history_rpc.d.ts +1 -1
- package/dist/lib/store/history_rpc.js +4 -4
- package/dist/lib/store/index.d.ts +1 -6
- package/dist/lib/store/index.js +91 -47
- package/dist/lib/store/index.js.map +1 -1
- package/dist/lib/stream_manager.d.ts +15 -0
- package/dist/lib/stream_manager.js +56 -0
- package/dist/lib/stream_manager.js.map +1 -0
- package/dist/lib/to_proto_message.js +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 +6 -5
- package/dist/lib/waku.js +6 -4
- package/dist/lib/waku.js.map +1 -1
- package/package.json +17 -33
- package/src/index.ts +6 -9
- package/src/lib/base_protocol.ts +49 -18
- package/src/lib/connection_manager.ts +132 -41
- package/src/lib/filter/filter_rpc.ts +4 -4
- package/src/lib/filter/index.ts +53 -41
- package/src/lib/filterPeers.ts +43 -0
- package/src/lib/keep_alive_manager.ts +79 -22
- package/src/lib/light_push/index.ts +132 -51
- package/src/lib/light_push/push_rpc.ts +3 -3
- package/src/lib/message/version_0.ts +27 -15
- package/src/lib/predefined_bootstrap_nodes.ts +7 -7
- package/src/lib/store/history_rpc.ts +6 -6
- package/src/lib/store/index.ts +121 -63
- package/src/lib/stream_manager.ts +72 -0
- package/src/lib/to_proto_message.ts +1 -1
- package/src/lib/wait_for_remote_peer.ts +11 -8
- package/src/lib/waku.ts +7 -4
- 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
@@ -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
|
2
|
-
import type {
|
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 "
|
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(
|
26
|
-
|
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
|
-
|
37
|
-
|
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
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
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
|
-
|
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 {
|
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
|
-
|
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
|
-
|
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.
|
50
|
+
this.pubsubTopics = options?.pubsubTopics ?? [DefaultPubSubTopic];
|
39
51
|
}
|
40
52
|
|
41
|
-
async
|
53
|
+
private async preparePushMessage(
|
42
54
|
encoder: IEncoder,
|
43
55
|
message: IMessage,
|
44
|
-
|
45
|
-
): Promise<
|
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
|
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
|
-
|
68
|
-
error: SendError.ENCODE_FAILED
|
68
|
+
query: null,
|
69
|
+
error: SendError.ENCODE_FAILED
|
69
70
|
};
|
70
71
|
}
|
71
|
-
|
72
|
-
const
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
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
|
-
|
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
|
150
|
+
return { recipients, error: SendError.DECODE_FAILED };
|
96
151
|
}
|
97
|
-
|
98
|
-
|
99
|
-
|
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
|
-
|
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
|
-
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(
|
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 [
|
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.
|
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(
|
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
|
-
|
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(
|
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.
|
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(
|
176
|
-
|
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
|
-
|
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.
|
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
|
|