@waku/core 0.0.22 → 0.0.24

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (73) hide show
  1. package/CHANGELOG.md +61 -0
  2. package/bundle/base_protocol-2a0c882e.js +1250 -0
  3. package/bundle/{browser-bde977a3.js → browser-90197c87.js} +26 -1
  4. package/bundle/index.js +20048 -3236
  5. package/bundle/lib/base_protocol.js +2 -116
  6. package/bundle/lib/message/version_0.js +2 -2
  7. package/bundle/lib/predefined_bootstrap_nodes.js +6 -6
  8. package/bundle/{version_0-86411fdf.js → version_0-f4afd324.js} +907 -814
  9. package/dist/.tsbuildinfo +1 -0
  10. package/dist/index.d.ts +5 -4
  11. package/dist/index.js +4 -3
  12. package/dist/index.js.map +1 -1
  13. package/dist/lib/base_protocol.d.ts +18 -5
  14. package/dist/lib/base_protocol.js +25 -8
  15. package/dist/lib/base_protocol.js.map +1 -1
  16. package/dist/lib/connection_manager.d.ts +15 -3
  17. package/dist/lib/connection_manager.js +92 -34
  18. package/dist/lib/connection_manager.js.map +1 -1
  19. package/dist/lib/filter/filter_rpc.js +4 -4
  20. package/dist/lib/filter/index.d.ts +4 -0
  21. package/dist/lib/filter/index.js +38 -29
  22. package/dist/lib/filter/index.js.map +1 -1
  23. package/dist/lib/filterPeers.d.ts +10 -0
  24. package/dist/lib/filterPeers.js +31 -0
  25. package/dist/lib/filterPeers.js.map +1 -0
  26. package/dist/lib/keep_alive_manager.d.ts +4 -2
  27. package/dist/lib/keep_alive_manager.js +62 -19
  28. package/dist/lib/keep_alive_manager.js.map +1 -1
  29. package/dist/lib/light_push/index.js +85 -38
  30. package/dist/lib/light_push/index.js.map +1 -1
  31. package/dist/lib/light_push/push_rpc.d.ts +1 -1
  32. package/dist/lib/light_push/push_rpc.js +3 -3
  33. package/dist/lib/message/version_0.d.ts +13 -13
  34. package/dist/lib/message/version_0.js +21 -18
  35. package/dist/lib/message/version_0.js.map +1 -1
  36. package/dist/lib/predefined_bootstrap_nodes.js +6 -6
  37. package/dist/lib/store/history_rpc.d.ts +1 -1
  38. package/dist/lib/store/history_rpc.js +4 -4
  39. package/dist/lib/store/index.d.ts +1 -6
  40. package/dist/lib/store/index.js +91 -47
  41. package/dist/lib/store/index.js.map +1 -1
  42. package/dist/lib/stream_manager.d.ts +15 -0
  43. package/dist/lib/stream_manager.js +56 -0
  44. package/dist/lib/stream_manager.js.map +1 -0
  45. package/dist/lib/to_proto_message.js +1 -1
  46. package/dist/lib/wait_for_remote_peer.d.ts +2 -2
  47. package/dist/lib/wait_for_remote_peer.js +10 -7
  48. package/dist/lib/wait_for_remote_peer.js.map +1 -1
  49. package/dist/lib/waku.d.ts +6 -5
  50. package/dist/lib/waku.js +6 -4
  51. package/dist/lib/waku.js.map +1 -1
  52. package/package.json +17 -33
  53. package/src/index.ts +6 -9
  54. package/src/lib/base_protocol.ts +49 -18
  55. package/src/lib/connection_manager.ts +132 -41
  56. package/src/lib/filter/filter_rpc.ts +4 -4
  57. package/src/lib/filter/index.ts +53 -41
  58. package/src/lib/filterPeers.ts +43 -0
  59. package/src/lib/keep_alive_manager.ts +79 -22
  60. package/src/lib/light_push/index.ts +132 -51
  61. package/src/lib/light_push/push_rpc.ts +3 -3
  62. package/src/lib/message/version_0.ts +27 -15
  63. package/src/lib/predefined_bootstrap_nodes.ts +7 -7
  64. package/src/lib/store/history_rpc.ts +6 -6
  65. package/src/lib/store/index.ts +121 -63
  66. package/src/lib/stream_manager.ts +72 -0
  67. package/src/lib/to_proto_message.ts +1 -1
  68. package/src/lib/wait_for_remote_peer.ts +11 -8
  69. package/src/lib/waku.ts +7 -4
  70. package/dist/lib/push_or_init_map.d.ts +0 -1
  71. package/dist/lib/push_or_init_map.js +0 -9
  72. package/dist/lib/push_or_init_map.js.map +0 -1
  73. package/src/lib/push_or_init_map.ts +0 -13
@@ -0,0 +1,1250 @@
1
+ import { d as debug } from './browser-90197c87.js';
2
+
3
+ // base-x encoding / decoding
4
+ // Copyright (c) 2018 base-x contributors
5
+ // Copyright (c) 2014-2018 The Bitcoin Core developers (base58.cpp)
6
+ // Distributed under the MIT software license, see the accompanying
7
+ // file LICENSE or http://www.opensource.org/licenses/mit-license.php.
8
+ function base (ALPHABET, name) {
9
+ if (ALPHABET.length >= 255) { throw new TypeError('Alphabet too long') }
10
+ var BASE_MAP = new Uint8Array(256);
11
+ for (var j = 0; j < BASE_MAP.length; j++) {
12
+ BASE_MAP[j] = 255;
13
+ }
14
+ for (var i = 0; i < ALPHABET.length; i++) {
15
+ var x = ALPHABET.charAt(i);
16
+ var xc = x.charCodeAt(0);
17
+ if (BASE_MAP[xc] !== 255) { throw new TypeError(x + ' is ambiguous') }
18
+ BASE_MAP[xc] = i;
19
+ }
20
+ var BASE = ALPHABET.length;
21
+ var LEADER = ALPHABET.charAt(0);
22
+ var FACTOR = Math.log(BASE) / Math.log(256); // log(BASE) / log(256), rounded up
23
+ var iFACTOR = Math.log(256) / Math.log(BASE); // log(256) / log(BASE), rounded up
24
+ function encode (source) {
25
+ if (source instanceof Uint8Array) ; else if (ArrayBuffer.isView(source)) {
26
+ source = new Uint8Array(source.buffer, source.byteOffset, source.byteLength);
27
+ } else if (Array.isArray(source)) {
28
+ source = Uint8Array.from(source);
29
+ }
30
+ if (!(source instanceof Uint8Array)) { throw new TypeError('Expected Uint8Array') }
31
+ if (source.length === 0) { return '' }
32
+ // Skip & count leading zeroes.
33
+ var zeroes = 0;
34
+ var length = 0;
35
+ var pbegin = 0;
36
+ var pend = source.length;
37
+ while (pbegin !== pend && source[pbegin] === 0) {
38
+ pbegin++;
39
+ zeroes++;
40
+ }
41
+ // Allocate enough space in big-endian base58 representation.
42
+ var size = ((pend - pbegin) * iFACTOR + 1) >>> 0;
43
+ var b58 = new Uint8Array(size);
44
+ // Process the bytes.
45
+ while (pbegin !== pend) {
46
+ var carry = source[pbegin];
47
+ // Apply "b58 = b58 * 256 + ch".
48
+ var i = 0;
49
+ for (var it1 = size - 1; (carry !== 0 || i < length) && (it1 !== -1); it1--, i++) {
50
+ carry += (256 * b58[it1]) >>> 0;
51
+ b58[it1] = (carry % BASE) >>> 0;
52
+ carry = (carry / BASE) >>> 0;
53
+ }
54
+ if (carry !== 0) { throw new Error('Non-zero carry') }
55
+ length = i;
56
+ pbegin++;
57
+ }
58
+ // Skip leading zeroes in base58 result.
59
+ var it2 = size - length;
60
+ while (it2 !== size && b58[it2] === 0) {
61
+ it2++;
62
+ }
63
+ // Translate the result into a string.
64
+ var str = LEADER.repeat(zeroes);
65
+ for (; it2 < size; ++it2) { str += ALPHABET.charAt(b58[it2]); }
66
+ return str
67
+ }
68
+ function decodeUnsafe (source) {
69
+ if (typeof source !== 'string') { throw new TypeError('Expected String') }
70
+ if (source.length === 0) { return new Uint8Array() }
71
+ var psz = 0;
72
+ // Skip leading spaces.
73
+ if (source[psz] === ' ') { return }
74
+ // Skip and count leading '1's.
75
+ var zeroes = 0;
76
+ var length = 0;
77
+ while (source[psz] === LEADER) {
78
+ zeroes++;
79
+ psz++;
80
+ }
81
+ // Allocate enough space in big-endian base256 representation.
82
+ var size = (((source.length - psz) * FACTOR) + 1) >>> 0; // log(58) / log(256), rounded up.
83
+ var b256 = new Uint8Array(size);
84
+ // Process the characters.
85
+ while (source[psz]) {
86
+ // Decode character
87
+ var carry = BASE_MAP[source.charCodeAt(psz)];
88
+ // Invalid character
89
+ if (carry === 255) { return }
90
+ var i = 0;
91
+ for (var it3 = size - 1; (carry !== 0 || i < length) && (it3 !== -1); it3--, i++) {
92
+ carry += (BASE * b256[it3]) >>> 0;
93
+ b256[it3] = (carry % 256) >>> 0;
94
+ carry = (carry / 256) >>> 0;
95
+ }
96
+ if (carry !== 0) { throw new Error('Non-zero carry') }
97
+ length = i;
98
+ psz++;
99
+ }
100
+ // Skip trailing spaces.
101
+ if (source[psz] === ' ') { return }
102
+ // Skip leading zeroes in b256.
103
+ var it4 = size - length;
104
+ while (it4 !== size && b256[it4] === 0) {
105
+ it4++;
106
+ }
107
+ var vch = new Uint8Array(zeroes + (size - it4));
108
+ var j = zeroes;
109
+ while (it4 !== size) {
110
+ vch[j++] = b256[it4++];
111
+ }
112
+ return vch
113
+ }
114
+ function decode (string) {
115
+ var buffer = decodeUnsafe(string);
116
+ if (buffer) { return buffer }
117
+ throw new Error(`Non-${name} character`)
118
+ }
119
+ return {
120
+ encode: encode,
121
+ decodeUnsafe: decodeUnsafe,
122
+ decode: decode
123
+ }
124
+ }
125
+ var src = base;
126
+
127
+ var _brrp__multiformats_scope_baseX = src;
128
+
129
+ /**
130
+ * @param {Uint8Array} aa
131
+ * @param {Uint8Array} bb
132
+ */
133
+ const equals = (aa, bb) => {
134
+ if (aa === bb) return true
135
+ if (aa.byteLength !== bb.byteLength) {
136
+ return false
137
+ }
138
+
139
+ for (let ii = 0; ii < aa.byteLength; ii++) {
140
+ if (aa[ii] !== bb[ii]) {
141
+ return false
142
+ }
143
+ }
144
+
145
+ return true
146
+ };
147
+
148
+ /**
149
+ * @param {ArrayBufferView|ArrayBuffer|Uint8Array} o
150
+ * @returns {Uint8Array}
151
+ */
152
+ const coerce = o => {
153
+ if (o instanceof Uint8Array && o.constructor.name === 'Uint8Array') return o
154
+ if (o instanceof ArrayBuffer) return new Uint8Array(o)
155
+ if (ArrayBuffer.isView(o)) {
156
+ return new Uint8Array(o.buffer, o.byteOffset, o.byteLength)
157
+ }
158
+ throw new Error('Unknown type, must be binary type')
159
+ };
160
+
161
+ /**
162
+ * @param {string} str
163
+ * @returns {Uint8Array}
164
+ */
165
+ const fromString$1 = str => (new TextEncoder()).encode(str);
166
+
167
+ /**
168
+ * @param {Uint8Array} b
169
+ * @returns {string}
170
+ */
171
+ const toString$1 = b => (new TextDecoder()).decode(b);
172
+
173
+ /**
174
+ * Class represents both BaseEncoder and MultibaseEncoder meaning it
175
+ * can be used to encode to multibase or base encode without multibase
176
+ * prefix.
177
+ *
178
+ * @class
179
+ * @template {string} Base
180
+ * @template {string} Prefix
181
+ * @implements {API.MultibaseEncoder<Prefix>}
182
+ * @implements {API.BaseEncoder}
183
+ */
184
+ class Encoder {
185
+ /**
186
+ * @param {Base} name
187
+ * @param {Prefix} prefix
188
+ * @param {(bytes:Uint8Array) => string} baseEncode
189
+ */
190
+ constructor (name, prefix, baseEncode) {
191
+ this.name = name;
192
+ this.prefix = prefix;
193
+ this.baseEncode = baseEncode;
194
+ }
195
+
196
+ /**
197
+ * @param {Uint8Array} bytes
198
+ * @returns {API.Multibase<Prefix>}
199
+ */
200
+ encode (bytes) {
201
+ if (bytes instanceof Uint8Array) {
202
+ return `${this.prefix}${this.baseEncode(bytes)}`
203
+ } else {
204
+ throw Error('Unknown type, must be binary type')
205
+ }
206
+ }
207
+ }
208
+
209
+ /**
210
+ * @template {string} Prefix
211
+ */
212
+ /**
213
+ * Class represents both BaseDecoder and MultibaseDecoder so it could be used
214
+ * to decode multibases (with matching prefix) or just base decode strings
215
+ * with corresponding base encoding.
216
+ *
217
+ * @class
218
+ * @template {string} Base
219
+ * @template {string} Prefix
220
+ * @implements {API.MultibaseDecoder<Prefix>}
221
+ * @implements {API.UnibaseDecoder<Prefix>}
222
+ * @implements {API.BaseDecoder}
223
+ */
224
+ class Decoder {
225
+ /**
226
+ * @param {Base} name
227
+ * @param {Prefix} prefix
228
+ * @param {(text:string) => Uint8Array} baseDecode
229
+ */
230
+ constructor (name, prefix, baseDecode) {
231
+ this.name = name;
232
+ this.prefix = prefix;
233
+ /* c8 ignore next 3 */
234
+ if (prefix.codePointAt(0) === undefined) {
235
+ throw new Error('Invalid prefix character')
236
+ }
237
+ /** @private */
238
+ this.prefixCodePoint = /** @type {number} */ (prefix.codePointAt(0));
239
+ this.baseDecode = baseDecode;
240
+ }
241
+
242
+ /**
243
+ * @param {string} text
244
+ */
245
+ decode (text) {
246
+ if (typeof text === 'string') {
247
+ if (text.codePointAt(0) !== this.prefixCodePoint) {
248
+ throw Error(`Unable to decode multibase string ${JSON.stringify(text)}, ${this.name} decoder only supports inputs prefixed with ${this.prefix}`)
249
+ }
250
+ return this.baseDecode(text.slice(this.prefix.length))
251
+ } else {
252
+ throw Error('Can only multibase decode strings')
253
+ }
254
+ }
255
+
256
+ /**
257
+ * @template {string} OtherPrefix
258
+ * @param {API.UnibaseDecoder<OtherPrefix>|ComposedDecoder<OtherPrefix>} decoder
259
+ * @returns {ComposedDecoder<Prefix|OtherPrefix>}
260
+ */
261
+ or (decoder) {
262
+ return or(this, decoder)
263
+ }
264
+ }
265
+
266
+ /**
267
+ * @template {string} Prefix
268
+ * @typedef {Record<Prefix, API.UnibaseDecoder<Prefix>>} Decoders
269
+ */
270
+
271
+ /**
272
+ * @template {string} Prefix
273
+ * @implements {API.MultibaseDecoder<Prefix>}
274
+ * @implements {API.CombobaseDecoder<Prefix>}
275
+ */
276
+ class ComposedDecoder {
277
+ /**
278
+ * @param {Decoders<Prefix>} decoders
279
+ */
280
+ constructor (decoders) {
281
+ this.decoders = decoders;
282
+ }
283
+
284
+ /**
285
+ * @template {string} OtherPrefix
286
+ * @param {API.UnibaseDecoder<OtherPrefix>|ComposedDecoder<OtherPrefix>} decoder
287
+ * @returns {ComposedDecoder<Prefix|OtherPrefix>}
288
+ */
289
+ or (decoder) {
290
+ return or(this, decoder)
291
+ }
292
+
293
+ /**
294
+ * @param {string} input
295
+ * @returns {Uint8Array}
296
+ */
297
+ decode (input) {
298
+ const prefix = /** @type {Prefix} */ (input[0]);
299
+ const decoder = this.decoders[prefix];
300
+ if (decoder) {
301
+ return decoder.decode(input)
302
+ } else {
303
+ throw RangeError(`Unable to decode multibase string ${JSON.stringify(input)}, only inputs prefixed with ${Object.keys(this.decoders)} are supported`)
304
+ }
305
+ }
306
+ }
307
+
308
+ /**
309
+ * @template {string} L
310
+ * @template {string} R
311
+ * @param {API.UnibaseDecoder<L>|API.CombobaseDecoder<L>} left
312
+ * @param {API.UnibaseDecoder<R>|API.CombobaseDecoder<R>} right
313
+ * @returns {ComposedDecoder<L|R>}
314
+ */
315
+ const or = (left, right) => new ComposedDecoder(/** @type {Decoders<L|R>} */({
316
+ ...(left.decoders || { [/** @type API.UnibaseDecoder<L> */(left).prefix]: left }),
317
+ ...(right.decoders || { [/** @type API.UnibaseDecoder<R> */(right).prefix]: right })
318
+ }));
319
+
320
+ /**
321
+ * @class
322
+ * @template {string} Base
323
+ * @template {string} Prefix
324
+ * @implements {API.MultibaseCodec<Prefix>}
325
+ * @implements {API.MultibaseEncoder<Prefix>}
326
+ * @implements {API.MultibaseDecoder<Prefix>}
327
+ * @implements {API.BaseCodec}
328
+ * @implements {API.BaseEncoder}
329
+ * @implements {API.BaseDecoder}
330
+ */
331
+ class Codec {
332
+ /**
333
+ * @param {Base} name
334
+ * @param {Prefix} prefix
335
+ * @param {(bytes:Uint8Array) => string} baseEncode
336
+ * @param {(text:string) => Uint8Array} baseDecode
337
+ */
338
+ constructor (name, prefix, baseEncode, baseDecode) {
339
+ this.name = name;
340
+ this.prefix = prefix;
341
+ this.baseEncode = baseEncode;
342
+ this.baseDecode = baseDecode;
343
+ this.encoder = new Encoder(name, prefix, baseEncode);
344
+ this.decoder = new Decoder(name, prefix, baseDecode);
345
+ }
346
+
347
+ /**
348
+ * @param {Uint8Array} input
349
+ */
350
+ encode (input) {
351
+ return this.encoder.encode(input)
352
+ }
353
+
354
+ /**
355
+ * @param {string} input
356
+ */
357
+ decode (input) {
358
+ return this.decoder.decode(input)
359
+ }
360
+ }
361
+
362
+ /**
363
+ * @template {string} Base
364
+ * @template {string} Prefix
365
+ * @param {object} options
366
+ * @param {Base} options.name
367
+ * @param {Prefix} options.prefix
368
+ * @param {(bytes:Uint8Array) => string} options.encode
369
+ * @param {(input:string) => Uint8Array} options.decode
370
+ * @returns {Codec<Base, Prefix>}
371
+ */
372
+ const from = ({ name, prefix, encode, decode }) =>
373
+ new Codec(name, prefix, encode, decode);
374
+
375
+ /**
376
+ * @template {string} Base
377
+ * @template {string} Prefix
378
+ * @param {object} options
379
+ * @param {Base} options.name
380
+ * @param {Prefix} options.prefix
381
+ * @param {string} options.alphabet
382
+ * @returns {Codec<Base, Prefix>}
383
+ */
384
+ const baseX = ({ prefix, name, alphabet }) => {
385
+ const { encode, decode } = _brrp__multiformats_scope_baseX(alphabet, name);
386
+ return from({
387
+ prefix,
388
+ name,
389
+ encode,
390
+ /**
391
+ * @param {string} text
392
+ */
393
+ decode: text => coerce(decode(text))
394
+ })
395
+ };
396
+
397
+ /**
398
+ * @param {string} string
399
+ * @param {string} alphabet
400
+ * @param {number} bitsPerChar
401
+ * @param {string} name
402
+ * @returns {Uint8Array}
403
+ */
404
+ const decode$1 = (string, alphabet, bitsPerChar, name) => {
405
+ // Build the character lookup table:
406
+ /** @type {Record<string, number>} */
407
+ const codes = {};
408
+ for (let i = 0; i < alphabet.length; ++i) {
409
+ codes[alphabet[i]] = i;
410
+ }
411
+
412
+ // Count the padding bytes:
413
+ let end = string.length;
414
+ while (string[end - 1] === '=') {
415
+ --end;
416
+ }
417
+
418
+ // Allocate the output:
419
+ const out = new Uint8Array((end * bitsPerChar / 8) | 0);
420
+
421
+ // Parse the data:
422
+ let bits = 0; // Number of bits currently in the buffer
423
+ let buffer = 0; // Bits waiting to be written out, MSB first
424
+ let written = 0; // Next byte to write
425
+ for (let i = 0; i < end; ++i) {
426
+ // Read one character from the string:
427
+ const value = codes[string[i]];
428
+ if (value === undefined) {
429
+ throw new SyntaxError(`Non-${name} character`)
430
+ }
431
+
432
+ // Append the bits to the buffer:
433
+ buffer = (buffer << bitsPerChar) | value;
434
+ bits += bitsPerChar;
435
+
436
+ // Write out some bits if the buffer has a byte's worth:
437
+ if (bits >= 8) {
438
+ bits -= 8;
439
+ out[written++] = 0xff & (buffer >> bits);
440
+ }
441
+ }
442
+
443
+ // Verify that we have received just enough bits:
444
+ if (bits >= bitsPerChar || 0xff & (buffer << (8 - bits))) {
445
+ throw new SyntaxError('Unexpected end of data')
446
+ }
447
+
448
+ return out
449
+ };
450
+
451
+ /**
452
+ * @param {Uint8Array} data
453
+ * @param {string} alphabet
454
+ * @param {number} bitsPerChar
455
+ * @returns {string}
456
+ */
457
+ const encode$1 = (data, alphabet, bitsPerChar) => {
458
+ const pad = alphabet[alphabet.length - 1] === '=';
459
+ const mask = (1 << bitsPerChar) - 1;
460
+ let out = '';
461
+
462
+ let bits = 0; // Number of bits currently in the buffer
463
+ let buffer = 0; // Bits waiting to be written out, MSB first
464
+ for (let i = 0; i < data.length; ++i) {
465
+ // Slurp data into the buffer:
466
+ buffer = (buffer << 8) | data[i];
467
+ bits += 8;
468
+
469
+ // Write out as much as we can:
470
+ while (bits > bitsPerChar) {
471
+ bits -= bitsPerChar;
472
+ out += alphabet[mask & (buffer >> bits)];
473
+ }
474
+ }
475
+
476
+ // Partial character:
477
+ if (bits) {
478
+ out += alphabet[mask & (buffer << (bitsPerChar - bits))];
479
+ }
480
+
481
+ // Add padding characters until we hit a byte boundary:
482
+ if (pad) {
483
+ while ((out.length * bitsPerChar) & 7) {
484
+ out += '=';
485
+ }
486
+ }
487
+
488
+ return out
489
+ };
490
+
491
+ /**
492
+ * RFC4648 Factory
493
+ *
494
+ * @template {string} Base
495
+ * @template {string} Prefix
496
+ * @param {object} options
497
+ * @param {Base} options.name
498
+ * @param {Prefix} options.prefix
499
+ * @param {string} options.alphabet
500
+ * @param {number} options.bitsPerChar
501
+ */
502
+ const rfc4648 = ({ name, prefix, bitsPerChar, alphabet }) => {
503
+ return from({
504
+ prefix,
505
+ name,
506
+ encode (input) {
507
+ return encode$1(input, alphabet, bitsPerChar)
508
+ },
509
+ decode (input) {
510
+ return decode$1(input, alphabet, bitsPerChar, name)
511
+ }
512
+ })
513
+ };
514
+
515
+ const base58btc = baseX({
516
+ name: 'base58btc',
517
+ prefix: 'z',
518
+ alphabet: '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'
519
+ });
520
+
521
+ const base58flickr = baseX({
522
+ name: 'base58flickr',
523
+ prefix: 'Z',
524
+ alphabet: '123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ'
525
+ });
526
+
527
+ var base58 = /*#__PURE__*/Object.freeze({
528
+ __proto__: null,
529
+ base58btc: base58btc,
530
+ base58flickr: base58flickr
531
+ });
532
+
533
+ const base32 = rfc4648({
534
+ prefix: 'b',
535
+ name: 'base32',
536
+ alphabet: 'abcdefghijklmnopqrstuvwxyz234567',
537
+ bitsPerChar: 5
538
+ });
539
+
540
+ const base32upper = rfc4648({
541
+ prefix: 'B',
542
+ name: 'base32upper',
543
+ alphabet: 'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567',
544
+ bitsPerChar: 5
545
+ });
546
+
547
+ const base32pad = rfc4648({
548
+ prefix: 'c',
549
+ name: 'base32pad',
550
+ alphabet: 'abcdefghijklmnopqrstuvwxyz234567=',
551
+ bitsPerChar: 5
552
+ });
553
+
554
+ const base32padupper = rfc4648({
555
+ prefix: 'C',
556
+ name: 'base32padupper',
557
+ alphabet: 'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567=',
558
+ bitsPerChar: 5
559
+ });
560
+
561
+ const base32hex = rfc4648({
562
+ prefix: 'v',
563
+ name: 'base32hex',
564
+ alphabet: '0123456789abcdefghijklmnopqrstuv',
565
+ bitsPerChar: 5
566
+ });
567
+
568
+ const base32hexupper = rfc4648({
569
+ prefix: 'V',
570
+ name: 'base32hexupper',
571
+ alphabet: '0123456789ABCDEFGHIJKLMNOPQRSTUV',
572
+ bitsPerChar: 5
573
+ });
574
+
575
+ const base32hexpad = rfc4648({
576
+ prefix: 't',
577
+ name: 'base32hexpad',
578
+ alphabet: '0123456789abcdefghijklmnopqrstuv=',
579
+ bitsPerChar: 5
580
+ });
581
+
582
+ const base32hexpadupper = rfc4648({
583
+ prefix: 'T',
584
+ name: 'base32hexpadupper',
585
+ alphabet: '0123456789ABCDEFGHIJKLMNOPQRSTUV=',
586
+ bitsPerChar: 5
587
+ });
588
+
589
+ const base32z = rfc4648({
590
+ prefix: 'h',
591
+ name: 'base32z',
592
+ alphabet: 'ybndrfg8ejkmcpqxot1uwisza345h769',
593
+ bitsPerChar: 5
594
+ });
595
+
596
+ var base32$1 = /*#__PURE__*/Object.freeze({
597
+ __proto__: null,
598
+ base32: base32,
599
+ base32hex: base32hex,
600
+ base32hexpad: base32hexpad,
601
+ base32hexpadupper: base32hexpadupper,
602
+ base32hexupper: base32hexupper,
603
+ base32pad: base32pad,
604
+ base32padupper: base32padupper,
605
+ base32upper: base32upper,
606
+ base32z: base32z
607
+ });
608
+
609
+ const base10 = baseX({
610
+ prefix: '9',
611
+ name: 'base10',
612
+ alphabet: '0123456789'
613
+ });
614
+
615
+ var base10$1 = /*#__PURE__*/Object.freeze({
616
+ __proto__: null,
617
+ base10: base10
618
+ });
619
+
620
+ // @ts-check
621
+
622
+
623
+ const base16 = rfc4648({
624
+ prefix: 'f',
625
+ name: 'base16',
626
+ alphabet: '0123456789abcdef',
627
+ bitsPerChar: 4
628
+ });
629
+
630
+ const base16upper = rfc4648({
631
+ prefix: 'F',
632
+ name: 'base16upper',
633
+ alphabet: '0123456789ABCDEF',
634
+ bitsPerChar: 4
635
+ });
636
+
637
+ var base16$1 = /*#__PURE__*/Object.freeze({
638
+ __proto__: null,
639
+ base16: base16,
640
+ base16upper: base16upper
641
+ });
642
+
643
+ // @ts-check
644
+
645
+
646
+ const base2 = rfc4648({
647
+ prefix: '0',
648
+ name: 'base2',
649
+ alphabet: '01',
650
+ bitsPerChar: 1
651
+ });
652
+
653
+ var base2$1 = /*#__PURE__*/Object.freeze({
654
+ __proto__: null,
655
+ base2: base2
656
+ });
657
+
658
+ const alphabet = Array.from('🚀🪐☄🛰🌌🌑🌒🌓🌔🌕🌖🌗🌘🌍🌏🌎🐉☀💻🖥💾💿😂❤😍🤣😊🙏💕😭😘👍😅👏😁🔥🥰💔💖💙😢🤔😆🙄💪😉☺👌🤗💜😔😎😇🌹🤦🎉💞✌✨🤷😱😌🌸🙌😋💗💚😏💛🙂💓🤩😄😀🖤😃💯🙈👇🎶😒🤭❣😜💋👀😪😑💥🙋😞😩😡🤪👊🥳😥🤤👉💃😳✋😚😝😴🌟😬🙃🍀🌷😻😓⭐✅🥺🌈😈🤘💦✔😣🏃💐☹🎊💘😠☝😕🌺🎂🌻😐🖕💝🙊😹🗣💫💀👑🎵🤞😛🔴😤🌼😫⚽🤙☕🏆🤫👈😮🙆🍻🍃🐶💁😲🌿🧡🎁⚡🌞🎈❌✊👋😰🤨😶🤝🚶💰🍓💢🤟🙁🚨💨🤬✈🎀🍺🤓😙💟🌱😖👶🥴▶➡❓💎💸⬇😨🌚🦋😷🕺⚠🙅😟😵👎🤲🤠🤧📌🔵💅🧐🐾🍒😗🤑🌊🤯🐷☎💧😯💆👆🎤🙇🍑❄🌴💣🐸💌📍🥀🤢👅💡💩👐📸👻🤐🤮🎼🥵🚩🍎🍊👼💍📣🥂');
659
+ const alphabetBytesToChars = /** @type {string[]} */ (alphabet.reduce((p, c, i) => { p[i] = c; return p }, /** @type {string[]} */([])));
660
+ const alphabetCharsToBytes = /** @type {number[]} */ (alphabet.reduce((p, c, i) => { p[/** @type {number} */ (c.codePointAt(0))] = i; return p }, /** @type {number[]} */([])));
661
+
662
+ /**
663
+ * @param {Uint8Array} data
664
+ * @returns {string}
665
+ */
666
+ function encode (data) {
667
+ return data.reduce((p, c) => {
668
+ p += alphabetBytesToChars[c];
669
+ return p
670
+ }, '')
671
+ }
672
+
673
+ /**
674
+ * @param {string} str
675
+ * @returns {Uint8Array}
676
+ */
677
+ function decode (str) {
678
+ const byts = [];
679
+ for (const char of str) {
680
+ const byt = alphabetCharsToBytes[/** @type {number} */ (char.codePointAt(0))];
681
+ if (byt === undefined) {
682
+ throw new Error(`Non-base256emoji character: ${char}`)
683
+ }
684
+ byts.push(byt);
685
+ }
686
+ return new Uint8Array(byts)
687
+ }
688
+
689
+ const base256emoji = from({
690
+ prefix: '🚀',
691
+ name: 'base256emoji',
692
+ encode,
693
+ decode
694
+ });
695
+
696
+ var base256emoji$1 = /*#__PURE__*/Object.freeze({
697
+ __proto__: null,
698
+ base256emoji: base256emoji
699
+ });
700
+
701
+ const base36 = baseX({
702
+ prefix: 'k',
703
+ name: 'base36',
704
+ alphabet: '0123456789abcdefghijklmnopqrstuvwxyz'
705
+ });
706
+
707
+ const base36upper = baseX({
708
+ prefix: 'K',
709
+ name: 'base36upper',
710
+ alphabet: '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'
711
+ });
712
+
713
+ var base36$1 = /*#__PURE__*/Object.freeze({
714
+ __proto__: null,
715
+ base36: base36,
716
+ base36upper: base36upper
717
+ });
718
+
719
+ // @ts-check
720
+
721
+
722
+ const base64 = rfc4648({
723
+ prefix: 'm',
724
+ name: 'base64',
725
+ alphabet: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/',
726
+ bitsPerChar: 6
727
+ });
728
+
729
+ const base64pad = rfc4648({
730
+ prefix: 'M',
731
+ name: 'base64pad',
732
+ alphabet: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',
733
+ bitsPerChar: 6
734
+ });
735
+
736
+ const base64url = rfc4648({
737
+ prefix: 'u',
738
+ name: 'base64url',
739
+ alphabet: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_',
740
+ bitsPerChar: 6
741
+ });
742
+
743
+ const base64urlpad = rfc4648({
744
+ prefix: 'U',
745
+ name: 'base64urlpad',
746
+ alphabet: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_=',
747
+ bitsPerChar: 6
748
+ });
749
+
750
+ var base64$1 = /*#__PURE__*/Object.freeze({
751
+ __proto__: null,
752
+ base64: base64,
753
+ base64pad: base64pad,
754
+ base64url: base64url,
755
+ base64urlpad: base64urlpad
756
+ });
757
+
758
+ // @ts-check
759
+
760
+
761
+ const base8 = rfc4648({
762
+ prefix: '7',
763
+ name: 'base8',
764
+ alphabet: '01234567',
765
+ bitsPerChar: 3
766
+ });
767
+
768
+ var base8$1 = /*#__PURE__*/Object.freeze({
769
+ __proto__: null,
770
+ base8: base8
771
+ });
772
+
773
+ // @ts-check
774
+
775
+
776
+ const identity = from({
777
+ prefix: '\x00',
778
+ name: 'identity',
779
+ encode: (buf) => toString$1(buf),
780
+ decode: (str) => fromString$1(str)
781
+ });
782
+
783
+ var identityBase = /*#__PURE__*/Object.freeze({
784
+ __proto__: null,
785
+ identity: identity
786
+ });
787
+
788
+ // @ts-check
789
+
790
+ /**
791
+ * @template T
792
+ * @typedef {import('./interface.js').ByteView<T>} ByteView
793
+ */
794
+
795
+ new TextEncoder();
796
+ new TextDecoder();
797
+
798
+ // @ts-check
799
+
800
+
801
+ const bases = { ...identityBase, ...base2$1, ...base8$1, ...base10$1, ...base16$1, ...base32$1, ...base36$1, ...base58, ...base64$1, ...base256emoji$1 };
802
+
803
+ /**
804
+ * To guarantee Uint8Array semantics, convert nodejs Buffers
805
+ * into vanilla Uint8Arrays
806
+ */
807
+ function asUint8Array(buf) {
808
+ if (globalThis.Buffer != null) {
809
+ return new Uint8Array(buf.buffer, buf.byteOffset, buf.byteLength);
810
+ }
811
+ return buf;
812
+ }
813
+
814
+ /**
815
+ * Returns a `Uint8Array` of the requested size. Referenced memory will
816
+ * be initialized to 0.
817
+ */
818
+ function alloc(size = 0) {
819
+ if (globalThis.Buffer?.alloc != null) {
820
+ return asUint8Array(globalThis.Buffer.alloc(size));
821
+ }
822
+ return new Uint8Array(size);
823
+ }
824
+ /**
825
+ * Where possible returns a Uint8Array of the requested size that references
826
+ * uninitialized memory. Only use if you are certain you will immediately
827
+ * overwrite every value in the returned `Uint8Array`.
828
+ */
829
+ function allocUnsafe(size = 0) {
830
+ if (globalThis.Buffer?.allocUnsafe != null) {
831
+ return asUint8Array(globalThis.Buffer.allocUnsafe(size));
832
+ }
833
+ return new Uint8Array(size);
834
+ }
835
+
836
+ function createCodec(name, prefix, encode, decode) {
837
+ return {
838
+ name,
839
+ prefix,
840
+ encoder: {
841
+ name,
842
+ prefix,
843
+ encode
844
+ },
845
+ decoder: {
846
+ decode
847
+ }
848
+ };
849
+ }
850
+ const string = createCodec('utf8', 'u', (buf) => {
851
+ const decoder = new TextDecoder('utf8');
852
+ return 'u' + decoder.decode(buf);
853
+ }, (str) => {
854
+ const encoder = new TextEncoder();
855
+ return encoder.encode(str.substring(1));
856
+ });
857
+ const ascii = createCodec('ascii', 'a', (buf) => {
858
+ let string = 'a';
859
+ for (let i = 0; i < buf.length; i++) {
860
+ string += String.fromCharCode(buf[i]);
861
+ }
862
+ return string;
863
+ }, (str) => {
864
+ str = str.substring(1);
865
+ const buf = allocUnsafe(str.length);
866
+ for (let i = 0; i < str.length; i++) {
867
+ buf[i] = str.charCodeAt(i);
868
+ }
869
+ return buf;
870
+ });
871
+ const BASES = {
872
+ utf8: string,
873
+ 'utf-8': string,
874
+ hex: bases.base16,
875
+ latin1: ascii,
876
+ ascii,
877
+ binary: ascii,
878
+ ...bases
879
+ };
880
+
881
+ /**
882
+ * Turns a `Uint8Array` into a string.
883
+ *
884
+ * Supports `utf8`, `utf-8` and any encoding supported by the multibase module.
885
+ *
886
+ * Also `ascii` which is similar to node's 'binary' encoding.
887
+ */
888
+ function toString(array, encoding = 'utf8') {
889
+ const base = BASES[encoding];
890
+ if (base == null) {
891
+ throw new Error(`Unsupported encoding "${encoding}"`);
892
+ }
893
+ if ((encoding === 'utf8' || encoding === 'utf-8') && globalThis.Buffer != null && globalThis.Buffer.from != null) {
894
+ return globalThis.Buffer.from(array.buffer, array.byteOffset, array.byteLength).toString('utf8');
895
+ }
896
+ // strip multibase prefix
897
+ return base.encoder.encode(array).substring(1);
898
+ }
899
+
900
+ /**
901
+ * Create a `Uint8Array` from the passed string
902
+ *
903
+ * Supports `utf8`, `utf-8`, `hex`, and any encoding supported by the multiformats module.
904
+ *
905
+ * Also `ascii` which is similar to node's 'binary' encoding.
906
+ */
907
+ function fromString(string, encoding = 'utf8') {
908
+ const base = BASES[encoding];
909
+ if (base == null) {
910
+ throw new Error(`Unsupported encoding "${encoding}"`);
911
+ }
912
+ if ((encoding === 'utf8' || encoding === 'utf-8') && globalThis.Buffer != null && globalThis.Buffer.from != null) {
913
+ return asUint8Array(globalThis.Buffer.from(string, 'utf-8'));
914
+ }
915
+ // add multibase prefix
916
+ return base.decoder.decode(`${base.prefix}${string}`); // eslint-disable-line @typescript-eslint/restrict-template-expressions
917
+ }
918
+
919
+ var Protocols;
920
+ (function (Protocols) {
921
+ Protocols["Relay"] = "relay";
922
+ Protocols["Store"] = "store";
923
+ Protocols["LightPush"] = "lightpush";
924
+ Protocols["Filter"] = "filter";
925
+ })(Protocols || (Protocols = {}));
926
+ var SendError;
927
+ (function (SendError) {
928
+ /** Could not determine the origin of the fault. Best to check connectivity and try again */
929
+ SendError["GENERIC_FAIL"] = "Generic error";
930
+ /** Failure to protobuf encode the message. This is not recoverable and needs
931
+ * further investigation. */
932
+ SendError["ENCODE_FAILED"] = "Failed to encode";
933
+ /** Failure to protobuf decode the message. May be due to a remote peer issue,
934
+ * ensuring that messages are sent via several peer enable mitigation of this error.. */
935
+ SendError["DECODE_FAILED"] = "Failed to decode";
936
+ /** The message size is above the maximum message size allowed on the Waku Network.
937
+ * Compressing the message or using an alternative strategy for large messages is recommended.
938
+ */
939
+ SendError["SIZE_TOO_BIG"] = "Size is too big";
940
+ /**
941
+ * The PubSubTopic passed to the send function is not configured on the Waku node.
942
+ * Please ensure that the PubSubTopic is used when initializing the Waku node.
943
+ */
944
+ SendError["TOPIC_NOT_CONFIGURED"] = "Topic not configured";
945
+ /**
946
+ * Failure to find a peer with suitable protocols. This may due to a connection issue.
947
+ * Mitigation can be: retrying after a given time period, display connectivity issue
948
+ * to user or listening for `peer:connected:bootstrap` or `peer:connected:peer-exchange`
949
+ * on the connection manager before retrying.
950
+ */
951
+ SendError["NO_PEER_AVAILABLE"] = "No peer available";
952
+ /**
953
+ * The remote peer did not behave as expected. Mitigation for `NO_PEER_AVAILABLE`
954
+ * or `DECODE_FAILED` can be used.
955
+ */
956
+ SendError["REMOTE_PEER_FAULT"] = "Remote peer fault";
957
+ /**
958
+ * The remote peer rejected the message. Information provided by the remote peer
959
+ * is logged. Review message validity, or mitigation for `NO_PEER_AVAILABLE`
960
+ * or `DECODE_FAILED` can be used.
961
+ */
962
+ SendError["REMOTE_PEER_REJECTED"] = "Remote peer rejected";
963
+ })(SendError || (SendError = {}));
964
+
965
+ var PageDirection;
966
+ (function (PageDirection) {
967
+ PageDirection["BACKWARD"] = "backward";
968
+ PageDirection["FORWARD"] = "forward";
969
+ })(PageDirection || (PageDirection = {}));
970
+
971
+ var Tags;
972
+ (function (Tags) {
973
+ Tags["BOOTSTRAP"] = "bootstrap";
974
+ Tags["PEER_EXCHANGE"] = "peer-exchange";
975
+ })(Tags || (Tags = {}));
976
+ var EPeersByDiscoveryEvents;
977
+ (function (EPeersByDiscoveryEvents) {
978
+ EPeersByDiscoveryEvents["PEER_DISCOVERY_BOOTSTRAP"] = "peer:discovery:bootstrap";
979
+ EPeersByDiscoveryEvents["PEER_DISCOVERY_PEER_EXCHANGE"] = "peer:discovery:peer-exchange";
980
+ EPeersByDiscoveryEvents["PEER_CONNECT_BOOTSTRAP"] = "peer:connected:bootstrap";
981
+ EPeersByDiscoveryEvents["PEER_CONNECT_PEER_EXCHANGE"] = "peer:connected:peer-exchange";
982
+ })(EPeersByDiscoveryEvents || (EPeersByDiscoveryEvents = {}));
983
+
984
+ /**
985
+ * Decode byte array to utf-8 string.
986
+ */
987
+ const bytesToUtf8 = (b) => toString(b, "utf8");
988
+ /**
989
+ * Encode utf-8 string to byte array.
990
+ */
991
+ const utf8ToBytes = (s) => fromString(s, "utf8");
992
+ /**
993
+ * Concatenate using Uint8Arrays as `Buffer` has a different behavior with `DataView`
994
+ */
995
+ function concat(byteArrays, totalLength) {
996
+ const len = totalLength ?? byteArrays.reduce((acc, curr) => acc + curr.length, 0);
997
+ const res = new Uint8Array(len);
998
+ let offset = 0;
999
+ for (const bytes of byteArrays) {
1000
+ res.set(bytes, offset);
1001
+ offset += bytes.length;
1002
+ }
1003
+ return res;
1004
+ }
1005
+
1006
+ const log = debug("waku:libp2p-utils");
1007
+ /**
1008
+ * Returns a pseudo-random peer that supports the given protocol.
1009
+ * Useful for protocols such as store and light push
1010
+ */
1011
+ function selectRandomPeer(peers) {
1012
+ if (peers.length === 0)
1013
+ return;
1014
+ const index = Math.round(Math.random() * (peers.length - 1));
1015
+ return peers[index];
1016
+ }
1017
+ /**
1018
+ * Returns the peer with the lowest latency.
1019
+ * @param peerStore - The Libp2p PeerStore
1020
+ * @param peers - The list of peers to choose from
1021
+ * @returns The peer with the lowest latency, or undefined if no peer could be reached
1022
+ */
1023
+ async function selectLowestLatencyPeer(peerStore, peers) {
1024
+ if (peers.length === 0)
1025
+ return;
1026
+ const results = await Promise.all(peers.map(async (peer) => {
1027
+ const pingBytes = (await peerStore.get(peer.id)).metadata.get("ping");
1028
+ if (!pingBytes)
1029
+ return { peer, ping: Infinity };
1030
+ const ping = Number(bytesToUtf8(pingBytes)) ?? Infinity;
1031
+ return { peer, ping };
1032
+ }));
1033
+ const lowestLatencyResult = results.sort((a, b) => a.ping - b.ping)[0];
1034
+ if (!lowestLatencyResult) {
1035
+ return undefined;
1036
+ }
1037
+ return lowestLatencyResult.ping !== Infinity
1038
+ ? lowestLatencyResult.peer
1039
+ : undefined;
1040
+ }
1041
+ /**
1042
+ * Returns the list of peers that supports the given protocol.
1043
+ */
1044
+ async function getPeersForProtocol(peerStore, protocols) {
1045
+ const peers = [];
1046
+ await peerStore.forEach((peer) => {
1047
+ for (let i = 0; i < protocols.length; i++) {
1048
+ if (peer.protocols.includes(protocols[i])) {
1049
+ peers.push(peer);
1050
+ break;
1051
+ }
1052
+ }
1053
+ });
1054
+ return peers;
1055
+ }
1056
+ /**
1057
+ * Returns a peer that supports the given protocol.
1058
+ * If peerId is provided, the peer with that id is returned.
1059
+ * Otherwise, the peer with the lowest latency is returned.
1060
+ * If no peer is found from the above criteria, a random peer is returned.
1061
+ */
1062
+ async function selectPeerForProtocol(peerStore, protocols, peerId) {
1063
+ let peer;
1064
+ if (peerId) {
1065
+ peer = await peerStore.get(peerId);
1066
+ if (!peer) {
1067
+ throw new Error(`Failed to retrieve connection details for provided peer in peer store: ${peerId.toString()}`);
1068
+ }
1069
+ }
1070
+ else {
1071
+ const peers = await getPeersForProtocol(peerStore, protocols);
1072
+ peer = await selectLowestLatencyPeer(peerStore, peers);
1073
+ if (!peer) {
1074
+ peer = selectRandomPeer(peers);
1075
+ if (!peer)
1076
+ throw new Error(`Failed to find known peer that registers protocols: ${protocols}`);
1077
+ }
1078
+ }
1079
+ let protocol;
1080
+ for (const codec of protocols) {
1081
+ if (peer.protocols.includes(codec)) {
1082
+ protocol = codec;
1083
+ // Do not break as we want to keep the last value
1084
+ }
1085
+ }
1086
+ log(`Using codec ${protocol}`);
1087
+ if (!protocol) {
1088
+ throw new Error(`Peer does not register required protocols (${peer.id.toString()}): ${protocols}`);
1089
+ }
1090
+ return { peer, protocol };
1091
+ }
1092
+ function selectConnection(connections) {
1093
+ if (!connections.length)
1094
+ return;
1095
+ if (connections.length === 1)
1096
+ return connections[0];
1097
+ let latestConnection;
1098
+ connections.forEach((connection) => {
1099
+ if (connection.status === "open") {
1100
+ if (!latestConnection) {
1101
+ latestConnection = connection;
1102
+ }
1103
+ else if (connection.timeline.open > latestConnection.timeline.open) {
1104
+ latestConnection = connection;
1105
+ }
1106
+ }
1107
+ });
1108
+ return latestConnection;
1109
+ }
1110
+
1111
+ /**
1112
+ * Retrieves a list of peers based on the specified criteria.
1113
+ *
1114
+ * @param peers - The list of peers to filter from.
1115
+ * @param numPeers - The total number of peers to retrieve. If 0, all peers are returned.
1116
+ * @param maxBootstrapPeers - The maximum number of bootstrap peers to retrieve.
1117
+ * @returns A Promise that resolves to an array of peers based on the specified criteria.
1118
+ */
1119
+ async function filterPeers(peers, numPeers, maxBootstrapPeers) {
1120
+ // Collect the bootstrap peers up to the specified maximum
1121
+ const bootstrapPeers = peers
1122
+ .filter((peer) => peer.tags.has(Tags.BOOTSTRAP))
1123
+ .slice(0, maxBootstrapPeers);
1124
+ // Collect non-bootstrap peers
1125
+ const nonBootstrapPeers = peers.filter((peer) => !peer.tags.has(Tags.BOOTSTRAP));
1126
+ // If numPeers is 0, return all peers
1127
+ if (numPeers === 0) {
1128
+ return [...bootstrapPeers, ...nonBootstrapPeers];
1129
+ }
1130
+ // Initialize the list of selected peers with the bootstrap peers
1131
+ const selectedPeers = [...bootstrapPeers];
1132
+ // Fill up to numPeers with remaining random peers if needed
1133
+ while (selectedPeers.length < numPeers && nonBootstrapPeers.length > 0) {
1134
+ const randomIndex = Math.floor(Math.random() * nonBootstrapPeers.length);
1135
+ const randomPeer = nonBootstrapPeers.splice(randomIndex, 1)[0];
1136
+ selectedPeers.push(randomPeer);
1137
+ }
1138
+ return selectedPeers;
1139
+ }
1140
+
1141
+ class StreamManager {
1142
+ multicodec;
1143
+ getConnections;
1144
+ addEventListener;
1145
+ streamPool;
1146
+ log;
1147
+ constructor(multicodec, getConnections, addEventListener) {
1148
+ this.multicodec = multicodec;
1149
+ this.getConnections = getConnections;
1150
+ this.addEventListener = addEventListener;
1151
+ this.log = debug(`waku:stream-manager:${multicodec}`);
1152
+ this.addEventListener("peer:update", this.handlePeerUpdateStreamPool.bind(this));
1153
+ this.getStream = this.getStream.bind(this);
1154
+ this.streamPool = new Map();
1155
+ }
1156
+ async getStream(peer) {
1157
+ const peerIdStr = peer.id.toString();
1158
+ const streamPromise = this.streamPool.get(peerIdStr);
1159
+ if (!streamPromise) {
1160
+ return this.newStream(peer); // fallback by creating a new stream on the spot
1161
+ }
1162
+ // We have the stream, let's remove it from the map
1163
+ this.streamPool.delete(peerIdStr);
1164
+ this.prepareNewStream(peer);
1165
+ const stream = await streamPromise;
1166
+ if (!stream || stream.status === "closed") {
1167
+ return this.newStream(peer); // fallback by creating a new stream on the spot
1168
+ }
1169
+ return stream;
1170
+ }
1171
+ async newStream(peer) {
1172
+ const connections = this.getConnections(peer.id);
1173
+ const connection = selectConnection(connections);
1174
+ if (!connection) {
1175
+ throw new Error("Failed to get a connection to the peer");
1176
+ }
1177
+ return connection.newStream(this.multicodec);
1178
+ }
1179
+ prepareNewStream(peer) {
1180
+ const streamPromise = this.newStream(peer).catch(() => {
1181
+ // No error thrown as this call is not triggered by the user
1182
+ this.log(`Failed to prepare a new stream for ${peer.id.toString()}`);
1183
+ });
1184
+ this.streamPool.set(peer.id.toString(), streamPromise);
1185
+ }
1186
+ handlePeerUpdateStreamPool = (evt) => {
1187
+ const peer = evt.detail.peer;
1188
+ if (peer.protocols.includes(this.multicodec)) {
1189
+ this.log(`Preemptively opening a stream to ${peer.id.toString()}`);
1190
+ this.prepareNewStream(peer);
1191
+ }
1192
+ };
1193
+ }
1194
+
1195
+ /**
1196
+ * A class with predefined helpers, to be used as a base to implement Waku
1197
+ * Protocols.
1198
+ */
1199
+ class BaseProtocol {
1200
+ multicodec;
1201
+ components;
1202
+ addLibp2pEventListener;
1203
+ removeLibp2pEventListener;
1204
+ streamManager;
1205
+ constructor(multicodec, components) {
1206
+ this.multicodec = multicodec;
1207
+ this.components = components;
1208
+ this.addLibp2pEventListener = components.events.addEventListener.bind(components.events);
1209
+ this.removeLibp2pEventListener = components.events.removeEventListener.bind(components.events);
1210
+ this.streamManager = new StreamManager(multicodec, components.connectionManager.getConnections.bind(components.connectionManager), this.addLibp2pEventListener);
1211
+ }
1212
+ async getStream(peer) {
1213
+ return this.streamManager.getStream(peer);
1214
+ }
1215
+ get peerStore() {
1216
+ return this.components.peerStore;
1217
+ }
1218
+ /**
1219
+ * Returns known peers from the address book (`libp2p.peerStore`) that support
1220
+ * the class protocol. Waku may or may not be currently connected to these
1221
+ * peers.
1222
+ */
1223
+ async peers() {
1224
+ return getPeersForProtocol(this.peerStore, [this.multicodec]);
1225
+ }
1226
+ async getPeer(peerId) {
1227
+ const { peer } = await selectPeerForProtocol(this.peerStore, [this.multicodec], peerId);
1228
+ return peer;
1229
+ }
1230
+ /**
1231
+ * Retrieves a list of peers based on the specified criteria.
1232
+ *
1233
+ * @param numPeers - The total number of peers to retrieve. If 0, all peers are returned.
1234
+ * @param maxBootstrapPeers - The maximum number of bootstrap peers to retrieve.
1235
+ * @returns A Promise that resolves to an array of peers based on the specified criteria.
1236
+ */
1237
+ async getPeers({ numPeers, maxBootstrapPeers } = {
1238
+ maxBootstrapPeers: 1,
1239
+ numPeers: 0
1240
+ }) {
1241
+ // Retrieve all peers that support the protocol
1242
+ const allPeersForProtocol = await getPeersForProtocol(this.peerStore, [
1243
+ this.multicodec
1244
+ ]);
1245
+ // Filter the peers based on the specified criteria
1246
+ return filterPeers(allPeersForProtocol, numPeers, maxBootstrapPeers);
1247
+ }
1248
+ }
1249
+
1250
+ export { BaseProtocol as B, EPeersByDiscoveryEvents as E, Protocols as P, SendError as S, Tags as T, base58btc as a, base32 as b, coerce as c, allocUnsafe as d, equals as e, asUint8Array as f, bases as g, fromString as h, alloc as i, concat as j, StreamManager as k, toString as t, utf8ToBytes as u };