@railgun-community/waku-broadcaster-client-node 9.0.5 → 9.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (31) hide show
  1. package/README.md +1 -2
  2. package/dist/models/broadcaster-config.d.ts +23 -0
  3. package/dist/models/broadcaster-config.js +78 -1
  4. package/dist/models/broadcaster-config.js.map +1 -1
  5. package/dist/models/constants.d.ts +16 -2
  6. package/dist/models/constants.js +30 -8
  7. package/dist/models/constants.js.map +1 -1
  8. package/dist/models/export-models.d.ts +6 -0
  9. package/dist/models/export-models.js.map +1 -1
  10. package/dist/waku/waku-broadcaster-peer-discovery-core-base.d.ts +54 -0
  11. package/dist/waku/waku-broadcaster-peer-discovery-core-base.js +223 -0
  12. package/dist/waku/waku-broadcaster-peer-discovery-core-base.js.map +1 -0
  13. package/dist/waku/waku-broadcaster-waku-core-base.d.ts +37 -6
  14. package/dist/waku/waku-broadcaster-waku-core-base.js +35 -10
  15. package/dist/waku/waku-broadcaster-waku-core-base.js.map +1 -1
  16. package/dist/waku/waku-broadcaster-waku-core.d.ts +14 -3
  17. package/dist/waku/waku-broadcaster-waku-core.js +42 -42
  18. package/dist/waku/waku-broadcaster-waku-core.js.map +1 -1
  19. package/dist/waku/waku-healthcheck.d.ts +62 -0
  20. package/dist/waku/waku-healthcheck.js +88 -0
  21. package/dist/waku/waku-healthcheck.js.map +1 -0
  22. package/dist/waku/waku-observers.d.ts +1 -0
  23. package/dist/waku/waku-observers.js +10 -4
  24. package/dist/waku/waku-observers.js.map +1 -1
  25. package/dist/waku/waku-peer-discovery.d.ts +31 -0
  26. package/dist/waku/waku-peer-discovery.js +90 -0
  27. package/dist/waku/waku-peer-discovery.js.map +1 -0
  28. package/dist/waku-broadcaster-client.d.ts +3 -0
  29. package/dist/waku-broadcaster-client.js +55 -8
  30. package/dist/waku-broadcaster-client.js.map +1 -1
  31. package/package.json +3 -3
@@ -4,9 +4,10 @@ import { BroadcasterDebug } from '../utils/broadcaster-debug.js';
4
4
  import { utf8ToBytes } from '../utils/conversion.js';
5
5
  import { isDefined } from '../utils/is-defined.js';
6
6
  import { createEncoder, createDecoder, } from '@waku/sdk';
7
- import { WAKU_RAILGUN_DEFAULT_SHARD, WAKU_RAILGUN_PUB_SUB_TOPIC, } from '../models/constants.js';
7
+ import { WAKU_RAILGUN_PUB_SUB_TOPIC, } from '../models/constants.js';
8
8
  import { BroadcasterFeeCache } from '../fees/broadcaster-fee-cache.js';
9
9
  import { BroadcasterConfig } from '../models/broadcaster-config.js';
10
+ import { getWakuHealthSnapshot } from './waku-healthcheck.js';
10
11
  export class WakuBroadcasterWakuCoreBase {
11
12
  static hasError = false;
12
13
  static restartCallback;
@@ -14,7 +15,6 @@ export class WakuBroadcasterWakuCoreBase {
14
15
  static pubSubTopic = WAKU_RAILGUN_PUB_SUB_TOPIC;
15
16
  static additionalDirectPeers = [];
16
17
  static peerDiscoveryTimeout = 60000;
17
- static defaultShard = WAKU_RAILGUN_DEFAULT_SHARD;
18
18
  static restartCount = 0;
19
19
  static async initWaku(chain) {
20
20
  try {
@@ -60,9 +60,12 @@ export class WakuBroadcasterWakuCoreBase {
60
60
  }
61
61
  static setBroadcasterOptions(broadcasterOptions) {
62
62
  BroadcasterConfig.trustedFeeSigner = broadcasterOptions.trustedFeeSigner;
63
- if (isDefined(broadcasterOptions.pubSubTopic)) {
64
- this.pubSubTopic = broadcasterOptions.pubSubTopic;
65
- }
63
+ BroadcasterConfig.configureWakuNetwork({
64
+ clusterId: broadcasterOptions.clusterId,
65
+ shardId: broadcasterOptions.shardId,
66
+ pubSubTopic: broadcasterOptions.pubSubTopic,
67
+ });
68
+ this.pubSubTopic = BroadcasterConfig.pubSubTopic;
66
69
  if (broadcasterOptions.additionalDirectPeers) {
67
70
  this.additionalDirectPeers =
68
71
  broadcasterOptions.additionalDirectPeers;
@@ -103,20 +106,42 @@ export class WakuBroadcasterWakuCoreBase {
103
106
  return 0;
104
107
  return this.waku.libp2p.getConnections().length;
105
108
  }
109
+ static async getHealthSnapshot() {
110
+ return getWakuHealthSnapshot({
111
+ hasError: this.hasError,
112
+ peerDiscoveryTimeout: this.peerDiscoveryTimeout,
113
+ restartCount: this.restartCount,
114
+ waku: this.waku,
115
+ });
116
+ }
117
+ static getLightPushAcceptedCount(result) {
118
+ if (Array.isArray(result.successes)) {
119
+ return result.successes.length;
120
+ }
121
+ if (Array.isArray(result.recipients)) {
122
+ return result.recipients.length;
123
+ }
124
+ return 0;
125
+ }
106
126
  static async broadcastMessage(data, topic) {
107
127
  if (!this.waku) {
108
128
  throw new Error('Waku not initialized');
109
129
  }
110
130
  const encoder = createEncoder({
111
131
  contentTopic: topic,
112
- routingInfo: WAKU_RAILGUN_DEFAULT_SHARD
132
+ routingInfo: BroadcasterConfig.getWakuRoutingInfo(),
113
133
  });
114
134
  const payload = utf8ToBytes(JSON.stringify(data));
115
135
  const result = await this.waku.lightPush.send(encoder, {
116
136
  payload,
117
137
  });
118
- if (result.failures && result.failures.length > 0) {
119
- throw new Error(`Failed to send message: ${result.failures.map(f => f.error).join(', ')}`);
138
+ const acceptedCount = this.getLightPushAcceptedCount(result);
139
+ const failures = result.failures ?? [];
140
+ if (failures.length > 0) {
141
+ if (acceptedCount > 0) {
142
+ return;
143
+ }
144
+ throw new Error('Failed to send message');
120
145
  }
121
146
  }
122
147
  static async retrieveHistoricalForTopic(topic) {
@@ -128,14 +153,14 @@ export class WakuBroadcasterWakuCoreBase {
128
153
  BroadcasterDebug.log(`No callback found for topic: ${topic}`);
129
154
  return;
130
155
  }
131
- const decoder = createDecoder(topic, WAKU_RAILGUN_DEFAULT_SHARD);
156
+ const decoder = createDecoder(topic, BroadcasterConfig.getWakuRoutingInfo());
132
157
  try {
133
158
  const startTime = new Date();
134
159
  startTime.setTime(Date.now() - (BroadcasterConfig.historicalLookBackTime));
135
160
  const endTime = new Date(Date.now());
136
161
  const options = {
137
162
  includeData: true,
138
- pubsubTopic: this.pubSubTopic,
163
+ pubsubTopic: BroadcasterConfig.pubSubTopic,
139
164
  contentTopics: [topic],
140
165
  paginationForward: true,
141
166
  };
@@ -1 +1 @@
1
- {"version":3,"file":"waku-broadcaster-waku-core-base.js","sourceRoot":"","sources":["../../src/waku/waku-broadcaster-waku-core-base.ts"],"names":[],"mappings":"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","sourcesContent":["import { Chain, delay } from '@railgun-community/shared-models';\nimport { WakuObservers } from './waku-observers.js';\nimport { BroadcasterDebug } from '../utils/broadcaster-debug.js';\nimport { utf8ToBytes } from '../utils/conversion.js';\nimport { isDefined } from '../utils/is-defined.js';\nimport {\n createEncoder,\n createDecoder,\n type LightNode,\n type IDecodedMessage,\n type QueryRequestParams,\n} from '@waku/sdk';\nimport { BroadcasterOptions } from '../models/index.js';\nimport {\n WAKU_RAILGUN_DEFAULT_SHARD,\n WAKU_RAILGUN_PUB_SUB_TOPIC,\n} from '../models/constants.js';\nimport { BroadcasterFeeCache } from '../fees/broadcaster-fee-cache.js';\nimport { BroadcasterConfig } from '../models/broadcaster-config.js';\n\nexport abstract class WakuBroadcasterWakuCoreBase {\n static hasError = false;\n static restartCallback: () => void;\n\n static waku: Optional<LightNode>;\n\n protected static pubSubTopic = WAKU_RAILGUN_PUB_SUB_TOPIC;\n protected static additionalDirectPeers: string[] = [];\n protected static peerDiscoveryTimeout = 60000;\n protected static defaultShard = WAKU_RAILGUN_DEFAULT_SHARD;\n public static restartCount = 0;\n\n static async initWaku(chain: Chain): Promise<void> {\n try {\n await this.connect();\n if (!this.waku) {\n BroadcasterDebug.log('No waku instance found');\n return;\n }\n WakuObservers.resetCurrentChain();\n await WakuObservers.setObserversForChain(\n this.waku,\n chain,\n );\n\n this.pollHistoricalTopics()\n\n } catch (err) {\n if (!(err instanceof Error)) {\n throw err;\n }\n BroadcasterDebug.error(err);\n throw err;\n }\n }\n\n static async pollHistoricalTopics() {\n BroadcasterDebug.log(\"Polling historical messages\")\n const topics = WakuObservers.getCurrentContentTopics();\n for (const topic of topics) {\n await this.retrieveHistoricalForTopic(topic);\n }\n await delay(10_000)\n }\n\n static setWakuRestartCallback(callback: () => void) {\n this.restartCallback = callback;\n }\n\n static async reinitWaku(chain: Chain) {\n if (\n isDefined(this.waku) &&\n this.waku.isStarted()\n ) {\n // Reset fees, which will reset status to \"Searching\".\n await this.disconnect();\n }\n BroadcasterFeeCache.resetCache(chain);\n BroadcasterDebug.log(\n `Reinit Waku, ${++this.restartCount}`,\n );\n await this.initWaku(chain);\n if (this.restartCallback) {\n this.restartCallback();\n }\n }\n\n static setBroadcasterOptions(broadcasterOptions: BroadcasterOptions) {\n BroadcasterConfig.trustedFeeSigner = broadcasterOptions.trustedFeeSigner;\n\n if (isDefined(broadcasterOptions.pubSubTopic)) {\n this.pubSubTopic = broadcasterOptions.pubSubTopic;\n }\n if (broadcasterOptions.additionalDirectPeers) {\n this.additionalDirectPeers =\n broadcasterOptions.additionalDirectPeers;\n }\n if (isDefined(broadcasterOptions.peerDiscoveryTimeout)) {\n this.peerDiscoveryTimeout =\n broadcasterOptions.peerDiscoveryTimeout;\n }\n if (isDefined(broadcasterOptions.feeExpirationTimeout)) {\n BroadcasterConfig.feeExpirationTimeout =\n broadcasterOptions.feeExpirationTimeout;\n }\n if (isDefined(broadcasterOptions.historicalLookBackTime)) {\n BroadcasterConfig.historicalLookBackTime = broadcasterOptions.historicalLookBackTime\n }\n }\n\n static async disconnect() {\n await WakuObservers.unsubscribe(this.waku);\n await this.waku?.stop();\n this.waku = undefined;\n }\n\n protected static connect(): Promise<void> {\n throw new Error(\"Method 'connect' must be implemented.\");\n }\n\n static getMeshPeerCount(): number {\n return 0;\n }\n\n static getPubSubPeerCount(): number {\n return 0;\n }\n\n static async getLightPushPeerCount(): Promise<number> {\n if (!this.waku) return 0;\n return this.waku.libp2p.getConnections().length;\n }\n\n static async getFilterPeerCount(): Promise<number> {\n if (!this.waku) return 0;\n return this.waku.libp2p.getConnections().length;\n }\n\n\n\n static async broadcastMessage(data: object, topic: string): Promise<void> {\n if (!this.waku) {\n throw new Error('Waku not initialized');\n }\n const encoder = createEncoder({\n contentTopic: topic,\n routingInfo: WAKU_RAILGUN_DEFAULT_SHARD\n });\n\n const payload = utf8ToBytes(JSON.stringify(data));\n\n const result = await this.waku.lightPush.send(encoder, {\n payload,\n });\n\n if (result.failures && result.failures.length > 0) {\n throw new Error(`Failed to send message: ${result.failures.map(f => f.error).join(', ')}`);\n }\n }\n\n static async retrieveHistoricalForTopic(topic: string): Promise<void> {\n if (!this.waku) {\n return;\n }\n\n const callback = WakuObservers.getCallbackForTopic(topic);\n if (!callback) {\n BroadcasterDebug.log(`No callback found for topic: ${topic}`);\n return;\n }\n\n const decoder = createDecoder(topic, WAKU_RAILGUN_DEFAULT_SHARD);\n\n try {\n const startTime = new Date()\n // TODO: make a variable\n startTime.setTime(Date.now() - (BroadcasterConfig.historicalLookBackTime))\n const endTime = new Date(Date.now())\n const options: QueryRequestParams = {\n includeData: true,\n pubsubTopic: this.pubSubTopic,\n contentTopics: [topic],\n paginationForward: true,\n }\n const lastMessage = WakuObservers.getLastMessage(topic);\n if (lastMessage) {\n const cursor = this.waku.store.createCursor(lastMessage)\n options.paginationCursor = cursor\n } else {\n options.timeStart = startTime\n options.timeEnd = endTime\n }\n const generator = this.waku.store.queryGenerator([decoder], options);\n for await (const messagesPromises of generator) {\n messagesPromises.reverse()\n for (const messagePromise of messagesPromises) {\n if (isDefined(messagePromise)) {\n const message = await messagePromise\n if (isDefined(message)) {\n callback(message);\n }\n }\n }\n }\n } catch (err) {\n if (err instanceof Error) {\n BroadcasterDebug.log(\n `Error retrieving historical messages: ${err.message}`,\n );\n }\n }\n }\n}\n"]}
1
+ {"version":3,"file":"waku-broadcaster-waku-core-base.js","sourceRoot":"","sources":["../../src/waku/waku-broadcaster-waku-core-base.ts"],"names":[],"mappings":"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","sourcesContent":["import { Chain, delay } from '@railgun-community/shared-models';\nimport { WakuObservers } from './waku-observers.js';\nimport { BroadcasterDebug } from '../utils/broadcaster-debug.js';\nimport { utf8ToBytes } from '../utils/conversion.js';\nimport { isDefined } from '../utils/is-defined.js';\nimport {\n createEncoder,\n createDecoder,\n type LightNode,\n type IDecodedMessage,\n type QueryRequestParams,\n} from '@waku/sdk';\nimport { BroadcasterOptions } from '../models/index.js';\nimport {\n WAKU_RAILGUN_PUB_SUB_TOPIC,\n} from '../models/constants.js';\nimport { BroadcasterFeeCache } from '../fees/broadcaster-fee-cache.js';\nimport { BroadcasterConfig } from '../models/broadcaster-config.js';\nimport { getWakuHealthSnapshot } from './waku-healthcheck.js';\n\nexport abstract class WakuBroadcasterWakuCoreBase {\n static hasError = false;\n static restartCallback: () => void;\n\n static waku: Optional<LightNode>;\n\n protected static pubSubTopic = WAKU_RAILGUN_PUB_SUB_TOPIC;\n protected static additionalDirectPeers: string[] = [];\n protected static peerDiscoveryTimeout = 60000;\n public static restartCount = 0;\n\n static async initWaku(chain: Chain): Promise<void> {\n try {\n await this.connect();\n if (!this.waku) {\n BroadcasterDebug.log('No waku instance found');\n return;\n }\n WakuObservers.resetCurrentChain();\n await WakuObservers.setObserversForChain(\n this.waku,\n chain,\n );\n\n this.pollHistoricalTopics()\n\n } catch (err) {\n if (!(err instanceof Error)) {\n throw err;\n }\n BroadcasterDebug.error(err);\n throw err;\n }\n }\n\n static async pollHistoricalTopics() {\n BroadcasterDebug.log(\"Polling historical messages\")\n const topics = WakuObservers.getCurrentContentTopics();\n for (const topic of topics) {\n await this.retrieveHistoricalForTopic(topic);\n }\n await delay(10_000)\n }\n\n static setWakuRestartCallback(callback: () => void) {\n this.restartCallback = callback;\n }\n\n static async reinitWaku(chain: Chain) {\n if (\n isDefined(this.waku) &&\n this.waku.isStarted()\n ) {\n // Reset fees, which will reset status to \"Searching\".\n await this.disconnect();\n }\n BroadcasterFeeCache.resetCache(chain);\n BroadcasterDebug.log(\n `Reinit Waku, ${++this.restartCount}`,\n );\n await this.initWaku(chain);\n if (this.restartCallback) {\n this.restartCallback();\n }\n }\n\n static setBroadcasterOptions(broadcasterOptions: BroadcasterOptions) {\n BroadcasterConfig.trustedFeeSigner = broadcasterOptions.trustedFeeSigner;\n\n BroadcasterConfig.configureWakuNetwork({\n clusterId: broadcasterOptions.clusterId,\n shardId: broadcasterOptions.shardId,\n pubSubTopic: broadcasterOptions.pubSubTopic,\n });\n\n this.pubSubTopic = BroadcasterConfig.pubSubTopic;\n if (broadcasterOptions.additionalDirectPeers) {\n this.additionalDirectPeers =\n broadcasterOptions.additionalDirectPeers;\n }\n if (isDefined(broadcasterOptions.peerDiscoveryTimeout)) {\n this.peerDiscoveryTimeout =\n broadcasterOptions.peerDiscoveryTimeout;\n }\n if (isDefined(broadcasterOptions.feeExpirationTimeout)) {\n BroadcasterConfig.feeExpirationTimeout =\n broadcasterOptions.feeExpirationTimeout;\n }\n if (isDefined(broadcasterOptions.historicalLookBackTime)) {\n BroadcasterConfig.historicalLookBackTime = broadcasterOptions.historicalLookBackTime\n }\n }\n\n static async disconnect() {\n await WakuObservers.unsubscribe(this.waku);\n await this.waku?.stop();\n this.waku = undefined;\n }\n\n protected static connect(): Promise<void> {\n throw new Error(\"Method 'connect' must be implemented.\");\n }\n\n static getMeshPeerCount(): number {\n return 0;\n }\n\n static getPubSubPeerCount(): number {\n return 0;\n }\n\n static async getLightPushPeerCount(): Promise<number> {\n if (!this.waku) return 0;\n return this.waku.libp2p.getConnections().length;\n }\n\n static async getFilterPeerCount(): Promise<number> {\n if (!this.waku) return 0;\n return this.waku.libp2p.getConnections().length;\n }\n\n static async getHealthSnapshot() {\n return getWakuHealthSnapshot({\n hasError: this.hasError,\n peerDiscoveryTimeout: this.peerDiscoveryTimeout,\n restartCount: this.restartCount,\n waku: this.waku,\n });\n }\n\n private static getLightPushAcceptedCount(result: {\n successes?: unknown[];\n recipients?: unknown[];\n failures?: unknown[];\n }): number {\n if (Array.isArray(result.successes)) {\n return result.successes.length;\n }\n if (Array.isArray(result.recipients)) {\n return result.recipients.length;\n }\n return 0;\n }\n\n static async broadcastMessage(data: object, topic: string): Promise<void> {\n if (!this.waku) {\n throw new Error('Waku not initialized');\n }\n const encoder = createEncoder({\n contentTopic: topic,\n routingInfo: BroadcasterConfig.getWakuRoutingInfo(),\n });\n\n const payload = utf8ToBytes(JSON.stringify(data));\n\n const result = await this.waku.lightPush.send(encoder, {\n payload,\n });\n\n const acceptedCount = this.getLightPushAcceptedCount(result);\n const failures = result.failures ?? [];\n\n if (failures.length > 0) {\n if (acceptedCount > 0) {\n return;\n }\n\n throw new Error('Failed to send message');\n }\n }\n\n static async retrieveHistoricalForTopic(topic: string): Promise<void> {\n if (!this.waku) {\n return;\n }\n\n const callback = WakuObservers.getCallbackForTopic(topic);\n if (!callback) {\n BroadcasterDebug.log(`No callback found for topic: ${topic}`);\n return;\n }\n\n const decoder = createDecoder(topic, BroadcasterConfig.getWakuRoutingInfo());\n\n try {\n const startTime = new Date()\n // TODO: make a variable\n startTime.setTime(Date.now() - (BroadcasterConfig.historicalLookBackTime))\n const endTime = new Date(Date.now())\n const options: QueryRequestParams = {\n includeData: true,\n pubsubTopic: BroadcasterConfig.pubSubTopic,\n contentTopics: [topic],\n paginationForward: true,\n }\n const lastMessage = WakuObservers.getLastMessage(topic);\n if (lastMessage) {\n const cursor = this.waku.store.createCursor(lastMessage)\n options.paginationCursor = cursor\n } else {\n options.timeStart = startTime\n options.timeEnd = endTime\n }\n const generator = this.waku.store.queryGenerator([decoder], options);\n for await (const messagesPromises of generator) {\n messagesPromises.reverse()\n for (const messagePromise of messagesPromises) {\n if (isDefined(messagePromise)) {\n const message = await messagePromise\n if (isDefined(message)) {\n callback(message);\n }\n }\n }\n }\n } catch (err) {\n if (err instanceof Error) {\n BroadcasterDebug.log(\n `Error retrieving historical messages: ${err.message}`,\n );\n }\n }\n }\n}\n"]}
@@ -1,4 +1,15 @@
1
- import { WakuBroadcasterWakuCoreBase } from './waku-broadcaster-waku-core-base.js';
2
- export declare class WakuBroadcasterWakuCore extends WakuBroadcasterWakuCoreBase {
3
- protected static connect(): Promise<void>;
1
+ import { createLightNode, type CreateLibp2pOptions } from '@waku/sdk';
2
+ import { wakuDnsDiscovery, wakuPeerExchangeDiscovery } from '@waku/discovery';
3
+ import { WakuBroadcasterPeerDiscoveryCoreBase } from './waku-broadcaster-peer-discovery-core-base.js';
4
+ export declare class WakuBroadcasterWakuCore extends WakuBroadcasterPeerDiscoveryCoreBase {
5
+ protected static createWakuNode: typeof createLightNode;
6
+ protected static createDnsPeerDiscovery: typeof wakuDnsDiscovery;
7
+ protected static createPeerExchangeDiscovery: typeof wakuPeerExchangeDiscovery;
8
+ protected static getEnrTrees(): {
9
+ SANDBOX: string;
10
+ TEST: string;
11
+ };
12
+ protected static getDefaultPeers(): string[];
13
+ protected static getBaseLibp2pOptions(): CreateLibp2pOptions;
14
+ protected static applyConnectionLimitGuard(): void;
4
15
  }
@@ -1,49 +1,49 @@
1
1
  import { tcp } from '@libp2p/tcp';
2
- import { createLightNode, Protocols } from '@waku/sdk';
2
+ import { createLightNode, } from '@waku/sdk';
3
3
  import { BroadcasterDebug } from '../utils/broadcaster-debug.js';
4
- import { WakuBroadcasterWakuCoreBase } from './waku-broadcaster-waku-core-base.js';
5
- import { enrTree, wakuDnsDiscovery } from '@waku/discovery';
6
- import { BroadcasterConfig } from '../models/broadcaster-config.js';
7
- import { isDefined } from '@railgun-community/shared-models';
8
- export class WakuBroadcasterWakuCore extends WakuBroadcasterWakuCoreBase {
9
- static async connect() {
10
- try {
11
- this.hasError = false;
12
- BroadcasterDebug.log(`Creating waku broadcast client`);
13
- const libp2pOptions = {
14
- transports: [tcp()],
15
- hideWebSocketInfo: true,
16
- };
17
- if (BroadcasterConfig.useDNSDiscovery) {
18
- const enrTreePeers = [];
19
- if (isDefined(BroadcasterConfig.customDNS)) {
20
- enrTreePeers.push(...BroadcasterConfig.customDNS.enrTreePeers);
21
- if (!BroadcasterConfig.customDNS.onlyCustom) {
22
- enrTreePeers.push(...[enrTree["SANDBOX"], enrTree["TEST"]]);
23
- }
24
- }
25
- libp2pOptions.peerDiscovery = [
26
- wakuDnsDiscovery(enrTreePeers),
27
- ];
28
- }
29
- let directPeers = [];
30
- if (BroadcasterConfig.additionalDirectPeers.length) {
31
- directPeers = BroadcasterConfig.additionalDirectPeers;
32
- }
33
- this.waku = await createLightNode({
34
- defaultBootstrap: directPeers.length === 0,
35
- bootstrapPeers: directPeers,
36
- libp2p: libp2pOptions
37
- });
38
- await this.waku.start();
39
- BroadcasterDebug.log('Waiting for remote peer.');
40
- await this.waku.waitForPeers([Protocols.Filter, Protocols.LightPush, Protocols.Store], this.peerDiscoveryTimeout);
41
- BroadcasterDebug.log('Waku initialized and connected to peers');
4
+ import { enrTree, wakuDnsDiscovery, wakuPeerExchangeDiscovery } from '@waku/discovery';
5
+ import { WakuBroadcasterPeerDiscoveryCoreBase } from './waku-broadcaster-peer-discovery-core-base.js';
6
+ import { WAKU_RAILGUN_DEFAULT_PEERS_NODE } from '../models/constants.js';
7
+ export class WakuBroadcasterWakuCore extends WakuBroadcasterPeerDiscoveryCoreBase {
8
+ static createWakuNode = createLightNode;
9
+ static createDnsPeerDiscovery = wakuDnsDiscovery;
10
+ static createPeerExchangeDiscovery = wakuPeerExchangeDiscovery;
11
+ static getEnrTrees() {
12
+ return enrTree;
13
+ }
14
+ static getDefaultPeers() {
15
+ return WAKU_RAILGUN_DEFAULT_PEERS_NODE;
16
+ }
17
+ static getBaseLibp2pOptions() {
18
+ return {
19
+ ...super.getBaseLibp2pOptions(),
20
+ transports: [tcp()],
21
+ };
22
+ }
23
+ static applyConnectionLimitGuard() {
24
+ const connectionManager = this.waku?.connectionManager;
25
+ const dialer = connectionManager?.dialer;
26
+ const libp2p = this.waku?.libp2p;
27
+ if (!dialer || !libp2p || dialer.__wakuConnectionLimitGuardApplied) {
28
+ return;
42
29
  }
43
- catch (err) {
44
- BroadcasterDebug.log(`Error initializing Waku: ${err.message}`);
45
- this.hasError = true;
30
+ const originalShouldSkipPeer = dialer.shouldSkipPeer?.bind(dialer);
31
+ if (typeof originalShouldSkipPeer !== 'function') {
32
+ return;
46
33
  }
34
+ dialer.shouldSkipPeer = async (peerId) => {
35
+ const shouldSkip = await originalShouldSkipPeer(peerId);
36
+ if (shouldSkip) {
37
+ return true;
38
+ }
39
+ const connectionCount = libp2p.getConnections().length;
40
+ if (connectionCount >= this.maxConnections) {
41
+ BroadcasterDebug.log(`Skipping peer ${this.formatDiscoveryPeerId(peerId)} - max connections ${this.maxConnections} reached`);
42
+ return true;
43
+ }
44
+ return false;
45
+ };
46
+ dialer.__wakuConnectionLimitGuardApplied = true;
47
47
  }
48
48
  }
49
49
  //# sourceMappingURL=waku-broadcaster-waku-core.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"waku-broadcaster-waku-core.js","sourceRoot":"","sources":["../../src/waku/waku-broadcaster-waku-core.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC;AAClC,OAAO,EAAE,eAAe,EAAE,SAAS,EAA4B,MAAM,WAAW,CAAC;AACjF,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AACjE,OAAO,EAAE,2BAA2B,EAAE,MAAM,sCAAsC,CAAC;AACnF,OAAO,EAAE,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAC5D,OAAO,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAC;AACpE,OAAO,EAAE,SAAS,EAAE,MAAM,kCAAkC,CAAC;AAE7D,MAAM,OAAO,uBAAwB,SAAQ,2BAA2B;IAC5D,MAAM,CAAC,KAAK,CAAC,OAAO;QAC5B,IAAI,CAAC;YACH,IAAI,CAAC,QAAQ,GAAG,KAAK,CAAC;YAEtB,gBAAgB,CAAC,GAAG,CAAC,gCAAgC,CAAC,CAAC;YACvD,MAAM,aAAa,GAAwB;gBACzC,UAAU,EAAE,CAAC,GAAG,EAAE,CAAC;gBACnB,iBAAiB,EAAE,IAAI;aACxB,CAAA;YACD,IAAI,iBAAiB,CAAC,eAAe,EAAE,CAAC;gBACtC,MAAM,YAAY,GAAG,EAAE,CAAA;gBACvB,IAAI,SAAS,CAAC,iBAAiB,CAAC,SAAS,CAAC,EAAE,CAAC;oBAC3C,YAAY,CAAC,IAAI,CAAC,GAAG,iBAAiB,CAAC,SAAS,CAAC,YAAY,CAAC,CAAA;oBAC9D,IAAI,CAAC,iBAAiB,CAAC,SAAS,CAAC,UAAU,EAAE,CAAC;wBAC5C,YAAY,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAA;oBAC7D,CAAC;gBACH,CAAC;gBACD,aAAa,CAAC,aAAa,GAAG;oBAC5B,gBAAgB,CAAC,YAAY,CAAC;iBAC/B,CAAA;YACH,CAAC;YAED,IAAI,WAAW,GAAa,EAAE,CAAA;YAC9B,IAAI,iBAAiB,CAAC,qBAAqB,CAAC,MAAM,EAAE,CAAC;gBACnD,WAAW,GAAG,iBAAiB,CAAC,qBAAqB,CAAA;YACvD,CAAC;YAED,IAAI,CAAC,IAAI,GAAG,MAAM,eAAe,CAAC;gBAChC,gBAAgB,EAAE,WAAW,CAAC,MAAM,KAAK,CAAC;gBAC1C,cAAc,EAAE,WAAW;gBAC3B,MAAM,EAAE,aAAa;aACtB,CAAC,CAAC;YAEH,MAAM,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;YAExB,gBAAgB,CAAC,GAAG,CAAC,0BAA0B,CAAC,CAAC;YACjD,MAAM,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,SAAS,CAAC,MAAM,EAAE,SAAS,CAAC,SAAS,EAAE,SAAS,CAAC,KAAK,CAAC,EAAE,IAAI,CAAC,oBAAoB,CAAC,CAAA;YAEjH,gBAAgB,CAAC,GAAG,CAAC,yCAAyC,CAAC,CAAC;QAClE,CAAC;QAAC,OAAO,GAAQ,EAAE,CAAC;YAClB,gBAAgB,CAAC,GAAG,CAAC,4BAA4B,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;YAChE,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;QACvB,CAAC;IACH,CAAC;CACF","sourcesContent":["import { tcp } from '@libp2p/tcp';\nimport { createLightNode, Protocols, type CreateLibp2pOptions } from '@waku/sdk';\nimport { BroadcasterDebug } from '../utils/broadcaster-debug.js';\nimport { WakuBroadcasterWakuCoreBase } from './waku-broadcaster-waku-core-base.js';\nimport { enrTree, wakuDnsDiscovery } from '@waku/discovery';\nimport { BroadcasterConfig } from '../models/broadcaster-config.js';\nimport { isDefined } from '@railgun-community/shared-models';\n\nexport class WakuBroadcasterWakuCore extends WakuBroadcasterWakuCoreBase {\n protected static async connect(): Promise<void> {\n try {\n this.hasError = false;\n\n BroadcasterDebug.log(`Creating waku broadcast client`);\n const libp2pOptions: CreateLibp2pOptions = {\n transports: [tcp()],\n hideWebSocketInfo: true,\n }\n if (BroadcasterConfig.useDNSDiscovery) {\n const enrTreePeers = []\n if (isDefined(BroadcasterConfig.customDNS)) {\n enrTreePeers.push(...BroadcasterConfig.customDNS.enrTreePeers)\n if (!BroadcasterConfig.customDNS.onlyCustom) {\n enrTreePeers.push(...[enrTree[\"SANDBOX\"], enrTree[\"TEST\"]])\n }\n }\n libp2pOptions.peerDiscovery = [\n wakuDnsDiscovery(enrTreePeers),\n ]\n }\n // handle static peers being set.\n let directPeers: string[] = []\n if (BroadcasterConfig.additionalDirectPeers.length) {\n directPeers = BroadcasterConfig.additionalDirectPeers\n }\n\n this.waku = await createLightNode({\n defaultBootstrap: directPeers.length === 0,\n bootstrapPeers: directPeers, // gets ignored if defaultBootstrap = true\n libp2p: libp2pOptions\n });\n\n await this.waku.start();\n\n BroadcasterDebug.log('Waiting for remote peer.');\n await this.waku.waitForPeers([Protocols.Filter, Protocols.LightPush, Protocols.Store], this.peerDiscoveryTimeout)\n\n BroadcasterDebug.log('Waku initialized and connected to peers');\n } catch (err: any) {\n BroadcasterDebug.log(`Error initializing Waku: ${err.message}`);\n this.hasError = true;\n }\n }\n}\n"]}
1
+ {"version":3,"file":"waku-broadcaster-waku-core.js","sourceRoot":"","sources":["../../src/waku/waku-broadcaster-waku-core.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC;AAClC,OAAO,EACL,eAAe,GAEhB,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AACjE,OAAO,EAAE,OAAO,EAAE,gBAAgB,EAAE,yBAAyB,EAAE,MAAM,iBAAiB,CAAC;AACvF,OAAO,EAAE,oCAAoC,EAAE,MAAM,gDAAgD,CAAC;AACtG,OAAO,EAAE,+BAA+B,EAAE,MAAM,wBAAwB,CAAC;AAEzE,MAAM,OAAO,uBAAwB,SAAQ,oCAAoC;IACrE,MAAM,CAAC,cAAc,GAAG,eAAe,CAAC;IACxC,MAAM,CAAC,sBAAsB,GAAG,gBAAgB,CAAC;IACjD,MAAM,CAAC,2BAA2B,GAAG,yBAAyB,CAAC;IAE/D,MAAM,CAAC,WAAW;QAC1B,OAAO,OAAO,CAAC;IACjB,CAAC;IAES,MAAM,CAAC,eAAe;QAC9B,OAAO,+BAA+B,CAAC;IACzC,CAAC;IAES,MAAM,CAAC,oBAAoB;QACnC,OAAO;YACL,GAAG,KAAK,CAAC,oBAAoB,EAAE;YAC/B,UAAU,EAAE,CAAC,GAAG,EAAE,CAAC;SACpB,CAAC;IACJ,CAAC;IAES,MAAM,CAAC,yBAAyB;QACxC,MAAM,iBAAiB,GAAI,IAAI,CAAC,IAAY,EAAE,iBAAiB,CAAC;QAChE,MAAM,MAAM,GAAG,iBAAiB,EAAE,MAAM,CAAC;QACzC,MAAM,MAAM,GAAI,IAAI,CAAC,IAAY,EAAE,MAAM,CAAC;QAC1C,IAAI,CAAC,MAAM,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,iCAAiC,EAAE,CAAC;YACnE,OAAO;QACT,CAAC;QAED,MAAM,sBAAsB,GAAG,MAAM,CAAC,cAAc,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;QACnE,IAAI,OAAO,sBAAsB,KAAK,UAAU,EAAE,CAAC;YACjD,OAAO;QACT,CAAC;QAED,MAAM,CAAC,cAAc,GAAG,KAAK,EAAE,MAAW,EAAE,EAAE;YAC5C,MAAM,UAAU,GAAG,MAAM,sBAAsB,CAAC,MAAM,CAAC,CAAC;YACxD,IAAI,UAAU,EAAE,CAAC;gBACf,OAAO,IAAI,CAAC;YACd,CAAC;YAED,MAAM,eAAe,GAAG,MAAM,CAAC,cAAc,EAAE,CAAC,MAAM,CAAC;YACvD,IAAI,eAAe,IAAI,IAAI,CAAC,cAAc,EAAE,CAAC;gBAC3C,gBAAgB,CAAC,GAAG,CAClB,iBAAiB,IAAI,CAAC,qBAAqB,CAAC,MAAM,CAAC,sBAAsB,IAAI,CAAC,cAAc,UAAU,CACvG,CAAC;gBACF,OAAO,IAAI,CAAC;YACd,CAAC;YAED,OAAO,KAAK,CAAC;QACf,CAAC,CAAC;QAEF,MAAM,CAAC,iCAAiC,GAAG,IAAI,CAAC;IAClD,CAAC","sourcesContent":["import { tcp } from '@libp2p/tcp';\nimport {\n createLightNode,\n type CreateLibp2pOptions,\n} from '@waku/sdk';\nimport { BroadcasterDebug } from '../utils/broadcaster-debug.js';\nimport { enrTree, wakuDnsDiscovery, wakuPeerExchangeDiscovery } from '@waku/discovery';\nimport { WakuBroadcasterPeerDiscoveryCoreBase } from './waku-broadcaster-peer-discovery-core-base.js';\nimport { WAKU_RAILGUN_DEFAULT_PEERS_NODE } from '../models/constants.js';\n\nexport class WakuBroadcasterWakuCore extends WakuBroadcasterPeerDiscoveryCoreBase {\n protected static createWakuNode = createLightNode;\n protected static createDnsPeerDiscovery = wakuDnsDiscovery;\n protected static createPeerExchangeDiscovery = wakuPeerExchangeDiscovery;\n\n protected static getEnrTrees() {\n return enrTree;\n }\n\n protected static getDefaultPeers(): string[] {\n return WAKU_RAILGUN_DEFAULT_PEERS_NODE;\n }\n\n protected static getBaseLibp2pOptions(): CreateLibp2pOptions {\n return {\n ...super.getBaseLibp2pOptions(),\n transports: [tcp()],\n };\n }\n\n protected static applyConnectionLimitGuard() {\n const connectionManager = (this.waku as any)?.connectionManager;\n const dialer = connectionManager?.dialer;\n const libp2p = (this.waku as any)?.libp2p;\n if (!dialer || !libp2p || dialer.__wakuConnectionLimitGuardApplied) {\n return;\n }\n\n const originalShouldSkipPeer = dialer.shouldSkipPeer?.bind(dialer);\n if (typeof originalShouldSkipPeer !== 'function') {\n return;\n }\n\n dialer.shouldSkipPeer = async (peerId: any) => {\n const shouldSkip = await originalShouldSkipPeer(peerId);\n if (shouldSkip) {\n return true;\n }\n\n const connectionCount = libp2p.getConnections().length;\n if (connectionCount >= this.maxConnections) {\n BroadcasterDebug.log(\n `Skipping peer ${this.formatDiscoveryPeerId(peerId)} - max connections ${this.maxConnections} reached`,\n );\n return true;\n }\n\n return false;\n };\n\n dialer.__wakuConnectionLimitGuardApplied = true;\n }\n}\n"]}
@@ -0,0 +1,62 @@
1
+ type HealthcheckConnection = {
2
+ remotePeer?: {
3
+ toString?: () => string;
4
+ } | string;
5
+ };
6
+ type HealthcheckPeer = {
7
+ id?: {
8
+ toString?: () => string;
9
+ } | string;
10
+ protocols?: string[];
11
+ tags?: Map<string, unknown>;
12
+ };
13
+ export declare const getWakuHealthSnapshot: (options: {
14
+ hasError: boolean;
15
+ peerDiscoveryTimeout: number;
16
+ restartCount: number;
17
+ waku?: {
18
+ isStarted?: () => boolean;
19
+ libp2p?: {
20
+ getConnections?: () => HealthcheckConnection[];
21
+ peerStore?: {
22
+ all?: () => Promise<HealthcheckPeer[]>;
23
+ };
24
+ };
25
+ };
26
+ }) => Promise<{
27
+ hasWaku: boolean;
28
+ isStarted: boolean;
29
+ hasError: boolean;
30
+ restartCount: number;
31
+ peerDiscoveryTimeout: number;
32
+ routing: import("../models/constants.js").WakuShardInfo;
33
+ networkConfig: import("../models/constants.js").WakuNetworkConfig;
34
+ configuredPeers: {
35
+ useDNSDiscovery: boolean;
36
+ dnsDiscoveryUrls: string[];
37
+ bootstrapPeers: string[];
38
+ storePeers: string[];
39
+ };
40
+ connections: {
41
+ count: number;
42
+ peers: string[];
43
+ };
44
+ discovery: {
45
+ connectedPeerDetails: {
46
+ peerId: string;
47
+ supportsPeerExchange: boolean;
48
+ protocols: string[];
49
+ tags: string[];
50
+ }[];
51
+ peerStore: {
52
+ count: number;
53
+ bootstrapCount: number;
54
+ peerExchangeCount: number;
55
+ bootstrapPeers: string[];
56
+ peerExchangePeers: string[];
57
+ connectedPeersSupportingPeerExchange: string[];
58
+ };
59
+ };
60
+ contentTopics: string[];
61
+ }>;
62
+ export {};
@@ -0,0 +1,88 @@
1
+ import { BroadcasterConfig } from '../models/broadcaster-config.js';
2
+ import { WakuObservers } from './waku-observers.js';
3
+ import { isDefined } from '../utils/is-defined.js';
4
+ const formatConnectionPeerId = (connection) => {
5
+ const peer = connection.remotePeer;
6
+ if (typeof peer === 'string') {
7
+ return peer;
8
+ }
9
+ if (peer && typeof peer.toString === 'function') {
10
+ return peer.toString();
11
+ }
12
+ return 'unknown-peer';
13
+ };
14
+ const formatPeerId = (peer) => {
15
+ const peerId = peer.id;
16
+ if (typeof peerId === 'string') {
17
+ return peerId;
18
+ }
19
+ if (peerId && typeof peerId.toString === 'function') {
20
+ return peerId.toString();
21
+ }
22
+ return 'unknown-peer';
23
+ };
24
+ const hasPeerExchangeProtocol = (protocols) => (protocols ?? []).includes('/vac/waku/peer-exchange/2.0.0-alpha1');
25
+ export const getWakuHealthSnapshot = async (options) => {
26
+ const connections = options.waku?.libp2p?.getConnections?.() ?? [];
27
+ const connectedPeerIds = new Set(connections.map(connection => formatConnectionPeerId(connection)));
28
+ const peerStore = options.waku?.libp2p?.peerStore;
29
+ const storedPeers = peerStore?.all
30
+ ? await peerStore.all().catch(() => [])
31
+ : [];
32
+ const bootstrapPeerIds = [];
33
+ const peerExchangePeerIds = [];
34
+ const connectedPeerDetails = [];
35
+ for (const peer of storedPeers) {
36
+ const peerId = formatPeerId(peer);
37
+ const tags = Array.from(peer.tags?.keys?.() ?? []);
38
+ const protocols = peer.protocols ?? [];
39
+ if (tags.includes('bootstrap')) {
40
+ bootstrapPeerIds.push(peerId);
41
+ }
42
+ if (tags.includes('peer-exchange')) {
43
+ peerExchangePeerIds.push(peerId);
44
+ }
45
+ if (connectedPeerIds.has(peerId)) {
46
+ connectedPeerDetails.push({
47
+ peerId,
48
+ supportsPeerExchange: hasPeerExchangeProtocol(protocols),
49
+ protocols,
50
+ tags,
51
+ });
52
+ }
53
+ }
54
+ return {
55
+ hasWaku: isDefined(options.waku),
56
+ isStarted: options.waku?.isStarted?.() ?? false,
57
+ hasError: options.hasError,
58
+ restartCount: options.restartCount,
59
+ peerDiscoveryTimeout: options.peerDiscoveryTimeout,
60
+ routing: BroadcasterConfig.getWakuRoutingInfo(),
61
+ networkConfig: BroadcasterConfig.getWakuNetworkConfig(),
62
+ configuredPeers: {
63
+ useDNSDiscovery: BroadcasterConfig.useDNSDiscovery,
64
+ dnsDiscoveryUrls: BroadcasterConfig.customDNS?.enrTreePeers ?? [],
65
+ bootstrapPeers: BroadcasterConfig.additionalDirectPeers,
66
+ storePeers: BroadcasterConfig.storePeers,
67
+ },
68
+ connections: {
69
+ count: connections.length,
70
+ peers: connections.map(connection => formatConnectionPeerId(connection)),
71
+ },
72
+ discovery: {
73
+ connectedPeerDetails,
74
+ peerStore: {
75
+ count: storedPeers.length,
76
+ bootstrapCount: bootstrapPeerIds.length,
77
+ peerExchangeCount: peerExchangePeerIds.length,
78
+ bootstrapPeers: bootstrapPeerIds,
79
+ peerExchangePeers: peerExchangePeerIds,
80
+ connectedPeersSupportingPeerExchange: connectedPeerDetails
81
+ .filter(peer => peer.supportsPeerExchange)
82
+ .map(peer => peer.peerId),
83
+ },
84
+ },
85
+ contentTopics: WakuObservers.getCurrentContentTopics(),
86
+ };
87
+ };
88
+ //# sourceMappingURL=waku-healthcheck.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"waku-healthcheck.js","sourceRoot":"","sources":["../../src/waku/waku-healthcheck.ts"],"names":[],"mappings":"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","sourcesContent":["import { BroadcasterConfig } from '../models/broadcaster-config.js';\nimport { WakuObservers } from './waku-observers.js';\nimport { isDefined } from '../utils/is-defined.js';\n\ntype HealthcheckConnection = {\n remotePeer?: {\n toString?: () => string;\n } | string;\n};\n\ntype HealthcheckPeer = {\n id?: {\n toString?: () => string;\n } | string;\n protocols?: string[];\n tags?: Map<string, unknown>;\n};\n\nconst formatConnectionPeerId = (connection: HealthcheckConnection): string => {\n const peer = connection.remotePeer;\n if (typeof peer === 'string') {\n return peer;\n }\n if (peer && typeof peer.toString === 'function') {\n return peer.toString();\n }\n return 'unknown-peer';\n};\n\nconst formatPeerId = (peer: HealthcheckPeer): string => {\n const peerId = peer.id;\n if (typeof peerId === 'string') {\n return peerId;\n }\n if (peerId && typeof peerId.toString === 'function') {\n return peerId.toString();\n }\n return 'unknown-peer';\n};\n\nconst hasPeerExchangeProtocol = (protocols?: string[]): boolean =>\n (protocols ?? []).includes('/vac/waku/peer-exchange/2.0.0-alpha1');\n\nexport const getWakuHealthSnapshot = async (options: {\n hasError: boolean;\n peerDiscoveryTimeout: number;\n restartCount: number;\n waku?: {\n isStarted?: () => boolean;\n libp2p?: {\n getConnections?: () => HealthcheckConnection[];\n peerStore?: {\n all?: () => Promise<HealthcheckPeer[]>;\n };\n };\n };\n}) => {\n const connections = options.waku?.libp2p?.getConnections?.() ?? [];\n const connectedPeerIds = new Set(\n connections.map(connection => formatConnectionPeerId(connection)),\n );\n const peerStore = options.waku?.libp2p?.peerStore;\n const storedPeers: HealthcheckPeer[] = peerStore?.all\n ? await peerStore.all().catch(() => [])\n : [];\n\n const bootstrapPeerIds: string[] = [];\n const peerExchangePeerIds: string[] = [];\n const connectedPeerDetails: {\n peerId: string;\n supportsPeerExchange: boolean;\n protocols: string[];\n tags: string[];\n }[] = [];\n\n for (const peer of storedPeers) {\n const peerId = formatPeerId(peer);\n const tags = Array.from(peer.tags?.keys?.() ?? []);\n const protocols = peer.protocols ?? [];\n\n if (tags.includes('bootstrap')) {\n bootstrapPeerIds.push(peerId);\n }\n if (tags.includes('peer-exchange')) {\n peerExchangePeerIds.push(peerId);\n }\n if (connectedPeerIds.has(peerId)) {\n connectedPeerDetails.push({\n peerId,\n supportsPeerExchange: hasPeerExchangeProtocol(protocols),\n protocols,\n tags,\n });\n }\n }\n\n return {\n hasWaku: isDefined(options.waku),\n isStarted: options.waku?.isStarted?.() ?? false,\n hasError: options.hasError,\n restartCount: options.restartCount,\n peerDiscoveryTimeout: options.peerDiscoveryTimeout,\n routing: BroadcasterConfig.getWakuRoutingInfo(),\n networkConfig: BroadcasterConfig.getWakuNetworkConfig(),\n configuredPeers: {\n useDNSDiscovery: BroadcasterConfig.useDNSDiscovery,\n dnsDiscoveryUrls: BroadcasterConfig.customDNS?.enrTreePeers ?? [],\n bootstrapPeers: BroadcasterConfig.additionalDirectPeers,\n storePeers: BroadcasterConfig.storePeers,\n },\n connections: {\n count: connections.length,\n peers: connections.map(connection => formatConnectionPeerId(connection)),\n },\n discovery: {\n connectedPeerDetails,\n peerStore: {\n count: storedPeers.length,\n bootstrapCount: bootstrapPeerIds.length,\n peerExchangeCount: peerExchangePeerIds.length,\n bootstrapPeers: bootstrapPeerIds,\n peerExchangePeers: peerExchangePeerIds,\n connectedPeersSupportingPeerExchange: connectedPeerDetails\n .filter(peer => peer.supportsPeerExchange)\n .map(peer => peer.peerId),\n },\n },\n contentTopics: WakuObservers.getCurrentContentTopics(),\n };\n};\n"]}
@@ -7,6 +7,7 @@ export declare class WakuObservers {
7
7
  private static messageCache;
8
8
  private static observedMessages;
9
9
  private static MAX_CACHE_SIZE;
10
+ private static resetMessageHistory;
10
11
  private static getMessageId;
11
12
  private static wrapCallbackWithCache;
12
13
  static setObserversForChain: (waku: Optional<LightNode>, chain: Chain) => Promise<void>;
@@ -5,8 +5,8 @@ import { handleBroadcasterFeesMessage } from '../fees/handle-fees-message.js';
5
5
  import { BroadcasterTransactResponse } from '../transact/broadcaster-transact-response.js';
6
6
  import { BroadcasterDebug } from '../utils/broadcaster-debug.js';
7
7
  import { isDefined } from '../utils/is-defined.js';
8
- import { WAKU_RAILGUN_DEFAULT_SHARD } from '../models/constants.js';
9
8
  import { bytesToHex } from '../utils/conversion.js';
9
+ import { BroadcasterConfig } from '../models/broadcaster-config.js';
10
10
  export class WakuObservers {
11
11
  static currentChain;
12
12
  static currentContentTopics = [];
@@ -14,6 +14,10 @@ export class WakuObservers {
14
14
  static messageCache = new Set();
15
15
  static observedMessages = [];
16
16
  static MAX_CACHE_SIZE = 5000;
17
+ static resetMessageHistory() {
18
+ this.messageCache = new Set();
19
+ this.observedMessages = [];
20
+ }
17
21
  static getMessageId(message) {
18
22
  const timestamp = message.timestamp ? message.timestamp.getTime() : 0;
19
23
  const payload = message.payload ? bytesToHex(message.payload) : '';
@@ -59,6 +63,7 @@ export class WakuObservers {
59
63
  };
60
64
  static resetCurrentChain = () => {
61
65
  this.currentChain = undefined;
66
+ this.resetMessageHistory();
62
67
  };
63
68
  static checkSubscriptionsHealth = async (waku) => {
64
69
  BroadcasterDebug.log(`WAKU Health Status: ${waku?.health.getHealthStatus()}`);
@@ -76,6 +81,7 @@ export class WakuObservers {
76
81
  }
77
82
  this.currentSubscriptions = [];
78
83
  this.currentContentTopics = [];
84
+ this.resetMessageHistory();
79
85
  }
80
86
  static removeAllObservers = async (waku) => {
81
87
  await this.unsubscribe(waku);
@@ -83,8 +89,8 @@ export class WakuObservers {
83
89
  static getDecodersForChain = (chain) => {
84
90
  const contentTopicFees = contentTopics.fees(chain);
85
91
  const contentTopicTransactResponse = contentTopics.transactResponse(chain);
86
- const feesDecoder = createDecoder(contentTopicFees, WAKU_RAILGUN_DEFAULT_SHARD);
87
- const transactResponseDecoder = createDecoder(contentTopicTransactResponse, WAKU_RAILGUN_DEFAULT_SHARD);
92
+ const feesDecoder = createDecoder(contentTopicFees, BroadcasterConfig.getWakuRoutingInfo());
93
+ const transactResponseDecoder = createDecoder(contentTopicTransactResponse, BroadcasterConfig.getWakuRoutingInfo());
88
94
  const feesCallback = this.wrapCallbackWithCache((message) => handleBroadcasterFeesMessage(chain, message, contentTopicFees));
89
95
  const transactResponseCallback = this.wrapCallbackWithCache((message) => BroadcasterTransactResponse.handleBroadcasterTransactionResponseMessage(message));
90
96
  return [
@@ -120,7 +126,7 @@ export class WakuObservers {
120
126
  return;
121
127
  }
122
128
  const transportTopic = contentTopics.encrypted(topic);
123
- const decoder = createDecoder(transportTopic, WAKU_RAILGUN_DEFAULT_SHARD);
129
+ const decoder = createDecoder(transportTopic, BroadcasterConfig.getWakuRoutingInfo());
124
130
  const wrappedCallback = this.wrapCallbackWithCache(callback);
125
131
  const params = {
126
132
  topic: transportTopic,
@@ -1 +1 @@
1
- {"version":3,"file":"waku-observers.js","sourceRoot":"","sources":["../../src/waku/waku-observers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAS,aAAa,EAAE,KAAK,EAAE,MAAM,kCAAkC,CAAC;AAC/E,OAAO,EACL,aAAa,GAKd,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,4BAA4B,EAAE,MAAM,gCAAgC,CAAC;AAC9E,OAAO,EAAE,2BAA2B,EAAE,MAAM,8CAA8C,CAAC;AAC3F,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AACjE,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACnD,OAAO,EAAE,0BAA0B,EAAE,MAAM,wBAAwB,CAAC;AACpE,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAYpD,MAAM,OAAO,aAAa;IAChB,MAAM,CAAC,YAAY,CAAkB;IACrC,MAAM,CAAC,oBAAoB,GAAa,EAAE,CAAC;IAC3C,MAAM,CAAC,oBAAoB,GAAqC,EAAE,CAAC;IACnE,MAAM,CAAC,YAAY,GAAgB,IAAI,GAAG,EAAE,CAAC;IAC7C,MAAM,CAAC,gBAAgB,GAAsB,EAAE,CAAC;IAChD,MAAM,CAAC,cAAc,GAAG,IAAI,CAAC;IAE7B,MAAM,CAAC,YAAY,CAAC,OAAiB;QAC3C,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;QACtE,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,UAAU,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QACnE,OAAO,GAAG,SAAS,IAAI,OAAO,EAAE,CAAC;IACnC,CAAC;IAEO,MAAM,CAAC,qBAAqB,CAClC,QAAqC;QAErC,OAAO,CAAC,OAAiB,EAAE,EAAE;YAC3B,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;gBACrB,OAAO;YACT,CAAC;YACD,MAAM,SAAS,GAAG,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC;YAC7C,IAAI,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC;gBACrC,OAAO;YACT,CAAC;YACD,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;YACjC,IAAI,IAAI,CAAC,YAAY,CAAC,IAAI,GAAG,IAAI,CAAC,cAAc,EAAE,CAAC;gBACjD,MAAM,KAAK,GAAG,IAAI,CAAC,YAAY,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC;gBACtD,IAAI,KAAK,EAAE,CAAC;oBACV,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;gBAClC,CAAC;YACH,CAAC;YACD,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,OAA0B,CAAC,CAAC;YACvD,IAAI,IAAI,CAAC,gBAAgB,CAAC,MAAM,GAAG,IAAI,CAAC,cAAc,EAAE,CAAC;gBACvD,IAAI,CAAC,gBAAgB,CAAC,KAAK,EAAE,CAAC;YAChC,CAAC;YACD,QAAQ,CAAC,OAAO,CAAC,CAAC;QACpB,CAAC,CAAC;IACJ,CAAC;IAED,MAAM,CAAC,oBAAoB,GAAG,KAAK,EACjC,IAAyB,EACzB,KAAY,EACZ,EAAE;QACF,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,OAAO;QACT,CAAC;QACD,IACE,aAAa,CAAC,YAAY;YAC1B,aAAa,CAAC,aAAa,CAAC,YAAY,EAAE,KAAK,CAAC,EAChD,CAAC;YACD,OAAO;QACT,CAAC;QACD,gBAAgB,CAAC,GAAG,CAClB,iCAAiC,KAAK,CAAC,IAAI,IAAI,KAAK,CAAC,EAAE,EAAE,CAC1D,CAAC;QACF,aAAa,CAAC,YAAY,GAAG,KAAK,CAAC;QACnC,MAAM,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,CAAC;QAEpC,gBAAgB,CAAC,GAAG,CAAC,uBAAuB,CAAC,CAAC;QAC9C,MAAM,IAAI,CAAC,iBAAiB,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QAC1C,gBAAgB,CAAC,GAAG,CAClB,uCAAuC,KAAK,CAAC,IAAI,IAAI,KAAK,CAAC,EAAE,EAAE,CAChE,CAAC;IACJ,CAAC,CAAC;IAEF,MAAM,CAAC,iBAAiB,GAAG,GAAG,EAAE;QAC9B,IAAI,CAAC,YAAY,GAAG,SAAS,CAAC;IAChC,CAAC,CAAC;IAEF,MAAM,CAAC,wBAAwB,GAAG,KAAK,EAAE,IAAyB,EAAE,EAAE;QACpE,gBAAgB,CAAC,GAAG,CAElB,uBAAuB,IAAI,EAAE,MAAM,CAAC,eAAe,EAAE,EAAE,CACxD,CAAC;QACF,IAAI,SAAS,CAAC,IAAI,CAAC,oBAAoB,CAAC,EAAE,CAAC;YACzC,IAAI,IAAI,CAAC,oBAAoB,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBAC3C,gBAAgB,CAAC,GAAG,CAAC,0BAA0B,CAAC,CAAC;YAEnD,CAAC;QACH,CAAC;QACD,MAAM,KAAK,CAAC,EAAE,GAAG,IAAI,CAAC,CAAC;QACvB,IAAI,CAAC,wBAAwB,CAAC,IAAI,CAAC,CAAC;IACtC,CAAC,CAAC;IAEF,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,IAAyB;QAChD,IAAI,SAAS,CAAC,IAAI,CAAC,IAAI,SAAS,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,SAAS,CAAC,IAAI,CAAC,oBAAoB,CAAC,EAAE,CAAC;YACvF,IAAI,CAAC,MAAM,CAAC,cAAc,EAAE,CAAA;QAC9B,CAAC;QACD,IAAI,CAAC,oBAAoB,GAAG,EAAE,CAAC;QAC/B,IAAI,CAAC,oBAAoB,GAAG,EAAE,CAAC;IACjC,CAAC;IAEO,MAAM,CAAC,kBAAkB,GAAG,KAAK,EAAE,IAAyB,EAAE,EAAE;QACtE,MAAM,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;IAC/B,CAAC,CAAC;IAEM,MAAM,CAAC,mBAAmB,GAAG,CAAC,KAAY,EAAE,EAAE;QACpD,MAAM,gBAAgB,GAAG,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACnD,MAAM,4BAA4B,GAAG,aAAa,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC;QAE3E,MAAM,WAAW,GAAG,aAAa,CAC/B,gBAAgB,EAChB,0BAA0B,CAC3B,CAAC;QACF,MAAM,uBAAuB,GAAG,aAAa,CAC3C,4BAA4B,EAC5B,0BAA0B,CAC3B,CAAC;QAEF,MAAM,YAAY,GAAG,IAAI,CAAC,qBAAqB,CAAC,CAAC,OAAiB,EAAE,EAAE,CACpE,4BAA4B,CAAC,KAAK,EAAE,OAAO,EAAE,gBAAgB,CAAC,CAAC,CAAC;QAClE,MAAM,wBAAwB,GAAG,IAAI,CAAC,qBAAqB,CAAC,CAAC,OAAiB,EAAE,EAAE,CAChF,2BAA2B,CAAC,2CAA2C,CACrE,OAAO,CACR,CAAC,CAAC;QAEL,OAAO;YACL;gBACE,KAAK,EAAE,gBAAgB;gBACvB,OAAO,EAAE,WAAW;gBACpB,QAAQ,EAAE,YAAY;aACvB;YACD;gBACE,KAAK,EAAE,4BAA4B;gBACnC,OAAO,EAAE,uBAAuB;gBAChC,QAAQ,EAAE,wBAAwB;aACnC;SACF,CAAC;IACJ,CAAC,CAAC;IAEM,MAAM,CAAC,iBAAiB,GAAG,KAAK,EAAE,IAAe,EAAE,KAAY,EAAE,EAAE;QACzE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;YAC5B,OAAO;QACT,CAAC;QAED,MAAM,IAAI,CAAC,gBAAgB,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,KAAK,CAC5C,GAAG,CAAC,EAAE;YACJ,gBAAgB,CAAC,GAAG,CAAC,2BAA2B,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;YAC/D,OAAO,SAAS,CAAC;QACnB,CAAC,CACF,CAAC;QAEF,MAAM,oBAAoB,GAAG,aAAa,CAAC,uBAAuB,EAAE,CAAC;QACrE,gBAAgB,CAAC,GAAG,CAAC,sBAAsB,CAAC,CAAC;QAC7C,KAAK,MAAM,QAAQ,IAAI,oBAAoB,EAAE,CAAC;YAC5C,gBAAgB,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QACjC,CAAC;IACH,CAAC,CAAC;IAEF,MAAM,CAAC,KAAK,CAAC,wBAAwB,CACnC,IAAyB,EACzB,KAAa,EACb,QAAgC;QAEhC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC;YACrB,gBAAgB,CAAC,GAAG,CAClB,2DAA2D,CAC5D,CAAC;YACF,OAAO;QACT,CAAC;QACD,MAAM,cAAc,GAAG,aAAa,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;QACtD,MAAM,OAAO,GAAG,aAAa,CAAC,cAAc,EAAE,0BAA0B,CAAC,CAAC;QAC1E,MAAM,eAAe,GAAG,IAAI,CAAC,qBAAqB,CAAC,QAAQ,CAAC,CAAC;QAC7D,MAAM,MAAM,GAAuB;YACjC,KAAK,EAAE,cAAc;YACrB,OAAO;YACP,QAAQ,EAAE,eAAe;SAC1B,CAAC;QACF,MAAM,IAAI,CAAC,MAAM,CAAC,SAAS,CACzB,OAAO,EACP,eAAe,CAChB,CAAC;QACF,IAAI,CAAC,oBAAoB,EAAE,IAAI,CAAC;YAC9B,MAAM;SACP,CAAC,CAAC;QACH,aAAa,CAAC,oBAAoB,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;IAC1D,CAAC;IAEO,MAAM,CAAC,KAAK,CAAC,gBAAgB,CACnC,KAAsB,EACtB,IAAyB;QAEzB,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC;YAC1C,gBAAgB,CAAC,GAAG,CAAC,4CAA4C,CAAC,CAAC;YACnE,OAAO;QACT,CAAC;QACD,MAAM,kBAAkB,GAAG,IAAI,CAAC,mBAAmB,CAAC,KAAK,CAAC,CAAC;QAC3D,MAAM,MAAM,GAAG,kBAAkB,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAC9D,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,CAC7B,KAAK,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,oBAAoB,CAAC,QAAQ,CAAC,KAAK,CAAC,CACpD,CAAC;QACF,IAAI,CAAC,oBAAoB,CAAC,IAAI,CAAC,GAAG,SAAS,CAAC,CAAC;QAC7C,KAAK,MAAM,MAAM,IAAI,kBAAkB,EAAE,CAAC;YACxC,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,GAAG,MAAM,CAAC;YACrC,MAAM,IAAI,CAAC,MAAM,CAAC,SAAS,CACzB,OAAO,EACP,QAAQ,CACT,CAAC;YACF,IAAI,CAAC,oBAAoB,EAAE,IAAI,CAAC;gBAC9B,MAAM;aACP,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,MAAM,CAAC,uBAAuB;QAC5B,OAAO,aAAa,CAAC,oBAAoB,CAAC;IAC5C,CAAC;IAED,MAAM,CAAC,cAAc,CAAC,KAAa;QACjC,IAAI,aAA0C,CAAC;QAC/C,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,gBAAgB,EAAE,CAAC;YACxC,IAAI,GAAG,CAAC,YAAY,KAAK,KAAK,EAAE,CAAC;gBAC/B,IAAI,CAAC,aAAa,EAAE,CAAC;oBACnB,aAAa,GAAG,GAAG,CAAC;oBACpB,SAAS;gBACX,CAAC;gBACD,MAAM,OAAO,GAAG,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;gBAC5D,MAAM,UAAU,GAAG,aAAa,CAAC,SAAS,CAAC,CAAC,CAAC,aAAa,CAAC,SAAS,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;gBACnF,IAAI,OAAO,GAAG,UAAU,EAAE,CAAC;oBACzB,aAAa,GAAG,GAAG,CAAC;gBACtB,CAAC;YACH,CAAC;QACH,CAAC;QACD,OAAO,aAAa,CAAC;IACvB,CAAC;IAED,MAAM,CAAC,mBAAmB,CAAC,KAAa;QACtC,MAAM,YAAY,GAAG,IAAI,CAAC,oBAAoB,EAAE,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,KAAK,KAAK,CAAC,CAAC;QACxF,OAAO,YAAY,EAAE,MAAM,CAAC,QAAQ,CAAC;IACvC,CAAC","sourcesContent":["import { Chain, compareChains, delay } from '@railgun-community/shared-models';\nimport {\n createDecoder,\n type IMessage,\n type IDecoder,\n type LightNode,\n type IDecodedMessage,\n} from '@waku/sdk';\nimport { contentTopics } from './waku-topics.js';\nimport { handleBroadcasterFeesMessage } from '../fees/handle-fees-message.js';\nimport { BroadcasterTransactResponse } from '../transact/broadcaster-transact-response.js';\nimport { BroadcasterDebug } from '../utils/broadcaster-debug.js';\nimport { isDefined } from '../utils/is-defined.js';\nimport { WAKU_RAILGUN_DEFAULT_SHARD } from '../models/constants.js';\nimport { bytesToHex } from '../utils/conversion.js';\n\ntype SubscriptionParams = {\n topic: string;\n decoder: IDecoder<any> | IDecoder<any>[];\n callback: (message: any) => void;\n};\n\ntype ActiveSubscription = {\n params: SubscriptionParams;\n};\n\nexport class WakuObservers {\n private static currentChain: Optional<Chain>;\n private static currentContentTopics: string[] = [];\n private static currentSubscriptions: ActiveSubscription[] | undefined = [];\n private static messageCache: Set<string> = new Set();\n private static observedMessages: IDecodedMessage[] = [];\n private static MAX_CACHE_SIZE = 5000;\n\n private static getMessageId(message: IMessage): string {\n const timestamp = message.timestamp ? message.timestamp.getTime() : 0;\n const payload = message.payload ? bytesToHex(message.payload) : '';\n return `${timestamp}-${payload}`;\n }\n\n private static wrapCallbackWithCache(\n callback: (message: IMessage) => void,\n ): (message: IMessage) => void {\n return (message: IMessage) => {\n if (!message.payload) {\n return;\n }\n const messageId = this.getMessageId(message);\n if (this.messageCache.has(messageId)) {\n return;\n }\n this.messageCache.add(messageId);\n if (this.messageCache.size > this.MAX_CACHE_SIZE) {\n const first = this.messageCache.values().next().value;\n if (first) {\n this.messageCache.delete(first);\n }\n }\n this.observedMessages.push(message as IDecodedMessage);\n if (this.observedMessages.length > this.MAX_CACHE_SIZE) {\n this.observedMessages.shift();\n }\n callback(message);\n };\n }\n\n static setObserversForChain = async (\n waku: Optional<LightNode>,\n chain: Chain,\n ) => {\n if (!waku) {\n return;\n }\n if (\n WakuObservers.currentChain &&\n compareChains(WakuObservers.currentChain, chain)\n ) {\n return;\n }\n BroadcasterDebug.log(\n `Add Waku observers for chain: ${chain.type}:${chain.id}`,\n );\n WakuObservers.currentChain = chain;\n await this.removeAllObservers(waku);\n\n BroadcasterDebug.log('Removed all observers');\n await this.addChainObservers(waku, chain);\n BroadcasterDebug.log(\n `Waku listening for events on chain: ${chain.type}:${chain.id}`,\n );\n };\n\n static resetCurrentChain = () => {\n this.currentChain = undefined;\n };\n\n static checkSubscriptionsHealth = async (waku: Optional<LightNode>) => {\n BroadcasterDebug.log(\n // @ts-ignore\n `WAKU Health Status: ${waku?.health.getHealthStatus()}`,\n );\n if (isDefined(this.currentSubscriptions)) {\n if (this.currentSubscriptions.length === 0) {\n BroadcasterDebug.log('No subscriptions to ping');\n // throw new Error('No subscriptions to ping');\n }\n }\n await delay(15 * 1000);\n this.checkSubscriptionsHealth(waku);\n };\n\n static async unsubscribe(waku: Optional<LightNode>) {\n if (isDefined(waku) && isDefined(waku?.filter) && isDefined(this.currentSubscriptions)) {\n waku.filter.unsubscribeAll()\n }\n this.currentSubscriptions = [];\n this.currentContentTopics = [];\n }\n\n private static removeAllObservers = async (waku: Optional<LightNode>) => {\n await this.unsubscribe(waku);\n };\n\n private static getDecodersForChain = (chain: Chain) => {\n const contentTopicFees = contentTopics.fees(chain);\n const contentTopicTransactResponse = contentTopics.transactResponse(chain);\n\n const feesDecoder = createDecoder(\n contentTopicFees,\n WAKU_RAILGUN_DEFAULT_SHARD,\n );\n const transactResponseDecoder = createDecoder(\n contentTopicTransactResponse,\n WAKU_RAILGUN_DEFAULT_SHARD,\n );\n\n const feesCallback = this.wrapCallbackWithCache((message: IMessage) =>\n handleBroadcasterFeesMessage(chain, message, contentTopicFees));\n const transactResponseCallback = this.wrapCallbackWithCache((message: IMessage) =>\n BroadcasterTransactResponse.handleBroadcasterTransactionResponseMessage(\n message,\n ));\n\n return [\n {\n topic: contentTopicFees,\n decoder: feesDecoder,\n callback: feesCallback,\n },\n {\n topic: contentTopicTransactResponse,\n decoder: transactResponseDecoder,\n callback: transactResponseCallback,\n },\n ];\n };\n\n private static addChainObservers = async (waku: LightNode, chain: Chain) => {\n if (!isDefined(waku.filter)) {\n return;\n }\n\n await this.addSubscriptions(chain, waku).catch(\n err => {\n BroadcasterDebug.log(`Error adding Observers. ${err.message}`);\n return undefined;\n },\n );\n // Log current list of observers\n const currentContentTopics = WakuObservers.getCurrentContentTopics();\n BroadcasterDebug.log('Waku content topics:');\n for (const observer of currentContentTopics) {\n BroadcasterDebug.log(observer);\n }\n };\n\n static async addTransportSubscription(\n waku: Optional<LightNode>,\n topic: string,\n callback: (message: any) => void,\n ): Promise<void> {\n if (!isDefined(waku)) {\n BroadcasterDebug.log(\n 'No waku instance found, Transport Subscription not added.',\n );\n return;\n }\n const transportTopic = contentTopics.encrypted(topic);\n const decoder = createDecoder(transportTopic, WAKU_RAILGUN_DEFAULT_SHARD);\n const wrappedCallback = this.wrapCallbackWithCache(callback);\n const params: SubscriptionParams = {\n topic: transportTopic,\n decoder,\n callback: wrappedCallback,\n };\n await waku.filter.subscribe(\n decoder,\n wrappedCallback,\n );\n this.currentSubscriptions?.push({\n params,\n });\n WakuObservers.currentContentTopics.push(transportTopic);\n }\n\n private static async addSubscriptions(\n chain: Optional<Chain>,\n waku: Optional<LightNode>,\n ) {\n if (!isDefined(chain) || !isDefined(waku)) {\n BroadcasterDebug.log('AddSubscription: No Waku or Chain defined.');\n return;\n }\n const subscriptionParams = this.getDecodersForChain(chain);\n const topics = subscriptionParams.map(params => params.topic);\n const newTopics = topics.filter(\n topic => !this.currentContentTopics.includes(topic),\n );\n this.currentContentTopics.push(...newTopics);\n for (const params of subscriptionParams) {\n const { decoder, callback } = params;\n await waku.filter.subscribe(\n decoder,\n callback,\n );\n this.currentSubscriptions?.push({\n params,\n });\n }\n }\n\n static getCurrentContentTopics(): string[] {\n return WakuObservers.currentContentTopics;\n }\n\n static getLastMessage(topic: string): IDecodedMessage | undefined {\n let latestMessage: IDecodedMessage | undefined;\n for (const msg of this.observedMessages) {\n if (msg.contentTopic === topic) {\n if (!latestMessage) {\n latestMessage = msg;\n continue;\n }\n const msgTime = msg.timestamp ? msg.timestamp.getTime() : 0;\n const latestTime = latestMessage.timestamp ? latestMessage.timestamp.getTime() : 0;\n if (msgTime > latestTime) {\n latestMessage = msg;\n }\n }\n }\n return latestMessage;\n }\n\n static getCallbackForTopic(topic: string): Optional<(message: any) => void> {\n const subscription = this.currentSubscriptions?.find(sub => sub.params.topic === topic);\n return subscription?.params.callback;\n }\n}\n"]}
1
+ {"version":3,"file":"waku-observers.js","sourceRoot":"","sources":["../../src/waku/waku-observers.ts"],"names":[],"mappings":"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","sourcesContent":["import { Chain, compareChains, delay } from '@railgun-community/shared-models';\nimport {\n createDecoder,\n type IMessage,\n type IDecoder,\n type LightNode,\n type IDecodedMessage,\n} from '@waku/sdk';\nimport { contentTopics } from './waku-topics.js';\nimport { handleBroadcasterFeesMessage } from '../fees/handle-fees-message.js';\nimport { BroadcasterTransactResponse } from '../transact/broadcaster-transact-response.js';\nimport { BroadcasterDebug } from '../utils/broadcaster-debug.js';\nimport { isDefined } from '../utils/is-defined.js';\nimport { bytesToHex } from '../utils/conversion.js';\nimport { BroadcasterConfig } from '../models/broadcaster-config.js';\n\ntype SubscriptionParams = {\n topic: string;\n decoder: IDecoder<any> | IDecoder<any>[];\n callback: (message: any) => void;\n};\n\ntype ActiveSubscription = {\n params: SubscriptionParams;\n};\n\nexport class WakuObservers {\n private static currentChain: Optional<Chain>;\n private static currentContentTopics: string[] = [];\n private static currentSubscriptions: ActiveSubscription[] | undefined = [];\n private static messageCache: Set<string> = new Set();\n private static observedMessages: IDecodedMessage[] = [];\n private static MAX_CACHE_SIZE = 5000;\n\n private static resetMessageHistory() {\n this.messageCache = new Set();\n this.observedMessages = [];\n }\n\n private static getMessageId(message: IMessage): string {\n const timestamp = message.timestamp ? message.timestamp.getTime() : 0;\n const payload = message.payload ? bytesToHex(message.payload) : '';\n return `${timestamp}-${payload}`;\n }\n\n private static wrapCallbackWithCache(\n callback: (message: IMessage) => void,\n ): (message: IMessage) => void {\n return (message: IMessage) => {\n if (!message.payload) {\n return;\n }\n const messageId = this.getMessageId(message);\n if (this.messageCache.has(messageId)) {\n return;\n }\n this.messageCache.add(messageId);\n if (this.messageCache.size > this.MAX_CACHE_SIZE) {\n const first = this.messageCache.values().next().value;\n if (first) {\n this.messageCache.delete(first);\n }\n }\n this.observedMessages.push(message as IDecodedMessage);\n if (this.observedMessages.length > this.MAX_CACHE_SIZE) {\n this.observedMessages.shift();\n }\n callback(message);\n };\n }\n\n static setObserversForChain = async (\n waku: Optional<LightNode>,\n chain: Chain,\n ) => {\n if (!waku) {\n return;\n }\n if (\n WakuObservers.currentChain &&\n compareChains(WakuObservers.currentChain, chain)\n ) {\n return;\n }\n BroadcasterDebug.log(\n `Add Waku observers for chain: ${chain.type}:${chain.id}`,\n );\n WakuObservers.currentChain = chain;\n await this.removeAllObservers(waku);\n\n BroadcasterDebug.log('Removed all observers');\n await this.addChainObservers(waku, chain);\n BroadcasterDebug.log(\n `Waku listening for events on chain: ${chain.type}:${chain.id}`,\n );\n };\n\n static resetCurrentChain = () => {\n this.currentChain = undefined;\n this.resetMessageHistory();\n };\n\n static checkSubscriptionsHealth = async (waku: Optional<LightNode>) => {\n BroadcasterDebug.log(\n // @ts-ignore\n `WAKU Health Status: ${waku?.health.getHealthStatus()}`,\n );\n if (isDefined(this.currentSubscriptions)) {\n if (this.currentSubscriptions.length === 0) {\n BroadcasterDebug.log('No subscriptions to ping');\n // throw new Error('No subscriptions to ping');\n }\n }\n await delay(15 * 1000);\n this.checkSubscriptionsHealth(waku);\n };\n\n static async unsubscribe(waku: Optional<LightNode>) {\n if (isDefined(waku) && isDefined(waku?.filter) && isDefined(this.currentSubscriptions)) {\n waku.filter.unsubscribeAll()\n }\n this.currentSubscriptions = [];\n this.currentContentTopics = [];\n this.resetMessageHistory();\n }\n\n private static removeAllObservers = async (waku: Optional<LightNode>) => {\n await this.unsubscribe(waku);\n };\n\n private static getDecodersForChain = (chain: Chain) => {\n const contentTopicFees = contentTopics.fees(chain);\n const contentTopicTransactResponse = contentTopics.transactResponse(chain);\n\n const feesDecoder = createDecoder(\n contentTopicFees,\n BroadcasterConfig.getWakuRoutingInfo(),\n );\n const transactResponseDecoder = createDecoder(\n contentTopicTransactResponse,\n BroadcasterConfig.getWakuRoutingInfo(),\n );\n\n const feesCallback = this.wrapCallbackWithCache((message: IMessage) =>\n handleBroadcasterFeesMessage(chain, message, contentTopicFees));\n const transactResponseCallback = this.wrapCallbackWithCache((message: IMessage) =>\n BroadcasterTransactResponse.handleBroadcasterTransactionResponseMessage(\n message,\n ));\n\n return [\n {\n topic: contentTopicFees,\n decoder: feesDecoder,\n callback: feesCallback,\n },\n {\n topic: contentTopicTransactResponse,\n decoder: transactResponseDecoder,\n callback: transactResponseCallback,\n },\n ];\n };\n\n private static addChainObservers = async (waku: LightNode, chain: Chain) => {\n if (!isDefined(waku.filter)) {\n return;\n }\n\n await this.addSubscriptions(chain, waku).catch(\n err => {\n BroadcasterDebug.log(`Error adding Observers. ${err.message}`);\n return undefined;\n },\n );\n // Log current list of observers\n const currentContentTopics = WakuObservers.getCurrentContentTopics();\n BroadcasterDebug.log('Waku content topics:');\n for (const observer of currentContentTopics) {\n BroadcasterDebug.log(observer);\n }\n };\n\n static async addTransportSubscription(\n waku: Optional<LightNode>,\n topic: string,\n callback: (message: any) => void,\n ): Promise<void> {\n if (!isDefined(waku)) {\n BroadcasterDebug.log(\n 'No waku instance found, Transport Subscription not added.',\n );\n return;\n }\n const transportTopic = contentTopics.encrypted(topic);\n const decoder = createDecoder(\n transportTopic,\n BroadcasterConfig.getWakuRoutingInfo(),\n );\n const wrappedCallback = this.wrapCallbackWithCache(callback);\n const params: SubscriptionParams = {\n topic: transportTopic,\n decoder,\n callback: wrappedCallback,\n };\n await waku.filter.subscribe(\n decoder,\n wrappedCallback,\n );\n this.currentSubscriptions?.push({\n params,\n });\n WakuObservers.currentContentTopics.push(transportTopic);\n }\n\n private static async addSubscriptions(\n chain: Optional<Chain>,\n waku: Optional<LightNode>,\n ) {\n if (!isDefined(chain) || !isDefined(waku)) {\n BroadcasterDebug.log('AddSubscription: No Waku or Chain defined.');\n return;\n }\n const subscriptionParams = this.getDecodersForChain(chain);\n const topics = subscriptionParams.map(params => params.topic);\n const newTopics = topics.filter(\n topic => !this.currentContentTopics.includes(topic),\n );\n this.currentContentTopics.push(...newTopics);\n for (const params of subscriptionParams) {\n const { decoder, callback } = params;\n await waku.filter.subscribe(\n decoder,\n callback,\n );\n this.currentSubscriptions?.push({\n params,\n });\n }\n }\n\n static getCurrentContentTopics(): string[] {\n return WakuObservers.currentContentTopics;\n }\n\n static getLastMessage(topic: string): IDecodedMessage | undefined {\n let latestMessage: IDecodedMessage | undefined;\n for (const msg of this.observedMessages) {\n if (msg.contentTopic === topic) {\n if (!latestMessage) {\n latestMessage = msg;\n continue;\n }\n const msgTime = msg.timestamp ? msg.timestamp.getTime() : 0;\n const latestTime = latestMessage.timestamp ? latestMessage.timestamp.getTime() : 0;\n if (msgTime > latestTime) {\n latestMessage = msg;\n }\n }\n }\n return latestMessage;\n }\n\n static getCallbackForTopic(topic: string): Optional<(message: any) => void> {\n const subscription = this.currentSubscriptions?.find(sub => sub.params.topic === topic);\n return subscription?.params.callback;\n }\n}\n"]}