@waku/core 0.0.33 → 0.0.34-00f2e75.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.
- package/bundle/base_protocol-Bp5a9PNG.js +152 -0
- package/bundle/{index-BIW3qNYx.js → index-G1eRBjeI.js} +118 -204
- package/bundle/index.js +1895 -179
- package/bundle/lib/base_protocol.js +2 -2
- package/bundle/lib/message/version_0.js +2 -2
- package/bundle/{version_0-CdmZMfkQ.js → version_0-DJZG2fB2.js} +283 -45
- package/dist/.tsbuildinfo +1 -1
- package/dist/index.d.ts +1 -3
- package/dist/index.js +1 -3
- package/dist/index.js.map +1 -1
- package/dist/lib/base_protocol.d.ts +3 -23
- package/dist/lib/base_protocol.js +3 -47
- package/dist/lib/base_protocol.js.map +1 -1
- package/dist/lib/connection_manager/connection_manager.d.ts +118 -0
- package/dist/lib/{connection_manager.js → connection_manager/connection_manager.js} +136 -36
- package/dist/lib/connection_manager/connection_manager.js.map +1 -0
- package/dist/lib/connection_manager/index.d.ts +1 -0
- package/dist/lib/connection_manager/index.js +2 -0
- package/dist/lib/connection_manager/index.js.map +1 -0
- package/dist/lib/{keep_alive_manager.d.ts → connection_manager/keep_alive_manager.d.ts} +4 -2
- package/dist/lib/{keep_alive_manager.js → connection_manager/keep_alive_manager.js} +2 -2
- package/dist/lib/connection_manager/keep_alive_manager.js.map +1 -0
- package/dist/lib/connection_manager/utils.d.ts +7 -0
- package/dist/lib/connection_manager/utils.js +22 -0
- package/dist/lib/connection_manager/utils.js.map +1 -0
- package/dist/lib/filter/filter.d.ts +18 -0
- package/dist/lib/filter/filter.js +209 -0
- package/dist/lib/filter/filter.js.map +1 -0
- package/dist/lib/filter/index.d.ts +1 -18
- package/dist/lib/filter/index.js +1 -208
- package/dist/lib/filter/index.js.map +1 -1
- package/dist/lib/light_push/index.d.ts +1 -15
- package/dist/lib/light_push/index.js +1 -143
- package/dist/lib/light_push/index.js.map +1 -1
- package/dist/lib/light_push/light_push.d.ts +15 -0
- package/dist/lib/light_push/light_push.js +144 -0
- package/dist/lib/light_push/light_push.js.map +1 -0
- package/dist/lib/light_push/utils.d.ts +0 -2
- package/dist/lib/light_push/utils.js +9 -17
- package/dist/lib/light_push/utils.js.map +1 -1
- package/dist/lib/metadata/index.d.ts +1 -3
- package/dist/lib/metadata/index.js +1 -118
- package/dist/lib/metadata/index.js.map +1 -1
- package/dist/lib/metadata/metadata.d.ts +3 -0
- package/dist/lib/metadata/metadata.js +119 -0
- package/dist/lib/metadata/metadata.js.map +1 -0
- package/dist/lib/store/index.d.ts +1 -9
- package/dist/lib/store/index.js +1 -82
- package/dist/lib/store/index.js.map +1 -1
- package/dist/lib/store/store.d.ts +9 -0
- package/dist/lib/store/store.js +83 -0
- package/dist/lib/store/store.js.map +1 -0
- package/dist/lib/stream_manager/stream_manager.d.ts +2 -2
- package/dist/lib/stream_manager/stream_manager.js +16 -17
- package/dist/lib/stream_manager/stream_manager.js.map +1 -1
- package/package.json +1 -126
- package/src/index.ts +1 -4
- package/src/lib/base_protocol.ts +3 -76
- package/src/lib/{connection_manager.ts → connection_manager/connection_manager.ts} +168 -63
- package/src/lib/connection_manager/index.ts +1 -0
- package/src/lib/{keep_alive_manager.ts → connection_manager/keep_alive_manager.ts} +7 -3
- package/src/lib/connection_manager/utils.ts +25 -0
- package/src/lib/filter/filter.ts +315 -0
- package/src/lib/filter/index.ts +1 -315
- package/src/lib/light_push/index.ts +1 -188
- package/src/lib/light_push/light_push.ts +188 -0
- package/src/lib/light_push/utils.ts +13 -21
- package/src/lib/metadata/index.ts +1 -182
- package/src/lib/metadata/metadata.ts +182 -0
- package/src/lib/store/index.ts +1 -136
- package/src/lib/store/store.ts +136 -0
- package/src/lib/stream_manager/stream_manager.ts +16 -18
- package/bundle/base_protocol-Dzv-QHPR.js +0 -275
- package/dist/lib/connection_manager.d.ts +0 -62
- package/dist/lib/connection_manager.js.map +0 -1
- package/dist/lib/filterPeers.d.ts +0 -13
- package/dist/lib/filterPeers.js +0 -38
- package/dist/lib/filterPeers.js.map +0 -1
- package/dist/lib/health_manager.d.ts +0 -14
- package/dist/lib/health_manager.js +0 -70
- package/dist/lib/health_manager.js.map +0 -1
- package/dist/lib/keep_alive_manager.js.map +0 -1
- package/src/lib/filterPeers.ts +0 -51
- package/src/lib/health_manager.ts +0 -90
package/bundle/index.js
CHANGED
@@ -1,8 +1,518 @@
|
|
1
|
-
import { v as version_0, e as encodingLength,
|
2
|
-
export {
|
3
|
-
import {
|
4
|
-
import { B as BaseProtocol } from './base_protocol-
|
5
|
-
export { S as StreamManager } from './base_protocol-
|
1
|
+
import { v as version_0, a as allocUnsafe, b as alloc, e as encodingLength$1, c as encode$2, d as decode$4, M as MessagePush, F as FilterSubscribeRequest, f as FilterSubscribeResponse$1, P as PushRpc$1, g as PushResponse, S as StoreQueryRequest$1, h as StoreQueryResponse$1, t as toString$1, i as bases, j as fromString, u as utf8ToBytes, k as createEncoder, p as pubsubTopicToSingleShardInfo, l as bytesToUtf8, s as shardInfoToPubsubTopics, W as WakuMetadataRequest, m as pubsubTopicsToShardInfo, n as WakuMetadataResponse } from './version_0-DJZG2fB2.js';
|
2
|
+
export { o as createDecoder } from './version_0-DJZG2fB2.js';
|
3
|
+
import { c as coerce, e as equals$2, b as base36, a as base32, d as base58btc, L as Logger, P as ProtocolError, T as Tags, E as EPeersByDiscoveryEvents, f as EConnectionStateEvents } from './index-G1eRBjeI.js';
|
4
|
+
import { B as BaseProtocol } from './base_protocol-Bp5a9PNG.js';
|
5
|
+
export { S as StreamManager } from './base_protocol-Bp5a9PNG.js';
|
6
|
+
|
7
|
+
/* eslint-disable */
|
8
|
+
var encode_1 = encode$1;
|
9
|
+
var MSB = 0x80, MSBALL = -128, INT = Math.pow(2, 31);
|
10
|
+
/**
|
11
|
+
* @param {number} num
|
12
|
+
* @param {number[]} out
|
13
|
+
* @param {number} offset
|
14
|
+
*/
|
15
|
+
function encode$1(num, out, offset) {
|
16
|
+
out = out || [];
|
17
|
+
offset = offset || 0;
|
18
|
+
var oldOffset = offset;
|
19
|
+
while (num >= INT) {
|
20
|
+
out[offset++] = (num & 0xFF) | MSB;
|
21
|
+
num /= 128;
|
22
|
+
}
|
23
|
+
while (num & MSBALL) {
|
24
|
+
out[offset++] = (num & 0xFF) | MSB;
|
25
|
+
num >>>= 7;
|
26
|
+
}
|
27
|
+
out[offset] = num | 0;
|
28
|
+
// @ts-ignore
|
29
|
+
encode$1.bytes = offset - oldOffset + 1;
|
30
|
+
return out;
|
31
|
+
}
|
32
|
+
var decode$3 = read;
|
33
|
+
var MSB$1 = 0x80, REST$1 = 0x7F;
|
34
|
+
/**
|
35
|
+
* @param {string | any[]} buf
|
36
|
+
* @param {number} offset
|
37
|
+
*/
|
38
|
+
function read(buf, offset) {
|
39
|
+
var res = 0, offset = offset || 0, shift = 0, counter = offset, b, l = buf.length;
|
40
|
+
do {
|
41
|
+
if (counter >= l) {
|
42
|
+
// @ts-ignore
|
43
|
+
read.bytes = 0;
|
44
|
+
throw new RangeError('Could not decode varint');
|
45
|
+
}
|
46
|
+
b = buf[counter++];
|
47
|
+
res += shift < 28
|
48
|
+
? (b & REST$1) << shift
|
49
|
+
: (b & REST$1) * Math.pow(2, shift);
|
50
|
+
shift += 7;
|
51
|
+
} while (b >= MSB$1);
|
52
|
+
// @ts-ignore
|
53
|
+
read.bytes = counter - offset;
|
54
|
+
return res;
|
55
|
+
}
|
56
|
+
var N1 = Math.pow(2, 7);
|
57
|
+
var N2 = Math.pow(2, 14);
|
58
|
+
var N3 = Math.pow(2, 21);
|
59
|
+
var N4 = Math.pow(2, 28);
|
60
|
+
var N5 = Math.pow(2, 35);
|
61
|
+
var N6 = Math.pow(2, 42);
|
62
|
+
var N7 = Math.pow(2, 49);
|
63
|
+
var N8 = Math.pow(2, 56);
|
64
|
+
var N9 = Math.pow(2, 63);
|
65
|
+
var length = function (/** @type {number} */ value) {
|
66
|
+
return (value < N1 ? 1
|
67
|
+
: value < N2 ? 2
|
68
|
+
: value < N3 ? 3
|
69
|
+
: value < N4 ? 4
|
70
|
+
: value < N5 ? 5
|
71
|
+
: value < N6 ? 6
|
72
|
+
: value < N7 ? 7
|
73
|
+
: value < N8 ? 8
|
74
|
+
: value < N9 ? 9
|
75
|
+
: 10);
|
76
|
+
};
|
77
|
+
var varint = {
|
78
|
+
encode: encode_1,
|
79
|
+
decode: decode$3,
|
80
|
+
encodingLength: length
|
81
|
+
};
|
82
|
+
var _brrp_varint = varint;
|
83
|
+
|
84
|
+
function decode$2(data, offset = 0) {
|
85
|
+
const code = _brrp_varint.decode(data, offset);
|
86
|
+
return [code, _brrp_varint.decode.bytes];
|
87
|
+
}
|
88
|
+
function encodeTo(int, target, offset = 0) {
|
89
|
+
_brrp_varint.encode(int, target, offset);
|
90
|
+
return target;
|
91
|
+
}
|
92
|
+
function encodingLength(int) {
|
93
|
+
return _brrp_varint.encodingLength(int);
|
94
|
+
}
|
95
|
+
|
96
|
+
/**
|
97
|
+
* Creates a multihash digest.
|
98
|
+
*/
|
99
|
+
function create(code, digest) {
|
100
|
+
const size = digest.byteLength;
|
101
|
+
const sizeOffset = encodingLength(code);
|
102
|
+
const digestOffset = sizeOffset + encodingLength(size);
|
103
|
+
const bytes = new Uint8Array(digestOffset + size);
|
104
|
+
encodeTo(code, bytes, 0);
|
105
|
+
encodeTo(size, bytes, sizeOffset);
|
106
|
+
bytes.set(digest, digestOffset);
|
107
|
+
return new Digest(code, size, digest, bytes);
|
108
|
+
}
|
109
|
+
/**
|
110
|
+
* Turns bytes representation of multihash digest into an instance.
|
111
|
+
*/
|
112
|
+
function decode$1(multihash) {
|
113
|
+
const bytes = coerce(multihash);
|
114
|
+
const [code, sizeOffset] = decode$2(bytes);
|
115
|
+
const [size, digestOffset] = decode$2(bytes.subarray(sizeOffset));
|
116
|
+
const digest = bytes.subarray(sizeOffset + digestOffset);
|
117
|
+
if (digest.byteLength !== size) {
|
118
|
+
throw new Error('Incorrect length');
|
119
|
+
}
|
120
|
+
return new Digest(code, size, digest, bytes);
|
121
|
+
}
|
122
|
+
function equals$1(a, b) {
|
123
|
+
if (a === b) {
|
124
|
+
return true;
|
125
|
+
}
|
126
|
+
else {
|
127
|
+
const data = b;
|
128
|
+
return (a.code === data.code &&
|
129
|
+
a.size === data.size &&
|
130
|
+
data.bytes instanceof Uint8Array &&
|
131
|
+
equals$2(a.bytes, data.bytes));
|
132
|
+
}
|
133
|
+
}
|
134
|
+
/**
|
135
|
+
* Represents a multihash digest which carries information about the
|
136
|
+
* hashing algorithm and an actual hash digest.
|
137
|
+
*/
|
138
|
+
class Digest {
|
139
|
+
code;
|
140
|
+
size;
|
141
|
+
digest;
|
142
|
+
bytes;
|
143
|
+
/**
|
144
|
+
* Creates a multihash digest.
|
145
|
+
*/
|
146
|
+
constructor(code, size, digest, bytes) {
|
147
|
+
this.code = code;
|
148
|
+
this.size = size;
|
149
|
+
this.digest = digest;
|
150
|
+
this.bytes = bytes;
|
151
|
+
}
|
152
|
+
}
|
153
|
+
|
154
|
+
function format(link, base) {
|
155
|
+
const { bytes, version } = link;
|
156
|
+
switch (version) {
|
157
|
+
case 0:
|
158
|
+
return toStringV0(bytes, baseCache(link), base ?? base58btc.encoder);
|
159
|
+
default:
|
160
|
+
return toStringV1(bytes, baseCache(link), (base ?? base32.encoder));
|
161
|
+
}
|
162
|
+
}
|
163
|
+
const cache = new WeakMap();
|
164
|
+
function baseCache(cid) {
|
165
|
+
const baseCache = cache.get(cid);
|
166
|
+
if (baseCache == null) {
|
167
|
+
const baseCache = new Map();
|
168
|
+
cache.set(cid, baseCache);
|
169
|
+
return baseCache;
|
170
|
+
}
|
171
|
+
return baseCache;
|
172
|
+
}
|
173
|
+
class CID {
|
174
|
+
code;
|
175
|
+
version;
|
176
|
+
multihash;
|
177
|
+
bytes;
|
178
|
+
'/';
|
179
|
+
/**
|
180
|
+
* @param version - Version of the CID
|
181
|
+
* @param code - Code of the codec content is encoded in, see https://github.com/multiformats/multicodec/blob/master/table.csv
|
182
|
+
* @param multihash - (Multi)hash of the of the content.
|
183
|
+
*/
|
184
|
+
constructor(version, code, multihash, bytes) {
|
185
|
+
this.code = code;
|
186
|
+
this.version = version;
|
187
|
+
this.multihash = multihash;
|
188
|
+
this.bytes = bytes;
|
189
|
+
// flag to serializers that this is a CID and
|
190
|
+
// should be treated specially
|
191
|
+
this['/'] = bytes;
|
192
|
+
}
|
193
|
+
/**
|
194
|
+
* Signalling `cid.asCID === cid` has been replaced with `cid['/'] === cid.bytes`
|
195
|
+
* please either use `CID.asCID(cid)` or switch to new signalling mechanism
|
196
|
+
*
|
197
|
+
* @deprecated
|
198
|
+
*/
|
199
|
+
get asCID() {
|
200
|
+
return this;
|
201
|
+
}
|
202
|
+
// ArrayBufferView
|
203
|
+
get byteOffset() {
|
204
|
+
return this.bytes.byteOffset;
|
205
|
+
}
|
206
|
+
// ArrayBufferView
|
207
|
+
get byteLength() {
|
208
|
+
return this.bytes.byteLength;
|
209
|
+
}
|
210
|
+
toV0() {
|
211
|
+
switch (this.version) {
|
212
|
+
case 0: {
|
213
|
+
return this;
|
214
|
+
}
|
215
|
+
case 1: {
|
216
|
+
const { code, multihash } = this;
|
217
|
+
if (code !== DAG_PB_CODE) {
|
218
|
+
throw new Error('Cannot convert a non dag-pb CID to CIDv0');
|
219
|
+
}
|
220
|
+
// sha2-256
|
221
|
+
if (multihash.code !== SHA_256_CODE) {
|
222
|
+
throw new Error('Cannot convert non sha2-256 multihash CID to CIDv0');
|
223
|
+
}
|
224
|
+
return (CID.createV0(multihash));
|
225
|
+
}
|
226
|
+
default: {
|
227
|
+
throw Error(`Can not convert CID version ${this.version} to version 0. This is a bug please report`);
|
228
|
+
}
|
229
|
+
}
|
230
|
+
}
|
231
|
+
toV1() {
|
232
|
+
switch (this.version) {
|
233
|
+
case 0: {
|
234
|
+
const { code, digest } = this.multihash;
|
235
|
+
const multihash = create(code, digest);
|
236
|
+
return (CID.createV1(this.code, multihash));
|
237
|
+
}
|
238
|
+
case 1: {
|
239
|
+
return this;
|
240
|
+
}
|
241
|
+
default: {
|
242
|
+
throw Error(`Can not convert CID version ${this.version} to version 1. This is a bug please report`);
|
243
|
+
}
|
244
|
+
}
|
245
|
+
}
|
246
|
+
equals(other) {
|
247
|
+
return CID.equals(this, other);
|
248
|
+
}
|
249
|
+
static equals(self, other) {
|
250
|
+
const unknown = other;
|
251
|
+
return (unknown != null &&
|
252
|
+
self.code === unknown.code &&
|
253
|
+
self.version === unknown.version &&
|
254
|
+
equals$1(self.multihash, unknown.multihash));
|
255
|
+
}
|
256
|
+
toString(base) {
|
257
|
+
return format(this, base);
|
258
|
+
}
|
259
|
+
toJSON() {
|
260
|
+
return { '/': format(this) };
|
261
|
+
}
|
262
|
+
link() {
|
263
|
+
return this;
|
264
|
+
}
|
265
|
+
[Symbol.toStringTag] = 'CID';
|
266
|
+
// Legacy
|
267
|
+
[Symbol.for('nodejs.util.inspect.custom')]() {
|
268
|
+
return `CID(${this.toString()})`;
|
269
|
+
}
|
270
|
+
/**
|
271
|
+
* Takes any input `value` and returns a `CID` instance if it was
|
272
|
+
* a `CID` otherwise returns `null`. If `value` is instanceof `CID`
|
273
|
+
* it will return value back. If `value` is not instance of this CID
|
274
|
+
* class, but is compatible CID it will return new instance of this
|
275
|
+
* `CID` class. Otherwise returns null.
|
276
|
+
*
|
277
|
+
* This allows two different incompatible versions of CID library to
|
278
|
+
* co-exist and interop as long as binary interface is compatible.
|
279
|
+
*/
|
280
|
+
static asCID(input) {
|
281
|
+
if (input == null) {
|
282
|
+
return null;
|
283
|
+
}
|
284
|
+
const value = input;
|
285
|
+
if (value instanceof CID) {
|
286
|
+
// If value is instance of CID then we're all set.
|
287
|
+
return value;
|
288
|
+
}
|
289
|
+
else if ((value['/'] != null && value['/'] === value.bytes) || value.asCID === value) {
|
290
|
+
// If value isn't instance of this CID class but `this.asCID === this` or
|
291
|
+
// `value['/'] === value.bytes` is true it is CID instance coming from a
|
292
|
+
// different implementation (diff version or duplicate). In that case we
|
293
|
+
// rebase it to this `CID` implementation so caller is guaranteed to get
|
294
|
+
// instance with expected API.
|
295
|
+
const { version, code, multihash, bytes } = value;
|
296
|
+
return new CID(version, code, multihash, bytes ?? encodeCID(version, code, multihash.bytes));
|
297
|
+
}
|
298
|
+
else if (value[cidSymbol] === true) {
|
299
|
+
// If value is a CID from older implementation that used to be tagged via
|
300
|
+
// symbol we still rebase it to the this `CID` implementation by
|
301
|
+
// delegating that to a constructor.
|
302
|
+
const { version, multihash, code } = value;
|
303
|
+
const digest = decode$1(multihash);
|
304
|
+
return CID.create(version, code, digest);
|
305
|
+
}
|
306
|
+
else {
|
307
|
+
// Otherwise value is not a CID (or an incompatible version of it) in
|
308
|
+
// which case we return `null`.
|
309
|
+
return null;
|
310
|
+
}
|
311
|
+
}
|
312
|
+
/**
|
313
|
+
* @param version - Version of the CID
|
314
|
+
* @param code - Code of the codec content is encoded in, see https://github.com/multiformats/multicodec/blob/master/table.csv
|
315
|
+
* @param digest - (Multi)hash of the of the content.
|
316
|
+
*/
|
317
|
+
static create(version, code, digest) {
|
318
|
+
if (typeof code !== 'number') {
|
319
|
+
throw new Error('String codecs are no longer supported');
|
320
|
+
}
|
321
|
+
if (!(digest.bytes instanceof Uint8Array)) {
|
322
|
+
throw new Error('Invalid digest');
|
323
|
+
}
|
324
|
+
switch (version) {
|
325
|
+
case 0: {
|
326
|
+
if (code !== DAG_PB_CODE) {
|
327
|
+
throw new Error(`Version 0 CID must use dag-pb (code: ${DAG_PB_CODE}) block encoding`);
|
328
|
+
}
|
329
|
+
else {
|
330
|
+
return new CID(version, code, digest, digest.bytes);
|
331
|
+
}
|
332
|
+
}
|
333
|
+
case 1: {
|
334
|
+
const bytes = encodeCID(version, code, digest.bytes);
|
335
|
+
return new CID(version, code, digest, bytes);
|
336
|
+
}
|
337
|
+
default: {
|
338
|
+
throw new Error('Invalid version');
|
339
|
+
}
|
340
|
+
}
|
341
|
+
}
|
342
|
+
/**
|
343
|
+
* Simplified version of `create` for CIDv0.
|
344
|
+
*/
|
345
|
+
static createV0(digest) {
|
346
|
+
return CID.create(0, DAG_PB_CODE, digest);
|
347
|
+
}
|
348
|
+
/**
|
349
|
+
* Simplified version of `create` for CIDv1.
|
350
|
+
*
|
351
|
+
* @param code - Content encoding format code.
|
352
|
+
* @param digest - Multihash of the content.
|
353
|
+
*/
|
354
|
+
static createV1(code, digest) {
|
355
|
+
return CID.create(1, code, digest);
|
356
|
+
}
|
357
|
+
/**
|
358
|
+
* Decoded a CID from its binary representation. The byte array must contain
|
359
|
+
* only the CID with no additional bytes.
|
360
|
+
*
|
361
|
+
* An error will be thrown if the bytes provided do not contain a valid
|
362
|
+
* binary representation of a CID.
|
363
|
+
*/
|
364
|
+
static decode(bytes) {
|
365
|
+
const [cid, remainder] = CID.decodeFirst(bytes);
|
366
|
+
if (remainder.length !== 0) {
|
367
|
+
throw new Error('Incorrect length');
|
368
|
+
}
|
369
|
+
return cid;
|
370
|
+
}
|
371
|
+
/**
|
372
|
+
* Decoded a CID from its binary representation at the beginning of a byte
|
373
|
+
* array.
|
374
|
+
*
|
375
|
+
* Returns an array with the first element containing the CID and the second
|
376
|
+
* element containing the remainder of the original byte array. The remainder
|
377
|
+
* will be a zero-length byte array if the provided bytes only contained a
|
378
|
+
* binary CID representation.
|
379
|
+
*/
|
380
|
+
static decodeFirst(bytes) {
|
381
|
+
const specs = CID.inspectBytes(bytes);
|
382
|
+
const prefixSize = specs.size - specs.multihashSize;
|
383
|
+
const multihashBytes = coerce(bytes.subarray(prefixSize, prefixSize + specs.multihashSize));
|
384
|
+
if (multihashBytes.byteLength !== specs.multihashSize) {
|
385
|
+
throw new Error('Incorrect length');
|
386
|
+
}
|
387
|
+
const digestBytes = multihashBytes.subarray(specs.multihashSize - specs.digestSize);
|
388
|
+
const digest = new Digest(specs.multihashCode, specs.digestSize, digestBytes, multihashBytes);
|
389
|
+
const cid = specs.version === 0
|
390
|
+
? CID.createV0(digest)
|
391
|
+
: CID.createV1(specs.codec, digest);
|
392
|
+
return [cid, bytes.subarray(specs.size)];
|
393
|
+
}
|
394
|
+
/**
|
395
|
+
* Inspect the initial bytes of a CID to determine its properties.
|
396
|
+
*
|
397
|
+
* Involves decoding up to 4 varints. Typically this will require only 4 to 6
|
398
|
+
* bytes but for larger multicodec code values and larger multihash digest
|
399
|
+
* lengths these varints can be quite large. It is recommended that at least
|
400
|
+
* 10 bytes be made available in the `initialBytes` argument for a complete
|
401
|
+
* inspection.
|
402
|
+
*/
|
403
|
+
static inspectBytes(initialBytes) {
|
404
|
+
let offset = 0;
|
405
|
+
const next = () => {
|
406
|
+
const [i, length] = decode$2(initialBytes.subarray(offset));
|
407
|
+
offset += length;
|
408
|
+
return i;
|
409
|
+
};
|
410
|
+
let version = next();
|
411
|
+
let codec = DAG_PB_CODE;
|
412
|
+
if (version === 18) {
|
413
|
+
// CIDv0
|
414
|
+
version = 0;
|
415
|
+
offset = 0;
|
416
|
+
}
|
417
|
+
else {
|
418
|
+
codec = next();
|
419
|
+
}
|
420
|
+
if (version !== 0 && version !== 1) {
|
421
|
+
throw new RangeError(`Invalid CID version ${version}`);
|
422
|
+
}
|
423
|
+
const prefixSize = offset;
|
424
|
+
const multihashCode = next(); // multihash code
|
425
|
+
const digestSize = next(); // multihash length
|
426
|
+
const size = offset + digestSize;
|
427
|
+
const multihashSize = size - prefixSize;
|
428
|
+
return { version, codec, multihashCode, digestSize, multihashSize, size };
|
429
|
+
}
|
430
|
+
/**
|
431
|
+
* Takes cid in a string representation and creates an instance. If `base`
|
432
|
+
* decoder is not provided will use a default from the configuration. It will
|
433
|
+
* throw an error if encoding of the CID is not compatible with supplied (or
|
434
|
+
* a default decoder).
|
435
|
+
*/
|
436
|
+
static parse(source, base) {
|
437
|
+
const [prefix, bytes] = parseCIDtoBytes(source, base);
|
438
|
+
const cid = CID.decode(bytes);
|
439
|
+
if (cid.version === 0 && source[0] !== 'Q') {
|
440
|
+
throw Error('Version 0 CID string must not include multibase prefix');
|
441
|
+
}
|
442
|
+
// Cache string representation to avoid computing it on `this.toString()`
|
443
|
+
baseCache(cid).set(prefix, source);
|
444
|
+
return cid;
|
445
|
+
}
|
446
|
+
}
|
447
|
+
function parseCIDtoBytes(source, base) {
|
448
|
+
switch (source[0]) {
|
449
|
+
// CIDv0 is parsed differently
|
450
|
+
case 'Q': {
|
451
|
+
const decoder = base ?? base58btc;
|
452
|
+
return [
|
453
|
+
base58btc.prefix,
|
454
|
+
decoder.decode(`${base58btc.prefix}${source}`)
|
455
|
+
];
|
456
|
+
}
|
457
|
+
case base58btc.prefix: {
|
458
|
+
const decoder = base ?? base58btc;
|
459
|
+
return [base58btc.prefix, decoder.decode(source)];
|
460
|
+
}
|
461
|
+
case base32.prefix: {
|
462
|
+
const decoder = base ?? base32;
|
463
|
+
return [base32.prefix, decoder.decode(source)];
|
464
|
+
}
|
465
|
+
case base36.prefix: {
|
466
|
+
const decoder = base ?? base36;
|
467
|
+
return [base36.prefix, decoder.decode(source)];
|
468
|
+
}
|
469
|
+
default: {
|
470
|
+
if (base == null) {
|
471
|
+
throw Error('To parse non base32, base36 or base58btc encoded CID multibase decoder must be provided');
|
472
|
+
}
|
473
|
+
return [source[0], base.decode(source)];
|
474
|
+
}
|
475
|
+
}
|
476
|
+
}
|
477
|
+
function toStringV0(bytes, cache, base) {
|
478
|
+
const { prefix } = base;
|
479
|
+
if (prefix !== base58btc.prefix) {
|
480
|
+
throw Error(`Cannot string encode V0 in ${base.name} encoding`);
|
481
|
+
}
|
482
|
+
const cid = cache.get(prefix);
|
483
|
+
if (cid == null) {
|
484
|
+
const cid = base.encode(bytes).slice(1);
|
485
|
+
cache.set(prefix, cid);
|
486
|
+
return cid;
|
487
|
+
}
|
488
|
+
else {
|
489
|
+
return cid;
|
490
|
+
}
|
491
|
+
}
|
492
|
+
function toStringV1(bytes, cache, base) {
|
493
|
+
const { prefix } = base;
|
494
|
+
const cid = cache.get(prefix);
|
495
|
+
if (cid == null) {
|
496
|
+
const cid = base.encode(bytes);
|
497
|
+
cache.set(prefix, cid);
|
498
|
+
return cid;
|
499
|
+
}
|
500
|
+
else {
|
501
|
+
return cid;
|
502
|
+
}
|
503
|
+
}
|
504
|
+
const DAG_PB_CODE = 0x70;
|
505
|
+
const SHA_256_CODE = 0x12;
|
506
|
+
function encodeCID(version, code, multihash) {
|
507
|
+
const codeOffset = encodingLength(version);
|
508
|
+
const hashOffset = codeOffset + encodingLength(code);
|
509
|
+
const bytes = new Uint8Array(hashOffset + multihash.byteLength);
|
510
|
+
encodeTo(version, bytes, 0);
|
511
|
+
encodeTo(code, bytes, codeOffset);
|
512
|
+
bytes.set(multihash, hashOffset);
|
513
|
+
return bytes;
|
514
|
+
}
|
515
|
+
const cidSymbol = Symbol.for('@ipld/js-cid/CID');
|
6
516
|
|
7
517
|
const MB = 1024 ** 2;
|
8
518
|
const SIZE_CAP_IN_MB = 1;
|
@@ -258,7 +768,7 @@ function equals(a, b) {
|
|
258
768
|
*
|
259
769
|
* Borrows liberally from [bl](https://www.npmjs.com/package/bl) but only uses native JS types.
|
260
770
|
*/
|
261
|
-
const symbol = Symbol.for('@achingbrain/uint8arraylist');
|
771
|
+
const symbol$1 = Symbol.for('@achingbrain/uint8arraylist');
|
262
772
|
function findBufAndOffset(bufs, index) {
|
263
773
|
if (index == null || index < 0) {
|
264
774
|
throw new RangeError('index is out of bounds');
|
@@ -290,12 +800,12 @@ function findBufAndOffset(bufs, index) {
|
|
290
800
|
* ```
|
291
801
|
*/
|
292
802
|
function isUint8ArrayList(value) {
|
293
|
-
return Boolean(value?.[symbol]);
|
803
|
+
return Boolean(value?.[symbol$1]);
|
294
804
|
}
|
295
805
|
class Uint8ArrayList {
|
296
806
|
bufs;
|
297
807
|
length;
|
298
|
-
[symbol] = true;
|
808
|
+
[symbol$1] = true;
|
299
809
|
constructor(...data) {
|
300
810
|
this.bufs = [];
|
301
811
|
this.length = 0;
|
@@ -751,9 +1261,9 @@ function isAsyncIterable$2(thing) {
|
|
751
1261
|
}
|
752
1262
|
|
753
1263
|
const defaultEncoder = (length) => {
|
754
|
-
const lengthLength = encodingLength(length);
|
1264
|
+
const lengthLength = encodingLength$1(length);
|
755
1265
|
const lengthBuf = allocUnsafe(lengthLength);
|
756
|
-
encode$
|
1266
|
+
encode$2(length, lengthBuf);
|
757
1267
|
defaultEncoder.bytes = lengthLength;
|
758
1268
|
return lengthBuf;
|
759
1269
|
};
|
@@ -840,8 +1350,8 @@ var ReadMode;
|
|
840
1350
|
ReadMode[ReadMode["DATA"] = 1] = "DATA";
|
841
1351
|
})(ReadMode || (ReadMode = {}));
|
842
1352
|
const defaultDecoder = (buf) => {
|
843
|
-
const length = decode$
|
844
|
-
defaultDecoder.bytes = encodingLength(length);
|
1353
|
+
const length = decode$4(buf);
|
1354
|
+
defaultDecoder.bytes = encodingLength$1(length);
|
845
1355
|
return length;
|
846
1356
|
};
|
847
1357
|
defaultDecoder.bytes = 0;
|
@@ -1491,7 +2001,7 @@ var native = {
|
|
1491
2001
|
};
|
1492
2002
|
|
1493
2003
|
function v4(options, buf, offset) {
|
1494
|
-
if (native.randomUUID &&
|
2004
|
+
if (native.randomUUID && true && !options) {
|
1495
2005
|
return native.randomUUID();
|
1496
2006
|
}
|
1497
2007
|
|
@@ -1620,7 +2130,7 @@ class FilterCore extends BaseProtocol {
|
|
1620
2130
|
handleIncomingMessage;
|
1621
2131
|
pubsubTopics;
|
1622
2132
|
constructor(handleIncomingMessage, pubsubTopics, libp2p) {
|
1623
|
-
super(FilterCodecs.SUBSCRIBE, libp2p.components,
|
2133
|
+
super(FilterCodecs.SUBSCRIBE, libp2p.components, pubsubTopics);
|
1624
2134
|
this.handleIncomingMessage = handleIncomingMessage;
|
1625
2135
|
this.pubsubTopics = pubsubTopics;
|
1626
2136
|
libp2p
|
@@ -1631,8 +2141,8 @@ class FilterCore extends BaseProtocol {
|
|
1631
2141
|
log$5.error("Failed to register ", FilterCodecs.PUSH, e);
|
1632
2142
|
});
|
1633
2143
|
}
|
1634
|
-
async subscribe(pubsubTopic,
|
1635
|
-
const stream = await this.getStream(
|
2144
|
+
async subscribe(pubsubTopic, peerId, contentTopics) {
|
2145
|
+
const stream = await this.getStream(peerId);
|
1636
2146
|
const request = FilterSubscribeRpc.createSubscribeRequest(pubsubTopic, contentTopics);
|
1637
2147
|
let res;
|
1638
2148
|
try {
|
@@ -1644,7 +2154,7 @@ class FilterCore extends BaseProtocol {
|
|
1644
2154
|
success: null,
|
1645
2155
|
failure: {
|
1646
2156
|
error: ProtocolError.GENERIC_FAIL,
|
1647
|
-
peerId:
|
2157
|
+
peerId: peerId
|
1648
2158
|
}
|
1649
2159
|
};
|
1650
2160
|
}
|
@@ -1654,28 +2164,28 @@ class FilterCore extends BaseProtocol {
|
|
1654
2164
|
return {
|
1655
2165
|
failure: {
|
1656
2166
|
error: ProtocolError.REMOTE_PEER_REJECTED,
|
1657
|
-
peerId:
|
2167
|
+
peerId: peerId
|
1658
2168
|
},
|
1659
2169
|
success: null
|
1660
2170
|
};
|
1661
2171
|
}
|
1662
2172
|
return {
|
1663
2173
|
failure: null,
|
1664
|
-
success:
|
2174
|
+
success: peerId
|
1665
2175
|
};
|
1666
2176
|
}
|
1667
|
-
async unsubscribe(pubsubTopic,
|
2177
|
+
async unsubscribe(pubsubTopic, peerId, contentTopics) {
|
1668
2178
|
let stream;
|
1669
2179
|
try {
|
1670
|
-
stream = await this.getStream(
|
2180
|
+
stream = await this.getStream(peerId);
|
1671
2181
|
}
|
1672
2182
|
catch (error) {
|
1673
|
-
log$5.error(`Failed to get a stream for remote peer${
|
2183
|
+
log$5.error(`Failed to get a stream for remote peer${peerId.toString()}`, error);
|
1674
2184
|
return {
|
1675
2185
|
success: null,
|
1676
2186
|
failure: {
|
1677
2187
|
error: ProtocolError.NO_STREAM_AVAILABLE,
|
1678
|
-
peerId:
|
2188
|
+
peerId: peerId
|
1679
2189
|
}
|
1680
2190
|
};
|
1681
2191
|
}
|
@@ -1689,24 +2199,24 @@ class FilterCore extends BaseProtocol {
|
|
1689
2199
|
success: null,
|
1690
2200
|
failure: {
|
1691
2201
|
error: ProtocolError.GENERIC_FAIL,
|
1692
|
-
peerId:
|
2202
|
+
peerId: peerId
|
1693
2203
|
}
|
1694
2204
|
};
|
1695
2205
|
}
|
1696
2206
|
return {
|
1697
|
-
success:
|
2207
|
+
success: peerId,
|
1698
2208
|
failure: null
|
1699
2209
|
};
|
1700
2210
|
}
|
1701
|
-
async unsubscribeAll(pubsubTopic,
|
1702
|
-
const stream = await this.getStream(
|
2211
|
+
async unsubscribeAll(pubsubTopic, peerId) {
|
2212
|
+
const stream = await this.getStream(peerId);
|
1703
2213
|
const request = FilterSubscribeRpc.createUnsubscribeAllRequest(pubsubTopic);
|
1704
2214
|
const res = await pipe([request.encode()], encode, stream, decode, async (source) => await all(source));
|
1705
2215
|
if (!res || !res.length) {
|
1706
2216
|
return {
|
1707
2217
|
failure: {
|
1708
2218
|
error: ProtocolError.NO_RESPONSE,
|
1709
|
-
peerId:
|
2219
|
+
peerId: peerId
|
1710
2220
|
},
|
1711
2221
|
success: null
|
1712
2222
|
};
|
@@ -1717,28 +2227,28 @@ class FilterCore extends BaseProtocol {
|
|
1717
2227
|
return {
|
1718
2228
|
failure: {
|
1719
2229
|
error: ProtocolError.REMOTE_PEER_REJECTED,
|
1720
|
-
peerId:
|
2230
|
+
peerId: peerId
|
1721
2231
|
},
|
1722
2232
|
success: null
|
1723
2233
|
};
|
1724
2234
|
}
|
1725
2235
|
return {
|
1726
2236
|
failure: null,
|
1727
|
-
success:
|
2237
|
+
success: peerId
|
1728
2238
|
};
|
1729
2239
|
}
|
1730
|
-
async ping(
|
2240
|
+
async ping(peerId) {
|
1731
2241
|
let stream;
|
1732
2242
|
try {
|
1733
|
-
stream = await this.getStream(
|
2243
|
+
stream = await this.getStream(peerId);
|
1734
2244
|
}
|
1735
2245
|
catch (error) {
|
1736
|
-
log$5.error(`Failed to get a stream for remote peer${
|
2246
|
+
log$5.error(`Failed to get a stream for remote peer${peerId.toString()}`, error);
|
1737
2247
|
return {
|
1738
2248
|
success: null,
|
1739
2249
|
failure: {
|
1740
2250
|
error: ProtocolError.NO_STREAM_AVAILABLE,
|
1741
|
-
peerId:
|
2251
|
+
peerId: peerId
|
1742
2252
|
}
|
1743
2253
|
};
|
1744
2254
|
}
|
@@ -1753,7 +2263,7 @@ class FilterCore extends BaseProtocol {
|
|
1753
2263
|
success: null,
|
1754
2264
|
failure: {
|
1755
2265
|
error: ProtocolError.GENERIC_FAIL,
|
1756
|
-
peerId:
|
2266
|
+
peerId: peerId
|
1757
2267
|
}
|
1758
2268
|
};
|
1759
2269
|
}
|
@@ -1762,7 +2272,7 @@ class FilterCore extends BaseProtocol {
|
|
1762
2272
|
success: null,
|
1763
2273
|
failure: {
|
1764
2274
|
error: ProtocolError.NO_RESPONSE,
|
1765
|
-
peerId:
|
2275
|
+
peerId: peerId
|
1766
2276
|
}
|
1767
2277
|
};
|
1768
2278
|
}
|
@@ -1773,12 +2283,12 @@ class FilterCore extends BaseProtocol {
|
|
1773
2283
|
success: null,
|
1774
2284
|
failure: {
|
1775
2285
|
error: ProtocolError.REMOTE_PEER_REJECTED,
|
1776
|
-
peerId:
|
2286
|
+
peerId: peerId
|
1777
2287
|
}
|
1778
2288
|
};
|
1779
2289
|
}
|
1780
2290
|
return {
|
1781
|
-
success:
|
2291
|
+
success: peerId,
|
1782
2292
|
failure: null
|
1783
2293
|
};
|
1784
2294
|
}
|
@@ -1852,26 +2362,19 @@ class PushRpc {
|
|
1852
2362
|
// should match nwaku
|
1853
2363
|
// https://github.com/waku-org/nwaku/blob/c3cb06ac6c03f0f382d3941ea53b330f6a8dd127/waku/waku_rln_relay/rln_relay.nim#L309
|
1854
2364
|
// https://github.com/waku-org/nwaku/blob/c3cb06ac6c03f0f382d3941ea53b330f6a8dd127/tests/waku_rln_relay/rln/waku_rln_relay_utils.nim#L20
|
1855
|
-
const RLN_GENERATION_PREFIX_ERROR = "could not generate rln
|
2365
|
+
const RLN_GENERATION_PREFIX_ERROR = "could not generate rln proof";
|
2366
|
+
const RLN_MESSAGE_ID_PREFIX_ERROR = "could not get new message id to generate an rln proof";
|
2367
|
+
// rare case on nwaku side
|
2368
|
+
// https://github.com/waku-org/nwaku/blob/a4e92a3d02448fd708857b7b6cac2a7faa7eb4f9/waku/waku_lightpush/callbacks.nim#L49
|
2369
|
+
// https://github.com/waku-org/nwaku/blob/a4e92a3d02448fd708857b7b6cac2a7faa7eb4f9/waku/node/waku_node.nim#L1117
|
2370
|
+
const RLN_REMOTE_VALIDATION = "RLN validation failed";
|
1856
2371
|
const isRLNResponseError = (info) => {
|
1857
2372
|
if (!info) {
|
1858
2373
|
return false;
|
1859
2374
|
}
|
1860
|
-
return info.includes(RLN_GENERATION_PREFIX_ERROR)
|
1861
|
-
|
1862
|
-
|
1863
|
-
const rlnErrorMap = {
|
1864
|
-
[ProtocolError.RLN_IDENTITY_MISSING]: ProtocolError.RLN_IDENTITY_MISSING,
|
1865
|
-
[ProtocolError.RLN_MEMBERSHIP_INDEX]: ProtocolError.RLN_MEMBERSHIP_INDEX,
|
1866
|
-
[ProtocolError.RLN_LIMIT_MISSING]: ProtocolError.RLN_LIMIT_MISSING
|
1867
|
-
};
|
1868
|
-
const infoLowerCase = info.toLowerCase();
|
1869
|
-
for (const errorKey in rlnErrorMap) {
|
1870
|
-
if (infoLowerCase.includes(errorKey.toLowerCase())) {
|
1871
|
-
return rlnErrorMap[errorKey];
|
1872
|
-
}
|
1873
|
-
}
|
1874
|
-
return ProtocolError.RLN_PROOF_GENERATION;
|
2375
|
+
return (info.includes(RLN_GENERATION_PREFIX_ERROR) ||
|
2376
|
+
info.includes(RLN_MESSAGE_ID_PREFIX_ERROR) ||
|
2377
|
+
info.includes(RLN_REMOTE_VALIDATION));
|
1875
2378
|
};
|
1876
2379
|
|
1877
2380
|
const log$4 = new Logger("light-push");
|
@@ -1882,7 +2385,7 @@ const LightPushCodec = "/vac/waku/lightpush/2.0.0-beta1";
|
|
1882
2385
|
class LightPushCore extends BaseProtocol {
|
1883
2386
|
pubsubTopics;
|
1884
2387
|
constructor(pubsubTopics, libp2p) {
|
1885
|
-
super(LightPushCodec, libp2p.components,
|
2388
|
+
super(LightPushCodec, libp2p.components, pubsubTopics);
|
1886
2389
|
this.pubsubTopics = pubsubTopics;
|
1887
2390
|
}
|
1888
2391
|
async preparePushMessage(encoder, message) {
|
@@ -1914,20 +2417,20 @@ class LightPushCore extends BaseProtocol {
|
|
1914
2417
|
};
|
1915
2418
|
}
|
1916
2419
|
}
|
1917
|
-
async send(encoder, message,
|
2420
|
+
async send(encoder, message, peerId) {
|
1918
2421
|
const { query, error: preparationError } = await this.preparePushMessage(encoder, message);
|
1919
2422
|
if (preparationError || !query) {
|
1920
2423
|
return {
|
1921
2424
|
success: null,
|
1922
2425
|
failure: {
|
1923
2426
|
error: preparationError,
|
1924
|
-
peerId
|
2427
|
+
peerId
|
1925
2428
|
}
|
1926
2429
|
};
|
1927
2430
|
}
|
1928
2431
|
let stream;
|
1929
2432
|
try {
|
1930
|
-
stream = await this.getStream(
|
2433
|
+
stream = await this.getStream(peerId);
|
1931
2434
|
}
|
1932
2435
|
catch (error) {
|
1933
2436
|
log$4.error("Failed to get stream", error);
|
@@ -1935,7 +2438,7 @@ class LightPushCore extends BaseProtocol {
|
|
1935
2438
|
success: null,
|
1936
2439
|
failure: {
|
1937
2440
|
error: ProtocolError.NO_STREAM_AVAILABLE,
|
1938
|
-
peerId:
|
2441
|
+
peerId: peerId
|
1939
2442
|
}
|
1940
2443
|
};
|
1941
2444
|
}
|
@@ -1944,12 +2447,13 @@ class LightPushCore extends BaseProtocol {
|
|
1944
2447
|
res = await pipe([query.encode()], encode, stream, decode, async (source) => await all(source));
|
1945
2448
|
}
|
1946
2449
|
catch (err) {
|
2450
|
+
// can fail only because of `stream` abortion
|
1947
2451
|
log$4.error("Failed to send waku light push request", err);
|
1948
2452
|
return {
|
1949
2453
|
success: null,
|
1950
2454
|
failure: {
|
1951
|
-
error: ProtocolError.
|
1952
|
-
peerId:
|
2455
|
+
error: ProtocolError.STREAM_ABORTED,
|
2456
|
+
peerId: peerId
|
1953
2457
|
}
|
1954
2458
|
};
|
1955
2459
|
}
|
@@ -1967,7 +2471,7 @@ class LightPushCore extends BaseProtocol {
|
|
1967
2471
|
success: null,
|
1968
2472
|
failure: {
|
1969
2473
|
error: ProtocolError.DECODE_FAILED,
|
1970
|
-
peerId:
|
2474
|
+
peerId: peerId
|
1971
2475
|
}
|
1972
2476
|
};
|
1973
2477
|
}
|
@@ -1977,18 +2481,17 @@ class LightPushCore extends BaseProtocol {
|
|
1977
2481
|
success: null,
|
1978
2482
|
failure: {
|
1979
2483
|
error: ProtocolError.NO_RESPONSE,
|
1980
|
-
peerId:
|
2484
|
+
peerId: peerId
|
1981
2485
|
}
|
1982
2486
|
};
|
1983
2487
|
}
|
1984
2488
|
if (isRLNResponseError(response.info)) {
|
1985
|
-
|
1986
|
-
log$4.error("Remote peer rejected the message: ", rlnErrorCase);
|
2489
|
+
log$4.error("Remote peer fault: RLN generation");
|
1987
2490
|
return {
|
1988
2491
|
success: null,
|
1989
2492
|
failure: {
|
1990
|
-
error:
|
1991
|
-
peerId:
|
2493
|
+
error: ProtocolError.RLN_PROOF_GENERATION,
|
2494
|
+
peerId: peerId
|
1992
2495
|
}
|
1993
2496
|
};
|
1994
2497
|
}
|
@@ -1998,11 +2501,11 @@ class LightPushCore extends BaseProtocol {
|
|
1998
2501
|
success: null,
|
1999
2502
|
failure: {
|
2000
2503
|
error: ProtocolError.REMOTE_PEER_REJECTED,
|
2001
|
-
peerId:
|
2504
|
+
peerId: peerId
|
2002
2505
|
}
|
2003
2506
|
};
|
2004
2507
|
}
|
2005
|
-
return { success:
|
2508
|
+
return { success: peerId, failure: null };
|
2006
2509
|
}
|
2007
2510
|
}
|
2008
2511
|
|
@@ -2103,10 +2606,10 @@ const StoreCodec = "/vac/waku/store-query/3.0.0";
|
|
2103
2606
|
class StoreCore extends BaseProtocol {
|
2104
2607
|
pubsubTopics;
|
2105
2608
|
constructor(pubsubTopics, libp2p) {
|
2106
|
-
super(StoreCodec, libp2p.components,
|
2609
|
+
super(StoreCodec, libp2p.components, pubsubTopics);
|
2107
2610
|
this.pubsubTopics = pubsubTopics;
|
2108
2611
|
}
|
2109
|
-
async *queryPerPage(queryOpts, decoders,
|
2612
|
+
async *queryPerPage(queryOpts, decoders, peerId) {
|
2110
2613
|
if (queryOpts.contentTopics.toString() !==
|
2111
2614
|
Array.from(decoders.keys()).toString()) {
|
2112
2615
|
throw new Error("Internal error, the decoders should match the query's content topics");
|
@@ -2119,7 +2622,7 @@ class StoreCore extends BaseProtocol {
|
|
2119
2622
|
});
|
2120
2623
|
let stream;
|
2121
2624
|
try {
|
2122
|
-
stream = await this.getStream(
|
2625
|
+
stream = await this.getStream(peerId);
|
2123
2626
|
}
|
2124
2627
|
catch (e) {
|
2125
2628
|
log$3.error("Failed to get stream", e);
|
@@ -2179,10 +2682,26 @@ var index = /*#__PURE__*/Object.freeze({
|
|
2179
2682
|
StoreCore: StoreCore
|
2180
2683
|
});
|
2181
2684
|
|
2182
|
-
/**
|
2685
|
+
/**
|
2686
|
+
* All PeerId implementations must use this symbol as the name of a property
|
2687
|
+
* with a boolean `true` value
|
2688
|
+
*/
|
2689
|
+
const peerIdSymbol = Symbol.for('@libp2p/peer-id');
|
2690
|
+
/**
|
2691
|
+
* Returns true if the passed argument is a PeerId implementation
|
2692
|
+
*/
|
2693
|
+
function isPeerId(other) {
|
2694
|
+
return Boolean(other?.[peerIdSymbol]);
|
2695
|
+
}
|
2696
|
+
|
2697
|
+
/**
|
2698
|
+
* Noop for browser compatibility
|
2699
|
+
*/
|
2183
2700
|
function setMaxListeners$1() { }
|
2184
2701
|
|
2185
|
-
|
2702
|
+
/**
|
2703
|
+
* Create a setMaxListeners that doesn't break browser usage
|
2704
|
+
*/
|
2186
2705
|
const setMaxListeners = (n, ...eventTargets) => {
|
2187
2706
|
try {
|
2188
2707
|
setMaxListeners$1(n, ...eventTargets);
|
@@ -2246,7 +2765,1154 @@ class TypedEventEmitter extends EventTarget {
|
|
2246
2765
|
return this.dispatchEvent(new CustomEvent(type, detail));
|
2247
2766
|
}
|
2248
2767
|
}
|
2249
|
-
|
2768
|
+
|
2769
|
+
/* eslint-disable @typescript-eslint/no-unsafe-return */
|
2770
|
+
class Parser {
|
2771
|
+
index = 0;
|
2772
|
+
input = "";
|
2773
|
+
new(input) {
|
2774
|
+
this.index = 0;
|
2775
|
+
this.input = input;
|
2776
|
+
return this;
|
2777
|
+
}
|
2778
|
+
/** Run a parser, and restore the pre-parse state if it fails. */
|
2779
|
+
readAtomically(fn) {
|
2780
|
+
const index = this.index;
|
2781
|
+
const result = fn();
|
2782
|
+
if (result === undefined) {
|
2783
|
+
this.index = index;
|
2784
|
+
}
|
2785
|
+
return result;
|
2786
|
+
}
|
2787
|
+
/** Run a parser, but fail if the entire input wasn't consumed. Doesn't run atomically. */
|
2788
|
+
parseWith(fn) {
|
2789
|
+
const result = fn();
|
2790
|
+
if (this.index !== this.input.length) {
|
2791
|
+
return undefined;
|
2792
|
+
}
|
2793
|
+
return result;
|
2794
|
+
}
|
2795
|
+
/** Peek the next character from the input */
|
2796
|
+
peekChar() {
|
2797
|
+
if (this.index >= this.input.length) {
|
2798
|
+
return undefined;
|
2799
|
+
}
|
2800
|
+
return this.input[this.index];
|
2801
|
+
}
|
2802
|
+
/** Read the next character from the input */
|
2803
|
+
readChar() {
|
2804
|
+
if (this.index >= this.input.length) {
|
2805
|
+
return undefined;
|
2806
|
+
}
|
2807
|
+
return this.input[this.index++];
|
2808
|
+
}
|
2809
|
+
/** Read the next character from the input if it matches the target. */
|
2810
|
+
readGivenChar(target) {
|
2811
|
+
return this.readAtomically(() => {
|
2812
|
+
const char = this.readChar();
|
2813
|
+
if (char !== target) {
|
2814
|
+
return undefined;
|
2815
|
+
}
|
2816
|
+
return char;
|
2817
|
+
});
|
2818
|
+
}
|
2819
|
+
/**
|
2820
|
+
* Helper for reading separators in an indexed loop. Reads the separator
|
2821
|
+
* character iff index > 0, then runs the parser. When used in a loop,
|
2822
|
+
* the separator character will only be read on index > 0 (see
|
2823
|
+
* readIPv4Addr for an example)
|
2824
|
+
*/
|
2825
|
+
readSeparator(sep, index, inner) {
|
2826
|
+
return this.readAtomically(() => {
|
2827
|
+
if (index > 0) {
|
2828
|
+
if (this.readGivenChar(sep) === undefined) {
|
2829
|
+
return undefined;
|
2830
|
+
}
|
2831
|
+
}
|
2832
|
+
return inner();
|
2833
|
+
});
|
2834
|
+
}
|
2835
|
+
/**
|
2836
|
+
* Read a number off the front of the input in the given radix, stopping
|
2837
|
+
* at the first non-digit character or eof. Fails if the number has more
|
2838
|
+
* digits than max_digits or if there is no number.
|
2839
|
+
*/
|
2840
|
+
readNumber(radix, maxDigits, allowZeroPrefix, maxBytes) {
|
2841
|
+
return this.readAtomically(() => {
|
2842
|
+
let result = 0;
|
2843
|
+
let digitCount = 0;
|
2844
|
+
const leadingChar = this.peekChar();
|
2845
|
+
if (leadingChar === undefined) {
|
2846
|
+
return undefined;
|
2847
|
+
}
|
2848
|
+
const hasLeadingZero = leadingChar === "0";
|
2849
|
+
const maxValue = 2 ** (8 * maxBytes) - 1;
|
2850
|
+
// eslint-disable-next-line no-constant-condition
|
2851
|
+
while (true) {
|
2852
|
+
const digit = this.readAtomically(() => {
|
2853
|
+
const char = this.readChar();
|
2854
|
+
if (char === undefined) {
|
2855
|
+
return undefined;
|
2856
|
+
}
|
2857
|
+
const num = Number.parseInt(char, radix);
|
2858
|
+
if (Number.isNaN(num)) {
|
2859
|
+
return undefined;
|
2860
|
+
}
|
2861
|
+
return num;
|
2862
|
+
});
|
2863
|
+
if (digit === undefined) {
|
2864
|
+
break;
|
2865
|
+
}
|
2866
|
+
result *= radix;
|
2867
|
+
result += digit;
|
2868
|
+
if (result > maxValue) {
|
2869
|
+
return undefined;
|
2870
|
+
}
|
2871
|
+
digitCount += 1;
|
2872
|
+
if (maxDigits !== undefined) {
|
2873
|
+
if (digitCount > maxDigits) {
|
2874
|
+
return undefined;
|
2875
|
+
}
|
2876
|
+
}
|
2877
|
+
}
|
2878
|
+
if (digitCount === 0) {
|
2879
|
+
return undefined;
|
2880
|
+
}
|
2881
|
+
else if (!allowZeroPrefix && hasLeadingZero && digitCount > 1) {
|
2882
|
+
return undefined;
|
2883
|
+
}
|
2884
|
+
else {
|
2885
|
+
return result;
|
2886
|
+
}
|
2887
|
+
});
|
2888
|
+
}
|
2889
|
+
/** Read an IPv4 address. */
|
2890
|
+
readIPv4Addr() {
|
2891
|
+
return this.readAtomically(() => {
|
2892
|
+
const out = new Uint8Array(4);
|
2893
|
+
for (let i = 0; i < out.length; i++) {
|
2894
|
+
const ix = this.readSeparator(".", i, () => this.readNumber(10, 3, false, 1));
|
2895
|
+
if (ix === undefined) {
|
2896
|
+
return undefined;
|
2897
|
+
}
|
2898
|
+
out[i] = ix;
|
2899
|
+
}
|
2900
|
+
return out;
|
2901
|
+
});
|
2902
|
+
}
|
2903
|
+
/** Read an IPv6 Address. */
|
2904
|
+
readIPv6Addr() {
|
2905
|
+
/**
|
2906
|
+
* Read a chunk of an IPv6 address into `groups`. Returns the number
|
2907
|
+
* of groups read, along with a bool indicating if an embedded
|
2908
|
+
* trailing IPv4 address was read. Specifically, read a series of
|
2909
|
+
* colon-separated IPv6 groups (0x0000 - 0xFFFF), with an optional
|
2910
|
+
* trailing embedded IPv4 address.
|
2911
|
+
*/
|
2912
|
+
const readGroups = (groups) => {
|
2913
|
+
for (let i = 0; i < groups.length / 2; i++) {
|
2914
|
+
const ix = i * 2;
|
2915
|
+
// Try to read a trailing embedded IPv4 address. There must be at least 4 groups left.
|
2916
|
+
if (i < groups.length - 3) {
|
2917
|
+
const ipv4 = this.readSeparator(":", i, () => this.readIPv4Addr());
|
2918
|
+
if (ipv4 !== undefined) {
|
2919
|
+
groups[ix] = ipv4[0];
|
2920
|
+
groups[ix + 1] = ipv4[1];
|
2921
|
+
groups[ix + 2] = ipv4[2];
|
2922
|
+
groups[ix + 3] = ipv4[3];
|
2923
|
+
return [ix + 4, true];
|
2924
|
+
}
|
2925
|
+
}
|
2926
|
+
const group = this.readSeparator(":", i, () => this.readNumber(16, 4, true, 2));
|
2927
|
+
if (group === undefined) {
|
2928
|
+
return [ix, false];
|
2929
|
+
}
|
2930
|
+
groups[ix] = group >> 8;
|
2931
|
+
groups[ix + 1] = group & 255;
|
2932
|
+
}
|
2933
|
+
return [groups.length, false];
|
2934
|
+
};
|
2935
|
+
return this.readAtomically(() => {
|
2936
|
+
// Read the front part of the address; either the whole thing, or up to the first ::
|
2937
|
+
const head = new Uint8Array(16);
|
2938
|
+
const [headSize, headIp4] = readGroups(head);
|
2939
|
+
if (headSize === 16) {
|
2940
|
+
return head;
|
2941
|
+
}
|
2942
|
+
// IPv4 part is not allowed before `::`
|
2943
|
+
if (headIp4) {
|
2944
|
+
return undefined;
|
2945
|
+
}
|
2946
|
+
// Read `::` if previous code parsed less than 8 groups.
|
2947
|
+
// `::` indicates one or more groups of 16 bits of zeros.
|
2948
|
+
if (this.readGivenChar(":") === undefined) {
|
2949
|
+
return undefined;
|
2950
|
+
}
|
2951
|
+
if (this.readGivenChar(":") === undefined) {
|
2952
|
+
return undefined;
|
2953
|
+
}
|
2954
|
+
// Read the back part of the address. The :: must contain at least one
|
2955
|
+
// set of zeroes, so our max length is 7.
|
2956
|
+
const tail = new Uint8Array(14);
|
2957
|
+
const limit = 16 - (headSize + 2);
|
2958
|
+
const [tailSize] = readGroups(tail.subarray(0, limit));
|
2959
|
+
// Concat the head and tail of the IP address
|
2960
|
+
head.set(tail.subarray(0, tailSize), 16 - tailSize);
|
2961
|
+
return head;
|
2962
|
+
});
|
2963
|
+
}
|
2964
|
+
/** Read an IP Address, either IPv4 or IPv6. */
|
2965
|
+
readIPAddr() {
|
2966
|
+
return this.readIPv4Addr() ?? this.readIPv6Addr();
|
2967
|
+
}
|
2968
|
+
}
|
2969
|
+
|
2970
|
+
// See https://stackoverflow.com/questions/166132/maximum-length-of-the-textual-representation-of-an-ipv6-address
|
2971
|
+
const MAX_IPV6_LENGTH = 45;
|
2972
|
+
const MAX_IPV4_LENGTH = 15;
|
2973
|
+
const parser = new Parser();
|
2974
|
+
/** Parse `input` into IPv4 bytes. */
|
2975
|
+
function parseIPv4(input) {
|
2976
|
+
if (input.length > MAX_IPV4_LENGTH) {
|
2977
|
+
return undefined;
|
2978
|
+
}
|
2979
|
+
return parser.new(input).parseWith(() => parser.readIPv4Addr());
|
2980
|
+
}
|
2981
|
+
/** Parse `input` into IPv6 bytes. */
|
2982
|
+
function parseIPv6(input) {
|
2983
|
+
// strip zone index if it is present
|
2984
|
+
if (input.includes("%")) {
|
2985
|
+
input = input.split("%")[0];
|
2986
|
+
}
|
2987
|
+
if (input.length > MAX_IPV6_LENGTH) {
|
2988
|
+
return undefined;
|
2989
|
+
}
|
2990
|
+
return parser.new(input).parseWith(() => parser.readIPv6Addr());
|
2991
|
+
}
|
2992
|
+
/** Parse `input` into IPv4 or IPv6 bytes. */
|
2993
|
+
function parseIP(input, mapIPv4ToIPv6 = false) {
|
2994
|
+
// strip zone index if it is present
|
2995
|
+
if (input.includes("%")) {
|
2996
|
+
input = input.split("%")[0];
|
2997
|
+
}
|
2998
|
+
if (input.length > MAX_IPV6_LENGTH) {
|
2999
|
+
return undefined;
|
3000
|
+
}
|
3001
|
+
const addr = parser.new(input).parseWith(() => parser.readIPAddr());
|
3002
|
+
if (!addr) {
|
3003
|
+
return undefined;
|
3004
|
+
}
|
3005
|
+
if (mapIPv4ToIPv6 && addr.length === 4) {
|
3006
|
+
return Uint8Array.from([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, addr[0], addr[1], addr[2], addr[3]]);
|
3007
|
+
}
|
3008
|
+
return addr;
|
3009
|
+
}
|
3010
|
+
|
3011
|
+
/** Check if `input` is IPv4. */
|
3012
|
+
function isIPv4(input) {
|
3013
|
+
return Boolean(parseIPv4(input));
|
3014
|
+
}
|
3015
|
+
/** Check if `input` is IPv6. */
|
3016
|
+
function isIPv6(input) {
|
3017
|
+
return Boolean(parseIPv6(input));
|
3018
|
+
}
|
3019
|
+
/** Check if `input` is IPv4 or IPv6. */
|
3020
|
+
function isIP(input) {
|
3021
|
+
return Boolean(parseIP(input));
|
3022
|
+
}
|
3023
|
+
|
3024
|
+
const isV4 = isIPv4;
|
3025
|
+
const isV6 = isIPv6;
|
3026
|
+
// Copied from https://github.com/indutny/node-ip/blob/master/lib/ip.js#L7
|
3027
|
+
// but with buf/offset args removed because we don't use them
|
3028
|
+
const toBytes = function (ip) {
|
3029
|
+
let offset = 0;
|
3030
|
+
ip = ip.toString().trim();
|
3031
|
+
if (isV4(ip)) {
|
3032
|
+
const bytes = new Uint8Array(offset + 4);
|
3033
|
+
ip.split(/\./g).forEach((byte) => {
|
3034
|
+
bytes[offset++] = parseInt(byte, 10) & 0xff;
|
3035
|
+
});
|
3036
|
+
return bytes;
|
3037
|
+
}
|
3038
|
+
if (isV6(ip)) {
|
3039
|
+
const sections = ip.split(':', 8);
|
3040
|
+
let i;
|
3041
|
+
for (i = 0; i < sections.length; i++) {
|
3042
|
+
const isv4 = isV4(sections[i]);
|
3043
|
+
let v4Buffer;
|
3044
|
+
if (isv4) {
|
3045
|
+
v4Buffer = toBytes(sections[i]);
|
3046
|
+
sections[i] = toString$1(v4Buffer.slice(0, 2), 'base16');
|
3047
|
+
}
|
3048
|
+
if (v4Buffer != null && ++i < 8) {
|
3049
|
+
sections.splice(i, 0, toString$1(v4Buffer.slice(2, 4), 'base16'));
|
3050
|
+
}
|
3051
|
+
}
|
3052
|
+
if (sections[0] === '') {
|
3053
|
+
while (sections.length < 8)
|
3054
|
+
sections.unshift('0');
|
3055
|
+
}
|
3056
|
+
else if (sections[sections.length - 1] === '') {
|
3057
|
+
while (sections.length < 8)
|
3058
|
+
sections.push('0');
|
3059
|
+
}
|
3060
|
+
else if (sections.length < 8) {
|
3061
|
+
for (i = 0; i < sections.length && sections[i] !== ''; i++)
|
3062
|
+
;
|
3063
|
+
const argv = [i, 1];
|
3064
|
+
for (i = 9 - sections.length; i > 0; i--) {
|
3065
|
+
argv.push('0');
|
3066
|
+
}
|
3067
|
+
sections.splice.apply(sections, argv);
|
3068
|
+
}
|
3069
|
+
const bytes = new Uint8Array(offset + 16);
|
3070
|
+
for (i = 0; i < sections.length; i++) {
|
3071
|
+
const word = parseInt(sections[i], 16);
|
3072
|
+
bytes[offset++] = (word >> 8) & 0xff;
|
3073
|
+
bytes[offset++] = word & 0xff;
|
3074
|
+
}
|
3075
|
+
return bytes;
|
3076
|
+
}
|
3077
|
+
throw new Error('invalid ip address');
|
3078
|
+
};
|
3079
|
+
// Copied from https://github.com/indutny/node-ip/blob/master/lib/ip.js#L63
|
3080
|
+
const toString = function (buf, offset = 0, length) {
|
3081
|
+
offset = ~~offset;
|
3082
|
+
length = length ?? (buf.length - offset);
|
3083
|
+
const view = new DataView(buf.buffer);
|
3084
|
+
if (length === 4) {
|
3085
|
+
const result = [];
|
3086
|
+
// IPv4
|
3087
|
+
for (let i = 0; i < length; i++) {
|
3088
|
+
result.push(buf[offset + i]);
|
3089
|
+
}
|
3090
|
+
return result.join('.');
|
3091
|
+
}
|
3092
|
+
if (length === 16) {
|
3093
|
+
const result = [];
|
3094
|
+
// IPv6
|
3095
|
+
for (let i = 0; i < length; i += 2) {
|
3096
|
+
result.push(view.getUint16(offset + i).toString(16));
|
3097
|
+
}
|
3098
|
+
return result.join(':')
|
3099
|
+
.replace(/(^|:)0(:0)*:0(:|$)/, '$1::$3')
|
3100
|
+
.replace(/:{3,4}/, '::');
|
3101
|
+
}
|
3102
|
+
return '';
|
3103
|
+
};
|
3104
|
+
|
3105
|
+
const V = -1;
|
3106
|
+
const names = {};
|
3107
|
+
const codes = {};
|
3108
|
+
const table = [
|
3109
|
+
[4, 32, 'ip4'],
|
3110
|
+
[6, 16, 'tcp'],
|
3111
|
+
[33, 16, 'dccp'],
|
3112
|
+
[41, 128, 'ip6'],
|
3113
|
+
[42, V, 'ip6zone'],
|
3114
|
+
[43, 8, 'ipcidr'],
|
3115
|
+
[53, V, 'dns', true],
|
3116
|
+
[54, V, 'dns4', true],
|
3117
|
+
[55, V, 'dns6', true],
|
3118
|
+
[56, V, 'dnsaddr', true],
|
3119
|
+
[132, 16, 'sctp'],
|
3120
|
+
[273, 16, 'udp'],
|
3121
|
+
[275, 0, 'p2p-webrtc-star'],
|
3122
|
+
[276, 0, 'p2p-webrtc-direct'],
|
3123
|
+
[277, 0, 'p2p-stardust'],
|
3124
|
+
[280, 0, 'webrtc-direct'],
|
3125
|
+
[281, 0, 'webrtc'],
|
3126
|
+
[290, 0, 'p2p-circuit'],
|
3127
|
+
[301, 0, 'udt'],
|
3128
|
+
[302, 0, 'utp'],
|
3129
|
+
[400, V, 'unix', false, true],
|
3130
|
+
// `ipfs` is added before `p2p` for legacy support.
|
3131
|
+
// All text representations will default to `p2p`, but `ipfs` will
|
3132
|
+
// still be supported
|
3133
|
+
[421, V, 'ipfs'],
|
3134
|
+
// `p2p` is the preferred name for 421, and is now the default
|
3135
|
+
[421, V, 'p2p'],
|
3136
|
+
[443, 0, 'https'],
|
3137
|
+
[444, 96, 'onion'],
|
3138
|
+
[445, 296, 'onion3'],
|
3139
|
+
[446, V, 'garlic64'],
|
3140
|
+
[448, 0, 'tls'],
|
3141
|
+
[449, V, 'sni'],
|
3142
|
+
[460, 0, 'quic'],
|
3143
|
+
[461, 0, 'quic-v1'],
|
3144
|
+
[465, 0, 'webtransport'],
|
3145
|
+
[466, V, 'certhash'],
|
3146
|
+
[477, 0, 'ws'],
|
3147
|
+
[478, 0, 'wss'],
|
3148
|
+
[479, 0, 'p2p-websocket-star'],
|
3149
|
+
[480, 0, 'http'],
|
3150
|
+
[481, V, 'http-path'],
|
3151
|
+
[777, V, 'memory']
|
3152
|
+
];
|
3153
|
+
// populate tables
|
3154
|
+
table.forEach(row => {
|
3155
|
+
const proto = createProtocol(...row);
|
3156
|
+
codes[proto.code] = proto;
|
3157
|
+
names[proto.name] = proto;
|
3158
|
+
});
|
3159
|
+
function createProtocol(code, size, name, resolvable, path) {
|
3160
|
+
return {
|
3161
|
+
code,
|
3162
|
+
size,
|
3163
|
+
name,
|
3164
|
+
resolvable: Boolean(resolvable),
|
3165
|
+
path: Boolean(path)
|
3166
|
+
};
|
3167
|
+
}
|
3168
|
+
/**
|
3169
|
+
* For the passed proto string or number, return a {@link Protocol}
|
3170
|
+
*
|
3171
|
+
* @example
|
3172
|
+
*
|
3173
|
+
* ```js
|
3174
|
+
* import { protocol } from '@multiformats/multiaddr'
|
3175
|
+
*
|
3176
|
+
* console.info(protocol(4))
|
3177
|
+
* // { code: 4, size: 32, name: 'ip4', resolvable: false, path: false }
|
3178
|
+
* ```
|
3179
|
+
*/
|
3180
|
+
function getProtocol(proto) {
|
3181
|
+
if (typeof proto === 'number') {
|
3182
|
+
if (codes[proto] != null) {
|
3183
|
+
return codes[proto];
|
3184
|
+
}
|
3185
|
+
throw new Error(`no protocol with code: ${proto}`);
|
3186
|
+
}
|
3187
|
+
else if (typeof proto === 'string') {
|
3188
|
+
if (names[proto] != null) {
|
3189
|
+
return names[proto];
|
3190
|
+
}
|
3191
|
+
throw new Error(`no protocol with name: ${proto}`);
|
3192
|
+
}
|
3193
|
+
throw new Error(`invalid protocol id type: ${typeof proto}`);
|
3194
|
+
}
|
3195
|
+
|
3196
|
+
getProtocol('ip4');
|
3197
|
+
getProtocol('ip6');
|
3198
|
+
getProtocol('ipcidr');
|
3199
|
+
/**
|
3200
|
+
* Convert [code,Uint8Array] to string
|
3201
|
+
*/
|
3202
|
+
// eslint-disable-next-line complexity
|
3203
|
+
function convertToString(proto, buf) {
|
3204
|
+
const protocol = getProtocol(proto);
|
3205
|
+
switch (protocol.code) {
|
3206
|
+
case 4: // ipv4
|
3207
|
+
case 41: // ipv6
|
3208
|
+
return bytes2ip(buf);
|
3209
|
+
case 42: // ipv6zone
|
3210
|
+
return bytes2str(buf);
|
3211
|
+
case 43: // ipcidr
|
3212
|
+
return toString$1(buf, 'base10');
|
3213
|
+
case 6: // tcp
|
3214
|
+
case 273: // udp
|
3215
|
+
case 33: // dccp
|
3216
|
+
case 132: // sctp
|
3217
|
+
return bytes2port(buf).toString();
|
3218
|
+
case 53: // dns
|
3219
|
+
case 54: // dns4
|
3220
|
+
case 55: // dns6
|
3221
|
+
case 56: // dnsaddr
|
3222
|
+
case 400: // unix
|
3223
|
+
case 449: // sni
|
3224
|
+
case 777: // memory
|
3225
|
+
return bytes2str(buf);
|
3226
|
+
case 421: // ipfs
|
3227
|
+
return bytes2mh(buf);
|
3228
|
+
case 444: // onion
|
3229
|
+
return bytes2onion(buf);
|
3230
|
+
case 445: // onion3
|
3231
|
+
return bytes2onion(buf);
|
3232
|
+
case 466: // certhash
|
3233
|
+
return bytes2mb(buf);
|
3234
|
+
case 481: // http-path
|
3235
|
+
return globalThis.encodeURIComponent(bytes2str(buf));
|
3236
|
+
default:
|
3237
|
+
return toString$1(buf, 'base16'); // no clue. convert to hex
|
3238
|
+
}
|
3239
|
+
}
|
3240
|
+
// eslint-disable-next-line complexity
|
3241
|
+
function convertToBytes(proto, str) {
|
3242
|
+
const protocol = getProtocol(proto);
|
3243
|
+
switch (protocol.code) {
|
3244
|
+
case 4: // ipv4
|
3245
|
+
return ip2bytes(str);
|
3246
|
+
case 41: // ipv6
|
3247
|
+
return ip2bytes(str);
|
3248
|
+
case 42: // ipv6zone
|
3249
|
+
return str2bytes(str);
|
3250
|
+
case 43: // ipcidr
|
3251
|
+
return fromString(str, 'base10');
|
3252
|
+
case 6: // tcp
|
3253
|
+
case 273: // udp
|
3254
|
+
case 33: // dccp
|
3255
|
+
case 132: // sctp
|
3256
|
+
return port2bytes(parseInt(str, 10));
|
3257
|
+
case 53: // dns
|
3258
|
+
case 54: // dns4
|
3259
|
+
case 55: // dns6
|
3260
|
+
case 56: // dnsaddr
|
3261
|
+
case 400: // unix
|
3262
|
+
case 449: // sni
|
3263
|
+
case 777: // memory
|
3264
|
+
return str2bytes(str);
|
3265
|
+
case 421: // ipfs
|
3266
|
+
return mh2bytes(str);
|
3267
|
+
case 444: // onion
|
3268
|
+
return onion2bytes(str);
|
3269
|
+
case 445: // onion3
|
3270
|
+
return onion32bytes(str);
|
3271
|
+
case 466: // certhash
|
3272
|
+
return mb2bytes(str);
|
3273
|
+
case 481: // http-path
|
3274
|
+
return str2bytes(globalThis.decodeURIComponent(str));
|
3275
|
+
default:
|
3276
|
+
return fromString(str, 'base16'); // no clue. convert from hex
|
3277
|
+
}
|
3278
|
+
}
|
3279
|
+
const decoders = Object.values(bases).map((c) => c.decoder);
|
3280
|
+
const anybaseDecoder = (function () {
|
3281
|
+
let acc = decoders[0].or(decoders[1]);
|
3282
|
+
decoders.slice(2).forEach((d) => (acc = acc.or(d)));
|
3283
|
+
return acc;
|
3284
|
+
})();
|
3285
|
+
function ip2bytes(ipString) {
|
3286
|
+
if (!isIP(ipString)) {
|
3287
|
+
throw new Error('invalid ip address');
|
3288
|
+
}
|
3289
|
+
return toBytes(ipString);
|
3290
|
+
}
|
3291
|
+
function bytes2ip(ipBuff) {
|
3292
|
+
const ipString = toString(ipBuff, 0, ipBuff.length);
|
3293
|
+
if (ipString == null) {
|
3294
|
+
throw new Error('ipBuff is required');
|
3295
|
+
}
|
3296
|
+
if (!isIP(ipString)) {
|
3297
|
+
throw new Error('invalid ip address');
|
3298
|
+
}
|
3299
|
+
return ipString;
|
3300
|
+
}
|
3301
|
+
function port2bytes(port) {
|
3302
|
+
const buf = new ArrayBuffer(2);
|
3303
|
+
const view = new DataView(buf);
|
3304
|
+
view.setUint16(0, port);
|
3305
|
+
return new Uint8Array(buf);
|
3306
|
+
}
|
3307
|
+
function bytes2port(buf) {
|
3308
|
+
const view = new DataView(buf.buffer);
|
3309
|
+
return view.getUint16(buf.byteOffset);
|
3310
|
+
}
|
3311
|
+
function str2bytes(str) {
|
3312
|
+
const buf = fromString(str);
|
3313
|
+
const size = Uint8Array.from(encode$2(buf.length));
|
3314
|
+
return concat([size, buf], size.length + buf.length);
|
3315
|
+
}
|
3316
|
+
function bytes2str(buf) {
|
3317
|
+
const size = decode$4(buf);
|
3318
|
+
buf = buf.slice(encodingLength$1(size));
|
3319
|
+
if (buf.length !== size) {
|
3320
|
+
throw new Error('inconsistent lengths');
|
3321
|
+
}
|
3322
|
+
return toString$1(buf);
|
3323
|
+
}
|
3324
|
+
function mh2bytes(hash) {
|
3325
|
+
let mh;
|
3326
|
+
if (hash[0] === 'Q' || hash[0] === '1') {
|
3327
|
+
mh = decode$1(base58btc.decode(`z${hash}`)).bytes;
|
3328
|
+
}
|
3329
|
+
else {
|
3330
|
+
mh = CID.parse(hash).multihash.bytes;
|
3331
|
+
}
|
3332
|
+
// the address is a varint prefixed multihash string representation
|
3333
|
+
const size = Uint8Array.from(encode$2(mh.length));
|
3334
|
+
return concat([size, mh], size.length + mh.length);
|
3335
|
+
}
|
3336
|
+
function mb2bytes(mbstr) {
|
3337
|
+
const mb = anybaseDecoder.decode(mbstr);
|
3338
|
+
const size = Uint8Array.from(encode$2(mb.length));
|
3339
|
+
return concat([size, mb], size.length + mb.length);
|
3340
|
+
}
|
3341
|
+
function bytes2mb(buf) {
|
3342
|
+
const size = decode$4(buf);
|
3343
|
+
const hash = buf.slice(encodingLength$1(size));
|
3344
|
+
if (hash.length !== size) {
|
3345
|
+
throw new Error('inconsistent lengths');
|
3346
|
+
}
|
3347
|
+
return 'u' + toString$1(hash, 'base64url');
|
3348
|
+
}
|
3349
|
+
/**
|
3350
|
+
* Converts bytes to bas58btc string
|
3351
|
+
*/
|
3352
|
+
function bytes2mh(buf) {
|
3353
|
+
const size = decode$4(buf);
|
3354
|
+
const address = buf.slice(encodingLength$1(size));
|
3355
|
+
if (address.length !== size) {
|
3356
|
+
throw new Error('inconsistent lengths');
|
3357
|
+
}
|
3358
|
+
return toString$1(address, 'base58btc');
|
3359
|
+
}
|
3360
|
+
function onion2bytes(str) {
|
3361
|
+
const addr = str.split(':');
|
3362
|
+
if (addr.length !== 2) {
|
3363
|
+
throw new Error(`failed to parse onion addr: ["'${addr.join('", "')}'"]' does not contain a port number`);
|
3364
|
+
}
|
3365
|
+
if (addr[0].length !== 16) {
|
3366
|
+
throw new Error(`failed to parse onion addr: ${addr[0]} not a Tor onion address.`);
|
3367
|
+
}
|
3368
|
+
// onion addresses do not include the multibase prefix, add it before decoding
|
3369
|
+
const buf = base32.decode('b' + addr[0]);
|
3370
|
+
// onion port number
|
3371
|
+
const port = parseInt(addr[1], 10);
|
3372
|
+
if (port < 1 || port > 65536) {
|
3373
|
+
throw new Error('Port number is not in range(1, 65536)');
|
3374
|
+
}
|
3375
|
+
const portBuf = port2bytes(port);
|
3376
|
+
return concat([buf, portBuf], buf.length + portBuf.length);
|
3377
|
+
}
|
3378
|
+
function onion32bytes(str) {
|
3379
|
+
const addr = str.split(':');
|
3380
|
+
if (addr.length !== 2) {
|
3381
|
+
throw new Error(`failed to parse onion addr: ["'${addr.join('", "')}'"]' does not contain a port number`);
|
3382
|
+
}
|
3383
|
+
if (addr[0].length !== 56) {
|
3384
|
+
throw new Error(`failed to parse onion addr: ${addr[0]} not a Tor onion3 address.`);
|
3385
|
+
}
|
3386
|
+
// onion addresses do not include the multibase prefix, add it before decoding
|
3387
|
+
const buf = base32.decode(`b${addr[0]}`);
|
3388
|
+
// onion port number
|
3389
|
+
const port = parseInt(addr[1], 10);
|
3390
|
+
if (port < 1 || port > 65536) {
|
3391
|
+
throw new Error('Port number is not in range(1, 65536)');
|
3392
|
+
}
|
3393
|
+
const portBuf = port2bytes(port);
|
3394
|
+
return concat([buf, portBuf], buf.length + portBuf.length);
|
3395
|
+
}
|
3396
|
+
function bytes2onion(buf) {
|
3397
|
+
const addrBytes = buf.slice(0, buf.length - 2);
|
3398
|
+
const portBytes = buf.slice(buf.length - 2);
|
3399
|
+
const addr = toString$1(addrBytes, 'base32');
|
3400
|
+
const port = bytes2port(portBytes);
|
3401
|
+
return `${addr}:${port}`;
|
3402
|
+
}
|
3403
|
+
|
3404
|
+
function stringToMultiaddrParts(str) {
|
3405
|
+
str = cleanPath(str);
|
3406
|
+
const tuples = [];
|
3407
|
+
const stringTuples = [];
|
3408
|
+
let path = null;
|
3409
|
+
const parts = str.split('/').slice(1);
|
3410
|
+
if (parts.length === 1 && parts[0] === '') {
|
3411
|
+
return {
|
3412
|
+
bytes: new Uint8Array(),
|
3413
|
+
string: '/',
|
3414
|
+
tuples: [],
|
3415
|
+
stringTuples: [],
|
3416
|
+
path: null
|
3417
|
+
};
|
3418
|
+
}
|
3419
|
+
for (let p = 0; p < parts.length; p++) {
|
3420
|
+
const part = parts[p];
|
3421
|
+
const proto = getProtocol(part);
|
3422
|
+
if (proto.size === 0) {
|
3423
|
+
tuples.push([proto.code]);
|
3424
|
+
stringTuples.push([proto.code]);
|
3425
|
+
// eslint-disable-next-line no-continue
|
3426
|
+
continue;
|
3427
|
+
}
|
3428
|
+
p++; // advance addr part
|
3429
|
+
if (p >= parts.length) {
|
3430
|
+
throw ParseError('invalid address: ' + str);
|
3431
|
+
}
|
3432
|
+
// if it's a path proto, take the rest
|
3433
|
+
if (proto.path === true) {
|
3434
|
+
// should we need to check each path part to see if it's a proto?
|
3435
|
+
// This would allow for other protocols to be added after a unix path,
|
3436
|
+
// however it would have issues if the path had a protocol name in the path
|
3437
|
+
path = cleanPath(parts.slice(p).join('/'));
|
3438
|
+
tuples.push([proto.code, convertToBytes(proto.code, path)]);
|
3439
|
+
stringTuples.push([proto.code, path]);
|
3440
|
+
break;
|
3441
|
+
}
|
3442
|
+
const bytes = convertToBytes(proto.code, parts[p]);
|
3443
|
+
tuples.push([proto.code, bytes]);
|
3444
|
+
stringTuples.push([proto.code, convertToString(proto.code, bytes)]);
|
3445
|
+
}
|
3446
|
+
return {
|
3447
|
+
string: stringTuplesToString(stringTuples),
|
3448
|
+
bytes: tuplesToBytes(tuples),
|
3449
|
+
tuples,
|
3450
|
+
stringTuples,
|
3451
|
+
path
|
3452
|
+
};
|
3453
|
+
}
|
3454
|
+
function bytesToMultiaddrParts(bytes) {
|
3455
|
+
const tuples = [];
|
3456
|
+
const stringTuples = [];
|
3457
|
+
let path = null;
|
3458
|
+
let i = 0;
|
3459
|
+
while (i < bytes.length) {
|
3460
|
+
const code = decode$4(bytes, i);
|
3461
|
+
const n = encodingLength$1(code);
|
3462
|
+
const p = getProtocol(code);
|
3463
|
+
const size = sizeForAddr(p, bytes.slice(i + n));
|
3464
|
+
if (size === 0) {
|
3465
|
+
tuples.push([code]);
|
3466
|
+
stringTuples.push([code]);
|
3467
|
+
i += n;
|
3468
|
+
// eslint-disable-next-line no-continue
|
3469
|
+
continue;
|
3470
|
+
}
|
3471
|
+
const addr = bytes.slice(i + n, i + n + size);
|
3472
|
+
i += (size + n);
|
3473
|
+
if (i > bytes.length) { // did not end _exactly_ at buffer.length
|
3474
|
+
throw ParseError('Invalid address Uint8Array: ' + toString$1(bytes, 'base16'));
|
3475
|
+
}
|
3476
|
+
// ok, tuple seems good.
|
3477
|
+
tuples.push([code, addr]);
|
3478
|
+
const stringAddr = convertToString(code, addr);
|
3479
|
+
stringTuples.push([code, stringAddr]);
|
3480
|
+
if (p.path === true) {
|
3481
|
+
// should we need to check each path part to see if it's a proto?
|
3482
|
+
// This would allow for other protocols to be added after a unix path,
|
3483
|
+
// however it would have issues if the path had a protocol name in the path
|
3484
|
+
path = stringAddr;
|
3485
|
+
break;
|
3486
|
+
}
|
3487
|
+
}
|
3488
|
+
return {
|
3489
|
+
bytes: Uint8Array.from(bytes),
|
3490
|
+
string: stringTuplesToString(stringTuples),
|
3491
|
+
tuples,
|
3492
|
+
stringTuples,
|
3493
|
+
path
|
3494
|
+
};
|
3495
|
+
}
|
3496
|
+
/**
|
3497
|
+
* [[str name, str addr]... ] -> string
|
3498
|
+
*/
|
3499
|
+
function stringTuplesToString(tuples) {
|
3500
|
+
const parts = [];
|
3501
|
+
tuples.map((tup) => {
|
3502
|
+
const proto = getProtocol(tup[0]);
|
3503
|
+
parts.push(proto.name);
|
3504
|
+
if (tup.length > 1 && tup[1] != null) {
|
3505
|
+
parts.push(tup[1]);
|
3506
|
+
}
|
3507
|
+
return null;
|
3508
|
+
});
|
3509
|
+
return cleanPath(parts.join('/'));
|
3510
|
+
}
|
3511
|
+
/**
|
3512
|
+
* [[int code, Uint8Array ]... ] -> Uint8Array
|
3513
|
+
*/
|
3514
|
+
function tuplesToBytes(tuples) {
|
3515
|
+
return concat(tuples.map((tup) => {
|
3516
|
+
const proto = getProtocol(tup[0]);
|
3517
|
+
let buf = Uint8Array.from(encode$2(proto.code));
|
3518
|
+
if (tup.length > 1 && tup[1] != null) {
|
3519
|
+
buf = concat([buf, tup[1]]); // add address buffer
|
3520
|
+
}
|
3521
|
+
return buf;
|
3522
|
+
}));
|
3523
|
+
}
|
3524
|
+
/**
|
3525
|
+
* For the passed address, return the serialized size
|
3526
|
+
*/
|
3527
|
+
function sizeForAddr(p, addr) {
|
3528
|
+
if (p.size > 0) {
|
3529
|
+
return p.size / 8;
|
3530
|
+
}
|
3531
|
+
else if (p.size === 0) {
|
3532
|
+
return 0;
|
3533
|
+
}
|
3534
|
+
else {
|
3535
|
+
const size = decode$4(addr instanceof Uint8Array ? addr : Uint8Array.from(addr));
|
3536
|
+
return size + encodingLength$1(size);
|
3537
|
+
}
|
3538
|
+
}
|
3539
|
+
function cleanPath(str) {
|
3540
|
+
return '/' + str.trim().split('/').filter((a) => a).join('/');
|
3541
|
+
}
|
3542
|
+
function ParseError(str) {
|
3543
|
+
return new Error('Error parsing address: ' + str);
|
3544
|
+
}
|
3545
|
+
|
3546
|
+
const inspect = Symbol.for('nodejs.util.inspect.custom');
|
3547
|
+
const symbol = Symbol.for('@multiformats/js-multiaddr/multiaddr');
|
3548
|
+
const DNS_CODES = [
|
3549
|
+
getProtocol('dns').code,
|
3550
|
+
getProtocol('dns4').code,
|
3551
|
+
getProtocol('dns6').code,
|
3552
|
+
getProtocol('dnsaddr').code
|
3553
|
+
];
|
3554
|
+
class NoAvailableResolverError extends Error {
|
3555
|
+
constructor(message = 'No available resolver') {
|
3556
|
+
super(message);
|
3557
|
+
this.name = 'NoAvailableResolverError';
|
3558
|
+
}
|
3559
|
+
}
|
3560
|
+
/**
|
3561
|
+
* Creates a {@link Multiaddr} from a {@link MultiaddrInput}
|
3562
|
+
*/
|
3563
|
+
class Multiaddr {
|
3564
|
+
bytes;
|
3565
|
+
#string;
|
3566
|
+
#tuples;
|
3567
|
+
#stringTuples;
|
3568
|
+
#path;
|
3569
|
+
[symbol] = true;
|
3570
|
+
constructor(addr) {
|
3571
|
+
// default
|
3572
|
+
if (addr == null) {
|
3573
|
+
addr = '';
|
3574
|
+
}
|
3575
|
+
let parts;
|
3576
|
+
if (addr instanceof Uint8Array) {
|
3577
|
+
parts = bytesToMultiaddrParts(addr);
|
3578
|
+
}
|
3579
|
+
else if (typeof addr === 'string') {
|
3580
|
+
if (addr.length > 0 && addr.charAt(0) !== '/') {
|
3581
|
+
throw new Error(`multiaddr "${addr}" must start with a "/"`);
|
3582
|
+
}
|
3583
|
+
parts = stringToMultiaddrParts(addr);
|
3584
|
+
}
|
3585
|
+
else if (isMultiaddr(addr)) { // Multiaddr
|
3586
|
+
parts = bytesToMultiaddrParts(addr.bytes);
|
3587
|
+
}
|
3588
|
+
else {
|
3589
|
+
throw new Error('addr must be a string, Buffer, or another Multiaddr');
|
3590
|
+
}
|
3591
|
+
this.bytes = parts.bytes;
|
3592
|
+
this.#string = parts.string;
|
3593
|
+
this.#tuples = parts.tuples;
|
3594
|
+
this.#stringTuples = parts.stringTuples;
|
3595
|
+
this.#path = parts.path;
|
3596
|
+
}
|
3597
|
+
toString() {
|
3598
|
+
return this.#string;
|
3599
|
+
}
|
3600
|
+
toJSON() {
|
3601
|
+
return this.toString();
|
3602
|
+
}
|
3603
|
+
toOptions() {
|
3604
|
+
let family;
|
3605
|
+
let transport;
|
3606
|
+
let host;
|
3607
|
+
let port;
|
3608
|
+
let zone = '';
|
3609
|
+
const tcp = getProtocol('tcp');
|
3610
|
+
const udp = getProtocol('udp');
|
3611
|
+
const ip4 = getProtocol('ip4');
|
3612
|
+
const ip6 = getProtocol('ip6');
|
3613
|
+
const dns6 = getProtocol('dns6');
|
3614
|
+
const ip6zone = getProtocol('ip6zone');
|
3615
|
+
for (const [code, value] of this.stringTuples()) {
|
3616
|
+
if (code === ip6zone.code) {
|
3617
|
+
zone = `%${value ?? ''}`;
|
3618
|
+
}
|
3619
|
+
// default to https when protocol & port are omitted from DNS addrs
|
3620
|
+
if (DNS_CODES.includes(code)) {
|
3621
|
+
transport = tcp.name;
|
3622
|
+
port = 443;
|
3623
|
+
host = `${value ?? ''}${zone}`;
|
3624
|
+
family = code === dns6.code ? 6 : 4;
|
3625
|
+
}
|
3626
|
+
if (code === tcp.code || code === udp.code) {
|
3627
|
+
transport = getProtocol(code).name;
|
3628
|
+
port = parseInt(value ?? '');
|
3629
|
+
}
|
3630
|
+
if (code === ip4.code || code === ip6.code) {
|
3631
|
+
transport = getProtocol(code).name;
|
3632
|
+
host = `${value ?? ''}${zone}`;
|
3633
|
+
family = code === ip6.code ? 6 : 4;
|
3634
|
+
}
|
3635
|
+
}
|
3636
|
+
if (family == null || transport == null || host == null || port == null) {
|
3637
|
+
throw new Error('multiaddr must have a valid format: "/{ip4, ip6, dns4, dns6, dnsaddr}/{address}/{tcp, udp}/{port}".');
|
3638
|
+
}
|
3639
|
+
const opts = {
|
3640
|
+
family,
|
3641
|
+
host,
|
3642
|
+
transport,
|
3643
|
+
port
|
3644
|
+
};
|
3645
|
+
return opts;
|
3646
|
+
}
|
3647
|
+
protos() {
|
3648
|
+
return this.#tuples.map(([code]) => Object.assign({}, getProtocol(code)));
|
3649
|
+
}
|
3650
|
+
protoCodes() {
|
3651
|
+
return this.#tuples.map(([code]) => code);
|
3652
|
+
}
|
3653
|
+
protoNames() {
|
3654
|
+
return this.#tuples.map(([code]) => getProtocol(code).name);
|
3655
|
+
}
|
3656
|
+
tuples() {
|
3657
|
+
return this.#tuples.map(([code, value]) => {
|
3658
|
+
if (value == null) {
|
3659
|
+
return [code];
|
3660
|
+
}
|
3661
|
+
return [code, value];
|
3662
|
+
});
|
3663
|
+
}
|
3664
|
+
stringTuples() {
|
3665
|
+
return this.#stringTuples.map(([code, value]) => {
|
3666
|
+
if (value == null) {
|
3667
|
+
return [code];
|
3668
|
+
}
|
3669
|
+
return [code, value];
|
3670
|
+
});
|
3671
|
+
}
|
3672
|
+
encapsulate(addr) {
|
3673
|
+
addr = new Multiaddr(addr);
|
3674
|
+
return new Multiaddr(this.toString() + addr.toString());
|
3675
|
+
}
|
3676
|
+
decapsulate(addr) {
|
3677
|
+
const addrString = addr.toString();
|
3678
|
+
const s = this.toString();
|
3679
|
+
const i = s.lastIndexOf(addrString);
|
3680
|
+
if (i < 0) {
|
3681
|
+
throw new Error(`Address ${this.toString()} does not contain subaddress: ${addr.toString()}`);
|
3682
|
+
}
|
3683
|
+
return new Multiaddr(s.slice(0, i));
|
3684
|
+
}
|
3685
|
+
decapsulateCode(code) {
|
3686
|
+
const tuples = this.tuples();
|
3687
|
+
for (let i = tuples.length - 1; i >= 0; i--) {
|
3688
|
+
if (tuples[i][0] === code) {
|
3689
|
+
return new Multiaddr(tuplesToBytes(tuples.slice(0, i)));
|
3690
|
+
}
|
3691
|
+
}
|
3692
|
+
return this;
|
3693
|
+
}
|
3694
|
+
getPeerId() {
|
3695
|
+
try {
|
3696
|
+
let tuples = [];
|
3697
|
+
this.stringTuples().forEach(([code, name]) => {
|
3698
|
+
if (code === names.p2p.code) {
|
3699
|
+
tuples.push([code, name]);
|
3700
|
+
}
|
3701
|
+
// if this is a p2p-circuit address, return the target peer id if present
|
3702
|
+
// not the peer id of the relay
|
3703
|
+
if (code === names['p2p-circuit'].code) {
|
3704
|
+
tuples = [];
|
3705
|
+
}
|
3706
|
+
});
|
3707
|
+
// Get the last ipfs tuple ['p2p', 'peerid string']
|
3708
|
+
const tuple = tuples.pop();
|
3709
|
+
if (tuple?.[1] != null) {
|
3710
|
+
const peerIdStr = tuple[1];
|
3711
|
+
// peer id is base58btc encoded string but not multibase encoded so add the `z`
|
3712
|
+
// prefix so we can validate that it is correctly encoded
|
3713
|
+
if (peerIdStr[0] === 'Q' || peerIdStr[0] === '1') {
|
3714
|
+
return toString$1(base58btc.decode(`z${peerIdStr}`), 'base58btc');
|
3715
|
+
}
|
3716
|
+
// try to parse peer id as CID
|
3717
|
+
return toString$1(CID.parse(peerIdStr).multihash.bytes, 'base58btc');
|
3718
|
+
}
|
3719
|
+
return null;
|
3720
|
+
}
|
3721
|
+
catch (e) {
|
3722
|
+
return null;
|
3723
|
+
}
|
3724
|
+
}
|
3725
|
+
getPath() {
|
3726
|
+
return this.#path;
|
3727
|
+
}
|
3728
|
+
equals(addr) {
|
3729
|
+
return equals(this.bytes, addr.bytes);
|
3730
|
+
}
|
3731
|
+
async resolve(options) {
|
3732
|
+
const resolvableProto = this.protos().find((p) => p.resolvable);
|
3733
|
+
// Multiaddr is not resolvable?
|
3734
|
+
if (resolvableProto == null) {
|
3735
|
+
return [this];
|
3736
|
+
}
|
3737
|
+
const resolver = resolvers.get(resolvableProto.name);
|
3738
|
+
if (resolver == null) {
|
3739
|
+
throw new NoAvailableResolverError(`no available resolver for ${resolvableProto.name}`);
|
3740
|
+
}
|
3741
|
+
const result = await resolver(this, options);
|
3742
|
+
return result.map(str => multiaddr(str));
|
3743
|
+
}
|
3744
|
+
nodeAddress() {
|
3745
|
+
const options = this.toOptions();
|
3746
|
+
if (options.transport !== 'tcp' && options.transport !== 'udp') {
|
3747
|
+
throw new Error(`multiaddr must have a valid format - no protocol with name: "${options.transport}". Must have a valid transport protocol: "{tcp, udp}"`);
|
3748
|
+
}
|
3749
|
+
return {
|
3750
|
+
family: options.family,
|
3751
|
+
address: options.host,
|
3752
|
+
port: options.port
|
3753
|
+
};
|
3754
|
+
}
|
3755
|
+
isThinWaistAddress(addr) {
|
3756
|
+
const protos = (addr ?? this).protos();
|
3757
|
+
if (protos.length !== 2) {
|
3758
|
+
return false;
|
3759
|
+
}
|
3760
|
+
if (protos[0].code !== 4 && protos[0].code !== 41) {
|
3761
|
+
return false;
|
3762
|
+
}
|
3763
|
+
if (protos[1].code !== 6 && protos[1].code !== 273) {
|
3764
|
+
return false;
|
3765
|
+
}
|
3766
|
+
return true;
|
3767
|
+
}
|
3768
|
+
/**
|
3769
|
+
* Returns Multiaddr as a human-readable string
|
3770
|
+
* https://nodejs.org/api/util.html#utilinspectcustom
|
3771
|
+
*
|
3772
|
+
* @example
|
3773
|
+
* ```js
|
3774
|
+
* import { multiaddr } from '@multiformats/multiaddr'
|
3775
|
+
*
|
3776
|
+
* console.info(multiaddr('/ip4/127.0.0.1/tcp/4001'))
|
3777
|
+
* // 'Multiaddr(/ip4/127.0.0.1/tcp/4001)'
|
3778
|
+
* ```
|
3779
|
+
*/
|
3780
|
+
[inspect]() {
|
3781
|
+
return `Multiaddr(${this.#string})`;
|
3782
|
+
}
|
3783
|
+
}
|
3784
|
+
|
3785
|
+
/**
|
3786
|
+
* @packageDocumentation
|
3787
|
+
*
|
3788
|
+
* A standard way to represent addresses that
|
3789
|
+
*
|
3790
|
+
* - support any standard network protocol
|
3791
|
+
* - are self-describing
|
3792
|
+
* - have a binary packed format
|
3793
|
+
* - have a nice string representation
|
3794
|
+
* - encapsulate well
|
3795
|
+
*
|
3796
|
+
* @example
|
3797
|
+
*
|
3798
|
+
* ```TypeScript
|
3799
|
+
* import { multiaddr } from '@multiformats/multiaddr'
|
3800
|
+
*
|
3801
|
+
* const addr = multiaddr('/ip4/127.0.0.1/udp/1234')
|
3802
|
+
* // Multiaddr(/ip4/127.0.0.1/udp/1234)
|
3803
|
+
*
|
3804
|
+
* addr.bytes
|
3805
|
+
* // <Uint8Array 04 7f 00 00 01 11 04 d2>
|
3806
|
+
*
|
3807
|
+
* addr.toString()
|
3808
|
+
* // '/ip4/127.0.0.1/udp/1234'
|
3809
|
+
*
|
3810
|
+
* addr.protos()
|
3811
|
+
* // [
|
3812
|
+
* // {code: 4, name: 'ip4', size: 32},
|
3813
|
+
* // {code: 273, name: 'udp', size: 16}
|
3814
|
+
* // ]
|
3815
|
+
*
|
3816
|
+
* // gives you an object that is friendly with what Node.js core modules expect for addresses
|
3817
|
+
* addr.nodeAddress()
|
3818
|
+
* // {
|
3819
|
+
* // family: 4,
|
3820
|
+
* // port: 1234,
|
3821
|
+
* // address: "127.0.0.1"
|
3822
|
+
* // }
|
3823
|
+
*
|
3824
|
+
* addr.encapsulate('/sctp/5678')
|
3825
|
+
* // Multiaddr(/ip4/127.0.0.1/udp/1234/sctp/5678)
|
3826
|
+
* ```
|
3827
|
+
*
|
3828
|
+
* ## Resolving DNSADDR addresses
|
3829
|
+
*
|
3830
|
+
* [DNSADDR](https://github.com/multiformats/multiaddr/blob/master/protocols/DNSADDR.md) is a spec that allows storing a TXT DNS record that contains a Multiaddr.
|
3831
|
+
*
|
3832
|
+
* To resolve DNSADDR addresses, call the `.resolve()` function the multiaddr, optionally passing a `DNS` resolver.
|
3833
|
+
*
|
3834
|
+
* DNSADDR addresses can resolve to multiple multiaddrs, since there is no limit to the number of TXT records that can be stored.
|
3835
|
+
*
|
3836
|
+
* @example Resolving DNSADDR Multiaddrs
|
3837
|
+
*
|
3838
|
+
* ```TypeScript
|
3839
|
+
* import { multiaddr, resolvers } from '@multiformats/multiaddr'
|
3840
|
+
* import { dnsaddrResolver } from '@multiformats/multiaddr/resolvers'
|
3841
|
+
*
|
3842
|
+
* resolvers.set('dnsaddr', dnsaddrResolver)
|
3843
|
+
*
|
3844
|
+
* const ma = multiaddr('/dnsaddr/bootstrap.libp2p.io')
|
3845
|
+
*
|
3846
|
+
* // resolve with a 5s timeout
|
3847
|
+
* const resolved = await ma.resolve({
|
3848
|
+
* signal: AbortSignal.timeout(5000)
|
3849
|
+
* })
|
3850
|
+
*
|
3851
|
+
* console.info(resolved)
|
3852
|
+
* // [Multiaddr('/ip4/147.75...'), Multiaddr('/ip4/147.75...'), Multiaddr('/ip4/147.75...')...]
|
3853
|
+
* ```
|
3854
|
+
*
|
3855
|
+
* @example Using a custom DNS resolver to resolve DNSADDR Multiaddrs
|
3856
|
+
*
|
3857
|
+
* See the docs for [@multiformats/dns](https://www.npmjs.com/package/@multiformats/dns) for a full breakdown of how to specify multiple resolvers or resolvers that can be used for specific TLDs.
|
3858
|
+
*
|
3859
|
+
* ```TypeScript
|
3860
|
+
* import { multiaddr } from '@multiformats/multiaddr'
|
3861
|
+
* import { dns } from '@multiformats/dns'
|
3862
|
+
* import { dnsJsonOverHttps } from '@multiformats/dns/resolvers'
|
3863
|
+
*
|
3864
|
+
* const resolver = dns({
|
3865
|
+
* resolvers: {
|
3866
|
+
* '.': dnsJsonOverHttps('https://cloudflare-dns.com/dns-query')
|
3867
|
+
* }
|
3868
|
+
* })
|
3869
|
+
*
|
3870
|
+
* const ma = multiaddr('/dnsaddr/bootstrap.libp2p.io')
|
3871
|
+
* const resolved = await ma.resolve({
|
3872
|
+
* dns: resolver
|
3873
|
+
* })
|
3874
|
+
*
|
3875
|
+
* console.info(resolved)
|
3876
|
+
* // [Multiaddr('/ip4/147.75...'), Multiaddr('/ip4/147.75...'), Multiaddr('/ip4/147.75...')...]
|
3877
|
+
* ```
|
3878
|
+
*/
|
3879
|
+
/**
|
3880
|
+
* All configured {@link Resolver}s
|
3881
|
+
*/
|
3882
|
+
const resolvers = new Map();
|
3883
|
+
/**
|
3884
|
+
* Check if object is a {@link Multiaddr} instance
|
3885
|
+
*
|
3886
|
+
* @example
|
3887
|
+
*
|
3888
|
+
* ```js
|
3889
|
+
* import { isMultiaddr, multiaddr } from '@multiformats/multiaddr'
|
3890
|
+
*
|
3891
|
+
* isMultiaddr(5)
|
3892
|
+
* // false
|
3893
|
+
* isMultiaddr(multiaddr('/ip4/127.0.0.1'))
|
3894
|
+
* // true
|
3895
|
+
* ```
|
3896
|
+
*/
|
3897
|
+
function isMultiaddr(value) {
|
3898
|
+
return Boolean(value?.[symbol]);
|
3899
|
+
}
|
3900
|
+
/**
|
3901
|
+
* A function that takes a {@link MultiaddrInput} and returns a {@link Multiaddr}
|
3902
|
+
*
|
3903
|
+
* @example
|
3904
|
+
* ```js
|
3905
|
+
* import { multiaddr } from '@libp2p/multiaddr'
|
3906
|
+
*
|
3907
|
+
* multiaddr('/ip4/127.0.0.1/tcp/4001')
|
3908
|
+
* // Multiaddr(/ip4/127.0.0.1/tcp/4001)
|
3909
|
+
* ```
|
3910
|
+
*
|
3911
|
+
* @param {MultiaddrInput} [addr] - If String or Uint8Array, needs to adhere to the address format of a [multiaddr](https://github.com/multiformats/multiaddr#string-format)
|
3912
|
+
*/
|
3913
|
+
function multiaddr(addr) {
|
3914
|
+
return new Multiaddr(addr);
|
3915
|
+
}
|
2250
3916
|
|
2251
3917
|
const RelayPingContentTopic = "/relay-ping/1/ping/null";
|
2252
3918
|
const log$2 = new Logger("keep-alive");
|
@@ -2357,13 +4023,36 @@ class KeepAliveManager {
|
|
2357
4023
|
}
|
2358
4024
|
}
|
2359
4025
|
|
4026
|
+
/**
|
4027
|
+
* Reads peer's metadata and retrieves ping value.
|
4028
|
+
* @param peer Peer or null
|
4029
|
+
* @returns -1 if no ping attached, otherwise returns ping value
|
4030
|
+
*/
|
4031
|
+
const getPeerPing = (peer) => {
|
4032
|
+
if (!peer) {
|
4033
|
+
return -1;
|
4034
|
+
}
|
4035
|
+
try {
|
4036
|
+
const bytes = peer.metadata.get("ping");
|
4037
|
+
if (!bytes) {
|
4038
|
+
return -1;
|
4039
|
+
}
|
4040
|
+
return Number(bytesToUtf8(bytes));
|
4041
|
+
}
|
4042
|
+
catch (e) {
|
4043
|
+
return -1;
|
4044
|
+
}
|
4045
|
+
};
|
4046
|
+
|
2360
4047
|
const log$1 = new Logger("connection-manager");
|
2361
4048
|
const DEFAULT_MAX_BOOTSTRAP_PEERS_ALLOWED = 1;
|
2362
4049
|
const DEFAULT_MAX_DIAL_ATTEMPTS_FOR_PEER = 3;
|
2363
4050
|
const DEFAULT_MAX_PARALLEL_DIALS = 3;
|
4051
|
+
const DEFAULT_PING_KEEP_ALIVE_SEC = 5 * 60;
|
4052
|
+
const DEFAULT_RELAY_KEEP_ALIVE_SEC = 5 * 60;
|
2364
4053
|
class ConnectionManager extends TypedEventEmitter {
|
2365
|
-
|
2366
|
-
|
4054
|
+
// TODO(weboko): make it private
|
4055
|
+
pubsubTopics;
|
2367
4056
|
keepAliveManager;
|
2368
4057
|
options;
|
2369
4058
|
libp2p;
|
@@ -2378,14 +4067,6 @@ class ConnectionManager extends TypedEventEmitter {
|
|
2378
4067
|
}
|
2379
4068
|
return this.isP2PNetworkConnected;
|
2380
4069
|
}
|
2381
|
-
static create(peerId, libp2p, keepAliveOptions, pubsubTopics, relay, options) {
|
2382
|
-
let instance = ConnectionManager.instances.get(peerId);
|
2383
|
-
if (!instance) {
|
2384
|
-
instance = new ConnectionManager(libp2p, keepAliveOptions, pubsubTopics, relay, options);
|
2385
|
-
ConnectionManager.instances.set(peerId, instance);
|
2386
|
-
}
|
2387
|
-
return instance;
|
2388
|
-
}
|
2389
4070
|
stop() {
|
2390
4071
|
this.keepAliveManager.stopAll();
|
2391
4072
|
this.libp2p.removeEventListener("peer:connect", this.onEventHandlers["peer:connect"]);
|
@@ -2452,21 +4133,25 @@ class ConnectionManager extends TypedEventEmitter {
|
|
2452
4133
|
}
|
2453
4134
|
};
|
2454
4135
|
}
|
2455
|
-
constructor(
|
4136
|
+
constructor(options) {
|
2456
4137
|
super();
|
2457
|
-
this.
|
2458
|
-
this.
|
2459
|
-
this.configuredPubsubTopics = configuredPubsubTopics;
|
4138
|
+
this.libp2p = options.libp2p;
|
4139
|
+
this.pubsubTopics = options.pubsubTopics;
|
2460
4140
|
this.options = {
|
2461
4141
|
maxDialAttemptsForPeer: DEFAULT_MAX_DIAL_ATTEMPTS_FOR_PEER,
|
2462
4142
|
maxBootstrapPeersAllowed: DEFAULT_MAX_BOOTSTRAP_PEERS_ALLOWED,
|
2463
4143
|
maxParallelDials: DEFAULT_MAX_PARALLEL_DIALS,
|
2464
|
-
|
4144
|
+
pingKeepAlive: DEFAULT_PING_KEEP_ALIVE_SEC,
|
4145
|
+
relayKeepAlive: DEFAULT_RELAY_KEEP_ALIVE_SEC,
|
4146
|
+
...options.config
|
2465
4147
|
};
|
2466
4148
|
this.keepAliveManager = new KeepAliveManager({
|
2467
|
-
relay,
|
2468
|
-
libp2p,
|
2469
|
-
options:
|
4149
|
+
relay: options.relay,
|
4150
|
+
libp2p: options.libp2p,
|
4151
|
+
options: {
|
4152
|
+
pingKeepAlive: this.options.pingKeepAlive,
|
4153
|
+
relayKeepAlive: this.options.relayKeepAlive
|
4154
|
+
}
|
2470
4155
|
});
|
2471
4156
|
this.startEventListeners()
|
2472
4157
|
.then(() => log$1.info(`Connection Manager is now running`))
|
@@ -2476,6 +4161,24 @@ class ConnectionManager extends TypedEventEmitter {
|
|
2476
4161
|
// we will dial the peers in peerStore ONCE before we start to listen to the `peer:discovery` events within the ConnectionManager
|
2477
4162
|
this.dialPeerStorePeers().catch((error) => log$1.error(`Unexpected error while dialing peer store peers`, error));
|
2478
4163
|
}
|
4164
|
+
async getConnectedPeers(codec) {
|
4165
|
+
const peerIDs = this.libp2p.getPeers();
|
4166
|
+
if (peerIDs.length === 0) {
|
4167
|
+
return [];
|
4168
|
+
}
|
4169
|
+
const peers = await Promise.all(peerIDs.map(async (id) => {
|
4170
|
+
try {
|
4171
|
+
return await this.libp2p.peerStore.get(id);
|
4172
|
+
}
|
4173
|
+
catch (e) {
|
4174
|
+
return null;
|
4175
|
+
}
|
4176
|
+
}));
|
4177
|
+
return peers
|
4178
|
+
.filter((p) => !!p)
|
4179
|
+
.filter((p) => (codec ? p.protocols.includes(codec) : true))
|
4180
|
+
.sort((left, right) => getPeerPing(left) - getPeerPing(right));
|
4181
|
+
}
|
2479
4182
|
async dialPeerStorePeers() {
|
2480
4183
|
const peerInfos = await this.libp2p.peerStore.all();
|
2481
4184
|
const dialPromises = [];
|
@@ -2497,13 +4200,59 @@ class ConnectionManager extends TypedEventEmitter {
|
|
2497
4200
|
this.startPeerDisconnectionListener();
|
2498
4201
|
this.startNetworkStatusListener();
|
2499
4202
|
}
|
2500
|
-
|
4203
|
+
/**
|
4204
|
+
* Attempts to establish a connection with a peer and set up specified protocols.
|
4205
|
+
* The method handles both PeerId and Multiaddr inputs, manages connection attempts,
|
4206
|
+
* and maintains the connection state.
|
4207
|
+
*
|
4208
|
+
* The dialing process includes:
|
4209
|
+
* 1. Converting input to dialable peer info
|
4210
|
+
* 2. Managing parallel dial attempts
|
4211
|
+
* 3. Attempting to establish protocol-specific connections
|
4212
|
+
* 4. Handling connection failures and retries
|
4213
|
+
* 5. Updating the peer store and connection state
|
4214
|
+
*
|
4215
|
+
* @param {PeerId | MultiaddrInput} peer - The peer to connect to, either as a PeerId or multiaddr
|
4216
|
+
* @param {string[]} [protocolCodecs] - Optional array of protocol-specific codec strings to establish
|
4217
|
+
* (e.g., for LightPush, Filter, Store protocols)
|
4218
|
+
*
|
4219
|
+
* @throws {Error} If the multiaddr is missing a peer ID
|
4220
|
+
* @throws {Error} If the maximum dial attempts are reached and the peer cannot be dialed
|
4221
|
+
* @throws {Error} If there's an error deleting an undialable peer from the peer store
|
4222
|
+
*
|
4223
|
+
* @example
|
4224
|
+
* ```typescript
|
4225
|
+
* // Dial using PeerId
|
4226
|
+
* await connectionManager.dialPeer(peerId);
|
4227
|
+
*
|
4228
|
+
* // Dial using multiaddr with specific protocols
|
4229
|
+
* await connectionManager.dialPeer(multiaddr, [
|
4230
|
+
* "/vac/waku/relay/2.0.0",
|
4231
|
+
* "/vac/waku/lightpush/2.0.0-beta1"
|
4232
|
+
* ]);
|
4233
|
+
* ```
|
4234
|
+
*
|
4235
|
+
* @remarks
|
4236
|
+
* - The method implements exponential backoff through multiple dial attempts
|
4237
|
+
* - Maintains a queue for parallel dial attempts (limited by maxParallelDials)
|
4238
|
+
* - Integrates with the KeepAliveManager for connection maintenance
|
4239
|
+
* - Updates the peer store and connection state after successful/failed attempts
|
4240
|
+
* - If all dial attempts fail, triggers DNS discovery as a fallback
|
4241
|
+
*/
|
4242
|
+
async dialPeer(peer) {
|
4243
|
+
let connection;
|
4244
|
+
let peerId;
|
4245
|
+
const peerDialInfo = this.getDialablePeerInfo(peer);
|
4246
|
+
const peerIdStr = isPeerId(peerDialInfo)
|
4247
|
+
? peerDialInfo.toString()
|
4248
|
+
: peerDialInfo.getPeerId();
|
2501
4249
|
this.currentActiveParallelDialCount += 1;
|
2502
4250
|
let dialAttempt = 0;
|
2503
4251
|
while (dialAttempt < this.options.maxDialAttemptsForPeer) {
|
2504
4252
|
try {
|
2505
|
-
log$1.info(`Dialing peer ${
|
2506
|
-
await this.libp2p.dial(
|
4253
|
+
log$1.info(`Dialing peer ${peerDialInfo} on attempt ${dialAttempt + 1}`);
|
4254
|
+
connection = await this.libp2p.dial(peerDialInfo);
|
4255
|
+
peerId = connection.remotePeer;
|
2507
4256
|
const tags = await this.getTagNamesForPeer(peerId);
|
2508
4257
|
// add tag to connection describing discovery mechanism
|
2509
4258
|
// don't add duplicate tags
|
@@ -2520,15 +4269,15 @@ class ConnectionManager extends TypedEventEmitter {
|
|
2520
4269
|
catch (error) {
|
2521
4270
|
if (error instanceof AggregateError) {
|
2522
4271
|
// Handle AggregateError
|
2523
|
-
log$1.error(`Error dialing peer ${
|
4272
|
+
log$1.error(`Error dialing peer ${peerIdStr} - ${error.errors}`);
|
2524
4273
|
}
|
2525
4274
|
else {
|
2526
4275
|
// Handle generic error
|
2527
|
-
log$1.error(`Error dialing peer ${
|
4276
|
+
log$1.error(`Error dialing peer ${peerIdStr} - ${error.message}`);
|
2528
4277
|
}
|
2529
|
-
this.dialErrorsForPeer.set(
|
4278
|
+
this.dialErrorsForPeer.set(peerIdStr, error);
|
2530
4279
|
dialAttempt++;
|
2531
|
-
this.dialAttemptsForPeer.set(
|
4280
|
+
this.dialAttemptsForPeer.set(peerIdStr, dialAttempt);
|
2532
4281
|
}
|
2533
4282
|
}
|
2534
4283
|
// Always decrease the active dial count and process the dial queue
|
@@ -2537,7 +4286,7 @@ class ConnectionManager extends TypedEventEmitter {
|
|
2537
4286
|
// If max dial attempts reached and dialing failed, delete the peer
|
2538
4287
|
if (dialAttempt === this.options.maxDialAttemptsForPeer) {
|
2539
4288
|
try {
|
2540
|
-
const error = this.dialErrorsForPeer.get(
|
4289
|
+
const error = this.dialErrorsForPeer.get(peerIdStr);
|
2541
4290
|
if (error) {
|
2542
4291
|
let errorMessage;
|
2543
4292
|
if (error instanceof AggregateError) {
|
@@ -2554,16 +4303,52 @@ class ConnectionManager extends TypedEventEmitter {
|
|
2554
4303
|
else {
|
2555
4304
|
errorMessage = error.message;
|
2556
4305
|
}
|
2557
|
-
log$1.info(`Deleting undialable peer ${
|
4306
|
+
log$1.info(`Deleting undialable peer ${peerIdStr} from peer store. Reason: ${errorMessage}`);
|
4307
|
+
}
|
4308
|
+
this.dialErrorsForPeer.delete(peerIdStr);
|
4309
|
+
if (peerId) {
|
4310
|
+
await this.libp2p.peerStore.delete(peerId);
|
2558
4311
|
}
|
2559
|
-
this.dialErrorsForPeer.delete(peerId.toString());
|
2560
|
-
await this.libp2p.peerStore.delete(peerId);
|
2561
4312
|
// if it was last available peer - attempt DNS discovery
|
2562
4313
|
await this.attemptDnsDiscovery();
|
2563
4314
|
}
|
2564
4315
|
catch (error) {
|
2565
|
-
throw new Error(`Error deleting undialable peer ${
|
4316
|
+
throw new Error(`Error deleting undialable peer ${peerIdStr} from peer store - ${error}`);
|
4317
|
+
}
|
4318
|
+
}
|
4319
|
+
if (!connection) {
|
4320
|
+
throw new Error(`Failed to dial peer ${peerDialInfo}`);
|
4321
|
+
}
|
4322
|
+
return connection;
|
4323
|
+
}
|
4324
|
+
/**
|
4325
|
+
* Dial a peer with specific protocols.
|
4326
|
+
* This method is a raw proxy to the libp2p dialProtocol method.
|
4327
|
+
* @param peer - The peer to connect to, either as a PeerId or multiaddr
|
4328
|
+
* @param protocolCodecs - Optional array of protocol-specific codec strings to establish
|
4329
|
+
* @returns A stream to the peer
|
4330
|
+
*/
|
4331
|
+
async rawDialPeerWithProtocols(peer, protocolCodecs) {
|
4332
|
+
const peerDialInfo = this.getDialablePeerInfo(peer);
|
4333
|
+
return await this.libp2p.dialProtocol(peerDialInfo, protocolCodecs);
|
4334
|
+
}
|
4335
|
+
/**
|
4336
|
+
* Internal utility to extract a PeerId or Multiaddr from a peer input.
|
4337
|
+
* This is used internally by the connection manager to handle different peer input formats.
|
4338
|
+
* @internal
|
4339
|
+
*/
|
4340
|
+
getDialablePeerInfo(peer) {
|
4341
|
+
if (isPeerId(peer)) {
|
4342
|
+
return peer;
|
4343
|
+
}
|
4344
|
+
else {
|
4345
|
+
// peer is of MultiaddrInput type
|
4346
|
+
const ma = multiaddr(peer);
|
4347
|
+
const peerIdStr = ma.getPeerId();
|
4348
|
+
if (!peerIdStr) {
|
4349
|
+
throw new Error("Failed to dial multiaddr: missing peer ID");
|
2566
4350
|
}
|
4351
|
+
return ma;
|
2567
4352
|
}
|
2568
4353
|
}
|
2569
4354
|
async attemptDnsDiscovery() {
|
@@ -2691,7 +4476,7 @@ class ConnectionManager extends TypedEventEmitter {
|
|
2691
4476
|
const isSameShard = await this.isPeerTopicConfigured(peerId);
|
2692
4477
|
if (!isSameShard) {
|
2693
4478
|
const shardInfo = await this.getPeerShardInfo(peerId, this.libp2p.peerStore);
|
2694
|
-
log$1.warn(`Discovered peer ${peerId.toString()} with ShardInfo ${shardInfo} is not part of any of the configured pubsub topics (${this.
|
4479
|
+
log$1.warn(`Discovered peer ${peerId.toString()} with ShardInfo ${shardInfo} is not part of any of the configured pubsub topics (${this.pubsubTopics}).
|
2695
4480
|
Not dialing.`);
|
2696
4481
|
return false;
|
2697
4482
|
}
|
@@ -2752,7 +4537,7 @@ class ConnectionManager extends TypedEventEmitter {
|
|
2752
4537
|
if (!shardInfo)
|
2753
4538
|
return true;
|
2754
4539
|
const pubsubTopics = shardInfoToPubsubTopics(shardInfo);
|
2755
|
-
const isTopicConfigured = pubsubTopics.some((topic) => this.
|
4540
|
+
const isTopicConfigured = pubsubTopics.some((topic) => this.pubsubTopics.includes(topic));
|
2756
4541
|
return isTopicConfigured;
|
2757
4542
|
}
|
2758
4543
|
async getPeerShardInfo(peerId, peerStore) {
|
@@ -2800,75 +4585,6 @@ class ConnectionManager extends TypedEventEmitter {
|
|
2800
4585
|
}
|
2801
4586
|
}
|
2802
4587
|
|
2803
|
-
class HealthManager {
|
2804
|
-
static instance;
|
2805
|
-
health;
|
2806
|
-
constructor() {
|
2807
|
-
this.health = {
|
2808
|
-
overallStatus: HealthStatus.Unhealthy,
|
2809
|
-
protocolStatuses: new Map()
|
2810
|
-
};
|
2811
|
-
}
|
2812
|
-
static getInstance() {
|
2813
|
-
if (!HealthManager.instance) {
|
2814
|
-
HealthManager.instance = new HealthManager();
|
2815
|
-
}
|
2816
|
-
return HealthManager.instance;
|
2817
|
-
}
|
2818
|
-
getHealthStatus() {
|
2819
|
-
return this.health.overallStatus;
|
2820
|
-
}
|
2821
|
-
getProtocolStatus(protocol) {
|
2822
|
-
return this.health.protocolStatuses.get(protocol);
|
2823
|
-
}
|
2824
|
-
updateProtocolHealth(multicodec, connectedPeers) {
|
2825
|
-
const protocol = this.getNameFromMulticodec(multicodec);
|
2826
|
-
let status = HealthStatus.Unhealthy;
|
2827
|
-
if (connectedPeers == 1) {
|
2828
|
-
status = HealthStatus.MinimallyHealthy;
|
2829
|
-
}
|
2830
|
-
else if (connectedPeers >= 2) {
|
2831
|
-
status = HealthStatus.SufficientlyHealthy;
|
2832
|
-
}
|
2833
|
-
this.health.protocolStatuses.set(protocol, {
|
2834
|
-
name: protocol,
|
2835
|
-
status: status,
|
2836
|
-
lastUpdate: new Date()
|
2837
|
-
});
|
2838
|
-
this.updateOverallHealth();
|
2839
|
-
}
|
2840
|
-
getNameFromMulticodec(multicodec) {
|
2841
|
-
let name;
|
2842
|
-
if (multicodec.includes("filter")) {
|
2843
|
-
name = Protocols.Filter;
|
2844
|
-
}
|
2845
|
-
else if (multicodec.includes("lightpush")) {
|
2846
|
-
name = Protocols.LightPush;
|
2847
|
-
}
|
2848
|
-
else if (multicodec.includes("store")) {
|
2849
|
-
name = Protocols.Store;
|
2850
|
-
}
|
2851
|
-
else {
|
2852
|
-
throw new Error(`Unknown protocol: ${multicodec}`);
|
2853
|
-
}
|
2854
|
-
return name;
|
2855
|
-
}
|
2856
|
-
updateOverallHealth() {
|
2857
|
-
const relevantProtocols = [Protocols.LightPush, Protocols.Filter];
|
2858
|
-
const statuses = relevantProtocols.map((p) => this.getProtocolStatus(p)?.status);
|
2859
|
-
if (statuses.some((status) => status === HealthStatus.Unhealthy)) {
|
2860
|
-
this.health.overallStatus = HealthStatus.Unhealthy;
|
2861
|
-
}
|
2862
|
-
else if (statuses.some((status) => status === HealthStatus.MinimallyHealthy)) {
|
2863
|
-
this.health.overallStatus = HealthStatus.MinimallyHealthy;
|
2864
|
-
}
|
2865
|
-
else {
|
2866
|
-
this.health.overallStatus = HealthStatus.SufficientlyHealthy;
|
2867
|
-
}
|
2868
|
-
}
|
2869
|
-
}
|
2870
|
-
const getHealthManager = () => HealthManager.getInstance();
|
2871
|
-
|
2872
4588
|
const log = new Logger("metadata");
|
2873
4589
|
const MetadataCodec = "/vac/waku/metadata/1.0.0";
|
2874
4590
|
class Metadata extends BaseProtocol {
|
@@ -2876,7 +4592,7 @@ class Metadata extends BaseProtocol {
|
|
2876
4592
|
libp2pComponents;
|
2877
4593
|
handshakesConfirmed = new Map();
|
2878
4594
|
constructor(pubsubTopics, libp2p) {
|
2879
|
-
super(MetadataCodec, libp2p.components,
|
4595
|
+
super(MetadataCodec, libp2p.components, pubsubTopics);
|
2880
4596
|
this.pubsubTopics = pubsubTopics;
|
2881
4597
|
this.libp2pComponents = libp2p;
|
2882
4598
|
void libp2p.registrar.handle(MetadataCodec, (streamData) => {
|
@@ -2897,7 +4613,7 @@ class Metadata extends BaseProtocol {
|
|
2897
4613
|
}
|
2898
4614
|
let stream;
|
2899
4615
|
try {
|
2900
|
-
stream = await this.getStream(
|
4616
|
+
stream = await this.getStream(peerId);
|
2901
4617
|
}
|
2902
4618
|
catch (error) {
|
2903
4619
|
log.error("Failed to get stream", error);
|
@@ -2980,4 +4696,4 @@ function wakuMetadata(pubsubTopics) {
|
|
2980
4696
|
return (components) => new Metadata(pubsubTopics, components);
|
2981
4697
|
}
|
2982
4698
|
|
2983
|
-
export { ConnectionManager, FilterCodecs, FilterCore,
|
4699
|
+
export { ConnectionManager, FilterCodecs, FilterCore, LightPushCodec, LightPushCore, MetadataCodec, StoreCodec, StoreCore, createEncoder, index$3 as message, wakuMetadata, index$2 as waku_filter, index$1 as waku_light_push, index as waku_store };
|