@waku/core 0.0.19 → 0.0.21
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 +47 -0
- package/bundle/index.js +404 -350
- package/bundle/lib/base_protocol.js +11 -6
- package/bundle/lib/message/version_0.js +1 -1
- package/bundle/lib/predefined_bootstrap_nodes.js +6 -6
- package/bundle/{version_0-9c941081.js → version_0-86411fdf.js} +3 -3
- package/dist/index.d.ts +2 -4
- package/dist/index.js +2 -4
- package/dist/index.js.map +1 -1
- package/dist/lib/base_protocol.d.ts +9 -5
- package/dist/lib/base_protocol.js +11 -6
- package/dist/lib/base_protocol.js.map +1 -1
- package/dist/lib/connection_manager.d.ts +14 -4
- package/dist/lib/connection_manager.js +174 -28
- package/dist/lib/connection_manager.js.map +1 -1
- package/dist/lib/filter/filter_rpc.js.map +1 -0
- package/dist/lib/filter/index.d.ts +2 -0
- package/dist/lib/filter/{v2/index.js → index.js} +14 -19
- package/dist/lib/filter/index.js.map +1 -0
- package/dist/lib/keep_alive_manager.d.ts +2 -2
- package/dist/lib/keep_alive_manager.js +1 -1
- package/dist/lib/keep_alive_manager.js.map +1 -1
- package/dist/lib/light_push/index.d.ts +1 -2
- package/dist/lib/light_push/index.js +1 -3
- package/dist/lib/light_push/index.js.map +1 -1
- package/dist/lib/predefined_bootstrap_nodes.js +6 -6
- package/dist/lib/predefined_bootstrap_nodes.js.map +1 -1
- package/dist/lib/store/index.d.ts +1 -2
- package/dist/lib/store/index.js +1 -3
- package/dist/lib/store/index.js.map +1 -1
- package/dist/lib/wait_for_remote_peer.d.ts +1 -1
- package/dist/lib/wait_for_remote_peer.js +4 -4
- package/dist/lib/wait_for_remote_peer.js.map +1 -1
- package/dist/lib/waku.d.ts +3 -4
- package/dist/lib/waku.js.map +1 -1
- package/package.json +11 -19
- package/src/index.ts +2 -5
- package/src/lib/base_protocol.ts +23 -9
- package/src/lib/connection_manager.ts +230 -42
- package/src/lib/filter/{v2/index.ts → index.ts} +19 -26
- package/src/lib/keep_alive_manager.ts +3 -3
- package/src/lib/light_push/index.ts +3 -3
- package/src/lib/predefined_bootstrap_nodes.ts +6 -6
- package/src/lib/store/index.ts +3 -3
- package/src/lib/wait_for_remote_peer.ts +8 -10
- package/src/lib/waku.ts +3 -4
- package/dist/lib/filter/v1/filter_rpc.d.ts +0 -23
- package/dist/lib/filter/v1/filter_rpc.js +0 -45
- package/dist/lib/filter/v1/filter_rpc.js.map +0 -1
- package/dist/lib/filter/v1/index.d.ts +0 -6
- package/dist/lib/filter/v1/index.js +0 -153
- package/dist/lib/filter/v1/index.js.map +0 -1
- package/dist/lib/filter/v2/filter_rpc.js.map +0 -1
- package/dist/lib/filter/v2/index.d.ts +0 -3
- package/dist/lib/filter/v2/index.js.map +0 -1
- package/src/lib/filter/v1/filter_rpc.ts +0 -53
- package/src/lib/filter/v1/index.ts +0 -248
- /package/dist/lib/filter/{v2/filter_rpc.d.ts → filter_rpc.d.ts} +0 -0
- /package/dist/lib/filter/{v2/filter_rpc.js → filter_rpc.js} +0 -0
- /package/src/lib/filter/{v2/filter_rpc.ts → filter_rpc.ts} +0 -0
package/bundle/index.js
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
import { g as getDefaultExportFromCjs, d as debug } from './browser-bde977a3.js';
|
2
|
-
import { c as createEncoder, v as version_0,
|
3
|
-
export {
|
2
|
+
import { c as createEncoder, v as version_0, M as MessagePush, F as FilterSubscribeRequest, a as FilterSubscribeResponse$1, P as PushRpc$1, b as PushResponse, H as HistoryRpc$1, d as PagingInfo, e as HistoryResponse } from './version_0-86411fdf.js';
|
3
|
+
export { f as createDecoder } from './version_0-86411fdf.js';
|
4
4
|
import { BaseProtocol } from './lib/base_protocol.js';
|
5
5
|
|
6
6
|
const symbol$2 = Symbol.for('@libp2p/peer-id');
|
@@ -1891,7 +1891,7 @@ const BASES = {
|
|
1891
1891
|
'utf-8': string,
|
1892
1892
|
hex: bases.base16,
|
1893
1893
|
latin1: ascii,
|
1894
|
-
ascii
|
1894
|
+
ascii,
|
1895
1895
|
binary: ascii,
|
1896
1896
|
...bases
|
1897
1897
|
};
|
@@ -2608,6 +2608,8 @@ function protoFromTuple(tup) {
|
|
2608
2608
|
* AbortSignal.
|
2609
2609
|
*/
|
2610
2610
|
class CodeError extends Error {
|
2611
|
+
code;
|
2612
|
+
props;
|
2611
2613
|
constructor(message, code, props) {
|
2612
2614
|
super(message);
|
2613
2615
|
this.code = code;
|
@@ -2973,9 +2975,86 @@ var Tags;
|
|
2973
2975
|
Tags["BOOTSTRAP"] = "bootstrap";
|
2974
2976
|
Tags["PEER_EXCHANGE"] = "peer-exchange";
|
2975
2977
|
})(Tags || (Tags = {}));
|
2978
|
+
var EPeersByDiscoveryEvents;
|
2979
|
+
(function (EPeersByDiscoveryEvents) {
|
2980
|
+
EPeersByDiscoveryEvents["PEER_DISCOVERY_BOOTSTRAP"] = "peer:discovery:bootstrap";
|
2981
|
+
EPeersByDiscoveryEvents["PEER_DISCOVERY_PEER_EXCHANGE"] = "peer:discovery:peer-exchange";
|
2982
|
+
EPeersByDiscoveryEvents["PEER_CONNECT_BOOTSTRAP"] = "peer:connected:bootstrap";
|
2983
|
+
EPeersByDiscoveryEvents["PEER_CONNECT_PEER_EXCHANGE"] = "peer:connected:peer-exchange";
|
2984
|
+
})(EPeersByDiscoveryEvents || (EPeersByDiscoveryEvents = {}));
|
2985
|
+
|
2986
|
+
/**
|
2987
|
+
* Adds types to the EventTarget class. Hopefully this won't be necessary forever.
|
2988
|
+
*
|
2989
|
+
* https://github.com/microsoft/TypeScript/issues/28357
|
2990
|
+
* https://github.com/microsoft/TypeScript/issues/43477
|
2991
|
+
* https://github.com/microsoft/TypeScript/issues/299
|
2992
|
+
* etc
|
2993
|
+
*/
|
2994
|
+
class EventEmitter extends EventTarget {
|
2995
|
+
#listeners = new Map();
|
2996
|
+
listenerCount(type) {
|
2997
|
+
const listeners = this.#listeners.get(type);
|
2998
|
+
if (listeners == null) {
|
2999
|
+
return 0;
|
3000
|
+
}
|
3001
|
+
return listeners.length;
|
3002
|
+
}
|
3003
|
+
addEventListener(type, listener, options) {
|
3004
|
+
super.addEventListener(type, listener, options);
|
3005
|
+
let list = this.#listeners.get(type);
|
3006
|
+
if (list == null) {
|
3007
|
+
list = [];
|
3008
|
+
this.#listeners.set(type, list);
|
3009
|
+
}
|
3010
|
+
list.push({
|
3011
|
+
callback: listener,
|
3012
|
+
once: (options !== true && options !== false && options?.once) ?? false
|
3013
|
+
});
|
3014
|
+
}
|
3015
|
+
removeEventListener(type, listener, options) {
|
3016
|
+
super.removeEventListener(type.toString(), listener ?? null, options);
|
3017
|
+
let list = this.#listeners.get(type);
|
3018
|
+
if (list == null) {
|
3019
|
+
return;
|
3020
|
+
}
|
3021
|
+
list = list.filter(({ callback }) => callback !== listener);
|
3022
|
+
this.#listeners.set(type, list);
|
3023
|
+
}
|
3024
|
+
dispatchEvent(event) {
|
3025
|
+
const result = super.dispatchEvent(event);
|
3026
|
+
let list = this.#listeners.get(event.type);
|
3027
|
+
if (list == null) {
|
3028
|
+
return result;
|
3029
|
+
}
|
3030
|
+
list = list.filter(({ once }) => !once);
|
3031
|
+
this.#listeners.set(event.type, list);
|
3032
|
+
return result;
|
3033
|
+
}
|
3034
|
+
safeDispatchEvent(type, detail) {
|
3035
|
+
return this.dispatchEvent(new CustomEvent(type, detail));
|
3036
|
+
}
|
3037
|
+
}
|
3038
|
+
/**
|
3039
|
+
* CustomEvent is a standard event but it's not supported by node.
|
3040
|
+
*
|
3041
|
+
* Remove this when https://github.com/nodejs/node/issues/40678 is closed.
|
3042
|
+
*
|
3043
|
+
* Ref: https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent
|
3044
|
+
*/
|
3045
|
+
class CustomEventPolyfill extends Event {
|
3046
|
+
/** Returns any custom data event was created with. Typically used for synthetic events. */
|
3047
|
+
detail;
|
3048
|
+
constructor(message, data) {
|
3049
|
+
super(message, data);
|
3050
|
+
// @ts-expect-error could be undefined
|
3051
|
+
this.detail = data?.detail;
|
3052
|
+
}
|
3053
|
+
}
|
3054
|
+
const CustomEvent = globalThis.CustomEvent ?? CustomEventPolyfill;
|
2976
3055
|
|
2977
3056
|
const RelayPingContentTopic = "/relay-ping/1/ping/null";
|
2978
|
-
const log$
|
3057
|
+
const log$6 = debug("waku:keep-alive");
|
2979
3058
|
class KeepAliveManager {
|
2980
3059
|
pingKeepAliveTimers;
|
2981
3060
|
relayKeepAliveTimers;
|
@@ -2994,8 +3073,8 @@ class KeepAliveManager {
|
|
2994
3073
|
const peerIdStr = peerId.toString();
|
2995
3074
|
if (pingPeriodSecs !== 0) {
|
2996
3075
|
const interval = setInterval(() => {
|
2997
|
-
libp2pPing(peerId).catch((e) => {
|
2998
|
-
log$
|
3076
|
+
libp2pPing.ping(peerId).catch((e) => {
|
3077
|
+
log$6(`Ping failed (${peerIdStr})`, e);
|
2999
3078
|
});
|
3000
3079
|
}, pingPeriodSecs * 1000);
|
3001
3080
|
this.pingKeepAliveTimers.set(peerIdStr, interval);
|
@@ -3007,10 +3086,10 @@ class KeepAliveManager {
|
|
3007
3086
|
ephemeral: true,
|
3008
3087
|
});
|
3009
3088
|
const interval = setInterval(() => {
|
3010
|
-
log$
|
3089
|
+
log$6("Sending Waku Relay ping message");
|
3011
3090
|
relay
|
3012
3091
|
.send(encoder, { payload: new Uint8Array([1]) })
|
3013
|
-
.catch((e) => log$
|
3092
|
+
.catch((e) => log$6("Failed to send relay ping", e));
|
3014
3093
|
}, relayPeriodSecs * 1000);
|
3015
3094
|
this.relayKeepAliveTimers.set(peerId, interval);
|
3016
3095
|
}
|
@@ -3038,16 +3117,19 @@ class KeepAliveManager {
|
|
3038
3117
|
}
|
3039
3118
|
}
|
3040
3119
|
|
3041
|
-
const log$
|
3120
|
+
const log$5 = debug("waku:connection-manager");
|
3042
3121
|
const DEFAULT_MAX_BOOTSTRAP_PEERS_ALLOWED = 1;
|
3043
3122
|
const DEFAULT_MAX_DIAL_ATTEMPTS_FOR_PEER = 3;
|
3044
|
-
|
3123
|
+
const DEFAULT_MAX_PARALLEL_DIALS = 3;
|
3124
|
+
class ConnectionManager extends EventEmitter {
|
3045
3125
|
static instances = new Map();
|
3046
3126
|
keepAliveManager;
|
3047
3127
|
options;
|
3048
|
-
|
3128
|
+
libp2p;
|
3049
3129
|
dialAttemptsForPeer = new Map();
|
3050
3130
|
dialErrorsForPeer = new Map();
|
3131
|
+
currentActiveDialCount = 0;
|
3132
|
+
pendingPeerDialQueue = [];
|
3051
3133
|
static create(peerId, libp2p, keepAliveOptions, relay, options) {
|
3052
3134
|
let instance = ConnectionManager.instances.get(peerId);
|
3053
3135
|
if (!instance) {
|
@@ -3056,17 +3138,77 @@ class ConnectionManager {
|
|
3056
3138
|
}
|
3057
3139
|
return instance;
|
3058
3140
|
}
|
3059
|
-
|
3060
|
-
|
3141
|
+
async getPeersByDiscovery() {
|
3142
|
+
const peersDiscovered = await this.libp2p.peerStore.all();
|
3143
|
+
const peersConnected = this.libp2p
|
3144
|
+
.getConnections()
|
3145
|
+
.map((conn) => conn.remotePeer);
|
3146
|
+
const peersDiscoveredByBootstrap = [];
|
3147
|
+
const peersDiscoveredByPeerExchange = [];
|
3148
|
+
const peersConnectedByBootstrap = [];
|
3149
|
+
const peersConnectedByPeerExchange = [];
|
3150
|
+
for (const peer of peersDiscovered) {
|
3151
|
+
const tags = await this.getTagNamesForPeer(peer.id);
|
3152
|
+
if (tags.includes(Tags.BOOTSTRAP)) {
|
3153
|
+
peersDiscoveredByBootstrap.push(peer);
|
3154
|
+
}
|
3155
|
+
else if (tags.includes(Tags.PEER_EXCHANGE)) {
|
3156
|
+
peersDiscoveredByPeerExchange.push(peer);
|
3157
|
+
}
|
3158
|
+
}
|
3159
|
+
for (const peerId of peersConnected) {
|
3160
|
+
const peer = await this.libp2p.peerStore.get(peerId);
|
3161
|
+
const tags = await this.getTagNamesForPeer(peerId);
|
3162
|
+
if (tags.includes(Tags.BOOTSTRAP)) {
|
3163
|
+
peersConnectedByBootstrap.push(peer);
|
3164
|
+
}
|
3165
|
+
else if (tags.includes(Tags.PEER_EXCHANGE)) {
|
3166
|
+
peersConnectedByPeerExchange.push(peer);
|
3167
|
+
}
|
3168
|
+
}
|
3169
|
+
return {
|
3170
|
+
DISCOVERED: {
|
3171
|
+
[Tags.BOOTSTRAP]: peersDiscoveredByBootstrap,
|
3172
|
+
[Tags.PEER_EXCHANGE]: peersDiscoveredByPeerExchange,
|
3173
|
+
},
|
3174
|
+
CONNECTED: {
|
3175
|
+
[Tags.BOOTSTRAP]: peersConnectedByBootstrap,
|
3176
|
+
[Tags.PEER_EXCHANGE]: peersConnectedByPeerExchange,
|
3177
|
+
},
|
3178
|
+
};
|
3179
|
+
}
|
3180
|
+
constructor(libp2p, keepAliveOptions, relay, options) {
|
3181
|
+
super();
|
3182
|
+
this.libp2p = libp2p;
|
3061
3183
|
this.options = {
|
3062
3184
|
maxDialAttemptsForPeer: DEFAULT_MAX_DIAL_ATTEMPTS_FOR_PEER,
|
3063
3185
|
maxBootstrapPeersAllowed: DEFAULT_MAX_BOOTSTRAP_PEERS_ALLOWED,
|
3186
|
+
maxParallelDials: DEFAULT_MAX_PARALLEL_DIALS,
|
3064
3187
|
...options,
|
3065
3188
|
};
|
3066
3189
|
this.keepAliveManager = new KeepAliveManager(keepAliveOptions, relay);
|
3067
3190
|
this.run()
|
3068
|
-
.then(() => log$
|
3069
|
-
.catch((error) => log$
|
3191
|
+
.then(() => log$5(`Connection Manager is now running`))
|
3192
|
+
.catch((error) => log$5(`Unexpected error while running service`, error));
|
3193
|
+
// libp2p emits `peer:discovery` events during its initialization
|
3194
|
+
// which means that before the ConnectionManager is initialized, some peers may have been discovered
|
3195
|
+
// we will dial the peers in peerStore ONCE before we start to listen to the `peer:discovery` events within the ConnectionManager
|
3196
|
+
this.dialPeerStorePeers().catch((error) => log$5(`Unexpected error while dialing peer store peers`, error));
|
3197
|
+
}
|
3198
|
+
async dialPeerStorePeers() {
|
3199
|
+
const peerInfos = await this.libp2p.peerStore.all();
|
3200
|
+
const dialPromises = [];
|
3201
|
+
for (const peerInfo of peerInfos) {
|
3202
|
+
if (this.libp2p.getConnections().find((c) => c.remotePeer === peerInfo.id))
|
3203
|
+
continue;
|
3204
|
+
dialPromises.push(this.attemptDial(peerInfo.id));
|
3205
|
+
}
|
3206
|
+
try {
|
3207
|
+
await Promise.all(dialPromises);
|
3208
|
+
}
|
3209
|
+
catch (error) {
|
3210
|
+
log$5(`Unexpected error while dialing peer store peers`, error);
|
3211
|
+
}
|
3070
3212
|
}
|
3071
3213
|
async run() {
|
3072
3214
|
// start event listeners
|
@@ -3076,20 +3218,21 @@ class ConnectionManager {
|
|
3076
3218
|
}
|
3077
3219
|
stop() {
|
3078
3220
|
this.keepAliveManager.stopAll();
|
3079
|
-
this.
|
3080
|
-
this.
|
3081
|
-
this.
|
3221
|
+
this.libp2p.removeEventListener("peer:connect", this.onEventHandlers["peer:connect"]);
|
3222
|
+
this.libp2p.removeEventListener("peer:disconnect", this.onEventHandlers["peer:disconnect"]);
|
3223
|
+
this.libp2p.removeEventListener("peer:discovery", this.onEventHandlers["peer:discovery"]);
|
3082
3224
|
}
|
3083
3225
|
async dialPeer(peerId) {
|
3226
|
+
this.currentActiveDialCount += 1;
|
3084
3227
|
let dialAttempt = 0;
|
3085
3228
|
while (dialAttempt <= this.options.maxDialAttemptsForPeer) {
|
3086
3229
|
try {
|
3087
|
-
log$
|
3088
|
-
await this.
|
3230
|
+
log$5(`Dialing peer ${peerId.toString()}`);
|
3231
|
+
await this.libp2p.dial(peerId);
|
3089
3232
|
const tags = await this.getTagNamesForPeer(peerId);
|
3090
3233
|
// add tag to connection describing discovery mechanism
|
3091
3234
|
// don't add duplicate tags
|
3092
|
-
this.
|
3235
|
+
this.libp2p
|
3093
3236
|
.getConnections(peerId)
|
3094
3237
|
.forEach((conn) => (conn.tags = Array.from(new Set([...conn.tags, ...tags]))));
|
3095
3238
|
this.dialAttemptsForPeer.delete(peerId.toString());
|
@@ -3098,29 +3241,54 @@ class ConnectionManager {
|
|
3098
3241
|
catch (e) {
|
3099
3242
|
const error = e;
|
3100
3243
|
this.dialErrorsForPeer.set(peerId.toString(), error);
|
3101
|
-
log$
|
3244
|
+
log$5(`Error dialing peer ${peerId.toString()} - ${error.errors}`);
|
3102
3245
|
dialAttempt = this.dialAttemptsForPeer.get(peerId.toString()) ?? 1;
|
3103
3246
|
this.dialAttemptsForPeer.set(peerId.toString(), dialAttempt + 1);
|
3104
3247
|
if (dialAttempt <= this.options.maxDialAttemptsForPeer) {
|
3105
|
-
log$
|
3248
|
+
log$5(`Reattempting dial (${dialAttempt})`);
|
3106
3249
|
}
|
3107
3250
|
}
|
3108
3251
|
}
|
3109
3252
|
try {
|
3110
|
-
log$
|
3253
|
+
log$5(`Deleting undialable peer ${peerId.toString()} from peer store. Error: ${JSON.stringify(this.dialErrorsForPeer.get(peerId.toString()).errors[0])}
|
3111
3254
|
}`);
|
3112
3255
|
this.dialErrorsForPeer.delete(peerId.toString());
|
3113
|
-
return await this.
|
3256
|
+
return await this.libp2p.peerStore.delete(peerId);
|
3114
3257
|
}
|
3115
3258
|
catch (error) {
|
3116
3259
|
throw `Error deleting undialable peer ${peerId.toString()} from peer store - ${error}`;
|
3117
3260
|
}
|
3261
|
+
finally {
|
3262
|
+
this.currentActiveDialCount -= 1;
|
3263
|
+
this.processDialQueue();
|
3264
|
+
}
|
3265
|
+
}
|
3266
|
+
async dropConnection(peerId) {
|
3267
|
+
try {
|
3268
|
+
this.keepAliveManager.stop(peerId);
|
3269
|
+
await this.libp2p.hangUp(peerId);
|
3270
|
+
log$5(`Dropped connection with peer ${peerId.toString()}`);
|
3271
|
+
}
|
3272
|
+
catch (error) {
|
3273
|
+
log$5(`Error dropping connection with peer ${peerId.toString()} - ${error}`);
|
3274
|
+
}
|
3275
|
+
}
|
3276
|
+
processDialQueue() {
|
3277
|
+
if (this.pendingPeerDialQueue.length > 0 &&
|
3278
|
+
this.currentActiveDialCount < this.options.maxParallelDials) {
|
3279
|
+
const peerId = this.pendingPeerDialQueue.shift();
|
3280
|
+
if (!peerId)
|
3281
|
+
return;
|
3282
|
+
this.attemptDial(peerId).catch((error) => {
|
3283
|
+
log$5(error);
|
3284
|
+
});
|
3285
|
+
}
|
3118
3286
|
}
|
3119
3287
|
startPeerDiscoveryListener() {
|
3120
|
-
this.
|
3288
|
+
this.libp2p.addEventListener("peer:discovery", this.onEventHandlers["peer:discovery"]);
|
3121
3289
|
}
|
3122
3290
|
startPeerConnectionListener() {
|
3123
|
-
this.
|
3291
|
+
this.libp2p.addEventListener("peer:connect", this.onEventHandlers["peer:connect"]);
|
3124
3292
|
}
|
3125
3293
|
startPeerDisconnectionListener() {
|
3126
3294
|
// TODO: ensure that these following issues are updated and confirmed
|
@@ -3135,23 +3303,71 @@ class ConnectionManager {
|
|
3135
3303
|
* >this event will **only** be triggered when the last connection is closed.
|
3136
3304
|
* @see https://github.com/libp2p/js-libp2p/blob/bad9e8c0ff58d60a78314077720c82ae331cc55b/doc/API.md?plain=1#L2100
|
3137
3305
|
*/
|
3138
|
-
this.
|
3306
|
+
this.libp2p.addEventListener("peer:disconnect", this.onEventHandlers["peer:disconnect"]);
|
3307
|
+
}
|
3308
|
+
async attemptDial(peerId) {
|
3309
|
+
if (this.currentActiveDialCount >= this.options.maxParallelDials) {
|
3310
|
+
this.pendingPeerDialQueue.push(peerId);
|
3311
|
+
return;
|
3312
|
+
}
|
3313
|
+
if (!(await this.shouldDialPeer(peerId)))
|
3314
|
+
return;
|
3315
|
+
this.dialPeer(peerId).catch((err) => {
|
3316
|
+
throw `Error dialing peer ${peerId.toString()} : ${err}`;
|
3317
|
+
});
|
3139
3318
|
}
|
3140
3319
|
onEventHandlers = {
|
3141
|
-
"peer:discovery":
|
3142
|
-
|
3143
|
-
|
3144
|
-
|
3145
|
-
|
3320
|
+
"peer:discovery": (evt) => {
|
3321
|
+
void (async () => {
|
3322
|
+
const { id: peerId } = evt.detail;
|
3323
|
+
const isBootstrap = (await this.getTagNamesForPeer(peerId)).includes(Tags.BOOTSTRAP);
|
3324
|
+
if (isBootstrap) {
|
3325
|
+
this.dispatchEvent(new CustomEvent(EPeersByDiscoveryEvents.PEER_DISCOVERY_BOOTSTRAP, {
|
3326
|
+
detail: peerId,
|
3327
|
+
}));
|
3328
|
+
}
|
3329
|
+
else {
|
3330
|
+
this.dispatchEvent(new CustomEvent(EPeersByDiscoveryEvents.PEER_DISCOVERY_PEER_EXCHANGE, {
|
3331
|
+
detail: peerId,
|
3332
|
+
}));
|
3333
|
+
}
|
3334
|
+
try {
|
3335
|
+
await this.attemptDial(peerId);
|
3336
|
+
}
|
3337
|
+
catch (error) {
|
3338
|
+
log$5(`Error dialing peer ${peerId.toString()} : ${error}`);
|
3339
|
+
}
|
3340
|
+
})();
|
3146
3341
|
},
|
3147
3342
|
"peer:connect": (evt) => {
|
3148
|
-
{
|
3149
|
-
|
3150
|
-
|
3343
|
+
void (async () => {
|
3344
|
+
const peerId = evt.detail;
|
3345
|
+
this.keepAliveManager.start(peerId, this.libp2p.services.ping);
|
3346
|
+
const isBootstrap = (await this.getTagNamesForPeer(peerId)).includes(Tags.BOOTSTRAP);
|
3347
|
+
if (isBootstrap) {
|
3348
|
+
const bootstrapConnections = this.libp2p
|
3349
|
+
.getConnections()
|
3350
|
+
.filter((conn) => conn.tags.includes(Tags.BOOTSTRAP));
|
3351
|
+
// If we have too many bootstrap connections, drop one
|
3352
|
+
if (bootstrapConnections.length > this.options.maxBootstrapPeersAllowed) {
|
3353
|
+
await this.dropConnection(peerId);
|
3354
|
+
}
|
3355
|
+
else {
|
3356
|
+
this.dispatchEvent(new CustomEvent(EPeersByDiscoveryEvents.PEER_CONNECT_BOOTSTRAP, {
|
3357
|
+
detail: peerId,
|
3358
|
+
}));
|
3359
|
+
}
|
3360
|
+
}
|
3361
|
+
else {
|
3362
|
+
this.dispatchEvent(new CustomEvent(EPeersByDiscoveryEvents.PEER_CONNECT_PEER_EXCHANGE, {
|
3363
|
+
detail: peerId,
|
3364
|
+
}));
|
3365
|
+
}
|
3366
|
+
})();
|
3151
3367
|
},
|
3152
3368
|
"peer:disconnect": () => {
|
3153
3369
|
return (evt) => {
|
3154
|
-
this.keepAliveManager.stop(evt.detail
|
3370
|
+
this.keepAliveManager.stop(evt.detail);
|
3155
3371
|
};
|
3156
3372
|
},
|
3157
3373
|
};
|
@@ -3161,15 +3377,16 @@ class ConnectionManager {
|
|
3161
3377
|
* 2. If the peer is not a bootstrap peer
|
3162
3378
|
*/
|
3163
3379
|
async shouldDialPeer(peerId) {
|
3164
|
-
const isConnected = this.
|
3380
|
+
const isConnected = this.libp2p.getConnections(peerId).length > 0;
|
3165
3381
|
if (isConnected)
|
3166
3382
|
return false;
|
3167
|
-
const
|
3383
|
+
const tagNames = await this.getTagNamesForPeer(peerId);
|
3384
|
+
const isBootstrap = tagNames.some((tagName) => tagName === Tags.BOOTSTRAP);
|
3168
3385
|
if (isBootstrap) {
|
3169
|
-
const currentBootstrapConnections = this.
|
3386
|
+
const currentBootstrapConnections = this.libp2p
|
3170
3387
|
.getConnections()
|
3171
3388
|
.filter((conn) => {
|
3172
|
-
conn.tags.find((name) => name === Tags.BOOTSTRAP);
|
3389
|
+
return conn.tags.find((name) => name === Tags.BOOTSTRAP);
|
3173
3390
|
}).length;
|
3174
3391
|
if (currentBootstrapConnections < this.options.maxBootstrapPeersAllowed)
|
3175
3392
|
return true;
|
@@ -3183,15 +3400,21 @@ class ConnectionManager {
|
|
3183
3400
|
* Fetches the tag names for a given peer
|
3184
3401
|
*/
|
3185
3402
|
async getTagNamesForPeer(peerId) {
|
3186
|
-
|
3187
|
-
|
3403
|
+
try {
|
3404
|
+
const peer = await this.libp2p.peerStore.get(peerId);
|
3405
|
+
return Array.from(peer.tags.keys());
|
3406
|
+
}
|
3407
|
+
catch (error) {
|
3408
|
+
log$5(`Failed to get peer ${peerId}, error: ${error}`);
|
3409
|
+
return [];
|
3410
|
+
}
|
3188
3411
|
}
|
3189
3412
|
}
|
3190
3413
|
|
3191
3414
|
const DefaultPingKeepAliveValueSecs = 0;
|
3192
3415
|
const DefaultRelayKeepAliveValueSecs = 5 * 60;
|
3193
3416
|
const DefaultUserAgent = "js-waku";
|
3194
|
-
const log$
|
3417
|
+
const log$4 = debug("waku:waku");
|
3195
3418
|
class WakuNode {
|
3196
3419
|
libp2p;
|
3197
3420
|
relay;
|
@@ -3219,7 +3442,7 @@ class WakuNode {
|
|
3219
3442
|
: 0;
|
3220
3443
|
const peerId = this.libp2p.peerId.toString();
|
3221
3444
|
this.connectionManager = ConnectionManager.create(peerId, libp2p, { pingKeepAlive, relayKeepAlive }, this.relay);
|
3222
|
-
log$
|
3445
|
+
log$4("Waku node created", peerId, `relay: ${!!this.relay}, store: ${!!this.store}, light push: ${!!this
|
3223
3446
|
.lightPush}, filter: ${!!this.filter}`);
|
3224
3447
|
}
|
3225
3448
|
/**
|
@@ -3243,7 +3466,7 @@ class WakuNode {
|
|
3243
3466
|
this.relay.gossipSub.multicodecs.forEach((codec) => codecs.push(codec));
|
3244
3467
|
}
|
3245
3468
|
else {
|
3246
|
-
log$
|
3469
|
+
log$4("Relay codec not included in dial codec: protocol not mounted locally");
|
3247
3470
|
}
|
3248
3471
|
}
|
3249
3472
|
if (_protocols.includes(Protocols.Store)) {
|
@@ -3251,7 +3474,7 @@ class WakuNode {
|
|
3251
3474
|
codecs.push(this.store.multicodec);
|
3252
3475
|
}
|
3253
3476
|
else {
|
3254
|
-
log$
|
3477
|
+
log$4("Store codec not included in dial codec: protocol not mounted locally");
|
3255
3478
|
}
|
3256
3479
|
}
|
3257
3480
|
if (_protocols.includes(Protocols.LightPush)) {
|
@@ -3259,7 +3482,7 @@ class WakuNode {
|
|
3259
3482
|
codecs.push(this.lightPush.multicodec);
|
3260
3483
|
}
|
3261
3484
|
else {
|
3262
|
-
log$
|
3485
|
+
log$4("Light Push codec not included in dial codec: protocol not mounted locally");
|
3263
3486
|
}
|
3264
3487
|
}
|
3265
3488
|
if (_protocols.includes(Protocols.Filter)) {
|
@@ -3267,10 +3490,10 @@ class WakuNode {
|
|
3267
3490
|
codecs.push(this.filter.multicodec);
|
3268
3491
|
}
|
3269
3492
|
else {
|
3270
|
-
log$
|
3493
|
+
log$4("Filter codec not included in dial codec: protocol not mounted locally");
|
3271
3494
|
}
|
3272
3495
|
}
|
3273
|
-
log$
|
3496
|
+
log$4(`Dialing to ${peerId.toString()} with protocols ${_protocols}`);
|
3274
3497
|
return this.libp2p.dialProtocol(peerId, codecs);
|
3275
3498
|
}
|
3276
3499
|
async start() {
|
@@ -3315,7 +3538,7 @@ var waku = /*#__PURE__*/Object.freeze({
|
|
3315
3538
|
*/
|
3316
3539
|
const DefaultPubSubTopic = "/waku/2/default-waku/proto";
|
3317
3540
|
|
3318
|
-
var index$
|
3541
|
+
var index$3 = /*#__PURE__*/Object.freeze({
|
3319
3542
|
__proto__: null,
|
3320
3543
|
version_0: version_0
|
3321
3544
|
});
|
@@ -3397,11 +3620,11 @@ const isSizeValid = (payload) => {
|
|
3397
3620
|
return true;
|
3398
3621
|
};
|
3399
3622
|
|
3400
|
-
function isAsyncIterable$
|
3623
|
+
function isAsyncIterable$3(thing) {
|
3401
3624
|
return thing[Symbol.asyncIterator] != null;
|
3402
3625
|
}
|
3403
3626
|
function all(source) {
|
3404
|
-
if (isAsyncIterable$
|
3627
|
+
if (isAsyncIterable$3(source)) {
|
3405
3628
|
return (async () => {
|
3406
3629
|
const arr = [];
|
3407
3630
|
for await (const entry of source) {
|
@@ -4158,7 +4381,7 @@ const unsigned = {
|
|
4158
4381
|
}
|
4159
4382
|
};
|
4160
4383
|
|
4161
|
-
function isAsyncIterable(thing) {
|
4384
|
+
function isAsyncIterable$2(thing) {
|
4162
4385
|
return thing[Symbol.asyncIterator] != null;
|
4163
4386
|
}
|
4164
4387
|
|
@@ -4191,7 +4414,7 @@ function encode(source, options) {
|
|
4191
4414
|
yield* chunk;
|
4192
4415
|
}
|
4193
4416
|
}
|
4194
|
-
if (isAsyncIterable(source)) {
|
4417
|
+
if (isAsyncIterable$2(source)) {
|
4195
4418
|
return (async function* () {
|
4196
4419
|
for await (const chunk of source) {
|
4197
4420
|
yield* maybeYield(chunk);
|
@@ -4347,7 +4570,7 @@ function decode(source, options) {
|
|
4347
4570
|
}
|
4348
4571
|
}
|
4349
4572
|
}
|
4350
|
-
if (isAsyncIterable(source)) {
|
4573
|
+
if (isAsyncIterable$2(source)) {
|
4351
4574
|
return (async function* () {
|
4352
4575
|
for await (const buf of source) {
|
4353
4576
|
buffer.append(buf);
|
@@ -4662,77 +4885,56 @@ function _pushable(getNext, options) {
|
|
4662
4885
|
return pushable;
|
4663
4886
|
}
|
4664
4887
|
|
4665
|
-
|
4666
|
-
|
4667
|
-
|
4668
|
-
|
4669
|
-
|
4670
|
-
|
4671
|
-
|
4672
|
-
|
4673
|
-
objectMode: true
|
4674
|
-
});
|
4675
|
-
void Promise.resolve().then(async () => {
|
4676
|
-
try {
|
4677
|
-
await Promise.all(sources.map(async (source) => {
|
4678
|
-
for await (const item of source) {
|
4679
|
-
output.push(item);
|
4680
|
-
}
|
4681
|
-
}));
|
4682
|
-
output.end();
|
4683
|
-
}
|
4684
|
-
catch (err) {
|
4685
|
-
output.end(err);
|
4888
|
+
function isAsyncIterable$1(thing) {
|
4889
|
+
return thing[Symbol.asyncIterator] != null;
|
4890
|
+
}
|
4891
|
+
function merge(...sources) {
|
4892
|
+
const syncSources = [];
|
4893
|
+
for (const source of sources) {
|
4894
|
+
if (!isAsyncIterable$1(source)) {
|
4895
|
+
syncSources.push(source);
|
4686
4896
|
}
|
4687
|
-
}
|
4688
|
-
|
4897
|
+
}
|
4898
|
+
if (syncSources.length === sources.length) {
|
4899
|
+
// all sources are synchronous
|
4900
|
+
return (function* () {
|
4901
|
+
for (const source of syncSources) {
|
4902
|
+
yield* source;
|
4903
|
+
}
|
4904
|
+
})();
|
4905
|
+
}
|
4906
|
+
return (async function* () {
|
4907
|
+
const output = pushable({
|
4908
|
+
objectMode: true
|
4909
|
+
});
|
4910
|
+
void Promise.resolve().then(async () => {
|
4911
|
+
try {
|
4912
|
+
await Promise.all(sources.map(async (source) => {
|
4913
|
+
for await (const item of source) {
|
4914
|
+
output.push(item);
|
4915
|
+
}
|
4916
|
+
}));
|
4917
|
+
output.end();
|
4918
|
+
}
|
4919
|
+
catch (err) {
|
4920
|
+
output.end(err);
|
4921
|
+
}
|
4922
|
+
});
|
4923
|
+
yield* output;
|
4924
|
+
})();
|
4689
4925
|
}
|
4690
4926
|
|
4691
|
-
const rawPipe = (...fns) => {
|
4692
|
-
let res;
|
4693
|
-
while (fns.length > 0) {
|
4694
|
-
res = fns.shift()(res);
|
4695
|
-
}
|
4696
|
-
return res;
|
4697
|
-
};
|
4698
|
-
const isIterable = (obj) => {
|
4699
|
-
return obj != null && (typeof obj[Symbol.asyncIterator] === 'function' ||
|
4700
|
-
typeof obj[Symbol.iterator] === 'function' ||
|
4701
|
-
typeof obj.next === 'function' // Probably, right?
|
4702
|
-
);
|
4703
|
-
};
|
4704
|
-
const isDuplex = (obj) => {
|
4705
|
-
return obj != null && typeof obj.sink === 'function' && isIterable(obj.source);
|
4706
|
-
};
|
4707
|
-
const duplexPipelineFn = (duplex) => {
|
4708
|
-
return (source) => {
|
4709
|
-
const p = duplex.sink(source);
|
4710
|
-
if (p.then != null) {
|
4711
|
-
const stream = pushable({
|
4712
|
-
objectMode: true
|
4713
|
-
});
|
4714
|
-
p.then(() => {
|
4715
|
-
stream.end();
|
4716
|
-
}, (err) => {
|
4717
|
-
stream.end(err);
|
4718
|
-
});
|
4719
|
-
const sourceWrap = async function* () {
|
4720
|
-
yield* duplex.source;
|
4721
|
-
stream.end();
|
4722
|
-
};
|
4723
|
-
return merge(stream, sourceWrap());
|
4724
|
-
}
|
4725
|
-
return duplex.source;
|
4726
|
-
};
|
4727
|
-
};
|
4728
4927
|
function pipe(first, ...rest) {
|
4928
|
+
if (first == null) {
|
4929
|
+
throw new Error('Empty pipeline');
|
4930
|
+
}
|
4729
4931
|
// Duplex at start: wrap in function and return duplex source
|
4730
4932
|
if (isDuplex(first)) {
|
4731
4933
|
const duplex = first;
|
4732
4934
|
first = () => duplex.source;
|
4733
4935
|
// Iterable at start: wrap in function
|
4734
4936
|
}
|
4735
|
-
else if (isIterable(first)) {
|
4937
|
+
else if (isIterable(first) || isAsyncIterable(first)) {
|
4736
4938
|
const source = first;
|
4737
4939
|
first = () => source;
|
4738
4940
|
}
|
@@ -4753,19 +4955,59 @@ function pipe(first, ...rest) {
|
|
4753
4955
|
}
|
4754
4956
|
return rawPipe(...fns);
|
4755
4957
|
}
|
4756
|
-
|
4757
|
-
|
4758
|
-
|
4759
|
-
|
4760
|
-
|
4761
|
-
|
4762
|
-
|
4763
|
-
|
4764
|
-
|
4958
|
+
const rawPipe = (...fns) => {
|
4959
|
+
let res;
|
4960
|
+
while (fns.length > 0) {
|
4961
|
+
res = fns.shift()(res);
|
4962
|
+
}
|
4963
|
+
return res;
|
4964
|
+
};
|
4965
|
+
const isAsyncIterable = (obj) => {
|
4966
|
+
return obj?.[Symbol.asyncIterator] != null;
|
4967
|
+
};
|
4968
|
+
const isIterable = (obj) => {
|
4969
|
+
return obj?.[Symbol.iterator] != null;
|
4970
|
+
};
|
4971
|
+
const isDuplex = (obj) => {
|
4972
|
+
if (obj == null) {
|
4973
|
+
return false;
|
4974
|
+
}
|
4975
|
+
return obj.sink != null && obj.source != null;
|
4976
|
+
};
|
4977
|
+
const duplexPipelineFn = (duplex) => {
|
4978
|
+
return (source) => {
|
4979
|
+
const p = duplex.sink(source);
|
4980
|
+
if (p?.then != null) {
|
4981
|
+
const stream = pushable({
|
4982
|
+
objectMode: true
|
4983
|
+
});
|
4984
|
+
p.then(() => {
|
4985
|
+
stream.end();
|
4986
|
+
}, (err) => {
|
4987
|
+
stream.end(err);
|
4988
|
+
});
|
4989
|
+
let sourceWrap;
|
4990
|
+
const source = duplex.source;
|
4991
|
+
if (isAsyncIterable(source)) {
|
4992
|
+
sourceWrap = async function* () {
|
4993
|
+
yield* source;
|
4994
|
+
stream.end();
|
4995
|
+
};
|
4996
|
+
}
|
4997
|
+
else if (isIterable(source)) {
|
4998
|
+
sourceWrap = function* () {
|
4999
|
+
yield* source;
|
5000
|
+
stream.end();
|
5001
|
+
};
|
5002
|
+
}
|
5003
|
+
else {
|
5004
|
+
throw new Error('Unknown duplex source type - must be Iterable or AsyncIterable');
|
5005
|
+
}
|
5006
|
+
return merge(stream, sourceWrap());
|
5007
|
+
}
|
5008
|
+
return duplex.source;
|
5009
|
+
};
|
4765
5010
|
};
|
4766
|
-
function toProtoMessage(wire) {
|
4767
|
-
return { ...EmptyMessage, ...wire };
|
4768
|
-
}
|
4769
5011
|
|
4770
5012
|
// Unique ID creation requires a high quality random # generator. In the browser we therefore
|
4771
5013
|
// require the crypto API and do not support built-in fallback to lower quality random number
|
@@ -4832,198 +5074,6 @@ function v4(options, buf, offset) {
|
|
4832
5074
|
return unsafeStringify(rnds);
|
4833
5075
|
}
|
4834
5076
|
|
4835
|
-
/**
|
4836
|
-
* FilterRPC represents a message conforming to the Waku Filter protocol
|
4837
|
-
*/
|
4838
|
-
class FilterRpc {
|
4839
|
-
proto;
|
4840
|
-
constructor(proto) {
|
4841
|
-
this.proto = proto;
|
4842
|
-
}
|
4843
|
-
static createRequest(topic, contentFilters, requestId, subscribe = true) {
|
4844
|
-
return new FilterRpc({
|
4845
|
-
requestId: requestId || v4(),
|
4846
|
-
request: {
|
4847
|
-
subscribe,
|
4848
|
-
topic,
|
4849
|
-
contentFilters,
|
4850
|
-
},
|
4851
|
-
push: undefined,
|
4852
|
-
});
|
4853
|
-
}
|
4854
|
-
/**
|
4855
|
-
*
|
4856
|
-
* @param bytes Uint8Array of bytes from a FilterRPC message
|
4857
|
-
* @returns FilterRpc
|
4858
|
-
*/
|
4859
|
-
static decode(bytes) {
|
4860
|
-
const res = FilterRpc$1.decode(bytes);
|
4861
|
-
return new FilterRpc(res);
|
4862
|
-
}
|
4863
|
-
/**
|
4864
|
-
* Encode the current FilterRPC request to bytes
|
4865
|
-
* @returns Uint8Array
|
4866
|
-
*/
|
4867
|
-
encode() {
|
4868
|
-
return FilterRpc$1.encode(this.proto);
|
4869
|
-
}
|
4870
|
-
get push() {
|
4871
|
-
return this.proto.push;
|
4872
|
-
}
|
4873
|
-
get requestId() {
|
4874
|
-
return this.proto.requestId;
|
4875
|
-
}
|
4876
|
-
}
|
4877
|
-
|
4878
|
-
const FilterCodec = "/vac/waku/filter/2.0.0-beta1";
|
4879
|
-
const log$4 = debug("waku:filter");
|
4880
|
-
/**
|
4881
|
-
* Implements client side of the [Waku v2 Filter protocol](https://rfc.vac.dev/spec/12/).
|
4882
|
-
*
|
4883
|
-
* Note this currently only works in NodeJS when the Waku node is listening on a port, see:
|
4884
|
-
* - https://github.com/status-im/go-waku/issues/245
|
4885
|
-
* - https://github.com/status-im/nwaku/issues/948
|
4886
|
-
*/
|
4887
|
-
class Filter extends BaseProtocol {
|
4888
|
-
libp2p;
|
4889
|
-
options;
|
4890
|
-
subscriptions;
|
4891
|
-
constructor(libp2p, options) {
|
4892
|
-
super(FilterCodec, libp2p.peerStore, libp2p.getConnections.bind(libp2p));
|
4893
|
-
this.libp2p = libp2p;
|
4894
|
-
this.options = options ?? {};
|
4895
|
-
this.subscriptions = new Map();
|
4896
|
-
this.libp2p
|
4897
|
-
.handle(this.multicodec, this.onRequest.bind(this))
|
4898
|
-
.catch((e) => log$4("Failed to register filter protocol", e));
|
4899
|
-
}
|
4900
|
-
/**
|
4901
|
-
* @param decoders Decoder or array of Decoders to use to decode messages, it also specifies the content topics.
|
4902
|
-
* @param callback A function that will be called on each message returned by the filter.
|
4903
|
-
* @param opts The FilterSubscriptionOpts used to narrow which messages are returned, and which peer to connect to.
|
4904
|
-
* @returns Unsubscribe function that can be used to end the subscription.
|
4905
|
-
*/
|
4906
|
-
async subscribe(decoders, callback, opts) {
|
4907
|
-
const decodersArray = Array.isArray(decoders) ? decoders : [decoders];
|
4908
|
-
const { pubSubTopic = DefaultPubSubTopic } = this.options;
|
4909
|
-
const contentTopics = Array.from(groupByContentTopic(decodersArray).keys());
|
4910
|
-
const contentFilters = contentTopics.map((contentTopic) => ({
|
4911
|
-
contentTopic,
|
4912
|
-
}));
|
4913
|
-
const request = FilterRpc.createRequest(pubSubTopic, contentFilters, undefined, true);
|
4914
|
-
const requestId = request.requestId;
|
4915
|
-
const peer = await this.getPeer(opts?.peerId);
|
4916
|
-
const stream = await this.newStream(peer);
|
4917
|
-
try {
|
4918
|
-
const res = await pipe([request.encode()], encode, stream, decode, async (source) => await all(source));
|
4919
|
-
log$4("response", res);
|
4920
|
-
}
|
4921
|
-
catch (e) {
|
4922
|
-
log$4("Error subscribing to peer ", peer.id.toString(), "for content topics", contentTopics, ": ", e);
|
4923
|
-
throw e;
|
4924
|
-
}
|
4925
|
-
const subscription = {
|
4926
|
-
callback,
|
4927
|
-
decoders: decodersArray,
|
4928
|
-
pubSubTopic,
|
4929
|
-
};
|
4930
|
-
this.subscriptions.set(requestId, subscription);
|
4931
|
-
return async () => {
|
4932
|
-
await this.unsubscribe(pubSubTopic, contentFilters, requestId, peer);
|
4933
|
-
this.subscriptions.delete(requestId);
|
4934
|
-
};
|
4935
|
-
}
|
4936
|
-
toSubscriptionIterator(decoders, opts) {
|
4937
|
-
return toAsyncIterator(this, decoders, opts);
|
4938
|
-
}
|
4939
|
-
getActiveSubscriptions() {
|
4940
|
-
const map = new Map();
|
4941
|
-
const subscriptions = this.subscriptions;
|
4942
|
-
for (const item of subscriptions.values()) {
|
4943
|
-
const values = map.get(item.pubSubTopic) || [];
|
4944
|
-
const nextValues = item.decoders.map((decoder) => decoder.contentTopic);
|
4945
|
-
map.set(item.pubSubTopic, [...values, ...nextValues]);
|
4946
|
-
}
|
4947
|
-
return map;
|
4948
|
-
}
|
4949
|
-
onRequest(streamData) {
|
4950
|
-
log$4("Receiving message push");
|
4951
|
-
try {
|
4952
|
-
pipe(streamData.stream, decode, async (source) => {
|
4953
|
-
for await (const bytes of source) {
|
4954
|
-
const res = FilterRpc.decode(bytes.slice());
|
4955
|
-
if (res.requestId && res.push?.messages?.length) {
|
4956
|
-
await this.pushMessages(res.requestId, res.push.messages);
|
4957
|
-
}
|
4958
|
-
}
|
4959
|
-
}).then(() => {
|
4960
|
-
log$4("Receiving pipe closed.");
|
4961
|
-
}, (e) => {
|
4962
|
-
log$4("Error with receiving pipe", e);
|
4963
|
-
});
|
4964
|
-
}
|
4965
|
-
catch (e) {
|
4966
|
-
log$4("Error decoding message", e);
|
4967
|
-
}
|
4968
|
-
}
|
4969
|
-
async pushMessages(requestId, messages) {
|
4970
|
-
const subscription = this.subscriptions.get(requestId);
|
4971
|
-
if (!subscription) {
|
4972
|
-
log$4(`No subscription locally registered for request ID ${requestId}`);
|
4973
|
-
return;
|
4974
|
-
}
|
4975
|
-
const { decoders, callback, pubSubTopic } = subscription;
|
4976
|
-
if (!decoders || !decoders.length) {
|
4977
|
-
log$4(`No decoder registered for request ID ${requestId}`);
|
4978
|
-
return;
|
4979
|
-
}
|
4980
|
-
for (const protoMessage of messages) {
|
4981
|
-
const contentTopic = protoMessage.contentTopic;
|
4982
|
-
if (!contentTopic) {
|
4983
|
-
log$4("Message has no content topic, skipping");
|
4984
|
-
return;
|
4985
|
-
}
|
4986
|
-
let didDecodeMsg = false;
|
4987
|
-
// We don't want to wait for decoding failure, just attempt to decode
|
4988
|
-
// all messages and do the call back on the one that works
|
4989
|
-
// noinspection ES6MissingAwait
|
4990
|
-
decoders.forEach(async (dec) => {
|
4991
|
-
if (didDecodeMsg)
|
4992
|
-
return;
|
4993
|
-
const decoded = await dec.fromProtoObj(pubSubTopic, toProtoMessage(protoMessage));
|
4994
|
-
if (!decoded) {
|
4995
|
-
log$4("Not able to decode message");
|
4996
|
-
return;
|
4997
|
-
}
|
4998
|
-
// This is just to prevent more decoding attempt
|
4999
|
-
// TODO: Could be better if we were to abort promises
|
5000
|
-
didDecodeMsg = Boolean(decoded);
|
5001
|
-
await callback(decoded);
|
5002
|
-
});
|
5003
|
-
}
|
5004
|
-
}
|
5005
|
-
async unsubscribe(topic, contentFilters, requestId, peer) {
|
5006
|
-
const unsubscribeRequest = FilterRpc.createRequest(topic, contentFilters, requestId, false);
|
5007
|
-
const stream = await this.newStream(peer);
|
5008
|
-
try {
|
5009
|
-
await pipe([unsubscribeRequest.encode()], encode, stream.sink);
|
5010
|
-
}
|
5011
|
-
catch (e) {
|
5012
|
-
log$4("Error unsubscribing", e);
|
5013
|
-
throw e;
|
5014
|
-
}
|
5015
|
-
}
|
5016
|
-
}
|
5017
|
-
function wakuFilter(init = {}) {
|
5018
|
-
return (libp2p) => new Filter(libp2p, init);
|
5019
|
-
}
|
5020
|
-
|
5021
|
-
var index$3 = /*#__PURE__*/Object.freeze({
|
5022
|
-
__proto__: null,
|
5023
|
-
FilterCodec: FilterCodec,
|
5024
|
-
wakuFilter: wakuFilter
|
5025
|
-
});
|
5026
|
-
|
5027
5077
|
/**
|
5028
5078
|
* FilterPushRPC represents a message conforming to the Waku FilterPush protocol.
|
5029
5079
|
* Protocol documentation: https://rfc.vac.dev/spec/12/
|
@@ -5132,7 +5182,7 @@ class FilterSubscribeResponse {
|
|
5132
5182
|
}
|
5133
5183
|
|
5134
5184
|
const log$3 = debug("waku:filter:v2");
|
5135
|
-
const
|
5185
|
+
const FilterCodecs = {
|
5136
5186
|
SUBSCRIBE: "/vac/waku/filter-subscribe/2.0.0-beta1",
|
5137
5187
|
PUSH: "/vac/waku/filter-push/2.0.0-beta1",
|
5138
5188
|
};
|
@@ -5239,8 +5289,7 @@ class Subscription {
|
|
5239
5289
|
await pushMessage(subscriptionCallback, this.pubSubTopic, message);
|
5240
5290
|
}
|
5241
5291
|
}
|
5242
|
-
class
|
5243
|
-
libp2p;
|
5292
|
+
class Filter extends BaseProtocol {
|
5244
5293
|
options;
|
5245
5294
|
activeSubscriptions = new Map();
|
5246
5295
|
getActiveSubscription(pubSubTopic, peerIdStr) {
|
@@ -5251,12 +5300,9 @@ class FilterV2 extends BaseProtocol {
|
|
5251
5300
|
return subscription;
|
5252
5301
|
}
|
5253
5302
|
constructor(libp2p, options) {
|
5254
|
-
super(
|
5255
|
-
this.
|
5256
|
-
|
5257
|
-
.handle(FilterV2Codecs.PUSH, this.onRequest.bind(this))
|
5258
|
-
.catch((e) => {
|
5259
|
-
log$3("Failed to register ", FilterV2Codecs.PUSH, e);
|
5303
|
+
super(FilterCodecs.SUBSCRIBE, libp2p.components);
|
5304
|
+
libp2p.handle(FilterCodecs.PUSH, this.onRequest.bind(this)).catch((e) => {
|
5305
|
+
log$3("Failed to register ", FilterCodecs.PUSH, e);
|
5260
5306
|
});
|
5261
5307
|
this.activeSubscriptions = new Map();
|
5262
5308
|
this.options = options ?? {};
|
@@ -5288,7 +5334,7 @@ class FilterV2 extends BaseProtocol {
|
|
5288
5334
|
*/
|
5289
5335
|
async subscribe(decoders, callback, opts) {
|
5290
5336
|
const subscription = await this.createSubscription(undefined, opts?.peerId);
|
5291
|
-
subscription.subscribe(decoders, callback);
|
5337
|
+
await subscription.subscribe(decoders, callback);
|
5292
5338
|
const contentTopics = Array.from(groupByContentTopic(Array.isArray(decoders) ? decoders : [decoders]).keys());
|
5293
5339
|
return async () => {
|
5294
5340
|
await subscription.unsubscribe(contentTopics);
|
@@ -5328,8 +5374,8 @@ class FilterV2 extends BaseProtocol {
|
|
5328
5374
|
}
|
5329
5375
|
}
|
5330
5376
|
}
|
5331
|
-
function
|
5332
|
-
return (libp2p) => new
|
5377
|
+
function wakuFilter(init = {}) {
|
5378
|
+
return (libp2p) => new Filter(libp2p, init);
|
5333
5379
|
}
|
5334
5380
|
async function pushMessage(subscriptionCallback, pubSubTopic, message) {
|
5335
5381
|
const { decoders, callback } = subscriptionCallback;
|
@@ -5342,25 +5388,24 @@ async function pushMessage(subscriptionCallback, pubSubTopic, message) {
|
|
5342
5388
|
// We don't want to wait for decoding failure, just attempt to decode
|
5343
5389
|
// all messages and do the call back on the one that works
|
5344
5390
|
// noinspection ES6MissingAwait
|
5345
|
-
|
5391
|
+
for (const dec of decoders) {
|
5346
5392
|
if (didDecodeMsg)
|
5347
|
-
|
5393
|
+
break;
|
5348
5394
|
const decoded = await dec.fromProtoObj(pubSubTopic, message);
|
5349
|
-
// const decoded = await dec.fromProtoObj(pubSubTopic, message);
|
5350
5395
|
if (!decoded) {
|
5351
5396
|
log$3("Not able to decode message");
|
5352
|
-
|
5397
|
+
continue;
|
5353
5398
|
}
|
5354
5399
|
// This is just to prevent more decoding attempt
|
5355
5400
|
// TODO: Could be better if we were to abort promises
|
5356
5401
|
didDecodeMsg = Boolean(decoded);
|
5357
5402
|
await callback(decoded);
|
5358
|
-
}
|
5403
|
+
}
|
5359
5404
|
}
|
5360
5405
|
|
5361
5406
|
var index$2 = /*#__PURE__*/Object.freeze({
|
5362
5407
|
__proto__: null,
|
5363
|
-
|
5408
|
+
wakuFilter: wakuFilter
|
5364
5409
|
});
|
5365
5410
|
|
5366
5411
|
class PushRpc {
|
@@ -5399,11 +5444,9 @@ const LightPushCodec = "/vac/waku/lightpush/2.0.0-beta1";
|
|
5399
5444
|
* Implements the [Waku v2 Light Push protocol](https://rfc.vac.dev/spec/19/).
|
5400
5445
|
*/
|
5401
5446
|
class LightPush extends BaseProtocol {
|
5402
|
-
libp2p;
|
5403
5447
|
options;
|
5404
5448
|
constructor(libp2p, options) {
|
5405
|
-
super(LightPushCodec, libp2p.
|
5406
|
-
this.libp2p = libp2p;
|
5449
|
+
super(LightPushCodec, libp2p.components);
|
5407
5450
|
this.options = options || {};
|
5408
5451
|
}
|
5409
5452
|
async send(encoder, message, opts) {
|
@@ -5804,6 +5847,19 @@ function concat(byteArrays, totalLength) {
|
|
5804
5847
|
return res;
|
5805
5848
|
}
|
5806
5849
|
|
5850
|
+
const EmptyMessage = {
|
5851
|
+
payload: new Uint8Array(),
|
5852
|
+
contentTopic: "",
|
5853
|
+
version: undefined,
|
5854
|
+
timestamp: undefined,
|
5855
|
+
meta: undefined,
|
5856
|
+
rateLimitProof: undefined,
|
5857
|
+
ephemeral: undefined,
|
5858
|
+
};
|
5859
|
+
function toProtoMessage(wire) {
|
5860
|
+
return { ...EmptyMessage, ...wire };
|
5861
|
+
}
|
5862
|
+
|
5807
5863
|
const OneMillion = BigInt(1000000);
|
5808
5864
|
var PageDirection;
|
5809
5865
|
(function (PageDirection) {
|
@@ -5884,11 +5940,9 @@ const DefaultPageSize = 10;
|
|
5884
5940
|
* The Waku Store protocol can be used to retrieved historical messages.
|
5885
5941
|
*/
|
5886
5942
|
class Store extends BaseProtocol {
|
5887
|
-
libp2p;
|
5888
5943
|
options;
|
5889
5944
|
constructor(libp2p, options) {
|
5890
|
-
super(StoreCodec, libp2p.
|
5891
|
-
this.libp2p = libp2p;
|
5945
|
+
super(StoreCodec, libp2p.components);
|
5892
5946
|
this.options = options ?? {};
|
5893
5947
|
}
|
5894
5948
|
/**
|
@@ -6313,7 +6367,7 @@ const log = debug("waku:wait-for-remote-peer");
|
|
6313
6367
|
* Wait for a remote peer to be ready given the passed protocols.
|
6314
6368
|
* Must be used after attempting to connect to nodes, using
|
6315
6369
|
* {@link @waku/core.WakuNode.dial} or a bootstrap method with
|
6316
|
-
* {@link @waku/
|
6370
|
+
* {@link @waku/sdk.createLightNode}.
|
6317
6371
|
*
|
6318
6372
|
* If the passed protocols is a GossipSub protocol, then it resolves only once
|
6319
6373
|
* a peer is in a mesh, to help ensure that other peers will send and receive
|
@@ -6372,13 +6426,13 @@ async function waitForConnectedPeer(protocol) {
|
|
6372
6426
|
}
|
6373
6427
|
await new Promise((resolve) => {
|
6374
6428
|
const cb = (evt) => {
|
6375
|
-
if (evt.detail
|
6429
|
+
if (evt.detail?.protocols?.includes(codec)) {
|
6376
6430
|
log("Resolving for", codec, evt.detail.protocols);
|
6377
|
-
protocol.
|
6431
|
+
protocol.removeLibp2pEventListener("peer:identify", cb);
|
6378
6432
|
resolve();
|
6379
6433
|
}
|
6380
6434
|
};
|
6381
|
-
protocol.
|
6435
|
+
protocol.addLibp2pEventListener("peer:identify", cb);
|
6382
6436
|
});
|
6383
6437
|
}
|
6384
6438
|
/**
|
@@ -6413,4 +6467,4 @@ function getEnabledProtocols(waku) {
|
|
6413
6467
|
return protocols;
|
6414
6468
|
}
|
6415
6469
|
|
6416
|
-
export { ConnectionManager, DefaultPubSubTopic, DefaultUserAgent, KeepAliveManager, LightPushCodec, PageDirection, StoreCodec, WakuNode, createCursor, createEncoder, index$
|
6470
|
+
export { ConnectionManager, DefaultPubSubTopic, DefaultUserAgent, KeepAliveManager, LightPushCodec, PageDirection, StoreCodec, WakuNode, createCursor, createEncoder, index$3 as message, waitForRemotePeer, waku, wakuFilter, wakuLightPush, wakuStore, index$2 as waku_filter, index$1 as waku_light_push, index as waku_store };
|