@waku/core 0.0.20 → 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.
Files changed (59) hide show
  1. package/CHANGELOG.md +27 -0
  2. package/bundle/index.js +256 -302
  3. package/bundle/lib/base_protocol.js +11 -6
  4. package/bundle/lib/message/version_0.js +1 -1
  5. package/bundle/lib/predefined_bootstrap_nodes.js +6 -6
  6. package/bundle/{version_0-9c941081.js → version_0-86411fdf.js} +3 -3
  7. package/dist/index.d.ts +2 -4
  8. package/dist/index.js +2 -4
  9. package/dist/index.js.map +1 -1
  10. package/dist/lib/base_protocol.d.ts +9 -5
  11. package/dist/lib/base_protocol.js +11 -6
  12. package/dist/lib/base_protocol.js.map +1 -1
  13. package/dist/lib/connection_manager.d.ts +6 -4
  14. package/dist/lib/connection_manager.js +120 -42
  15. package/dist/lib/connection_manager.js.map +1 -1
  16. package/dist/lib/filter/filter_rpc.js.map +1 -0
  17. package/dist/lib/filter/index.d.ts +2 -0
  18. package/dist/lib/filter/{v2/index.js → index.js} +14 -19
  19. package/dist/lib/filter/index.js.map +1 -0
  20. package/dist/lib/keep_alive_manager.d.ts +2 -2
  21. package/dist/lib/keep_alive_manager.js +1 -1
  22. package/dist/lib/keep_alive_manager.js.map +1 -1
  23. package/dist/lib/light_push/index.d.ts +1 -2
  24. package/dist/lib/light_push/index.js +1 -3
  25. package/dist/lib/light_push/index.js.map +1 -1
  26. package/dist/lib/predefined_bootstrap_nodes.js +6 -6
  27. package/dist/lib/predefined_bootstrap_nodes.js.map +1 -1
  28. package/dist/lib/store/index.d.ts +1 -2
  29. package/dist/lib/store/index.js +1 -3
  30. package/dist/lib/store/index.js.map +1 -1
  31. package/dist/lib/wait_for_remote_peer.js +3 -3
  32. package/dist/lib/wait_for_remote_peer.js.map +1 -1
  33. package/dist/lib/waku.d.ts +3 -4
  34. package/dist/lib/waku.js.map +1 -1
  35. package/package.json +9 -17
  36. package/src/index.ts +2 -5
  37. package/src/lib/base_protocol.ts +23 -9
  38. package/src/lib/connection_manager.ts +165 -65
  39. package/src/lib/filter/{v2/index.ts → index.ts} +19 -26
  40. package/src/lib/keep_alive_manager.ts +3 -3
  41. package/src/lib/light_push/index.ts +3 -3
  42. package/src/lib/predefined_bootstrap_nodes.ts +6 -6
  43. package/src/lib/store/index.ts +3 -3
  44. package/src/lib/wait_for_remote_peer.ts +7 -9
  45. package/src/lib/waku.ts +3 -4
  46. package/dist/lib/filter/v1/filter_rpc.d.ts +0 -23
  47. package/dist/lib/filter/v1/filter_rpc.js +0 -45
  48. package/dist/lib/filter/v1/filter_rpc.js.map +0 -1
  49. package/dist/lib/filter/v1/index.d.ts +0 -6
  50. package/dist/lib/filter/v1/index.js +0 -153
  51. package/dist/lib/filter/v1/index.js.map +0 -1
  52. package/dist/lib/filter/v2/filter_rpc.js.map +0 -1
  53. package/dist/lib/filter/v2/index.d.ts +0 -3
  54. package/dist/lib/filter/v2/index.js.map +0 -1
  55. package/src/lib/filter/v1/filter_rpc.ts +0 -53
  56. package/src/lib/filter/v1/index.ts +0 -248
  57. /package/dist/lib/filter/{v2/filter_rpc.d.ts → filter_rpc.d.ts} +0 -0
  58. /package/dist/lib/filter/{v2/filter_rpc.js → filter_rpc.js} +0 -0
  59. /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, F as FilterRpc$1, M as MessagePush, a as FilterSubscribeRequest, b as FilterSubscribeResponse$1, P as PushRpc$1, d as PushResponse, H as HistoryRpc$1, e as PagingInfo, f as HistoryResponse } from './version_0-9c941081.js';
3
- export { g as createDecoder } from './version_0-9c941081.js';
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: 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$7 = debug("waku:keep-alive");
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$7(`Ping failed (${peerIdStr})`, e);
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$7("Sending Waku Relay ping message");
3089
+ log$6("Sending Waku Relay ping message");
3011
3090
  relay
3012
3091
  .send(encoder, { payload: new Uint8Array([1]) })
3013
- .catch((e) => log$7("Failed to send relay ping", e));
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,15 +3117,15 @@ class KeepAliveManager {
3038
3117
  }
3039
3118
  }
3040
3119
 
3041
- const log$6 = debug("waku:connection-manager");
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;
3045
- class ConnectionManager {
3124
+ class ConnectionManager extends EventEmitter {
3046
3125
  static instances = new Map();
3047
3126
  keepAliveManager;
3048
3127
  options;
3049
- libp2pComponents;
3128
+ libp2p;
3050
3129
  dialAttemptsForPeer = new Map();
3051
3130
  dialErrorsForPeer = new Map();
3052
3131
  currentActiveDialCount = 0;
@@ -3059,8 +3138,48 @@ class ConnectionManager {
3059
3138
  }
3060
3139
  return instance;
3061
3140
  }
3062
- constructor(libp2pComponents, keepAliveOptions, relay, options) {
3063
- this.libp2pComponents = libp2pComponents;
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;
3064
3183
  this.options = {
3065
3184
  maxDialAttemptsForPeer: DEFAULT_MAX_DIAL_ATTEMPTS_FOR_PEER,
3066
3185
  maxBootstrapPeersAllowed: DEFAULT_MAX_BOOTSTRAP_PEERS_ALLOWED,
@@ -3069,20 +3188,18 @@ class ConnectionManager {
3069
3188
  };
3070
3189
  this.keepAliveManager = new KeepAliveManager(keepAliveOptions, relay);
3071
3190
  this.run()
3072
- .then(() => log$6(`Connection Manager is now running`))
3073
- .catch((error) => log$6(`Unexpected error while running service`, error));
3191
+ .then(() => log$5(`Connection Manager is now running`))
3192
+ .catch((error) => log$5(`Unexpected error while running service`, error));
3074
3193
  // libp2p emits `peer:discovery` events during its initialization
3075
3194
  // which means that before the ConnectionManager is initialized, some peers may have been discovered
3076
3195
  // we will dial the peers in peerStore ONCE before we start to listen to the `peer:discovery` events within the ConnectionManager
3077
- this.dialPeerStorePeers();
3196
+ this.dialPeerStorePeers().catch((error) => log$5(`Unexpected error while dialing peer store peers`, error));
3078
3197
  }
3079
3198
  async dialPeerStorePeers() {
3080
- const peerInfos = await this.libp2pComponents.peerStore.all();
3199
+ const peerInfos = await this.libp2p.peerStore.all();
3081
3200
  const dialPromises = [];
3082
3201
  for (const peerInfo of peerInfos) {
3083
- if (this.libp2pComponents
3084
- .getConnections()
3085
- .find((c) => c.remotePeer === peerInfo.id))
3202
+ if (this.libp2p.getConnections().find((c) => c.remotePeer === peerInfo.id))
3086
3203
  continue;
3087
3204
  dialPromises.push(this.attemptDial(peerInfo.id));
3088
3205
  }
@@ -3090,7 +3207,7 @@ class ConnectionManager {
3090
3207
  await Promise.all(dialPromises);
3091
3208
  }
3092
3209
  catch (error) {
3093
- log$6(`Unexpected error while dialing peer store peers`, error);
3210
+ log$5(`Unexpected error while dialing peer store peers`, error);
3094
3211
  }
3095
3212
  }
3096
3213
  async run() {
@@ -3101,21 +3218,21 @@ class ConnectionManager {
3101
3218
  }
3102
3219
  stop() {
3103
3220
  this.keepAliveManager.stopAll();
3104
- this.libp2pComponents.removeEventListener("peer:connect", this.onEventHandlers["peer:connect"]);
3105
- this.libp2pComponents.removeEventListener("peer:disconnect", this.onEventHandlers["peer:disconnect"]);
3106
- this.libp2pComponents.removeEventListener("peer:discovery", this.onEventHandlers["peer:discovery"]);
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"]);
3107
3224
  }
3108
3225
  async dialPeer(peerId) {
3109
3226
  this.currentActiveDialCount += 1;
3110
3227
  let dialAttempt = 0;
3111
3228
  while (dialAttempt <= this.options.maxDialAttemptsForPeer) {
3112
3229
  try {
3113
- log$6(`Dialing peer ${peerId.toString()}`);
3114
- await this.libp2pComponents.dial(peerId);
3230
+ log$5(`Dialing peer ${peerId.toString()}`);
3231
+ await this.libp2p.dial(peerId);
3115
3232
  const tags = await this.getTagNamesForPeer(peerId);
3116
3233
  // add tag to connection describing discovery mechanism
3117
3234
  // don't add duplicate tags
3118
- this.libp2pComponents
3235
+ this.libp2p
3119
3236
  .getConnections(peerId)
3120
3237
  .forEach((conn) => (conn.tags = Array.from(new Set([...conn.tags, ...tags]))));
3121
3238
  this.dialAttemptsForPeer.delete(peerId.toString());
@@ -3124,19 +3241,19 @@ class ConnectionManager {
3124
3241
  catch (e) {
3125
3242
  const error = e;
3126
3243
  this.dialErrorsForPeer.set(peerId.toString(), error);
3127
- log$6(`Error dialing peer ${peerId.toString()} - ${error.errors}`);
3244
+ log$5(`Error dialing peer ${peerId.toString()} - ${error.errors}`);
3128
3245
  dialAttempt = this.dialAttemptsForPeer.get(peerId.toString()) ?? 1;
3129
3246
  this.dialAttemptsForPeer.set(peerId.toString(), dialAttempt + 1);
3130
3247
  if (dialAttempt <= this.options.maxDialAttemptsForPeer) {
3131
- log$6(`Reattempting dial (${dialAttempt})`);
3248
+ log$5(`Reattempting dial (${dialAttempt})`);
3132
3249
  }
3133
3250
  }
3134
3251
  }
3135
3252
  try {
3136
- log$6(`Deleting undialable peer ${peerId.toString()} from peer store. Error: ${JSON.stringify(this.dialErrorsForPeer.get(peerId.toString()).errors[0])}
3253
+ log$5(`Deleting undialable peer ${peerId.toString()} from peer store. Error: ${JSON.stringify(this.dialErrorsForPeer.get(peerId.toString()).errors[0])}
3137
3254
  }`);
3138
3255
  this.dialErrorsForPeer.delete(peerId.toString());
3139
- return await this.libp2pComponents.peerStore.delete(peerId);
3256
+ return await this.libp2p.peerStore.delete(peerId);
3140
3257
  }
3141
3258
  catch (error) {
3142
3259
  throw `Error deleting undialable peer ${peerId.toString()} from peer store - ${error}`;
@@ -3148,29 +3265,30 @@ class ConnectionManager {
3148
3265
  }
3149
3266
  async dropConnection(peerId) {
3150
3267
  try {
3151
- await this.libp2pComponents.hangUp(peerId);
3152
- log$6(`Dropped connection with peer ${peerId.toString()}`);
3268
+ this.keepAliveManager.stop(peerId);
3269
+ await this.libp2p.hangUp(peerId);
3270
+ log$5(`Dropped connection with peer ${peerId.toString()}`);
3153
3271
  }
3154
3272
  catch (error) {
3155
- log$6(`Error dropping connection with peer ${peerId.toString()} - ${error}`);
3273
+ log$5(`Error dropping connection with peer ${peerId.toString()} - ${error}`);
3156
3274
  }
3157
3275
  }
3158
- async processDialQueue() {
3276
+ processDialQueue() {
3159
3277
  if (this.pendingPeerDialQueue.length > 0 &&
3160
3278
  this.currentActiveDialCount < this.options.maxParallelDials) {
3161
3279
  const peerId = this.pendingPeerDialQueue.shift();
3162
3280
  if (!peerId)
3163
3281
  return;
3164
3282
  this.attemptDial(peerId).catch((error) => {
3165
- log$6(error);
3283
+ log$5(error);
3166
3284
  });
3167
3285
  }
3168
3286
  }
3169
3287
  startPeerDiscoveryListener() {
3170
- this.libp2pComponents.peerStore.addEventListener("peer", this.onEventHandlers["peer:discovery"]);
3288
+ this.libp2p.addEventListener("peer:discovery", this.onEventHandlers["peer:discovery"]);
3171
3289
  }
3172
3290
  startPeerConnectionListener() {
3173
- this.libp2pComponents.addEventListener("peer:connect", this.onEventHandlers["peer:connect"]);
3291
+ this.libp2p.addEventListener("peer:connect", this.onEventHandlers["peer:connect"]);
3174
3292
  }
3175
3293
  startPeerDisconnectionListener() {
3176
3294
  // TODO: ensure that these following issues are updated and confirmed
@@ -3185,7 +3303,7 @@ class ConnectionManager {
3185
3303
  * >this event will **only** be triggered when the last connection is closed.
3186
3304
  * @see https://github.com/libp2p/js-libp2p/blob/bad9e8c0ff58d60a78314077720c82ae331cc55b/doc/API.md?plain=1#L2100
3187
3305
  */
3188
- this.libp2pComponents.addEventListener("peer:disconnect", this.onEventHandlers["peer:disconnect"]);
3306
+ this.libp2p.addEventListener("peer:disconnect", this.onEventHandlers["peer:disconnect"]);
3189
3307
  }
3190
3308
  async attemptDial(peerId) {
3191
3309
  if (this.currentActiveDialCount >= this.options.maxParallelDials) {
@@ -3199,27 +3317,57 @@ class ConnectionManager {
3199
3317
  });
3200
3318
  }
3201
3319
  onEventHandlers = {
3202
- "peer:discovery": async (evt) => {
3203
- const { id: peerId } = evt.detail;
3204
- this.attemptDial(peerId).catch((err) => log$6(`Error dialing peer ${peerId.toString()} : ${err}`));
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
+ })();
3205
3341
  },
3206
- "peer:connect": async (evt) => {
3207
- const { remotePeer: peerId } = evt.detail;
3208
- this.keepAliveManager.start(peerId, this.libp2pComponents.ping.bind(this));
3209
- const isBootstrap = (await this.getTagNamesForPeer(peerId)).includes(Tags.BOOTSTRAP);
3210
- if (isBootstrap) {
3211
- const bootstrapConnections = this.libp2pComponents
3212
- .getConnections()
3213
- .filter((conn) => conn.tags.includes(Tags.BOOTSTRAP));
3214
- // If we have too many bootstrap connections, drop one
3215
- if (bootstrapConnections.length > this.options.maxBootstrapPeersAllowed) {
3216
- await this.dropConnection(peerId);
3342
+ "peer:connect": (evt) => {
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
+ }
3217
3360
  }
3218
- }
3361
+ else {
3362
+ this.dispatchEvent(new CustomEvent(EPeersByDiscoveryEvents.PEER_CONNECT_PEER_EXCHANGE, {
3363
+ detail: peerId,
3364
+ }));
3365
+ }
3366
+ })();
3219
3367
  },
3220
3368
  "peer:disconnect": () => {
3221
3369
  return (evt) => {
3222
- this.keepAliveManager.stop(evt.detail.remotePeer);
3370
+ this.keepAliveManager.stop(evt.detail);
3223
3371
  };
3224
3372
  },
3225
3373
  };
@@ -3229,15 +3377,16 @@ class ConnectionManager {
3229
3377
  * 2. If the peer is not a bootstrap peer
3230
3378
  */
3231
3379
  async shouldDialPeer(peerId) {
3232
- const isConnected = this.libp2pComponents.getConnections(peerId).length > 0;
3380
+ const isConnected = this.libp2p.getConnections(peerId).length > 0;
3233
3381
  if (isConnected)
3234
3382
  return false;
3235
- const isBootstrap = (await this.getTagNamesForPeer(peerId)).some((tagName) => tagName === Tags.BOOTSTRAP);
3383
+ const tagNames = await this.getTagNamesForPeer(peerId);
3384
+ const isBootstrap = tagNames.some((tagName) => tagName === Tags.BOOTSTRAP);
3236
3385
  if (isBootstrap) {
3237
- const currentBootstrapConnections = this.libp2pComponents
3386
+ const currentBootstrapConnections = this.libp2p
3238
3387
  .getConnections()
3239
3388
  .filter((conn) => {
3240
- conn.tags.find((name) => name === Tags.BOOTSTRAP);
3389
+ return conn.tags.find((name) => name === Tags.BOOTSTRAP);
3241
3390
  }).length;
3242
3391
  if (currentBootstrapConnections < this.options.maxBootstrapPeersAllowed)
3243
3392
  return true;
@@ -3251,15 +3400,21 @@ class ConnectionManager {
3251
3400
  * Fetches the tag names for a given peer
3252
3401
  */
3253
3402
  async getTagNamesForPeer(peerId) {
3254
- const tags = (await this.libp2pComponents.peerStore.getTags(peerId)).map((tag) => tag.name);
3255
- return tags;
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
+ }
3256
3411
  }
3257
3412
  }
3258
3413
 
3259
3414
  const DefaultPingKeepAliveValueSecs = 0;
3260
3415
  const DefaultRelayKeepAliveValueSecs = 5 * 60;
3261
3416
  const DefaultUserAgent = "js-waku";
3262
- const log$5 = debug("waku:waku");
3417
+ const log$4 = debug("waku:waku");
3263
3418
  class WakuNode {
3264
3419
  libp2p;
3265
3420
  relay;
@@ -3287,7 +3442,7 @@ class WakuNode {
3287
3442
  : 0;
3288
3443
  const peerId = this.libp2p.peerId.toString();
3289
3444
  this.connectionManager = ConnectionManager.create(peerId, libp2p, { pingKeepAlive, relayKeepAlive }, this.relay);
3290
- log$5("Waku node created", peerId, `relay: ${!!this.relay}, store: ${!!this.store}, light push: ${!!this
3445
+ log$4("Waku node created", peerId, `relay: ${!!this.relay}, store: ${!!this.store}, light push: ${!!this
3291
3446
  .lightPush}, filter: ${!!this.filter}`);
3292
3447
  }
3293
3448
  /**
@@ -3311,7 +3466,7 @@ class WakuNode {
3311
3466
  this.relay.gossipSub.multicodecs.forEach((codec) => codecs.push(codec));
3312
3467
  }
3313
3468
  else {
3314
- log$5("Relay codec not included in dial codec: protocol not mounted locally");
3469
+ log$4("Relay codec not included in dial codec: protocol not mounted locally");
3315
3470
  }
3316
3471
  }
3317
3472
  if (_protocols.includes(Protocols.Store)) {
@@ -3319,7 +3474,7 @@ class WakuNode {
3319
3474
  codecs.push(this.store.multicodec);
3320
3475
  }
3321
3476
  else {
3322
- log$5("Store codec not included in dial codec: protocol not mounted locally");
3477
+ log$4("Store codec not included in dial codec: protocol not mounted locally");
3323
3478
  }
3324
3479
  }
3325
3480
  if (_protocols.includes(Protocols.LightPush)) {
@@ -3327,7 +3482,7 @@ class WakuNode {
3327
3482
  codecs.push(this.lightPush.multicodec);
3328
3483
  }
3329
3484
  else {
3330
- log$5("Light Push codec not included in dial codec: protocol not mounted locally");
3485
+ log$4("Light Push codec not included in dial codec: protocol not mounted locally");
3331
3486
  }
3332
3487
  }
3333
3488
  if (_protocols.includes(Protocols.Filter)) {
@@ -3335,10 +3490,10 @@ class WakuNode {
3335
3490
  codecs.push(this.filter.multicodec);
3336
3491
  }
3337
3492
  else {
3338
- log$5("Filter codec not included in dial codec: protocol not mounted locally");
3493
+ log$4("Filter codec not included in dial codec: protocol not mounted locally");
3339
3494
  }
3340
3495
  }
3341
- log$5(`Dialing to ${peerId.toString()} with protocols ${_protocols}`);
3496
+ log$4(`Dialing to ${peerId.toString()} with protocols ${_protocols}`);
3342
3497
  return this.libp2p.dialProtocol(peerId, codecs);
3343
3498
  }
3344
3499
  async start() {
@@ -3383,7 +3538,7 @@ var waku = /*#__PURE__*/Object.freeze({
3383
3538
  */
3384
3539
  const DefaultPubSubTopic = "/waku/2/default-waku/proto";
3385
3540
 
3386
- var index$4 = /*#__PURE__*/Object.freeze({
3541
+ var index$3 = /*#__PURE__*/Object.freeze({
3387
3542
  __proto__: null,
3388
3543
  version_0: version_0
3389
3544
  });
@@ -4854,19 +5009,6 @@ const duplexPipelineFn = (duplex) => {
4854
5009
  };
4855
5010
  };
4856
5011
 
4857
- const EmptyMessage = {
4858
- payload: new Uint8Array(),
4859
- contentTopic: "",
4860
- version: undefined,
4861
- timestamp: undefined,
4862
- meta: undefined,
4863
- rateLimitProof: undefined,
4864
- ephemeral: undefined,
4865
- };
4866
- function toProtoMessage(wire) {
4867
- return { ...EmptyMessage, ...wire };
4868
- }
4869
-
4870
5012
  // Unique ID creation requires a high quality random # generator. In the browser we therefore
4871
5013
  // require the crypto API and do not support built-in fallback to lower quality random number
4872
5014
  // generators (like Math.random()).
@@ -4932,198 +5074,6 @@ function v4(options, buf, offset) {
4932
5074
  return unsafeStringify(rnds);
4933
5075
  }
4934
5076
 
4935
- /**
4936
- * FilterRPC represents a message conforming to the Waku Filter protocol
4937
- */
4938
- class FilterRpc {
4939
- proto;
4940
- constructor(proto) {
4941
- this.proto = proto;
4942
- }
4943
- static createRequest(topic, contentFilters, requestId, subscribe = true) {
4944
- return new FilterRpc({
4945
- requestId: requestId || v4(),
4946
- request: {
4947
- subscribe,
4948
- topic,
4949
- contentFilters,
4950
- },
4951
- push: undefined,
4952
- });
4953
- }
4954
- /**
4955
- *
4956
- * @param bytes Uint8Array of bytes from a FilterRPC message
4957
- * @returns FilterRpc
4958
- */
4959
- static decode(bytes) {
4960
- const res = FilterRpc$1.decode(bytes);
4961
- return new FilterRpc(res);
4962
- }
4963
- /**
4964
- * Encode the current FilterRPC request to bytes
4965
- * @returns Uint8Array
4966
- */
4967
- encode() {
4968
- return FilterRpc$1.encode(this.proto);
4969
- }
4970
- get push() {
4971
- return this.proto.push;
4972
- }
4973
- get requestId() {
4974
- return this.proto.requestId;
4975
- }
4976
- }
4977
-
4978
- const FilterCodec = "/vac/waku/filter/2.0.0-beta1";
4979
- const log$4 = debug("waku:filter");
4980
- /**
4981
- * Implements client side of the [Waku v2 Filter protocol](https://rfc.vac.dev/spec/12/).
4982
- *
4983
- * Note this currently only works in NodeJS when the Waku node is listening on a port, see:
4984
- * - https://github.com/status-im/go-waku/issues/245
4985
- * - https://github.com/status-im/nwaku/issues/948
4986
- */
4987
- class Filter extends BaseProtocol {
4988
- libp2p;
4989
- options;
4990
- subscriptions;
4991
- constructor(libp2p, options) {
4992
- super(FilterCodec, libp2p.peerStore, libp2p.getConnections.bind(libp2p));
4993
- this.libp2p = libp2p;
4994
- this.options = options ?? {};
4995
- this.subscriptions = new Map();
4996
- this.libp2p
4997
- .handle(this.multicodec, this.onRequest.bind(this))
4998
- .catch((e) => log$4("Failed to register filter protocol", e));
4999
- }
5000
- /**
5001
- * @param decoders Decoder or array of Decoders to use to decode messages, it also specifies the content topics.
5002
- * @param callback A function that will be called on each message returned by the filter.
5003
- * @param opts The FilterSubscriptionOpts used to narrow which messages are returned, and which peer to connect to.
5004
- * @returns Unsubscribe function that can be used to end the subscription.
5005
- */
5006
- async subscribe(decoders, callback, opts) {
5007
- const decodersArray = Array.isArray(decoders) ? decoders : [decoders];
5008
- const { pubSubTopic = DefaultPubSubTopic } = this.options;
5009
- const contentTopics = Array.from(groupByContentTopic(decodersArray).keys());
5010
- const contentFilters = contentTopics.map((contentTopic) => ({
5011
- contentTopic,
5012
- }));
5013
- const request = FilterRpc.createRequest(pubSubTopic, contentFilters, undefined, true);
5014
- const requestId = request.requestId;
5015
- const peer = await this.getPeer(opts?.peerId);
5016
- const stream = await this.newStream(peer);
5017
- try {
5018
- const res = await pipe([request.encode()], encode, stream, decode, async (source) => await all(source));
5019
- log$4("response", res);
5020
- }
5021
- catch (e) {
5022
- log$4("Error subscribing to peer ", peer.id.toString(), "for content topics", contentTopics, ": ", e);
5023
- throw e;
5024
- }
5025
- const subscription = {
5026
- callback,
5027
- decoders: decodersArray,
5028
- pubSubTopic,
5029
- };
5030
- this.subscriptions.set(requestId, subscription);
5031
- return async () => {
5032
- await this.unsubscribe(pubSubTopic, contentFilters, requestId, peer);
5033
- this.subscriptions.delete(requestId);
5034
- };
5035
- }
5036
- toSubscriptionIterator(decoders, opts) {
5037
- return toAsyncIterator(this, decoders, opts);
5038
- }
5039
- getActiveSubscriptions() {
5040
- const map = new Map();
5041
- const subscriptions = this.subscriptions;
5042
- for (const item of subscriptions.values()) {
5043
- const values = map.get(item.pubSubTopic) || [];
5044
- const nextValues = item.decoders.map((decoder) => decoder.contentTopic);
5045
- map.set(item.pubSubTopic, [...values, ...nextValues]);
5046
- }
5047
- return map;
5048
- }
5049
- onRequest(streamData) {
5050
- log$4("Receiving message push");
5051
- try {
5052
- pipe(streamData.stream, decode, async (source) => {
5053
- for await (const bytes of source) {
5054
- const res = FilterRpc.decode(bytes.slice());
5055
- if (res.requestId && res.push?.messages?.length) {
5056
- await this.pushMessages(res.requestId, res.push.messages);
5057
- }
5058
- }
5059
- }).then(() => {
5060
- log$4("Receiving pipe closed.");
5061
- }, (e) => {
5062
- log$4("Error with receiving pipe", e);
5063
- });
5064
- }
5065
- catch (e) {
5066
- log$4("Error decoding message", e);
5067
- }
5068
- }
5069
- async pushMessages(requestId, messages) {
5070
- const subscription = this.subscriptions.get(requestId);
5071
- if (!subscription) {
5072
- log$4(`No subscription locally registered for request ID ${requestId}`);
5073
- return;
5074
- }
5075
- const { decoders, callback, pubSubTopic } = subscription;
5076
- if (!decoders || !decoders.length) {
5077
- log$4(`No decoder registered for request ID ${requestId}`);
5078
- return;
5079
- }
5080
- for (const protoMessage of messages) {
5081
- const contentTopic = protoMessage.contentTopic;
5082
- if (!contentTopic) {
5083
- log$4("Message has no content topic, skipping");
5084
- return;
5085
- }
5086
- let didDecodeMsg = false;
5087
- // We don't want to wait for decoding failure, just attempt to decode
5088
- // all messages and do the call back on the one that works
5089
- // noinspection ES6MissingAwait
5090
- decoders.forEach(async (dec) => {
5091
- if (didDecodeMsg)
5092
- return;
5093
- const decoded = await dec.fromProtoObj(pubSubTopic, toProtoMessage(protoMessage));
5094
- if (!decoded) {
5095
- log$4("Not able to decode message");
5096
- return;
5097
- }
5098
- // This is just to prevent more decoding attempt
5099
- // TODO: Could be better if we were to abort promises
5100
- didDecodeMsg = Boolean(decoded);
5101
- await callback(decoded);
5102
- });
5103
- }
5104
- }
5105
- async unsubscribe(topic, contentFilters, requestId, peer) {
5106
- const unsubscribeRequest = FilterRpc.createRequest(topic, contentFilters, requestId, false);
5107
- const stream = await this.newStream(peer);
5108
- try {
5109
- await pipe([unsubscribeRequest.encode()], encode, stream.sink);
5110
- }
5111
- catch (e) {
5112
- log$4("Error unsubscribing", e);
5113
- throw e;
5114
- }
5115
- }
5116
- }
5117
- function wakuFilter(init = {}) {
5118
- return (libp2p) => new Filter(libp2p, init);
5119
- }
5120
-
5121
- var index$3 = /*#__PURE__*/Object.freeze({
5122
- __proto__: null,
5123
- FilterCodec: FilterCodec,
5124
- wakuFilter: wakuFilter
5125
- });
5126
-
5127
5077
  /**
5128
5078
  * FilterPushRPC represents a message conforming to the Waku FilterPush protocol.
5129
5079
  * Protocol documentation: https://rfc.vac.dev/spec/12/
@@ -5232,7 +5182,7 @@ class FilterSubscribeResponse {
5232
5182
  }
5233
5183
 
5234
5184
  const log$3 = debug("waku:filter:v2");
5235
- const FilterV2Codecs = {
5185
+ const FilterCodecs = {
5236
5186
  SUBSCRIBE: "/vac/waku/filter-subscribe/2.0.0-beta1",
5237
5187
  PUSH: "/vac/waku/filter-push/2.0.0-beta1",
5238
5188
  };
@@ -5339,8 +5289,7 @@ class Subscription {
5339
5289
  await pushMessage(subscriptionCallback, this.pubSubTopic, message);
5340
5290
  }
5341
5291
  }
5342
- class FilterV2 extends BaseProtocol {
5343
- libp2p;
5292
+ class Filter extends BaseProtocol {
5344
5293
  options;
5345
5294
  activeSubscriptions = new Map();
5346
5295
  getActiveSubscription(pubSubTopic, peerIdStr) {
@@ -5351,12 +5300,9 @@ class FilterV2 extends BaseProtocol {
5351
5300
  return subscription;
5352
5301
  }
5353
5302
  constructor(libp2p, options) {
5354
- super(FilterV2Codecs.SUBSCRIBE, libp2p.peerStore, libp2p.getConnections.bind(libp2p));
5355
- this.libp2p = libp2p;
5356
- this.libp2p
5357
- .handle(FilterV2Codecs.PUSH, this.onRequest.bind(this))
5358
- .catch((e) => {
5359
- 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);
5360
5306
  });
5361
5307
  this.activeSubscriptions = new Map();
5362
5308
  this.options = options ?? {};
@@ -5388,7 +5334,7 @@ class FilterV2 extends BaseProtocol {
5388
5334
  */
5389
5335
  async subscribe(decoders, callback, opts) {
5390
5336
  const subscription = await this.createSubscription(undefined, opts?.peerId);
5391
- subscription.subscribe(decoders, callback);
5337
+ await subscription.subscribe(decoders, callback);
5392
5338
  const contentTopics = Array.from(groupByContentTopic(Array.isArray(decoders) ? decoders : [decoders]).keys());
5393
5339
  return async () => {
5394
5340
  await subscription.unsubscribe(contentTopics);
@@ -5428,8 +5374,8 @@ class FilterV2 extends BaseProtocol {
5428
5374
  }
5429
5375
  }
5430
5376
  }
5431
- function wakuFilterV2(init = {}) {
5432
- return (libp2p) => new FilterV2(libp2p, init);
5377
+ function wakuFilter(init = {}) {
5378
+ return (libp2p) => new Filter(libp2p, init);
5433
5379
  }
5434
5380
  async function pushMessage(subscriptionCallback, pubSubTopic, message) {
5435
5381
  const { decoders, callback } = subscriptionCallback;
@@ -5442,25 +5388,24 @@ async function pushMessage(subscriptionCallback, pubSubTopic, message) {
5442
5388
  // We don't want to wait for decoding failure, just attempt to decode
5443
5389
  // all messages and do the call back on the one that works
5444
5390
  // noinspection ES6MissingAwait
5445
- decoders.forEach(async (dec) => {
5391
+ for (const dec of decoders) {
5446
5392
  if (didDecodeMsg)
5447
- return;
5393
+ break;
5448
5394
  const decoded = await dec.fromProtoObj(pubSubTopic, message);
5449
- // const decoded = await dec.fromProtoObj(pubSubTopic, message);
5450
5395
  if (!decoded) {
5451
5396
  log$3("Not able to decode message");
5452
- return;
5397
+ continue;
5453
5398
  }
5454
5399
  // This is just to prevent more decoding attempt
5455
5400
  // TODO: Could be better if we were to abort promises
5456
5401
  didDecodeMsg = Boolean(decoded);
5457
5402
  await callback(decoded);
5458
- });
5403
+ }
5459
5404
  }
5460
5405
 
5461
5406
  var index$2 = /*#__PURE__*/Object.freeze({
5462
5407
  __proto__: null,
5463
- wakuFilterV2: wakuFilterV2
5408
+ wakuFilter: wakuFilter
5464
5409
  });
5465
5410
 
5466
5411
  class PushRpc {
@@ -5499,11 +5444,9 @@ const LightPushCodec = "/vac/waku/lightpush/2.0.0-beta1";
5499
5444
  * Implements the [Waku v2 Light Push protocol](https://rfc.vac.dev/spec/19/).
5500
5445
  */
5501
5446
  class LightPush extends BaseProtocol {
5502
- libp2p;
5503
5447
  options;
5504
5448
  constructor(libp2p, options) {
5505
- super(LightPushCodec, libp2p.peerStore, libp2p.getConnections.bind(libp2p));
5506
- this.libp2p = libp2p;
5449
+ super(LightPushCodec, libp2p.components);
5507
5450
  this.options = options || {};
5508
5451
  }
5509
5452
  async send(encoder, message, opts) {
@@ -5904,6 +5847,19 @@ function concat(byteArrays, totalLength) {
5904
5847
  return res;
5905
5848
  }
5906
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
+
5907
5863
  const OneMillion = BigInt(1000000);
5908
5864
  var PageDirection;
5909
5865
  (function (PageDirection) {
@@ -5984,11 +5940,9 @@ const DefaultPageSize = 10;
5984
5940
  * The Waku Store protocol can be used to retrieved historical messages.
5985
5941
  */
5986
5942
  class Store extends BaseProtocol {
5987
- libp2p;
5988
5943
  options;
5989
5944
  constructor(libp2p, options) {
5990
- super(StoreCodec, libp2p.peerStore, libp2p.getConnections.bind(libp2p));
5991
- this.libp2p = libp2p;
5945
+ super(StoreCodec, libp2p.components);
5992
5946
  this.options = options ?? {};
5993
5947
  }
5994
5948
  /**
@@ -6472,13 +6426,13 @@ async function waitForConnectedPeer(protocol) {
6472
6426
  }
6473
6427
  await new Promise((resolve) => {
6474
6428
  const cb = (evt) => {
6475
- if (evt.detail.protocols.includes(codec)) {
6429
+ if (evt.detail?.protocols?.includes(codec)) {
6476
6430
  log("Resolving for", codec, evt.detail.protocols);
6477
- protocol.peerStore.removeEventListener("change:protocols", cb);
6431
+ protocol.removeLibp2pEventListener("peer:identify", cb);
6478
6432
  resolve();
6479
6433
  }
6480
6434
  };
6481
- protocol.peerStore.addEventListener("change:protocols", cb);
6435
+ protocol.addLibp2pEventListener("peer:identify", cb);
6482
6436
  });
6483
6437
  }
6484
6438
  /**
@@ -6513,4 +6467,4 @@ function getEnabledProtocols(waku) {
6513
6467
  return protocols;
6514
6468
  }
6515
6469
 
6516
- export { ConnectionManager, DefaultPubSubTopic, DefaultUserAgent, KeepAliveManager, LightPushCodec, PageDirection, StoreCodec, WakuNode, createCursor, createEncoder, index$4 as message, waitForRemotePeer, waku, wakuFilter as wakuFilterV1, wakuFilterV2, wakuLightPush, wakuStore, index$3 as waku_filter_v1, index$2 as waku_filter_v2, index$1 as waku_light_push, index as waku_store };
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 };