@waku/discovery 0.0.11-e224c05.0 → 0.0.11-e800af3.0

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 (64) hide show
  1. package/bundle/index.js +324 -384
  2. package/dist/.tsbuildinfo +1 -1
  3. package/dist/dns/constants.d.ts +1 -2
  4. package/dist/dns/constants.js +0 -5
  5. package/dist/dns/constants.js.map +1 -1
  6. package/dist/dns/dns.d.ts +3 -12
  7. package/dist/dns/dns.js +16 -39
  8. package/dist/dns/dns.js.map +1 -1
  9. package/dist/dns/dns_discovery.d.ts +3 -3
  10. package/dist/dns/dns_discovery.js +6 -7
  11. package/dist/dns/dns_discovery.js.map +1 -1
  12. package/dist/dns/fetch_nodes.d.ts +5 -11
  13. package/dist/dns/fetch_nodes.js +15 -117
  14. package/dist/dns/fetch_nodes.js.map +1 -1
  15. package/dist/index.d.ts +2 -3
  16. package/dist/index.js +2 -6
  17. package/dist/index.js.map +1 -1
  18. package/dist/peer-cache/constants.d.ts +3 -0
  19. package/dist/peer-cache/constants.js +4 -0
  20. package/dist/peer-cache/constants.js.map +1 -0
  21. package/dist/peer-cache/index.d.ts +1 -0
  22. package/dist/peer-cache/index.js +2 -0
  23. package/dist/peer-cache/index.js.map +1 -0
  24. package/dist/peer-cache/peer_cache.d.ts +17 -0
  25. package/dist/peer-cache/peer_cache.js +99 -0
  26. package/dist/peer-cache/peer_cache.js.map +1 -0
  27. package/dist/peer-cache/utils.d.ts +2 -0
  28. package/dist/peer-cache/utils.js +65 -0
  29. package/dist/peer-cache/utils.js.map +1 -0
  30. package/dist/peer-exchange/constants.d.ts +6 -0
  31. package/dist/peer-exchange/constants.js +8 -0
  32. package/dist/peer-exchange/constants.js.map +1 -0
  33. package/dist/peer-exchange/index.d.ts +2 -2
  34. package/dist/peer-exchange/index.js +2 -2
  35. package/dist/peer-exchange/index.js.map +1 -1
  36. package/dist/peer-exchange/{waku_peer_exchange.d.ts → peer_exchange.d.ts} +1 -7
  37. package/dist/peer-exchange/{waku_peer_exchange.js → peer_exchange.js} +8 -18
  38. package/dist/peer-exchange/peer_exchange.js.map +1 -0
  39. package/dist/peer-exchange/peer_exchange_discovery.d.ts +42 -0
  40. package/dist/peer-exchange/peer_exchange_discovery.js +165 -0
  41. package/dist/peer-exchange/peer_exchange_discovery.js.map +1 -0
  42. package/package.json +1 -1
  43. package/src/dns/constants.ts +1 -7
  44. package/src/dns/dns.ts +20 -68
  45. package/src/dns/dns_discovery.ts +10 -16
  46. package/src/dns/fetch_nodes.ts +20 -157
  47. package/src/index.ts +6 -13
  48. package/src/peer-cache/constants.ts +4 -0
  49. package/src/peer-cache/index.ts +1 -0
  50. package/src/peer-cache/peer_cache.ts +152 -0
  51. package/src/peer-cache/utils.ts +73 -0
  52. package/src/peer-exchange/constants.ts +10 -0
  53. package/src/peer-exchange/index.ts +3 -8
  54. package/src/peer-exchange/{waku_peer_exchange.ts → peer_exchange.ts} +10 -20
  55. package/src/peer-exchange/peer_exchange_discovery.ts +264 -0
  56. package/dist/local-peer-cache/index.d.ts +0 -23
  57. package/dist/local-peer-cache/index.js +0 -110
  58. package/dist/local-peer-cache/index.js.map +0 -1
  59. package/dist/peer-exchange/waku_peer_exchange.js.map +0 -1
  60. package/dist/peer-exchange/waku_peer_exchange_discovery.d.ts +0 -57
  61. package/dist/peer-exchange/waku_peer_exchange_discovery.js +0 -182
  62. package/dist/peer-exchange/waku_peer_exchange_discovery.js.map +0 -1
  63. package/src/local-peer-cache/index.ts +0 -163
  64. package/src/peer-exchange/waku_peer_exchange_discovery.ts +0 -317
package/bundle/index.js CHANGED
@@ -286,12 +286,18 @@ var ProtocolError;
286
286
  ProtocolError["INVALID_DECODER_TOPICS"] = "Invalid decoder topics";
287
287
  })(ProtocolError || (ProtocolError = {}));
288
288
 
289
+ var WakuEventType;
290
+ (function (WakuEventType) {
291
+ WakuEventType["Connection"] = "waku:connection";
292
+ WakuEventType["Health"] = "waku:health";
293
+ })(WakuEventType || (WakuEventType = {}));
294
+
289
295
  // Peer tags
290
296
  var Tags;
291
297
  (function (Tags) {
292
298
  Tags["BOOTSTRAP"] = "bootstrap";
293
299
  Tags["PEER_EXCHANGE"] = "peer-exchange";
294
- Tags["LOCAL"] = "local-peer-cache";
300
+ Tags["PEER_CACHE"] = "peer-cache";
295
301
  })(Tags || (Tags = {}));
296
302
 
297
303
  const DNS_DISCOVERY_TAG = "@waku/bootstrap";
@@ -316,6 +322,25 @@ function isDefined(value) {
316
322
  return Boolean(value);
317
323
  }
318
324
 
325
+ /**
326
+ * Return pseudo random subset of the input.
327
+ */
328
+ function shuffle(arr) {
329
+ if (arr.length <= 1) {
330
+ return arr;
331
+ }
332
+ const randInt = () => {
333
+ return Math.floor(Math.random() * Math.floor(arr.length));
334
+ };
335
+ for (let i = 0; i < arr.length; i++) {
336
+ const j = randInt();
337
+ const tmp = arr[i];
338
+ arr[i] = arr[j];
339
+ arr[j] = tmp;
340
+ }
341
+ return arr;
342
+ }
343
+
319
344
  const crypto$2 = typeof globalThis === 'object' && 'crypto' in globalThis ? globalThis.crypto : undefined;
320
345
 
321
346
  /**
@@ -2355,14 +2380,6 @@ const encodeRelayShard = (shardInfo) => {
2355
2380
  return new Uint8Array(buffer);
2356
2381
  };
2357
2382
 
2358
- function getWsMultiaddrFromMultiaddrs(addresses) {
2359
- const wsMultiaddr = addresses.find((addr) => addr.toString().includes("ws") || addr.toString().includes("wss"));
2360
- if (!wsMultiaddr) {
2361
- throw new Error("No ws multiaddr found in the given addresses");
2362
- }
2363
- return wsMultiaddr;
2364
- }
2365
-
2366
2383
  var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
2367
2384
 
2368
2385
  function getDefaultExportFromCjs (x) {
@@ -3151,11 +3168,6 @@ const enrTree = {
3151
3168
  const DEFAULT_BOOTSTRAP_TAG_NAME = Tags.BOOTSTRAP;
3152
3169
  const DEFAULT_BOOTSTRAP_TAG_VALUE = 50;
3153
3170
  const DEFAULT_BOOTSTRAP_TAG_TTL = 100_000_000;
3154
- const DEFAULT_NODE_REQUIREMENTS = {
3155
- store: 1,
3156
- filter: 2,
3157
- lightPush: 2
3158
- };
3159
3171
 
3160
3172
  // Maximum encoded size of an ENR
3161
3173
  const ERR_INVALID_ID = "Invalid record id";
@@ -15099,188 +15111,63 @@ class ENRTree {
15099
15111
 
15100
15112
  const log$5 = new Logger$1("discovery:fetch_nodes");
15101
15113
  /**
15102
- * Fetch nodes using passed [[getNode]] until all wanted capabilities are
15103
- * fulfilled or the number of [[getNode]] call exceeds the sum of
15104
- * [[wantedNodeCapabilityCount]] plus [[errorTolerance]].
15114
+ * Fetch nodes using passed [[getNode]] until it has been called [[maxGet]]
15115
+ * times, or it has returned empty or duplicate results more than [[maxErrors]]
15116
+ * times.
15105
15117
  */
15106
- async function fetchNodesUntilCapabilitiesFulfilled(wantedNodeCapabilityCount, errorTolerance, getNode) {
15107
- const wanted = {
15108
- relay: wantedNodeCapabilityCount.relay ?? 0,
15109
- store: wantedNodeCapabilityCount.store ?? 0,
15110
- filter: wantedNodeCapabilityCount.filter ?? 0,
15111
- lightPush: wantedNodeCapabilityCount.lightPush ?? 0
15112
- };
15113
- const maxSearches = wanted.relay + wanted.store + wanted.filter + wanted.lightPush;
15114
- const actual = {
15115
- relay: 0,
15116
- store: 0,
15117
- filter: 0,
15118
- lightPush: 0
15119
- };
15118
+ async function* fetchNodes(getNode, maxGet = 10, maxErrors = 3) {
15119
+ const peerNodeIds = new Set();
15120
15120
  let totalSearches = 0;
15121
- const peers = [];
15122
- while (!isSatisfied(wanted, actual) &&
15123
- totalSearches < maxSearches + errorTolerance) {
15124
- const peer = await getNode();
15125
- if (peer && isNewPeer(peer, peers)) {
15126
- // ENRs without a waku2 key are ignored.
15127
- if (peer.waku2) {
15128
- if (helpsSatisfyCapabilities(peer.waku2, wanted, actual)) {
15129
- addCapabilities(peer.waku2, actual);
15130
- peers.push(peer);
15131
- }
15132
- }
15133
- log$5.info(`got new peer candidate from DNS address=${peer.nodeId}@${peer.ip}`);
15134
- }
15121
+ let erroneousSearches = 0;
15122
+ while (totalSearches < maxGet &&
15123
+ erroneousSearches < maxErrors // Allows a couple of empty results before calling it quit
15124
+ ) {
15135
15125
  totalSearches++;
15136
- }
15137
- return peers;
15138
- }
15139
- /**
15140
- * Fetch nodes using passed [[getNode]] until all wanted capabilities are
15141
- * fulfilled or the number of [[getNode]] call exceeds the sum of
15142
- * [[wantedNodeCapabilityCount]] plus [[errorTolerance]].
15143
- */
15144
- async function* yieldNodesUntilCapabilitiesFulfilled(wantedNodeCapabilityCount, errorTolerance, getNode) {
15145
- const wanted = {
15146
- relay: wantedNodeCapabilityCount.relay ?? 0,
15147
- store: wantedNodeCapabilityCount.store ?? 0,
15148
- filter: wantedNodeCapabilityCount.filter ?? 0,
15149
- lightPush: wantedNodeCapabilityCount.lightPush ?? 0
15150
- };
15151
- const maxSearches = wanted.relay + wanted.store + wanted.filter + wanted.lightPush;
15152
- const actual = {
15153
- relay: 0,
15154
- store: 0,
15155
- filter: 0,
15156
- lightPush: 0
15157
- };
15158
- let totalSearches = 0;
15159
- const peerNodeIds = new Set();
15160
- while (!isSatisfied(wanted, actual) &&
15161
- totalSearches < maxSearches + errorTolerance) {
15162
15126
  const peer = await getNode();
15163
- if (peer && peer.nodeId && !peerNodeIds.has(peer.nodeId)) {
15127
+ if (!peer || !peer.nodeId) {
15128
+ erroneousSearches++;
15129
+ continue;
15130
+ }
15131
+ if (!peerNodeIds.has(peer.nodeId)) {
15164
15132
  peerNodeIds.add(peer.nodeId);
15165
15133
  // ENRs without a waku2 key are ignored.
15166
15134
  if (peer.waku2) {
15167
- if (helpsSatisfyCapabilities(peer.waku2, wanted, actual)) {
15168
- addCapabilities(peer.waku2, actual);
15169
- yield peer;
15170
- }
15135
+ yield peer;
15171
15136
  }
15172
15137
  log$5.info(`got new peer candidate from DNS address=${peer.nodeId}@${peer.ip}`);
15173
15138
  }
15174
- totalSearches++;
15175
- }
15176
- }
15177
- function isSatisfied(wanted, actual) {
15178
- return (actual.relay >= wanted.relay &&
15179
- actual.store >= wanted.store &&
15180
- actual.filter >= wanted.filter &&
15181
- actual.lightPush >= wanted.lightPush);
15182
- }
15183
- function isNewPeer(peer, peers) {
15184
- if (!peer.nodeId)
15185
- return false;
15186
- for (const existingPeer of peers) {
15187
- if (peer.nodeId === existingPeer.nodeId) {
15188
- return false;
15189
- }
15190
15139
  }
15191
- return true;
15192
- }
15193
- function addCapabilities(node, total) {
15194
- if (node.relay)
15195
- total.relay += 1;
15196
- if (node.store)
15197
- total.store += 1;
15198
- if (node.filter)
15199
- total.filter += 1;
15200
- if (node.lightPush)
15201
- total.lightPush += 1;
15202
- }
15203
- /**
15204
- * Checks if the proposed ENR [[node]] helps satisfy the [[wanted]] capabilities,
15205
- * considering the [[actual]] capabilities of nodes retrieved so far..
15206
- *
15207
- * @throws If the function is called when the wanted capabilities are already fulfilled.
15208
- */
15209
- function helpsSatisfyCapabilities(node, wanted, actual) {
15210
- if (isSatisfied(wanted, actual)) {
15211
- throw "Internal Error: Waku2 wanted capabilities are already fulfilled";
15212
- }
15213
- const missing = missingCapabilities(wanted, actual);
15214
- return ((missing.relay && node.relay) ||
15215
- (missing.store && node.store) ||
15216
- (missing.filter && node.filter) ||
15217
- (missing.lightPush && node.lightPush));
15218
- }
15219
- /**
15220
- * Return a [[Waku2]] Object for which capabilities are set to true if they are
15221
- * [[wanted]] yet missing from [[actual]].
15222
- */
15223
- function missingCapabilities(wanted, actual) {
15224
- return {
15225
- relay: actual.relay < wanted.relay,
15226
- store: actual.store < wanted.store,
15227
- filter: actual.filter < wanted.filter,
15228
- lightPush: actual.lightPush < wanted.lightPush
15229
- };
15230
15140
  }
15231
15141
 
15232
15142
  const log$4 = new Logger$1("discovery:dns");
15233
15143
  class DnsNodeDiscovery {
15234
15144
  dns;
15235
15145
  _DNSTreeCache;
15236
- _errorTolerance = 10;
15237
15146
  static async dnsOverHttp(dnsClient) {
15238
15147
  if (!dnsClient) {
15239
15148
  dnsClient = await DnsOverHttps.create();
15240
15149
  }
15241
15150
  return new DnsNodeDiscovery(dnsClient);
15242
15151
  }
15243
- /**
15244
- * Returns a list of verified peers listed in an EIP-1459 DNS tree. Method may
15245
- * return fewer peers than requested if @link wantedNodeCapabilityCount requires
15246
- * larger quantity of peers than available or the number of errors/duplicate
15247
- * peers encountered by randomized search exceeds the sum of the fields of
15248
- * @link wantedNodeCapabilityCount plus the @link _errorTolerance factor.
15249
- */
15250
- async getPeers(enrTreeUrls, wantedNodeCapabilityCount) {
15251
- const networkIndex = Math.floor(Math.random() * enrTreeUrls.length);
15252
- const { publicKey, domain } = ENRTree.parseTree(enrTreeUrls[networkIndex]);
15253
- const context = {
15254
- domain,
15255
- publicKey,
15256
- visits: {}
15257
- };
15258
- const peers = await fetchNodesUntilCapabilitiesFulfilled(wantedNodeCapabilityCount, this._errorTolerance, () => this._search(domain, context));
15259
- log$4.info("retrieved peers: ", peers.map((peer) => {
15260
- return {
15261
- id: peer.peerId?.toString(),
15262
- multiaddrs: peer.multiaddrs?.map((ma) => ma.toString())
15263
- };
15264
- }));
15265
- return peers;
15266
- }
15267
15152
  constructor(dns) {
15268
15153
  this._DNSTreeCache = {};
15269
15154
  this.dns = dns;
15270
15155
  }
15271
15156
  /**
15272
- * {@inheritDoc getPeers}
15157
+ * Retrieve the next peers from the passed [[enrTreeUrls]],
15273
15158
  */
15274
- async *getNextPeer(enrTreeUrls, wantedNodeCapabilityCount) {
15275
- const networkIndex = Math.floor(Math.random() * enrTreeUrls.length);
15276
- const { publicKey, domain } = ENRTree.parseTree(enrTreeUrls[networkIndex]);
15277
- const context = {
15278
- domain,
15279
- publicKey,
15280
- visits: {}
15281
- };
15282
- for await (const peer of yieldNodesUntilCapabilitiesFulfilled(wantedNodeCapabilityCount, this._errorTolerance, () => this._search(domain, context))) {
15283
- yield peer;
15159
+ async *getNextPeer(enrTreeUrls) {
15160
+ // Shuffle the ENR Trees so that not all clients connect to same nodes first.
15161
+ for (const enrTreeUrl of shuffle(enrTreeUrls)) {
15162
+ const { publicKey, domain } = ENRTree.parseTree(enrTreeUrl);
15163
+ const context = {
15164
+ domain,
15165
+ publicKey,
15166
+ visits: {}
15167
+ };
15168
+ for await (const peer of fetchNodes(() => this._search(domain, context))) {
15169
+ yield peer;
15170
+ }
15284
15171
  }
15285
15172
  }
15286
15173
  /**
@@ -15338,7 +15225,7 @@ class DnsNodeDiscovery {
15338
15225
  throw new Error("Received empty result array while fetching TXT record");
15339
15226
  if (!response[0].length)
15340
15227
  throw new Error("Received empty TXT record");
15341
- // Branch entries can be an array of strings of comma delimited subdomains, with
15228
+ // Branch entries can be an array of strings of comma-delimited subdomains, with
15342
15229
  // some subdomain strings split across the array elements
15343
15230
  const result = response.join("");
15344
15231
  this._DNSTreeCache[subdomain] = result;
@@ -15414,9 +15301,8 @@ class PeerDiscoveryDns extends TypedEventEmitter {
15414
15301
  let { enrUrls } = this._options;
15415
15302
  if (!Array.isArray(enrUrls))
15416
15303
  enrUrls = [enrUrls];
15417
- const { wantedNodeCapabilityCount } = this._options;
15418
15304
  const dns = await DnsNodeDiscovery.dnsOverHttp();
15419
- this.nextPeer = dns.getNextPeer.bind(dns, enrUrls, wantedNodeCapabilityCount);
15305
+ this.nextPeer = dns.getNextPeer.bind(dns, enrUrls);
15420
15306
  }
15421
15307
  for await (const peerEnr of this.nextPeer()) {
15422
15308
  if (!this._started) {
@@ -15433,8 +15319,8 @@ class PeerDiscoveryDns extends TypedEventEmitter {
15433
15319
  }
15434
15320
  };
15435
15321
  let isPeerChanged = false;
15436
- const isPeerExists = await this._components.peerStore.has(peerInfo.id);
15437
- if (isPeerExists) {
15322
+ const isPeerAlreadyInPeerStore = await this._components.peerStore.has(peerInfo.id);
15323
+ if (isPeerAlreadyInPeerStore) {
15438
15324
  const peer = await this._components.peerStore.get(peerInfo.id);
15439
15325
  const hasBootstrapTag = peer.tags.has(DEFAULT_BOOTSTRAP_TAG_NAME);
15440
15326
  if (!hasBootstrapTag) {
@@ -15473,10 +15359,17 @@ class PeerDiscoveryDns extends TypedEventEmitter {
15473
15359
  return DNS_DISCOVERY_TAG;
15474
15360
  }
15475
15361
  }
15476
- function wakuDnsDiscovery(enrUrls, wantedNodeCapabilityCount = DEFAULT_NODE_REQUIREMENTS) {
15477
- return (components) => new PeerDiscoveryDns(components, { enrUrls, wantedNodeCapabilityCount });
15362
+ function wakuDnsDiscovery(enrUrls) {
15363
+ return (components) => new PeerDiscoveryDns(components, { enrUrls });
15478
15364
  }
15479
15365
 
15366
+ // amount of peers available per specification
15367
+ const DEFAULT_PEER_EXCHANGE_REQUEST_NODES = 60;
15368
+ const DEFAULT_PEER_EXCHANGE_TAG_NAME = Tags.PEER_EXCHANGE;
15369
+ const DEFAULT_PEER_EXCHANGE_TAG_VALUE = 50;
15370
+ const DEFAULT_PEER_EXCHANGE_TAG_TTL = 30_000;
15371
+ const PeerExchangeCodec = "/vac/waku/peer-exchange/2.0.0-alpha1";
15372
+
15480
15373
  /* eslint-disable import/export */
15481
15374
  /* eslint-disable complexity */
15482
15375
  /* eslint-disable @typescript-eslint/no-namespace */
@@ -18020,6 +17913,10 @@ var SdsMessage;
18020
17913
  if (opts.lengthDelimited !== false) {
18021
17914
  w.fork();
18022
17915
  }
17916
+ if ((obj.senderId != null && obj.senderId !== '')) {
17917
+ w.uint32(10);
17918
+ w.string(obj.senderId);
17919
+ }
18023
17920
  if ((obj.messageId != null && obj.messageId !== '')) {
18024
17921
  w.uint32(18);
18025
17922
  w.string(obj.messageId);
@@ -18051,6 +17948,7 @@ var SdsMessage;
18051
17948
  }
18052
17949
  }, (reader, length, opts = {}) => {
18053
17950
  const obj = {
17951
+ senderId: '',
18054
17952
  messageId: '',
18055
17953
  channelId: '',
18056
17954
  causalHistory: []
@@ -18059,6 +17957,10 @@ var SdsMessage;
18059
17957
  while (reader.pos < end) {
18060
17958
  const tag = reader.uint32();
18061
17959
  switch (tag >>> 3) {
17960
+ case 1: {
17961
+ obj.senderId = reader.string();
17962
+ break;
17963
+ }
18062
17964
  case 2: {
18063
17965
  obj.messageId = reader.string();
18064
17966
  break;
@@ -19072,27 +18974,32 @@ class StreamManager {
19072
18974
  this.libp2p.events.addEventListener("peer:update", this.handlePeerUpdateStreamPool);
19073
18975
  }
19074
18976
  async getStream(peerId) {
19075
- const peerIdStr = peerId.toString();
19076
- const scheduledStream = this.streamPool.get(peerIdStr);
19077
- if (scheduledStream) {
19078
- this.streamPool.delete(peerIdStr);
19079
- await scheduledStream;
19080
- }
19081
- let stream = this.getOpenStreamForCodec(peerId);
19082
- if (stream) {
19083
- this.log.info(`Found existing stream peerId=${peerIdStr} multicodec=${this.multicodec}`);
18977
+ try {
18978
+ const peerIdStr = peerId.toString();
18979
+ const scheduledStream = this.streamPool.get(peerIdStr);
18980
+ if (scheduledStream) {
18981
+ this.streamPool.delete(peerIdStr);
18982
+ await scheduledStream;
18983
+ }
18984
+ const stream = this.getOpenStreamForCodec(peerId) || (await this.createStream(peerId));
18985
+ if (!stream) {
18986
+ return;
18987
+ }
18988
+ this.log.info(`Using stream for peerId=${peerIdStr} multicodec=${this.multicodec}`);
19084
18989
  this.lockStream(peerIdStr, stream);
19085
18990
  return stream;
19086
18991
  }
19087
- stream = await this.createStream(peerId);
19088
- this.lockStream(peerIdStr, stream);
19089
- return stream;
18992
+ catch (error) {
18993
+ this.log.error(`Failed to getStream:`, error);
18994
+ return;
18995
+ }
19090
18996
  }
19091
18997
  async createStream(peerId, retries = 0) {
19092
18998
  const connections = this.libp2p.connectionManager.getConnections(peerId);
19093
18999
  const connection = selectOpenConnection(connections);
19094
19000
  if (!connection) {
19095
- throw new Error(`Failed to get a connection to the peer peerId=${peerId.toString()} multicodec=${this.multicodec}`);
19001
+ this.log.error(`Failed to get a connection to the peer peerId=${peerId.toString()} multicodec=${this.multicodec}`);
19002
+ return;
19096
19003
  }
19097
19004
  let lastError;
19098
19005
  let stream;
@@ -19108,7 +19015,8 @@ class StreamManager {
19108
19015
  }
19109
19016
  }
19110
19017
  if (!stream) {
19111
- throw new Error(`Failed to create a new stream for ${peerId.toString()} -- ` + lastError);
19018
+ this.log.error(`Failed to create a new stream for ${peerId.toString()} -- ` + lastError);
19019
+ return;
19112
19020
  }
19113
19021
  return stream;
19114
19022
  }
@@ -19153,16 +19061,20 @@ class StreamManager {
19153
19061
  const connections = this.libp2p.connectionManager.getConnections(peerId);
19154
19062
  const connection = selectOpenConnection(connections);
19155
19063
  if (!connection) {
19064
+ this.log.info(`No open connection found for peerId=${peerId.toString()} multicodec=${this.multicodec}`);
19156
19065
  return;
19157
19066
  }
19158
19067
  const stream = connection.streams.find((s) => s.protocol === this.multicodec);
19159
19068
  if (!stream) {
19069
+ this.log.info(`No open stream found for peerId=${peerId.toString()} multicodec=${this.multicodec}`);
19160
19070
  return;
19161
19071
  }
19162
19072
  const isStreamUnusable = ["done", "closed", "closing"].includes(stream.writeStatus || "");
19163
19073
  if (isStreamUnusable || this.isStreamLocked(stream)) {
19074
+ this.log.info(`Stream for peerId=${peerId.toString()} multicodec=${this.multicodec} is unusable`);
19164
19075
  return;
19165
19076
  }
19077
+ this.log.info(`Found open stream for peerId=${peerId.toString()} multicodec=${this.multicodec}`);
19166
19078
  return stream;
19167
19079
  }
19168
19080
  lockStream(peerId, stream) {
@@ -19234,12 +19146,11 @@ class PeerExchangeRPC {
19234
19146
  }
19235
19147
  }
19236
19148
 
19237
- const PeerExchangeCodec = "/vac/waku/peer-exchange/2.0.0-alpha1";
19238
19149
  const log$2 = new Logger$1("peer-exchange");
19239
19150
  /**
19240
19151
  * Implementation of the Peer Exchange protocol (https://rfc.vac.dev/spec/34/)
19241
19152
  */
19242
- class WakuPeerExchange {
19153
+ class PeerExchange {
19243
19154
  components;
19244
19155
  streamManager;
19245
19156
  /**
@@ -19257,19 +19168,16 @@ class WakuPeerExchange {
19257
19168
  const rpcQuery = PeerExchangeRPC.createRequest({
19258
19169
  numPeers: BigInt(numPeers)
19259
19170
  });
19260
- const peer = await this.components.peerStore.get(peerId);
19261
- if (!peer) {
19171
+ const hasPeer = await this.components.peerStore.has(peerId);
19172
+ if (!hasPeer) {
19262
19173
  return {
19263
19174
  peerInfos: null,
19264
19175
  error: ProtocolError.NO_PEER_AVAILABLE
19265
19176
  };
19266
19177
  }
19267
- let stream;
19268
- try {
19269
- stream = await this.streamManager.getStream(peerId);
19270
- }
19271
- catch (err) {
19272
- log$2.error("Failed to get stream", err);
19178
+ const stream = await this.streamManager.getStream(peerId);
19179
+ if (!stream) {
19180
+ log$2.error(`Failed to get a stream for remote peer:${peerId?.toString?.()}`);
19273
19181
  return {
19274
19182
  peerInfos: null,
19275
19183
  error: ProtocolError.NO_STREAM_AVAILABLE
@@ -19309,64 +19217,56 @@ class WakuPeerExchange {
19309
19217
  }
19310
19218
  }
19311
19219
  }
19312
- /**
19313
- *
19314
- * @returns A function that creates a new peer exchange protocol
19315
- */
19316
- function wakuPeerExchange() {
19317
- return (components) => new WakuPeerExchange(components);
19318
- }
19319
19220
 
19320
19221
  const log$1 = new Logger$1("peer-exchange-discovery");
19321
- const DEFAULT_PEER_EXCHANGE_REQUEST_NODES = 10;
19322
- const DEFAULT_PEER_EXCHANGE_QUERY_INTERVAL_MS = 10 * 1000;
19323
- const DEFAULT_MAX_RETRIES = 3;
19324
- const DEFAULT_PEER_EXCHANGE_TAG_NAME = Tags.PEER_EXCHANGE;
19325
- const DEFAULT_PEER_EXCHANGE_TAG_VALUE = 50;
19326
- const DEFAULT_PEER_EXCHANGE_TAG_TTL = 100_000_000;
19327
19222
  class PeerExchangeDiscovery extends TypedEventEmitter {
19328
19223
  components;
19329
19224
  peerExchange;
19330
19225
  options;
19331
- isStarted;
19226
+ isStarted = false;
19332
19227
  queryingPeers = new Set();
19333
- queryAttempts = new Map();
19334
- handleDiscoveredPeer = (event) => {
19335
- const { protocols, peerId } = event.detail;
19336
- if (!protocols.includes(PeerExchangeCodec) ||
19337
- this.queryingPeers.has(peerId.toString()))
19338
- return;
19339
- this.queryingPeers.add(peerId.toString());
19340
- this.startRecurringQueries(peerId).catch((error) => log$1.error(`Error querying peer ${error}`));
19341
- };
19228
+ peerExpirationRecords = new Map();
19229
+ continuousDiscoveryInterval = null;
19342
19230
  constructor(components, options = {}) {
19343
19231
  super();
19344
19232
  this.components = components;
19345
- this.peerExchange = new WakuPeerExchange(components);
19346
- this.options = options;
19347
- this.isStarted = false;
19233
+ this.peerExchange = new PeerExchange(components);
19234
+ this.options = {
19235
+ ...options,
19236
+ TTL: options.TTL ?? DEFAULT_PEER_EXCHANGE_TAG_TTL
19237
+ };
19238
+ this.handleDiscoveredPeer = this.handleDiscoveredPeer.bind(this);
19348
19239
  }
19349
19240
  /**
19350
- * Start emitting events
19241
+ * Start Peer Exchange.
19242
+ * Subscribe to "peer:identify" events and handle them.
19351
19243
  */
19352
19244
  start() {
19353
19245
  if (this.isStarted) {
19354
19246
  return;
19355
19247
  }
19356
- this.dispatchEvent(new CustomEvent("waku:peer-exchange:started", { detail: true }));
19357
19248
  log$1.info("Starting peer exchange node discovery, discovering peers");
19358
- // might be better to use "peer:identify" or "peer:update"
19249
+ this.isStarted = true;
19359
19250
  this.components.events.addEventListener("peer:identify", this.handleDiscoveredPeer);
19251
+ this.continuousDiscoveryInterval = setInterval(() => {
19252
+ void this.handlePeriodicDiscovery();
19253
+ }, this.options.TTL);
19360
19254
  }
19361
19255
  /**
19362
- * Remove event listener
19256
+ * Stop Peer Exchange.
19257
+ * Unsubscribe from "peer:identify" events.
19363
19258
  */
19364
19259
  stop() {
19365
- if (!this.isStarted)
19260
+ if (!this.isStarted) {
19366
19261
  return;
19262
+ }
19367
19263
  log$1.info("Stopping peer exchange node discovery");
19368
19264
  this.isStarted = false;
19369
19265
  this.queryingPeers.clear();
19266
+ this.peerExpirationRecords.clear();
19267
+ if (this.continuousDiscoveryInterval) {
19268
+ clearInterval(this.continuousDiscoveryInterval);
19269
+ }
19370
19270
  this.components.events.removeEventListener("peer:identify", this.handleDiscoveredPeer);
19371
19271
  }
19372
19272
  get [peerDiscoverySymbol]() {
@@ -19375,228 +19275,268 @@ class PeerExchangeDiscovery extends TypedEventEmitter {
19375
19275
  get [Symbol.toStringTag]() {
19376
19276
  return "@waku/peer-exchange";
19377
19277
  }
19378
- startRecurringQueries = async (peerId) => {
19379
- const peerIdStr = peerId.toString();
19380
- const { queryInterval = DEFAULT_PEER_EXCHANGE_QUERY_INTERVAL_MS, maxRetries = DEFAULT_MAX_RETRIES } = this.options;
19381
- log$1.info(`Querying peer: ${peerIdStr} (attempt ${this.queryAttempts.get(peerIdStr) ?? 1})`);
19382
- await this.query(peerId);
19383
- const currentAttempt = this.queryAttempts.get(peerIdStr) ?? 1;
19384
- if (currentAttempt > maxRetries) {
19385
- this.abortQueriesForPeer(peerIdStr);
19278
+ async handleDiscoveredPeer(event) {
19279
+ void this.runQuery(event.detail.peerId, event.detail.protocols);
19280
+ }
19281
+ async handlePeriodicDiscovery() {
19282
+ const connections = this.components.connectionManager.getConnections();
19283
+ await Promise.all(connections.map(async (connection) => {
19284
+ try {
19285
+ const peerIdStr = connection.remotePeer.toString();
19286
+ const shouldQuery = this.peerExpirationRecords.has(peerIdStr)
19287
+ ? this.peerExpirationRecords.get(peerIdStr) <= Date.now()
19288
+ : true;
19289
+ if (!shouldQuery) {
19290
+ return null;
19291
+ }
19292
+ const peer = await this.components.peerStore.get(connection.remotePeer);
19293
+ return this.runQuery(connection.remotePeer, peer.protocols);
19294
+ }
19295
+ catch (error) {
19296
+ log$1.warn("Error getting peer info", error);
19297
+ return null;
19298
+ }
19299
+ }));
19300
+ }
19301
+ async runQuery(peerId, protocols) {
19302
+ if (!protocols.includes(PeerExchangeCodec) ||
19303
+ this.queryingPeers.has(peerId.toString())) {
19304
+ log$1.info(`Skipping peer ${peerId} as it is already querying or does not support peer exchange`);
19386
19305
  return;
19387
19306
  }
19388
- setTimeout(() => {
19389
- this.queryAttempts.set(peerIdStr, currentAttempt + 1);
19390
- this.startRecurringQueries(peerId).catch((error) => {
19391
- log$1.error(`Error in startRecurringQueries: ${error}`);
19392
- });
19393
- }, queryInterval * currentAttempt);
19394
- };
19307
+ try {
19308
+ this.queryingPeers.add(peerId.toString());
19309
+ await this.query(peerId);
19310
+ }
19311
+ catch (error) {
19312
+ log$1.error("Error querying peer", error);
19313
+ }
19314
+ this.peerExpirationRecords.set(peerId.toString(), Date.now() + this.options.TTL);
19315
+ this.queryingPeers.delete(peerId.toString());
19316
+ }
19395
19317
  async query(peerId) {
19318
+ const peerIdStr = peerId.toString();
19319
+ log$1.info(`Querying peer exchange for ${peerIdStr}`);
19396
19320
  const { error, peerInfos } = await this.peerExchange.query({
19397
19321
  numPeers: DEFAULT_PEER_EXCHANGE_REQUEST_NODES,
19398
19322
  peerId
19399
19323
  });
19400
19324
  if (error) {
19401
- log$1.error("Peer exchange query failed", error);
19402
- return { error, peerInfos: null };
19325
+ log$1.error(`Peer exchange query to ${peerIdStr} failed`, error);
19326
+ return;
19403
19327
  }
19404
- for (const _peerInfo of peerInfos) {
19405
- const { ENR } = _peerInfo;
19328
+ for (const { ENR } of peerInfos) {
19406
19329
  if (!ENR) {
19407
- log$1.warn("No ENR in peerInfo object, skipping");
19330
+ log$1.warn(`No ENR in peerInfo object from ${peerIdStr}, skipping`);
19408
19331
  continue;
19409
19332
  }
19410
- const { peerId, peerInfo, shardInfo } = ENR;
19411
- if (!peerId || !peerInfo) {
19333
+ const { peerInfo, shardInfo } = ENR;
19334
+ if (!peerInfo) {
19335
+ log$1.warn(`No peerInfo in ENR from ${peerIdStr}, skipping`);
19412
19336
  continue;
19413
19337
  }
19414
- const hasPeer = await this.components.peerStore.has(peerId);
19415
- if (hasPeer) {
19416
- const { hasMultiaddrDiff, hasShardDiff } = await this.checkPeerInfoDiff(peerInfo, shardInfo);
19417
- if (hasMultiaddrDiff || hasShardDiff) {
19418
- log$1.info(`Peer ${peerId.toString()} has updated multiaddrs or shardInfo, updating`);
19419
- if (hasMultiaddrDiff) {
19420
- log$1.info(`Peer ${peerId.toString()} has updated multiaddrs, updating`);
19421
- await this.components.peerStore.patch(peerId, {
19422
- multiaddrs: peerInfo.multiaddrs
19423
- });
19424
- }
19425
- if (hasShardDiff && shardInfo) {
19426
- log$1.info(`Peer ${peerId.toString()} has updated shardInfo, updating`);
19427
- await this.components.peerStore.merge(peerId, {
19428
- metadata: {
19429
- shardInfo: encodeRelayShard(shardInfo)
19430
- }
19431
- });
19432
- this.dispatchEvent(new CustomEvent("peer", {
19433
- detail: {
19434
- id: peerId,
19435
- multiaddrs: peerInfo.multiaddrs
19436
- }
19437
- }));
19438
- }
19439
- continue;
19440
- }
19441
- }
19442
- // update the tags for the peer
19443
- await this.components.peerStore.save(peerId, {
19338
+ const hasPrevShardInfo = await this.hasShardInfo(peerInfo.id);
19339
+ const metadata = !hasPrevShardInfo && shardInfo
19340
+ ? { metadata: { shardInfo: encodeRelayShard(shardInfo) } }
19341
+ : undefined;
19342
+ // merge is smart enough to overwrite only changed parts
19343
+ await this.components.peerStore.merge(peerInfo.id, {
19444
19344
  tags: {
19445
19345
  [DEFAULT_PEER_EXCHANGE_TAG_NAME]: {
19446
- value: this.options.tagValue ?? DEFAULT_PEER_EXCHANGE_TAG_VALUE,
19447
- ttl: this.options.tagTTL ?? DEFAULT_PEER_EXCHANGE_TAG_TTL
19346
+ value: DEFAULT_PEER_EXCHANGE_TAG_VALUE
19448
19347
  }
19449
19348
  },
19450
- ...(shardInfo && {
19451
- metadata: {
19452
- shardInfo: encodeRelayShard(shardInfo)
19453
- }
19454
- }),
19349
+ ...metadata,
19455
19350
  ...(peerInfo.multiaddrs && {
19456
19351
  multiaddrs: peerInfo.multiaddrs
19457
19352
  })
19458
19353
  });
19459
- log$1.info(`Discovered peer: ${peerId.toString()}`);
19354
+ log$1.info(`Discovered peer: ${peerInfo.id.toString()}`);
19460
19355
  this.dispatchEvent(new CustomEvent("peer", {
19461
19356
  detail: {
19462
- id: peerId,
19357
+ id: peerInfo.id,
19463
19358
  multiaddrs: peerInfo.multiaddrs
19464
19359
  }
19465
19360
  }));
19466
19361
  }
19467
- return { error: null, peerInfos };
19468
- }
19469
- abortQueriesForPeer(peerIdStr) {
19470
- log$1.info(`Aborting queries for peer: ${peerIdStr}`);
19471
- this.queryingPeers.delete(peerIdStr);
19472
- this.queryAttempts.delete(peerIdStr);
19473
- }
19474
- async checkPeerInfoDiff(peerInfo, shardInfo) {
19475
- const { id: peerId } = peerInfo;
19476
- const peer = await this.components.peerStore.get(peerId);
19477
- const existingMultiaddrs = peer.addresses.map((a) => a.multiaddr.toString());
19478
- const newMultiaddrs = peerInfo.multiaddrs.map((ma) => ma.toString());
19479
- const hasMultiaddrDiff = existingMultiaddrs.some((ma) => !newMultiaddrs.includes(ma));
19480
- let hasShardDiff = false;
19481
- const existingShardInfoBytes = peer.metadata.get("shardInfo");
19482
- if (existingShardInfoBytes) {
19483
- const existingShardInfo = decodeRelayShard(existingShardInfoBytes);
19484
- if (existingShardInfo || shardInfo) {
19485
- hasShardDiff =
19486
- existingShardInfo.clusterId !== shardInfo?.clusterId ||
19487
- existingShardInfo.shards.some((shard) => !shardInfo?.shards.includes(shard));
19362
+ }
19363
+ async hasShardInfo(peerId) {
19364
+ try {
19365
+ const peer = await this.components.peerStore.get(peerId);
19366
+ if (!peer) {
19367
+ return false;
19488
19368
  }
19369
+ return peer.metadata.has("shardInfo");
19370
+ }
19371
+ catch (err) {
19372
+ log$1.warn(`Error getting shard info for ${peerId.toString()}`, err);
19489
19373
  }
19490
- return { hasMultiaddrDiff, hasShardDiff };
19374
+ return false;
19491
19375
  }
19492
19376
  }
19493
- function wakuPeerExchangeDiscovery() {
19494
- return (components) => new PeerExchangeDiscovery(components);
19377
+ function wakuPeerExchangeDiscovery(options = {}) {
19378
+ return (components) => new PeerExchangeDiscovery(components, options);
19379
+ }
19380
+
19381
+ const DEFAULT_PEER_CACHE_TAG_NAME = Tags.PEER_CACHE;
19382
+ const DEFAULT_PEER_CACHE_TAG_VALUE = 50;
19383
+
19384
+ const isValidStoredPeer = (peer) => {
19385
+ return (!!peer &&
19386
+ typeof peer === "object" &&
19387
+ "id" in peer &&
19388
+ typeof peer.id === "string" &&
19389
+ "multiaddrs" in peer &&
19390
+ Array.isArray(peer.multiaddrs));
19391
+ };
19392
+ /**
19393
+ * A noop cache that will be used in environments where localStorage is not available.
19394
+ */
19395
+ class NoopCache {
19396
+ get() {
19397
+ return [];
19398
+ }
19399
+ set(_value) {
19400
+ return;
19401
+ }
19402
+ remove() {
19403
+ return;
19404
+ }
19405
+ }
19406
+ /**
19407
+ * A cache that uses localStorage to store peer information.
19408
+ */
19409
+ class LocalStorageCache {
19410
+ get() {
19411
+ try {
19412
+ const cachedPeers = localStorage.getItem("waku:peers");
19413
+ const peers = cachedPeers ? JSON.parse(cachedPeers) : [];
19414
+ return peers.filter(isValidStoredPeer);
19415
+ }
19416
+ catch (e) {
19417
+ return [];
19418
+ }
19419
+ }
19420
+ set(_value) {
19421
+ try {
19422
+ localStorage.setItem("waku:peers", JSON.stringify(_value));
19423
+ }
19424
+ catch (e) {
19425
+ // ignore
19426
+ }
19427
+ }
19428
+ remove() {
19429
+ try {
19430
+ localStorage.removeItem("waku:peers");
19431
+ }
19432
+ catch (e) {
19433
+ // ignore
19434
+ }
19435
+ }
19495
19436
  }
19437
+ const defaultCache = () => {
19438
+ try {
19439
+ if (typeof localStorage !== "undefined") {
19440
+ return new LocalStorageCache();
19441
+ }
19442
+ }
19443
+ catch (_e) {
19444
+ // ignore
19445
+ }
19446
+ return new NoopCache();
19447
+ };
19496
19448
 
19497
- const log = new Logger$1("local-cache-discovery");
19498
- const DEFAULT_LOCAL_TAG_NAME = Tags.LOCAL;
19499
- const DEFAULT_LOCAL_TAG_VALUE = 50;
19500
- const DEFAULT_LOCAL_TAG_TTL = 100_000_000;
19501
- class LocalPeerCacheDiscovery extends TypedEventEmitter {
19449
+ const log = new Logger$1("peer-cache");
19450
+ class PeerCacheDiscovery extends TypedEventEmitter {
19502
19451
  components;
19503
- options;
19504
- isStarted;
19505
- peers = [];
19452
+ isStarted = false;
19453
+ cache;
19506
19454
  constructor(components, options) {
19507
19455
  super();
19508
19456
  this.components = components;
19509
- this.options = options;
19510
- this.isStarted = false;
19511
- this.peers = this.getPeersFromLocalStorage();
19457
+ this.cache = options?.cache ?? defaultCache();
19512
19458
  }
19513
19459
  get [Symbol.toStringTag]() {
19514
- return "@waku/local-peer-cache-discovery";
19460
+ return `@waku/${DEFAULT_PEER_CACHE_TAG_NAME}`;
19515
19461
  }
19516
19462
  async start() {
19517
- if (this.isStarted)
19463
+ if (this.isStarted) {
19518
19464
  return;
19519
- log.info("Starting Local Storage Discovery");
19520
- this.components.events.addEventListener("peer:identify", this.handleNewPeers);
19521
- for (const { id: idStr, address } of this.peers) {
19522
- const peerId = peerIdFromString(idStr);
19523
- if (await this.components.peerStore.has(peerId))
19524
- continue;
19525
- await this.components.peerStore.save(peerId, {
19526
- multiaddrs: [multiaddr(address)],
19527
- tags: {
19528
- [this.options?.tagName ?? DEFAULT_LOCAL_TAG_NAME]: {
19529
- value: this.options?.tagValue ?? DEFAULT_LOCAL_TAG_VALUE,
19530
- ttl: this.options?.tagTTL ?? DEFAULT_LOCAL_TAG_TTL
19531
- }
19532
- }
19533
- });
19534
- this.dispatchEvent(new CustomEvent("peer", {
19535
- detail: {
19536
- id: peerId,
19537
- multiaddrs: [multiaddr(address)]
19538
- }
19539
- }));
19540
19465
  }
19541
- log.info(`Discovered ${this.peers.length} peers`);
19466
+ log.info("Starting Peer Cache Discovery");
19467
+ this.components.events.addEventListener("peer:identify", this.handleDiscoveredPeer);
19468
+ await this.discoverPeers();
19542
19469
  this.isStarted = true;
19543
19470
  }
19544
19471
  stop() {
19545
- if (!this.isStarted)
19472
+ if (!this.isStarted) {
19546
19473
  return;
19547
- log.info("Stopping Local Storage Discovery");
19548
- this.components.events.removeEventListener("peer:identify", this.handleNewPeers);
19474
+ }
19475
+ log.info("Stopping Peer Cache Discovery");
19476
+ this.components.events.removeEventListener("peer:identify", this.handleDiscoveredPeer);
19549
19477
  this.isStarted = false;
19550
- this.savePeersToLocalStorage();
19551
19478
  }
19552
- handleNewPeers = (event) => {
19479
+ handleDiscoveredPeer = (event) => {
19553
19480
  const { peerId, listenAddrs } = event.detail;
19554
- const websocketMultiaddr = getWsMultiaddrFromMultiaddrs(listenAddrs);
19555
- const localStoragePeers = this.getPeersFromLocalStorage();
19556
- const existingPeerIndex = localStoragePeers.findIndex((_peer) => _peer.id === peerId.toString());
19557
- if (existingPeerIndex >= 0) {
19558
- localStoragePeers[existingPeerIndex].address =
19559
- websocketMultiaddr.toString();
19481
+ const multiaddrs = listenAddrs.map((addr) => addr.toString());
19482
+ const peerIdStr = peerId.toString();
19483
+ const knownPeers = this.readPeerInfoFromCache();
19484
+ const peerIndex = knownPeers.findIndex((p) => p.id === peerIdStr);
19485
+ if (peerIndex !== -1) {
19486
+ knownPeers[peerIndex].multiaddrs = multiaddrs;
19560
19487
  }
19561
19488
  else {
19562
- localStoragePeers.push({
19563
- id: peerId.toString(),
19564
- address: websocketMultiaddr.toString()
19489
+ knownPeers.push({
19490
+ id: peerIdStr,
19491
+ multiaddrs
19565
19492
  });
19566
19493
  }
19567
- this.peers = localStoragePeers;
19568
- this.savePeersToLocalStorage();
19494
+ this.writePeerInfoToCache(knownPeers);
19569
19495
  };
19570
- getPeersFromLocalStorage() {
19496
+ async discoverPeers() {
19497
+ const knownPeers = this.readPeerInfoFromCache();
19498
+ for (const peer of knownPeers) {
19499
+ const peerId = peerIdFromString(peer.id);
19500
+ const multiaddrs = peer.multiaddrs.map((addr) => multiaddr(addr));
19501
+ if (await this.components.peerStore.has(peerId)) {
19502
+ continue;
19503
+ }
19504
+ await this.components.peerStore.save(peerId, {
19505
+ multiaddrs,
19506
+ tags: {
19507
+ [DEFAULT_PEER_CACHE_TAG_NAME]: {
19508
+ value: DEFAULT_PEER_CACHE_TAG_VALUE
19509
+ }
19510
+ }
19511
+ });
19512
+ this.dispatchEvent(new CustomEvent("peer", {
19513
+ detail: {
19514
+ id: peerId,
19515
+ multiaddrs
19516
+ }
19517
+ }));
19518
+ }
19519
+ }
19520
+ readPeerInfoFromCache() {
19571
19521
  try {
19572
- const storedPeersData = localStorage.getItem("waku:peers");
19573
- if (!storedPeersData)
19574
- return [];
19575
- const peers = JSON.parse(storedPeersData);
19576
- return peers.filter(isValidStoredPeer);
19522
+ return this.cache.get();
19577
19523
  }
19578
19524
  catch (error) {
19579
- log.error("Error parsing peers from local storage:", error);
19525
+ log.error("Error parsing peers from cache:", error);
19580
19526
  return [];
19581
19527
  }
19582
19528
  }
19583
- savePeersToLocalStorage() {
19529
+ writePeerInfoToCache(peers) {
19584
19530
  try {
19585
- localStorage.setItem("waku:peers", JSON.stringify(this.peers));
19531
+ this.cache.set(peers);
19586
19532
  }
19587
19533
  catch (error) {
19588
- log.error("Error saving peers to local storage:", error);
19534
+ log.error("Error saving peers to cache:", error);
19589
19535
  }
19590
19536
  }
19591
19537
  }
19592
- function isValidStoredPeer(peer) {
19593
- return (peer &&
19594
- typeof peer === "object" &&
19595
- typeof peer.id === "string" &&
19596
- typeof peer.address === "string");
19597
- }
19598
- function wakuLocalPeerCacheDiscovery() {
19599
- return (components, options) => new LocalPeerCacheDiscovery(components, options);
19538
+ function wakuPeerCacheDiscovery(options = {}) {
19539
+ return (components) => new PeerCacheDiscovery(components, options);
19600
19540
  }
19601
19541
 
19602
- export { DnsNodeDiscovery, LocalPeerCacheDiscovery, PeerDiscoveryDns, PeerExchangeCodec, PeerExchangeDiscovery, WakuPeerExchange, enrTree, wakuDnsDiscovery, wakuLocalPeerCacheDiscovery, wakuPeerExchange, wakuPeerExchangeDiscovery };
19542
+ export { DnsNodeDiscovery, PeerCacheDiscovery, PeerDiscoveryDns, PeerExchangeCodec, PeerExchangeDiscovery, enrTree, wakuDnsDiscovery, wakuPeerCacheDiscovery, wakuPeerExchangeDiscovery };