@waku/core 0.0.31-ce62600.0 → 0.0.31-f387f59.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-C6HnrRx8.js → base_protocol-Dge5_tvU.js} +22 -25
- package/bundle/{index-DnW8ifxc.js → index-Gts2Ddu_.js} +41 -56
- package/bundle/index.js +291 -288
- package/bundle/lib/base_protocol.js +2 -2
- package/bundle/lib/message/version_0.js +2 -2
- package/bundle/{version_0-DQ9xsSLk.js → version_0-CNRKFufI.js} +154 -308
- package/dist/.tsbuildinfo +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/lib/base_protocol.d.ts +3 -4
- package/dist/lib/base_protocol.js +4 -8
- package/dist/lib/base_protocol.js.map +1 -1
- package/dist/lib/connection_manager.d.ts +2 -2
- package/dist/lib/connection_manager.js +21 -23
- package/dist/lib/connection_manager.js.map +1 -1
- package/dist/lib/filter/filter_rpc.js.map +1 -1
- package/dist/lib/filter/index.d.ts +4 -3
- package/dist/lib/filter/index.js +33 -31
- package/dist/lib/filter/index.js.map +1 -1
- package/dist/lib/health_manager.d.ts +14 -0
- package/dist/lib/health_manager.js +70 -0
- package/dist/lib/health_manager.js.map +1 -0
- package/dist/lib/keep_alive_manager.d.ts +13 -7
- package/dist/lib/keep_alive_manager.js +9 -9
- package/dist/lib/keep_alive_manager.js.map +1 -1
- package/dist/lib/light_push/index.d.ts +3 -2
- package/dist/lib/light_push/index.js +4 -2
- package/dist/lib/light_push/index.js.map +1 -1
- package/dist/lib/light_push/push_rpc.js.map +1 -1
- package/dist/lib/message/version_0.js.map +1 -1
- package/dist/lib/metadata/index.d.ts +2 -2
- package/dist/lib/metadata/index.js +26 -26
- package/dist/lib/metadata/index.js.map +1 -1
- package/dist/lib/store/index.d.ts +5 -44
- package/dist/lib/store/index.js +39 -45
- package/dist/lib/store/index.js.map +1 -1
- package/dist/lib/store/rpc.d.ts +22 -0
- package/dist/lib/store/rpc.js +74 -0
- package/dist/lib/store/rpc.js.map +1 -0
- package/dist/lib/stream_manager/index.d.ts +1 -0
- package/dist/lib/stream_manager/index.js +2 -0
- package/dist/lib/stream_manager/index.js.map +1 -0
- package/dist/lib/{stream_manager.js → stream_manager/stream_manager.js} +1 -1
- package/dist/lib/stream_manager/stream_manager.js.map +1 -0
- package/dist/lib/stream_manager/utils.d.ts +2 -0
- package/dist/lib/stream_manager/utils.js +19 -0
- package/dist/lib/stream_manager/utils.js.map +1 -0
- package/package.json +1 -1
- package/src/index.ts +3 -3
- package/src/lib/base_protocol.ts +7 -10
- package/src/lib/connection_manager.ts +29 -30
- package/src/lib/filter/filter_rpc.ts +21 -19
- package/src/lib/filter/index.ts +50 -52
- package/src/lib/health_manager.ts +90 -0
- package/src/lib/keep_alive_manager.ts +27 -18
- package/src/lib/light_push/index.ts +7 -10
- package/src/lib/light_push/push_rpc.ts +5 -5
- package/src/lib/message/version_0.ts +17 -15
- package/src/lib/metadata/index.ts +43 -44
- package/src/lib/store/index.ts +54 -94
- package/src/lib/store/rpc.ts +92 -0
- package/src/lib/stream_manager/index.ts +1 -0
- package/src/lib/{stream_manager.ts → stream_manager/stream_manager.ts} +3 -2
- package/src/lib/stream_manager/utils.ts +22 -0
- package/dist/lib/store/history_rpc.d.ts +0 -27
- package/dist/lib/store/history_rpc.js +0 -72
- package/dist/lib/store/history_rpc.js.map +0 -1
- package/dist/lib/stream_manager.js.map +0 -1
- package/src/lib/store/history_rpc.ts +0 -93
- /package/dist/lib/{stream_manager.d.ts → stream_manager/stream_manager.d.ts} +0 -0
package/bundle/index.js
CHANGED
@@ -1,8 +1,8 @@
|
|
1
|
-
import { v as version_0, e as encodingLength, a as encode$1, d as decode$1, M as MessagePush, F as FilterSubscribeRequest, b as FilterSubscribeResponse$1, P as PushRpc$1, c as PushResponse,
|
2
|
-
export {
|
3
|
-
import { a as allocUnsafe, b as alloc,
|
4
|
-
import { B as BaseProtocol, d as decodeRelayShard, e as encodeRelayShard } from './base_protocol-
|
5
|
-
export { S as StreamManager } from './base_protocol-
|
1
|
+
import { v as version_0, e as encodingLength, a as encode$1, d as decode$1, M as MessagePush, F as FilterSubscribeRequest, b as FilterSubscribeResponse$1, P as PushRpc$1, c as PushResponse, S as StoreQueryRequest$1, f as StoreQueryResponse$1, g as createEncoder, W as WakuMetadataRequest, h as WakuMetadataResponse } from './version_0-CNRKFufI.js';
|
2
|
+
export { i as createDecoder } from './version_0-CNRKFufI.js';
|
3
|
+
import { a as allocUnsafe, b as alloc, L as Logger, P as ProtocolError, c as Protocols, u as utf8ToBytes, p as pubsubTopicToSingleShardInfo, E as EConnectionStateEvents, T as Tags, d as EPeersByDiscoveryEvents, s as shardInfoToPubsubTopics, H as HealthStatus, e as pubsubTopicsToShardInfo } from './index-Gts2Ddu_.js';
|
4
|
+
import { B as BaseProtocol, d as decodeRelayShard, e as encodeRelayShard } from './base_protocol-Dge5_tvU.js';
|
5
|
+
export { S as StreamManager } from './base_protocol-Dge5_tvU.js';
|
6
6
|
|
7
7
|
const MB = 1024 ** 2;
|
8
8
|
const SIZE_CAP_IN_MB = 1;
|
@@ -743,74 +743,35 @@ encode.single = (chunk, options) => {
|
|
743
743
|
};
|
744
744
|
|
745
745
|
/**
|
746
|
-
*
|
747
|
-
* @typedef {Error} Err
|
748
|
-
* @property {string} message
|
746
|
+
* The reported length of the next data message was not a positive integer
|
749
747
|
*/
|
750
|
-
|
748
|
+
class InvalidMessageLengthError extends Error {
|
749
|
+
name = 'InvalidMessageLengthError';
|
750
|
+
code = 'ERR_INVALID_MSG_LENGTH';
|
751
|
+
}
|
751
752
|
/**
|
752
|
-
*
|
753
|
-
*
|
754
|
-
* @param {Extensions} props
|
755
|
-
* @returns {Error & Extensions}
|
753
|
+
* The reported length of the next data message was larger than the configured
|
754
|
+
* max allowable value
|
756
755
|
*/
|
757
|
-
|
758
|
-
|
759
|
-
|
760
|
-
value: props[key],
|
761
|
-
enumerable: true,
|
762
|
-
configurable: true,
|
763
|
-
});
|
764
|
-
}
|
765
|
-
|
766
|
-
return obj;
|
756
|
+
class InvalidDataLengthError extends Error {
|
757
|
+
name = 'InvalidDataLengthError';
|
758
|
+
code = 'ERR_MSG_DATA_TOO_LONG';
|
767
759
|
}
|
768
|
-
|
769
760
|
/**
|
770
|
-
*
|
771
|
-
*
|
772
|
-
* @param {string|Extensions} code - A string code or props to set on the error
|
773
|
-
* @param {Extensions} [props] - Props to set on the error
|
774
|
-
* @returns {Error & Extensions}
|
761
|
+
* The varint used to specify the length of the next data message contained more
|
762
|
+
* bytes than the configured max allowable value
|
775
763
|
*/
|
776
|
-
|
777
|
-
|
778
|
-
|
779
|
-
|
780
|
-
|
781
|
-
|
782
|
-
|
783
|
-
|
784
|
-
|
785
|
-
|
786
|
-
props = code;
|
787
|
-
code = '';
|
788
|
-
}
|
789
|
-
|
790
|
-
if (code) {
|
791
|
-
props.code = code;
|
792
|
-
}
|
793
|
-
|
794
|
-
try {
|
795
|
-
return assign(err, props);
|
796
|
-
} catch (_) {
|
797
|
-
props.message = err.message;
|
798
|
-
props.stack = err.stack;
|
799
|
-
|
800
|
-
const ErrClass = function () {};
|
801
|
-
|
802
|
-
ErrClass.prototype = Object.create(Object.getPrototypeOf(err));
|
803
|
-
|
804
|
-
// @ts-ignore
|
805
|
-
const output = assign(new ErrClass(), props);
|
806
|
-
|
807
|
-
return output;
|
808
|
-
}
|
764
|
+
class InvalidDataLengthLengthError extends Error {
|
765
|
+
name = 'InvalidDataLengthLengthError';
|
766
|
+
code = 'ERR_MSG_LENGTH_TOO_LONG';
|
767
|
+
}
|
768
|
+
/**
|
769
|
+
* The incoming stream ended before the expected number of bytes were read
|
770
|
+
*/
|
771
|
+
class UnexpectedEOFError extends Error {
|
772
|
+
name = 'UnexpectedEOFError';
|
773
|
+
code = 'ERR_UNEXPECTED_EOF';
|
809
774
|
}
|
810
|
-
|
811
|
-
var errCode = createError;
|
812
|
-
|
813
|
-
var errCode$1 = /*@__PURE__*/getDefaultExportFromCjs(errCode);
|
814
775
|
|
815
776
|
/* eslint max-depth: ["error", 6] */
|
816
777
|
// Maximum length of the length section of the message
|
@@ -842,10 +803,10 @@ function decode(source, options) {
|
|
842
803
|
try {
|
843
804
|
dataLength = lengthDecoder(buffer);
|
844
805
|
if (dataLength < 0) {
|
845
|
-
throw
|
806
|
+
throw new InvalidMessageLengthError('Invalid message length');
|
846
807
|
}
|
847
808
|
if (dataLength > maxDataLength) {
|
848
|
-
throw
|
809
|
+
throw new InvalidDataLengthError('Message length too long');
|
849
810
|
}
|
850
811
|
const dataLengthLength = lengthDecoder.bytes;
|
851
812
|
buffer.consume(dataLengthLength);
|
@@ -857,7 +818,7 @@ function decode(source, options) {
|
|
857
818
|
catch (err) {
|
858
819
|
if (err instanceof RangeError) {
|
859
820
|
if (buffer.byteLength > maxLengthLength) {
|
860
|
-
throw
|
821
|
+
throw new InvalidDataLengthLengthError('Message length length too long');
|
861
822
|
}
|
862
823
|
break;
|
863
824
|
}
|
@@ -886,7 +847,7 @@ function decode(source, options) {
|
|
886
847
|
yield* maybeYield();
|
887
848
|
}
|
888
849
|
if (buffer.byteLength > 0) {
|
889
|
-
throw
|
850
|
+
throw new UnexpectedEOFError('Unexpected end of input');
|
890
851
|
}
|
891
852
|
})();
|
892
853
|
}
|
@@ -896,7 +857,7 @@ function decode(source, options) {
|
|
896
857
|
yield* maybeYield();
|
897
858
|
}
|
898
859
|
if (buffer.byteLength > 0) {
|
899
|
-
throw
|
860
|
+
throw new UnexpectedEOFError('Unexpected end of input');
|
900
861
|
}
|
901
862
|
})();
|
902
863
|
}
|
@@ -1484,16 +1445,6 @@ function v4(options, buf, offset) {
|
|
1484
1445
|
rnds[6] = rnds[6] & 0x0f | 0x40;
|
1485
1446
|
rnds[8] = rnds[8] & 0x3f | 0x80; // Copy bytes to buffer, if provided
|
1486
1447
|
|
1487
|
-
if (buf) {
|
1488
|
-
offset = offset || 0;
|
1489
|
-
|
1490
|
-
for (let i = 0; i < 16; ++i) {
|
1491
|
-
buf[offset + i] = rnds[i];
|
1492
|
-
}
|
1493
|
-
|
1494
|
-
return buf;
|
1495
|
-
}
|
1496
|
-
|
1497
1448
|
return unsafeStringify(rnds);
|
1498
1449
|
}
|
1499
1450
|
|
@@ -1611,9 +1562,11 @@ const FilterCodecs = {
|
|
1611
1562
|
};
|
1612
1563
|
class FilterCore extends BaseProtocol {
|
1613
1564
|
handleIncomingMessage;
|
1614
|
-
|
1615
|
-
|
1565
|
+
pubsubTopics;
|
1566
|
+
constructor(handleIncomingMessage, pubsubTopics, libp2p) {
|
1567
|
+
super(FilterCodecs.SUBSCRIBE, libp2p.components, log$6, pubsubTopics);
|
1616
1568
|
this.handleIncomingMessage = handleIncomingMessage;
|
1569
|
+
this.pubsubTopics = pubsubTopics;
|
1617
1570
|
libp2p
|
1618
1571
|
.handle(FilterCodecs.PUSH, this.onRequest.bind(this), {
|
1619
1572
|
maxInboundStreams: 100
|
@@ -1622,35 +1575,6 @@ class FilterCore extends BaseProtocol {
|
|
1622
1575
|
log$6.error("Failed to register ", FilterCodecs.PUSH, e);
|
1623
1576
|
});
|
1624
1577
|
}
|
1625
|
-
onRequest(streamData) {
|
1626
|
-
const { connection, stream } = streamData;
|
1627
|
-
const { remotePeer } = connection;
|
1628
|
-
log$6.info(`Received message from ${remotePeer.toString()}`);
|
1629
|
-
try {
|
1630
|
-
pipe(stream, decode, async (source) => {
|
1631
|
-
for await (const bytes of source) {
|
1632
|
-
const response = FilterPushRpc.decode(bytes.slice());
|
1633
|
-
const { pubsubTopic, wakuMessage } = response;
|
1634
|
-
if (!wakuMessage) {
|
1635
|
-
log$6.error("Received empty message");
|
1636
|
-
return;
|
1637
|
-
}
|
1638
|
-
if (!pubsubTopic) {
|
1639
|
-
log$6.error("Pubsub topic missing from push message");
|
1640
|
-
return;
|
1641
|
-
}
|
1642
|
-
await this.handleIncomingMessage(pubsubTopic, wakuMessage);
|
1643
|
-
}
|
1644
|
-
}).then(() => {
|
1645
|
-
log$6.info("Receiving pipe closed.");
|
1646
|
-
}, (e) => {
|
1647
|
-
log$6.error("Error with receiving pipe", e);
|
1648
|
-
});
|
1649
|
-
}
|
1650
|
-
catch (e) {
|
1651
|
-
log$6.error("Error decoding message", e);
|
1652
|
-
}
|
1653
|
-
}
|
1654
1578
|
async subscribe(pubsubTopic, peer, contentTopics) {
|
1655
1579
|
const stream = await this.getStream(peer);
|
1656
1580
|
const request = FilterSubscribeRpc.createSubscribeRequest(pubsubTopic, contentTopics);
|
@@ -1802,6 +1726,35 @@ class FilterCore extends BaseProtocol {
|
|
1802
1726
|
failure: null
|
1803
1727
|
};
|
1804
1728
|
}
|
1729
|
+
onRequest(streamData) {
|
1730
|
+
const { connection, stream } = streamData;
|
1731
|
+
const { remotePeer } = connection;
|
1732
|
+
log$6.info(`Received message from ${remotePeer.toString()}`);
|
1733
|
+
try {
|
1734
|
+
pipe(stream, decode, async (source) => {
|
1735
|
+
for await (const bytes of source) {
|
1736
|
+
const response = FilterPushRpc.decode(bytes.slice());
|
1737
|
+
const { pubsubTopic, wakuMessage } = response;
|
1738
|
+
if (!wakuMessage) {
|
1739
|
+
log$6.error("Received empty message");
|
1740
|
+
return;
|
1741
|
+
}
|
1742
|
+
if (!pubsubTopic) {
|
1743
|
+
log$6.error("Pubsub topic missing from push message");
|
1744
|
+
return;
|
1745
|
+
}
|
1746
|
+
await this.handleIncomingMessage(pubsubTopic, wakuMessage, connection.remotePeer.toString());
|
1747
|
+
}
|
1748
|
+
}).then(() => {
|
1749
|
+
log$6.info("Receiving pipe closed.");
|
1750
|
+
}, (e) => {
|
1751
|
+
log$6.error("Error with receiving pipe", e);
|
1752
|
+
});
|
1753
|
+
}
|
1754
|
+
catch (e) {
|
1755
|
+
log$6.error("Error decoding message", e);
|
1756
|
+
}
|
1757
|
+
}
|
1805
1758
|
}
|
1806
1759
|
|
1807
1760
|
var index$2 = /*#__PURE__*/Object.freeze({
|
@@ -1846,8 +1799,10 @@ const LightPushCodec = "/vac/waku/lightpush/2.0.0-beta1";
|
|
1846
1799
|
* Implements the [Waku v2 Light Push protocol](https://rfc.vac.dev/spec/19/).
|
1847
1800
|
*/
|
1848
1801
|
class LightPushCore extends BaseProtocol {
|
1849
|
-
|
1850
|
-
|
1802
|
+
pubsubTopics;
|
1803
|
+
constructor(pubsubTopics, libp2p) {
|
1804
|
+
super(LightPushCodec, libp2p.components, log$5, pubsubTopics);
|
1805
|
+
this.pubsubTopics = pubsubTopics;
|
1851
1806
|
}
|
1852
1807
|
async preparePushMessage(encoder, message) {
|
1853
1808
|
try {
|
@@ -1979,97 +1934,97 @@ function toProtoMessage(wire) {
|
|
1979
1934
|
return { ...EmptyMessage, ...wire };
|
1980
1935
|
}
|
1981
1936
|
|
1982
|
-
|
1983
|
-
|
1984
|
-
|
1985
|
-
|
1986
|
-
|
1987
|
-
})(PageDirection || (PageDirection = {}));
|
1988
|
-
class HistoryRpc {
|
1937
|
+
// https://github.com/waku-org/nwaku/blob/7205f95cff9f49ca0bb762e8fd0bf56a6a7f3b3b/waku/waku_store/common.nim#L12
|
1938
|
+
const DEFAULT_PAGE_SIZE = 20;
|
1939
|
+
const MAX_PAGE_SIZE = 100;
|
1940
|
+
const ONE_MILLION = 1_000000;
|
1941
|
+
class StoreQueryRequest {
|
1989
1942
|
proto;
|
1990
1943
|
constructor(proto) {
|
1991
1944
|
this.proto = proto;
|
1992
1945
|
}
|
1993
|
-
|
1994
|
-
|
1995
|
-
|
1996
|
-
|
1997
|
-
|
1998
|
-
|
1999
|
-
|
2000
|
-
|
2001
|
-
|
2002
|
-
|
2003
|
-
|
2004
|
-
|
1946
|
+
static create(params) {
|
1947
|
+
const request = new StoreQueryRequest({
|
1948
|
+
...params,
|
1949
|
+
requestId: v4(),
|
1950
|
+
timeStart: params.timeStart
|
1951
|
+
? BigInt(params.timeStart.getTime() * ONE_MILLION)
|
1952
|
+
: undefined,
|
1953
|
+
timeEnd: params.timeEnd
|
1954
|
+
? BigInt(params.timeEnd.getTime() * ONE_MILLION)
|
1955
|
+
: undefined,
|
1956
|
+
messageHashes: params.messageHashes || [],
|
1957
|
+
paginationLimit: params.paginationLimit
|
1958
|
+
? BigInt(params.paginationLimit)
|
1959
|
+
: undefined
|
2005
1960
|
});
|
2006
|
-
|
2007
|
-
|
2008
|
-
|
2009
|
-
|
2010
|
-
direction
|
2011
|
-
};
|
2012
|
-
let startTime, endTime;
|
2013
|
-
if (params.startTime) {
|
2014
|
-
// milliseconds 10^-3 to nanoseconds 10^-9
|
2015
|
-
startTime = BigInt(params.startTime.valueOf()) * OneMillion;
|
1961
|
+
// Validate request parameters based on RFC
|
1962
|
+
if ((params.pubsubTopic && !params.contentTopics) ||
|
1963
|
+
(!params.pubsubTopic && params.contentTopics)) {
|
1964
|
+
throw new Error("Both pubsubTopic and contentTopics must be set or unset");
|
2016
1965
|
}
|
2017
|
-
if (params.
|
2018
|
-
|
2019
|
-
|
1966
|
+
if (params.messageHashes &&
|
1967
|
+
(params.pubsubTopic ||
|
1968
|
+
params.contentTopics ||
|
1969
|
+
params.timeStart ||
|
1970
|
+
params.timeEnd)) {
|
1971
|
+
throw new Error("Message hash lookup queries cannot include content filter criteria");
|
2020
1972
|
}
|
2021
|
-
return
|
2022
|
-
requestId: v4(),
|
2023
|
-
query: {
|
2024
|
-
pubsubTopic: params.pubsubTopic,
|
2025
|
-
contentFilters,
|
2026
|
-
pagingInfo,
|
2027
|
-
startTime,
|
2028
|
-
endTime
|
2029
|
-
},
|
2030
|
-
response: undefined
|
2031
|
-
});
|
1973
|
+
return request;
|
2032
1974
|
}
|
2033
|
-
decode(bytes) {
|
2034
|
-
const res =
|
2035
|
-
return new
|
1975
|
+
static decode(bytes) {
|
1976
|
+
const res = StoreQueryRequest$1.decode(bytes);
|
1977
|
+
return new StoreQueryRequest(res);
|
2036
1978
|
}
|
2037
1979
|
encode() {
|
2038
|
-
return
|
1980
|
+
return StoreQueryRequest$1.encode(this.proto);
|
2039
1981
|
}
|
2040
1982
|
}
|
2041
|
-
|
2042
|
-
|
2043
|
-
|
2044
|
-
|
2045
|
-
|
2046
|
-
|
2047
|
-
|
2048
|
-
|
1983
|
+
class StoreQueryResponse {
|
1984
|
+
proto;
|
1985
|
+
constructor(proto) {
|
1986
|
+
this.proto = proto;
|
1987
|
+
}
|
1988
|
+
static decode(bytes) {
|
1989
|
+
const res = StoreQueryResponse$1.decode(bytes);
|
1990
|
+
return new StoreQueryResponse(res);
|
1991
|
+
}
|
1992
|
+
encode() {
|
1993
|
+
return StoreQueryResponse$1.encode(this.proto);
|
1994
|
+
}
|
1995
|
+
get statusCode() {
|
1996
|
+
return this.proto.statusCode;
|
1997
|
+
}
|
1998
|
+
get statusDesc() {
|
1999
|
+
return this.proto.statusDesc;
|
2000
|
+
}
|
2001
|
+
get messages() {
|
2002
|
+
return this.proto.messages;
|
2003
|
+
}
|
2004
|
+
get paginationCursor() {
|
2005
|
+
return this.proto.paginationCursor;
|
2049
2006
|
}
|
2050
2007
|
}
|
2051
2008
|
|
2052
|
-
var HistoryError = HistoryResponse.HistoryError;
|
2053
2009
|
const log$4 = new Logger("store");
|
2054
|
-
const StoreCodec = "/vac/waku/store/
|
2055
|
-
/**
|
2056
|
-
* Implements the [Waku v2 Store protocol](https://rfc.vac.dev/spec/13/).
|
2057
|
-
*
|
2058
|
-
* The Waku Store protocol can be used to retrieved historical messages.
|
2059
|
-
*/
|
2010
|
+
const StoreCodec = "/vac/waku/store-query/3.0.0";
|
2060
2011
|
class StoreCore extends BaseProtocol {
|
2061
|
-
|
2062
|
-
|
2012
|
+
pubsubTopics;
|
2013
|
+
constructor(pubsubTopics, libp2p) {
|
2014
|
+
super(StoreCodec, libp2p.components, log$4, pubsubTopics);
|
2015
|
+
this.pubsubTopics = pubsubTopics;
|
2063
2016
|
}
|
2064
2017
|
async *queryPerPage(queryOpts, decoders, peer) {
|
2065
2018
|
if (queryOpts.contentTopics.toString() !==
|
2066
2019
|
Array.from(decoders.keys()).toString()) {
|
2067
2020
|
throw new Error("Internal error, the decoders should match the query's content topics");
|
2068
2021
|
}
|
2069
|
-
let currentCursor = queryOpts.
|
2022
|
+
let currentCursor = queryOpts.paginationCursor;
|
2070
2023
|
while (true) {
|
2071
|
-
|
2072
|
-
|
2024
|
+
const storeQueryRequest = StoreQueryRequest.create({
|
2025
|
+
...queryOpts,
|
2026
|
+
paginationCursor: currentCursor
|
2027
|
+
});
|
2073
2028
|
let stream;
|
2074
2029
|
try {
|
2075
2030
|
stream = await this.getStream(peer);
|
@@ -2078,50 +2033,48 @@ class StoreCore extends BaseProtocol {
|
|
2078
2033
|
log$4.error("Failed to get stream", e);
|
2079
2034
|
break;
|
2080
2035
|
}
|
2081
|
-
const res = await pipe([
|
2036
|
+
const res = await pipe([storeQueryRequest.encode()], encode, stream, decode, async (source) => await all(source));
|
2082
2037
|
const bytes = new Uint8ArrayList();
|
2083
2038
|
res.forEach((chunk) => {
|
2084
2039
|
bytes.append(chunk);
|
2085
2040
|
});
|
2086
|
-
const
|
2087
|
-
if (!
|
2088
|
-
|
2041
|
+
const storeQueryResponse = StoreQueryResponse.decode(bytes);
|
2042
|
+
if (!storeQueryResponse.statusCode ||
|
2043
|
+
storeQueryResponse.statusCode >= 300) {
|
2044
|
+
const errorMessage = `Store query failed with status code: ${storeQueryResponse.statusCode}, description: ${storeQueryResponse.statusDesc}`;
|
2045
|
+
log$4.error(errorMessage);
|
2046
|
+
throw new Error(errorMessage);
|
2047
|
+
}
|
2048
|
+
if (!storeQueryResponse.messages || !storeQueryResponse.messages.length) {
|
2049
|
+
log$4.warn("Stopping pagination due to empty messages in response");
|
2089
2050
|
break;
|
2090
2051
|
}
|
2091
|
-
|
2092
|
-
|
2093
|
-
|
2094
|
-
|
2095
|
-
|
2096
|
-
|
2097
|
-
|
2098
|
-
}
|
2099
|
-
log$4.error(`${response.messages.length} messages retrieved from store`);
|
2100
|
-
yield response.messages.map((protoMsg) => {
|
2101
|
-
const contentTopic = protoMsg.contentTopic;
|
2102
|
-
if (typeof contentTopic !== "undefined") {
|
2052
|
+
log$4.info(`${storeQueryResponse.messages.length} messages retrieved from store`);
|
2053
|
+
const decodedMessages = storeQueryResponse.messages.map((protoMsg) => {
|
2054
|
+
if (!protoMsg.message) {
|
2055
|
+
return Promise.resolve(undefined);
|
2056
|
+
}
|
2057
|
+
const contentTopic = protoMsg.message.contentTopic;
|
2058
|
+
if (contentTopic) {
|
2103
2059
|
const decoder = decoders.get(contentTopic);
|
2104
2060
|
if (decoder) {
|
2105
|
-
return decoder.fromProtoObj(
|
2061
|
+
return decoder.fromProtoObj(protoMsg.pubsubTopic || "", toProtoMessage(protoMsg.message));
|
2106
2062
|
}
|
2107
2063
|
}
|
2108
2064
|
return Promise.resolve(undefined);
|
2109
2065
|
});
|
2110
|
-
|
2111
|
-
if (
|
2112
|
-
|
2113
|
-
|
2114
|
-
|
2115
|
-
break;
|
2066
|
+
yield decodedMessages;
|
2067
|
+
if (queryOpts.paginationForward) {
|
2068
|
+
currentCursor =
|
2069
|
+
storeQueryResponse.messages[storeQueryResponse.messages.length - 1]
|
2070
|
+
.messageHash;
|
2116
2071
|
}
|
2117
|
-
|
2118
|
-
|
2119
|
-
|
2120
|
-
if (
|
2121
|
-
|
2122
|
-
|
2123
|
-
queryPageSize &&
|
2124
|
-
responsePageSize < queryPageSize) {
|
2072
|
+
else {
|
2073
|
+
currentCursor = storeQueryResponse.messages[0].messageHash;
|
2074
|
+
}
|
2075
|
+
if (storeQueryResponse.messages.length > MAX_PAGE_SIZE &&
|
2076
|
+
storeQueryResponse.messages.length <
|
2077
|
+
(queryOpts.paginationLimit || DEFAULT_PAGE_SIZE)) {
|
2125
2078
|
break;
|
2126
2079
|
}
|
2127
2080
|
}
|
@@ -2130,7 +2083,6 @@ class StoreCore extends BaseProtocol {
|
|
2130
2083
|
|
2131
2084
|
var index = /*#__PURE__*/Object.freeze({
|
2132
2085
|
__proto__: null,
|
2133
|
-
get PageDirection () { return PageDirection; },
|
2134
2086
|
StoreCodec: StoreCodec,
|
2135
2087
|
StoreCore: StoreCore
|
2136
2088
|
});
|
@@ -2573,38 +2525,22 @@ class TypedEventEmitter extends EventTarget {
|
|
2573
2525
|
return this.dispatchEvent(new CustomEvent(type, detail));
|
2574
2526
|
}
|
2575
2527
|
}
|
2576
|
-
|
2577
|
-
* CustomEvent is a standard event but it's not supported by node.
|
2578
|
-
*
|
2579
|
-
* Remove this when https://github.com/nodejs/node/issues/40678 is closed.
|
2580
|
-
*
|
2581
|
-
* Ref: https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent
|
2582
|
-
*/
|
2583
|
-
class CustomEventPolyfill extends Event {
|
2584
|
-
/** Returns any custom data event was created with. Typically used for synthetic events. */
|
2585
|
-
detail;
|
2586
|
-
constructor(message, data) {
|
2587
|
-
super(message, data);
|
2588
|
-
// @ts-expect-error could be undefined
|
2589
|
-
this.detail = data?.detail;
|
2590
|
-
}
|
2591
|
-
}
|
2592
|
-
const CustomEvent = globalThis.CustomEvent ?? CustomEventPolyfill;
|
2528
|
+
const CustomEvent = globalThis.CustomEvent;
|
2593
2529
|
|
2594
2530
|
const RelayPingContentTopic = "/relay-ping/1/ping/null";
|
2595
2531
|
const log$2 = new Logger("keep-alive");
|
2596
2532
|
class KeepAliveManager {
|
2597
|
-
pingKeepAliveTimers;
|
2598
|
-
relayKeepAliveTimers;
|
2599
|
-
options;
|
2600
2533
|
relay;
|
2601
|
-
|
2602
|
-
|
2603
|
-
|
2534
|
+
libp2p;
|
2535
|
+
options;
|
2536
|
+
pingKeepAliveTimers = new Map();
|
2537
|
+
relayKeepAliveTimers = new Map();
|
2538
|
+
constructor({ options, relay, libp2p }) {
|
2604
2539
|
this.options = options;
|
2605
2540
|
this.relay = relay;
|
2541
|
+
this.libp2p = libp2p;
|
2606
2542
|
}
|
2607
|
-
start(peerId
|
2543
|
+
start(peerId) {
|
2608
2544
|
// Just in case a timer already exists for this peer
|
2609
2545
|
this.stop(peerId);
|
2610
2546
|
const { pingKeepAlive: pingPeriodSecs, relayKeepAlive: relayPeriodSecs } = this.options;
|
@@ -2619,7 +2555,7 @@ class KeepAliveManager {
|
|
2619
2555
|
// ping the peer for keep alive
|
2620
2556
|
// also update the peer store with the latency
|
2621
2557
|
try {
|
2622
|
-
ping = await
|
2558
|
+
ping = await this.libp2p.services.ping.ping(peerId);
|
2623
2559
|
log$2.info(`Ping succeeded (${peerIdStr})`, ping);
|
2624
2560
|
}
|
2625
2561
|
catch (error) {
|
@@ -2629,7 +2565,7 @@ class KeepAliveManager {
|
|
2629
2565
|
return;
|
2630
2566
|
}
|
2631
2567
|
try {
|
2632
|
-
await peerStore.merge(peerId, {
|
2568
|
+
await this.libp2p.peerStore.merge(peerId, {
|
2633
2569
|
metadata: {
|
2634
2570
|
ping: utf8ToBytes(ping.toString())
|
2635
2571
|
}
|
@@ -2818,7 +2754,11 @@ class ConnectionManager extends TypedEventEmitter {
|
|
2818
2754
|
maxParallelDials: DEFAULT_MAX_PARALLEL_DIALS,
|
2819
2755
|
...options
|
2820
2756
|
};
|
2821
|
-
this.keepAliveManager = new KeepAliveManager(
|
2757
|
+
this.keepAliveManager = new KeepAliveManager({
|
2758
|
+
relay,
|
2759
|
+
libp2p,
|
2760
|
+
options: keepAliveOptions
|
2761
|
+
});
|
2822
2762
|
this.run()
|
2823
2763
|
.then(() => log$1.info(`Connection Manager is now running`))
|
2824
2764
|
.catch((error) => log$1.error(`Unexpected error while running service`, error));
|
@@ -2865,6 +2805,7 @@ class ConnectionManager extends TypedEventEmitter {
|
|
2865
2805
|
// this helps us keep track of peers that have been dialed before
|
2866
2806
|
this.dialAttemptsForPeer.set(peerId.toString(), -1);
|
2867
2807
|
// Dialing succeeded, break the loop
|
2808
|
+
this.keepAliveManager.start(peerId);
|
2868
2809
|
break;
|
2869
2810
|
}
|
2870
2811
|
catch (error) {
|
@@ -2953,9 +2894,7 @@ class ConnectionManager extends TypedEventEmitter {
|
|
2953
2894
|
this.pendingPeerDialQueue.push(peerId);
|
2954
2895
|
return;
|
2955
2896
|
}
|
2956
|
-
this.dialPeer(peerId)
|
2957
|
-
log$1.error(`Error dialing peer ${peerId.toString()} : ${err}`);
|
2958
|
-
});
|
2897
|
+
await this.dialPeer(peerId);
|
2959
2898
|
}
|
2960
2899
|
onEventHandlers = {
|
2961
2900
|
"peer:discovery": (evt) => {
|
@@ -2974,7 +2913,7 @@ class ConnectionManager extends TypedEventEmitter {
|
|
2974
2913
|
void (async () => {
|
2975
2914
|
log$1.info(`Connected to peer ${evt.detail.toString()}`);
|
2976
2915
|
const peerId = evt.detail;
|
2977
|
-
this.keepAliveManager.start(peerId
|
2916
|
+
this.keepAliveManager.start(peerId);
|
2978
2917
|
const isBootstrap = (await this.getTagNamesForPeer(peerId)).includes(Tags.BOOTSTRAP);
|
2979
2918
|
if (isBootstrap) {
|
2980
2919
|
const bootstrapConnections = this.libp2p
|
@@ -3014,26 +2953,25 @@ class ConnectionManager extends TypedEventEmitter {
|
|
3014
2953
|
* @returns true if the peer should be dialed, false otherwise
|
3015
2954
|
*/
|
3016
2955
|
async shouldDialPeer(peerId) {
|
3017
|
-
// if we're already connected to the peer, don't dial
|
3018
2956
|
const isConnected = this.libp2p.getConnections(peerId).length > 0;
|
3019
2957
|
if (isConnected) {
|
3020
2958
|
log$1.warn(`Already connected to peer ${peerId.toString()}. Not dialing.`);
|
3021
2959
|
return false;
|
3022
2960
|
}
|
3023
|
-
|
3024
|
-
if (!
|
2961
|
+
const isSameShard = await this.isPeerTopicConfigured(peerId);
|
2962
|
+
if (!isSameShard) {
|
3025
2963
|
const shardInfo = await this.getPeerShardInfo(peerId, this.libp2p.peerStore);
|
3026
2964
|
log$1.warn(`Discovered peer ${peerId.toString()} with ShardInfo ${shardInfo} is not part of any of the configured pubsub topics (${this.configuredPubsubTopics}).
|
3027
2965
|
Not dialing.`);
|
3028
2966
|
return false;
|
3029
2967
|
}
|
3030
|
-
|
3031
|
-
if (!
|
2968
|
+
const isPreferredBasedOnBootstrap = await this.isPeerDialableBasedOnBootstrapStatus(peerId);
|
2969
|
+
if (!isPreferredBasedOnBootstrap) {
|
3032
2970
|
log$1.warn(`Peer ${peerId.toString()} is not dialable based on bootstrap status. Not dialing.`);
|
3033
2971
|
return false;
|
3034
2972
|
}
|
3035
|
-
|
3036
|
-
if (
|
2973
|
+
const hasBeenDialed = this.dialAttemptsForPeer.has(peerId.toString());
|
2974
|
+
if (hasBeenDialed) {
|
3037
2975
|
log$1.warn(`Peer ${peerId.toString()} has already been attempted dial before, or already has a dial attempt in progress, skipping dial`);
|
3038
2976
|
return false;
|
3039
2977
|
}
|
@@ -3047,19 +2985,15 @@ class ConnectionManager extends TypedEventEmitter {
|
|
3047
2985
|
async isPeerDialableBasedOnBootstrapStatus(peerId) {
|
3048
2986
|
const tagNames = await this.getTagNamesForPeer(peerId);
|
3049
2987
|
const isBootstrap = tagNames.some((tagName) => tagName === Tags.BOOTSTRAP);
|
3050
|
-
if (isBootstrap) {
|
3051
|
-
const currentBootstrapConnections = this.libp2p
|
3052
|
-
.getConnections()
|
3053
|
-
.filter((conn) => {
|
3054
|
-
return conn.tags.find((name) => name === Tags.BOOTSTRAP);
|
3055
|
-
}).length;
|
3056
|
-
if (currentBootstrapConnections < this.options.maxBootstrapPeersAllowed)
|
3057
|
-
return true;
|
3058
|
-
}
|
3059
|
-
else {
|
2988
|
+
if (!isBootstrap) {
|
3060
2989
|
return true;
|
3061
2990
|
}
|
3062
|
-
|
2991
|
+
const currentBootstrapConnections = this.libp2p
|
2992
|
+
.getConnections()
|
2993
|
+
.filter((conn) => {
|
2994
|
+
return conn.tags.find((name) => name === Tags.BOOTSTRAP);
|
2995
|
+
}).length;
|
2996
|
+
return currentBootstrapConnections < this.options.maxBootstrapPeersAllowed;
|
3063
2997
|
}
|
3064
2998
|
async dispatchDiscoveryEvent(peerId) {
|
3065
2999
|
const isBootstrap = (await this.getTagNamesForPeer(peerId)).includes(Tags.BOOTSTRAP);
|
@@ -3100,43 +3034,94 @@ class ConnectionManager extends TypedEventEmitter {
|
|
3100
3034
|
}
|
3101
3035
|
}
|
3102
3036
|
|
3037
|
+
class HealthManager {
|
3038
|
+
static instance;
|
3039
|
+
health;
|
3040
|
+
constructor() {
|
3041
|
+
this.health = {
|
3042
|
+
overallStatus: HealthStatus.Unhealthy,
|
3043
|
+
protocolStatuses: new Map()
|
3044
|
+
};
|
3045
|
+
}
|
3046
|
+
static getInstance() {
|
3047
|
+
if (!HealthManager.instance) {
|
3048
|
+
HealthManager.instance = new HealthManager();
|
3049
|
+
}
|
3050
|
+
return HealthManager.instance;
|
3051
|
+
}
|
3052
|
+
getHealthStatus() {
|
3053
|
+
return this.health.overallStatus;
|
3054
|
+
}
|
3055
|
+
getProtocolStatus(protocol) {
|
3056
|
+
return this.health.protocolStatuses.get(protocol);
|
3057
|
+
}
|
3058
|
+
updateProtocolHealth(multicodec, connectedPeers) {
|
3059
|
+
const protocol = this.getNameFromMulticodec(multicodec);
|
3060
|
+
let status = HealthStatus.Unhealthy;
|
3061
|
+
if (connectedPeers == 1) {
|
3062
|
+
status = HealthStatus.MinimallyHealthy;
|
3063
|
+
}
|
3064
|
+
else if (connectedPeers >= 2) {
|
3065
|
+
status = HealthStatus.SufficientlyHealthy;
|
3066
|
+
}
|
3067
|
+
this.health.protocolStatuses.set(protocol, {
|
3068
|
+
name: protocol,
|
3069
|
+
status: status,
|
3070
|
+
lastUpdate: new Date()
|
3071
|
+
});
|
3072
|
+
this.updateOverallHealth();
|
3073
|
+
}
|
3074
|
+
getNameFromMulticodec(multicodec) {
|
3075
|
+
let name;
|
3076
|
+
if (multicodec.includes("filter")) {
|
3077
|
+
name = Protocols.Filter;
|
3078
|
+
}
|
3079
|
+
else if (multicodec.includes("lightpush")) {
|
3080
|
+
name = Protocols.LightPush;
|
3081
|
+
}
|
3082
|
+
else if (multicodec.includes("store")) {
|
3083
|
+
name = Protocols.Store;
|
3084
|
+
}
|
3085
|
+
else {
|
3086
|
+
throw new Error(`Unknown protocol: ${multicodec}`);
|
3087
|
+
}
|
3088
|
+
return name;
|
3089
|
+
}
|
3090
|
+
updateOverallHealth() {
|
3091
|
+
const relevantProtocols = [Protocols.LightPush, Protocols.Filter];
|
3092
|
+
const statuses = relevantProtocols.map((p) => this.getProtocolStatus(p)?.status);
|
3093
|
+
if (statuses.some((status) => status === HealthStatus.Unhealthy)) {
|
3094
|
+
this.health.overallStatus = HealthStatus.Unhealthy;
|
3095
|
+
}
|
3096
|
+
else if (statuses.some((status) => status === HealthStatus.MinimallyHealthy)) {
|
3097
|
+
this.health.overallStatus = HealthStatus.MinimallyHealthy;
|
3098
|
+
}
|
3099
|
+
else {
|
3100
|
+
this.health.overallStatus = HealthStatus.SufficientlyHealthy;
|
3101
|
+
}
|
3102
|
+
}
|
3103
|
+
}
|
3104
|
+
const getHealthManager = () => HealthManager.getInstance();
|
3105
|
+
|
3103
3106
|
const log = new Logger("metadata");
|
3104
3107
|
const MetadataCodec = "/vac/waku/metadata/1.0.0";
|
3105
3108
|
class Metadata extends BaseProtocol {
|
3106
|
-
|
3109
|
+
pubsubTopics;
|
3107
3110
|
libp2pComponents;
|
3108
3111
|
handshakesConfirmed = new Map();
|
3109
|
-
constructor(
|
3110
|
-
super(MetadataCodec, libp2p.components, log,
|
3111
|
-
this.
|
3112
|
+
constructor(pubsubTopics, libp2p) {
|
3113
|
+
super(MetadataCodec, libp2p.components, log, pubsubTopics);
|
3114
|
+
this.pubsubTopics = pubsubTopics;
|
3112
3115
|
this.libp2pComponents = libp2p;
|
3113
3116
|
void libp2p.registrar.handle(MetadataCodec, (streamData) => {
|
3114
3117
|
void this.onRequest(streamData);
|
3115
3118
|
});
|
3116
3119
|
}
|
3117
|
-
/**
|
3118
|
-
* Handle an incoming metadata request
|
3119
|
-
*/
|
3120
|
-
async onRequest(streamData) {
|
3121
|
-
try {
|
3122
|
-
const { stream, connection } = streamData;
|
3123
|
-
const encodedShardInfo = WakuMetadataResponse.encode(this.shardInfo);
|
3124
|
-
const encodedResponse = await pipe([encodedShardInfo], encode, stream, decode, async (source) => await all(source));
|
3125
|
-
const { error, shardInfo } = this.decodeMetadataResponse(encodedResponse);
|
3126
|
-
if (error) {
|
3127
|
-
return;
|
3128
|
-
}
|
3129
|
-
await this.savePeerShardInfo(connection.remotePeer, shardInfo);
|
3130
|
-
}
|
3131
|
-
catch (error) {
|
3132
|
-
log.error("Error handling metadata request", error);
|
3133
|
-
}
|
3134
|
-
}
|
3135
3120
|
/**
|
3136
3121
|
* Make a metadata query to a peer
|
3137
3122
|
*/
|
3138
3123
|
async query(peerId) {
|
3139
|
-
const request = WakuMetadataRequest.encode(this.
|
3124
|
+
const request = WakuMetadataRequest.encode(pubsubTopicsToShardInfo(this.pubsubTopics));
|
3140
3125
|
const peer = await this.peerStore.get(peerId);
|
3141
3126
|
if (!peer) {
|
3142
3127
|
return {
|
@@ -3179,6 +3164,24 @@ class Metadata extends BaseProtocol {
|
|
3179
3164
|
}
|
3180
3165
|
return await this.query(peerId);
|
3181
3166
|
}
|
3167
|
+
/**
|
3168
|
+
* Handle an incoming metadata request
|
3169
|
+
*/
|
3170
|
+
async onRequest(streamData) {
|
3171
|
+
try {
|
3172
|
+
const { stream, connection } = streamData;
|
3173
|
+
const encodedShardInfo = WakuMetadataResponse.encode(pubsubTopicsToShardInfo(this.pubsubTopics));
|
3174
|
+
const encodedResponse = await pipe([encodedShardInfo], encode, stream, decode, async (source) => await all(source));
|
3175
|
+
const { error, shardInfo } = this.decodeMetadataResponse(encodedResponse);
|
3176
|
+
if (error) {
|
3177
|
+
return;
|
3178
|
+
}
|
3179
|
+
await this.savePeerShardInfo(connection.remotePeer, shardInfo);
|
3180
|
+
}
|
3181
|
+
catch (error) {
|
3182
|
+
log.error("Error handling metadata request", error);
|
3183
|
+
}
|
3184
|
+
}
|
3182
3185
|
decodeMetadataResponse(encodedResponse) {
|
3183
3186
|
const bytes = new Uint8ArrayList();
|
3184
3187
|
encodedResponse.forEach((chunk) => {
|
@@ -3207,8 +3210,8 @@ class Metadata extends BaseProtocol {
|
|
3207
3210
|
this.handshakesConfirmed.set(peerId.toString(), shardInfo);
|
3208
3211
|
}
|
3209
3212
|
}
|
3210
|
-
function wakuMetadata(
|
3211
|
-
return (components) => new Metadata(
|
3213
|
+
function wakuMetadata(pubsubTopics) {
|
3214
|
+
return (components) => new Metadata(pubsubTopics, components);
|
3212
3215
|
}
|
3213
3216
|
|
3214
|
-
export { ConnectionManager, FilterCodecs, FilterCore, KeepAliveManager, LightPushCodec, LightPushCore, MetadataCodec,
|
3217
|
+
export { ConnectionManager, FilterCodecs, FilterCore, KeepAliveManager, LightPushCodec, LightPushCore, MetadataCodec, StoreCore, createEncoder, getHealthManager, index$3 as message, waitForRemotePeer, wakuMetadata, index$2 as waku_filter, index$1 as waku_light_push, index as waku_store };
|